writer_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. package logx
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "log"
  7. "sync/atomic"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func TestNewWriter(t *testing.T) {
  12. const literal = "foo bar"
  13. var buf bytes.Buffer
  14. w := NewWriter(&buf)
  15. w.Info(literal)
  16. assert.Contains(t, buf.String(), literal)
  17. buf.Reset()
  18. w.Debug(literal)
  19. assert.Contains(t, buf.String(), literal)
  20. }
  21. func TestConsoleWriter(t *testing.T) {
  22. var buf bytes.Buffer
  23. w := newConsoleWriter()
  24. lw := newLogWriter(log.New(&buf, "", 0))
  25. w.(*concreteWriter).errorLog = lw
  26. w.Alert("foo bar 1")
  27. var val mockedEntry
  28. if err := json.Unmarshal(buf.Bytes(), &val); err != nil {
  29. t.Fatal(err)
  30. }
  31. assert.Equal(t, levelAlert, val.Level)
  32. assert.Equal(t, "foo bar 1", val.Content)
  33. buf.Reset()
  34. w.(*concreteWriter).errorLog = lw
  35. w.Error("foo bar 2")
  36. if err := json.Unmarshal(buf.Bytes(), &val); err != nil {
  37. t.Fatal(err)
  38. }
  39. assert.Equal(t, levelError, val.Level)
  40. assert.Equal(t, "foo bar 2", val.Content)
  41. buf.Reset()
  42. w.(*concreteWriter).infoLog = lw
  43. w.Info("foo bar 3")
  44. if err := json.Unmarshal(buf.Bytes(), &val); err != nil {
  45. t.Fatal(err)
  46. }
  47. assert.Equal(t, levelInfo, val.Level)
  48. assert.Equal(t, "foo bar 3", val.Content)
  49. buf.Reset()
  50. w.(*concreteWriter).severeLog = lw
  51. w.Severe("foo bar 4")
  52. if err := json.Unmarshal(buf.Bytes(), &val); err != nil {
  53. t.Fatal(err)
  54. }
  55. assert.Equal(t, levelFatal, val.Level)
  56. assert.Equal(t, "foo bar 4", val.Content)
  57. buf.Reset()
  58. w.(*concreteWriter).slowLog = lw
  59. w.Slow("foo bar 5")
  60. if err := json.Unmarshal(buf.Bytes(), &val); err != nil {
  61. t.Fatal(err)
  62. }
  63. assert.Equal(t, levelSlow, val.Level)
  64. assert.Equal(t, "foo bar 5", val.Content)
  65. buf.Reset()
  66. w.(*concreteWriter).statLog = lw
  67. w.Stat("foo bar 6")
  68. if err := json.Unmarshal(buf.Bytes(), &val); err != nil {
  69. t.Fatal(err)
  70. }
  71. assert.Equal(t, levelStat, val.Level)
  72. assert.Equal(t, "foo bar 6", val.Content)
  73. w.(*concreteWriter).infoLog = hardToCloseWriter{}
  74. assert.NotNil(t, w.Close())
  75. w.(*concreteWriter).infoLog = easyToCloseWriter{}
  76. w.(*concreteWriter).errorLog = hardToCloseWriter{}
  77. assert.NotNil(t, w.Close())
  78. w.(*concreteWriter).errorLog = easyToCloseWriter{}
  79. w.(*concreteWriter).severeLog = hardToCloseWriter{}
  80. assert.NotNil(t, w.Close())
  81. w.(*concreteWriter).severeLog = easyToCloseWriter{}
  82. w.(*concreteWriter).slowLog = hardToCloseWriter{}
  83. assert.NotNil(t, w.Close())
  84. w.(*concreteWriter).slowLog = easyToCloseWriter{}
  85. w.(*concreteWriter).statLog = hardToCloseWriter{}
  86. assert.NotNil(t, w.Close())
  87. w.(*concreteWriter).statLog = easyToCloseWriter{}
  88. }
  89. func TestNewFileWriter(t *testing.T) {
  90. t.Run("access", func(t *testing.T) {
  91. _, err := newFileWriter(LogConf{
  92. Path: "/not-exists",
  93. })
  94. assert.Error(t, err)
  95. })
  96. }
  97. func TestNopWriter(t *testing.T) {
  98. assert.NotPanics(t, func() {
  99. var w nopWriter
  100. w.Alert("foo")
  101. w.Debug("foo")
  102. w.Error("foo")
  103. w.Info("foo")
  104. w.Severe("foo")
  105. w.Stack("foo")
  106. w.Stat("foo")
  107. w.Slow("foo")
  108. _ = w.Close()
  109. })
  110. }
  111. func TestWriteJson(t *testing.T) {
  112. var buf bytes.Buffer
  113. log.SetOutput(&buf)
  114. writeJson(nil, "foo")
  115. assert.Contains(t, buf.String(), "foo")
  116. buf.Reset()
  117. writeJson(nil, make(chan int))
  118. assert.Contains(t, buf.String(), "unsupported type")
  119. buf.Reset()
  120. type C struct {
  121. RC func()
  122. }
  123. writeJson(nil, C{
  124. RC: func() {},
  125. })
  126. assert.Contains(t, buf.String(), "runtime/debug.Stack")
  127. }
  128. func TestWritePlainAny(t *testing.T) {
  129. var buf bytes.Buffer
  130. log.SetOutput(&buf)
  131. writePlainAny(nil, levelInfo, "foo")
  132. assert.Contains(t, buf.String(), "foo")
  133. buf.Reset()
  134. writePlainAny(nil, levelDebug, make(chan int))
  135. assert.Contains(t, buf.String(), "unsupported type")
  136. writePlainAny(nil, levelDebug, 100)
  137. assert.Contains(t, buf.String(), "100")
  138. buf.Reset()
  139. writePlainAny(nil, levelError, make(chan int))
  140. assert.Contains(t, buf.String(), "unsupported type")
  141. writePlainAny(nil, levelSlow, 100)
  142. assert.Contains(t, buf.String(), "100")
  143. buf.Reset()
  144. writePlainAny(hardToWriteWriter{}, levelStat, 100)
  145. assert.Contains(t, buf.String(), "write error")
  146. buf.Reset()
  147. writePlainAny(hardToWriteWriter{}, levelSevere, "foo")
  148. assert.Contains(t, buf.String(), "write error")
  149. buf.Reset()
  150. writePlainAny(hardToWriteWriter{}, levelAlert, "foo")
  151. assert.Contains(t, buf.String(), "write error")
  152. buf.Reset()
  153. writePlainAny(hardToWriteWriter{}, levelFatal, "foo")
  154. assert.Contains(t, buf.String(), "write error")
  155. buf.Reset()
  156. type C struct {
  157. RC func()
  158. }
  159. writePlainAny(nil, levelError, C{
  160. RC: func() {},
  161. })
  162. assert.Contains(t, buf.String(), "runtime/debug.Stack")
  163. }
  164. func TestLogWithLimitContentLength(t *testing.T) {
  165. maxLen := atomic.LoadUint32(&maxContentLength)
  166. atomic.StoreUint32(&maxContentLength, 10)
  167. t.Cleanup(func() {
  168. atomic.StoreUint32(&maxContentLength, maxLen)
  169. })
  170. t.Run("alert", func(t *testing.T) {
  171. var buf bytes.Buffer
  172. w := NewWriter(&buf)
  173. w.Info("1234567890")
  174. var v1 mockedEntry
  175. if err := json.Unmarshal(buf.Bytes(), &v1); err != nil {
  176. t.Fatal(err)
  177. }
  178. assert.Equal(t, "1234567890", v1.Content)
  179. assert.False(t, v1.Truncated)
  180. buf.Reset()
  181. var v2 mockedEntry
  182. w.Info("12345678901")
  183. if err := json.Unmarshal(buf.Bytes(), &v2); err != nil {
  184. t.Fatal(err)
  185. }
  186. assert.Equal(t, "1234567890", v2.Content)
  187. assert.True(t, v2.Truncated)
  188. })
  189. }
  190. type mockedEntry struct {
  191. Level string `json:"level"`
  192. Content string `json:"content"`
  193. Truncated bool `json:"truncated"`
  194. }
  195. type easyToCloseWriter struct{}
  196. func (h easyToCloseWriter) Write(_ []byte) (_ int, _ error) {
  197. return
  198. }
  199. func (h easyToCloseWriter) Close() error {
  200. return nil
  201. }
  202. type hardToCloseWriter struct{}
  203. func (h hardToCloseWriter) Write(_ []byte) (_ int, _ error) {
  204. return
  205. }
  206. func (h hardToCloseWriter) Close() error {
  207. return errors.New("close error")
  208. }
  209. type hardToWriteWriter struct{}
  210. func (h hardToWriteWriter) Write(_ []byte) (_ int, _ error) {
  211. return 0, errors.New("write error")
  212. }