writer_test.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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(hardToWriteWriter{}, "foo")
  118. assert.Contains(t, buf.String(), "write error")
  119. buf.Reset()
  120. writeJson(nil, make(chan int))
  121. assert.Contains(t, buf.String(), "unsupported type")
  122. buf.Reset()
  123. type C struct {
  124. RC func()
  125. }
  126. writeJson(nil, C{
  127. RC: func() {},
  128. })
  129. assert.Contains(t, buf.String(), "runtime/debug.Stack")
  130. }
  131. func TestWritePlainAny(t *testing.T) {
  132. var buf bytes.Buffer
  133. log.SetOutput(&buf)
  134. writePlainAny(nil, levelInfo, "foo")
  135. assert.Contains(t, buf.String(), "foo")
  136. buf.Reset()
  137. writePlainAny(nil, levelDebug, make(chan int))
  138. assert.Contains(t, buf.String(), "unsupported type")
  139. writePlainAny(nil, levelDebug, 100)
  140. assert.Contains(t, buf.String(), "100")
  141. buf.Reset()
  142. writePlainAny(nil, levelError, make(chan int))
  143. assert.Contains(t, buf.String(), "unsupported type")
  144. writePlainAny(nil, levelSlow, 100)
  145. assert.Contains(t, buf.String(), "100")
  146. buf.Reset()
  147. writePlainAny(hardToWriteWriter{}, levelStat, 100)
  148. assert.Contains(t, buf.String(), "write error")
  149. buf.Reset()
  150. writePlainAny(hardToWriteWriter{}, levelSevere, "foo")
  151. assert.Contains(t, buf.String(), "write error")
  152. buf.Reset()
  153. writePlainAny(hardToWriteWriter{}, levelAlert, "foo")
  154. assert.Contains(t, buf.String(), "write error")
  155. buf.Reset()
  156. writePlainAny(hardToWriteWriter{}, levelFatal, "foo")
  157. assert.Contains(t, buf.String(), "write error")
  158. buf.Reset()
  159. type C struct {
  160. RC func()
  161. }
  162. writePlainAny(nil, levelError, C{
  163. RC: func() {},
  164. })
  165. assert.Contains(t, buf.String(), "runtime/debug.Stack")
  166. }
  167. func TestLogWithLimitContentLength(t *testing.T) {
  168. maxLen := atomic.LoadUint32(&maxContentLength)
  169. atomic.StoreUint32(&maxContentLength, 10)
  170. t.Cleanup(func() {
  171. atomic.StoreUint32(&maxContentLength, maxLen)
  172. })
  173. t.Run("alert", func(t *testing.T) {
  174. var buf bytes.Buffer
  175. w := NewWriter(&buf)
  176. w.Info("1234567890")
  177. var v1 mockedEntry
  178. if err := json.Unmarshal(buf.Bytes(), &v1); err != nil {
  179. t.Fatal(err)
  180. }
  181. assert.Equal(t, "1234567890", v1.Content)
  182. assert.False(t, v1.Truncated)
  183. buf.Reset()
  184. var v2 mockedEntry
  185. w.Info("12345678901")
  186. if err := json.Unmarshal(buf.Bytes(), &v2); err != nil {
  187. t.Fatal(err)
  188. }
  189. assert.Equal(t, "1234567890", v2.Content)
  190. assert.True(t, v2.Truncated)
  191. })
  192. }
  193. type mockedEntry struct {
  194. Level string `json:"level"`
  195. Content string `json:"content"`
  196. Truncated bool `json:"truncated"`
  197. }
  198. type easyToCloseWriter struct{}
  199. func (h easyToCloseWriter) Write(_ []byte) (_ int, _ error) {
  200. return
  201. }
  202. func (h easyToCloseWriter) Close() error {
  203. return nil
  204. }
  205. type hardToCloseWriter struct{}
  206. func (h hardToCloseWriter) Write(_ []byte) (_ int, _ error) {
  207. return
  208. }
  209. func (h hardToCloseWriter) Close() error {
  210. return errors.New("close error")
  211. }
  212. type hardToWriteWriter struct{}
  213. func (h hardToWriteWriter) Write(_ []byte) (_ int, _ error) {
  214. return 0, errors.New("write error")
  215. }