logs_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. package logx
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "log"
  8. "os"
  9. "reflect"
  10. "runtime"
  11. "strings"
  12. "sync"
  13. "sync/atomic"
  14. "testing"
  15. "time"
  16. "github.com/stretchr/testify/assert"
  17. )
  18. var (
  19. s = []byte("Sending #11 notification (id: 1451875113812010473) in #1 connection")
  20. pool = make(chan []byte, 1)
  21. _ Writer = (*mockWriter)(nil)
  22. )
  23. type mockWriter struct {
  24. lock sync.Mutex
  25. builder strings.Builder
  26. }
  27. func (mw *mockWriter) Alert(v interface{}) {
  28. mw.lock.Lock()
  29. defer mw.lock.Unlock()
  30. output(&mw.builder, levelAlert, v)
  31. }
  32. func (mw *mockWriter) Debug(v interface{}, fields ...LogField) {
  33. mw.lock.Lock()
  34. defer mw.lock.Unlock()
  35. output(&mw.builder, levelDebug, v, fields...)
  36. }
  37. func (mw *mockWriter) Error(v interface{}, fields ...LogField) {
  38. mw.lock.Lock()
  39. defer mw.lock.Unlock()
  40. output(&mw.builder, levelError, v, fields...)
  41. }
  42. func (mw *mockWriter) Info(v interface{}, fields ...LogField) {
  43. mw.lock.Lock()
  44. defer mw.lock.Unlock()
  45. output(&mw.builder, levelInfo, v, fields...)
  46. }
  47. func (mw *mockWriter) Severe(v interface{}) {
  48. mw.lock.Lock()
  49. defer mw.lock.Unlock()
  50. output(&mw.builder, levelSevere, v)
  51. }
  52. func (mw *mockWriter) Slow(v interface{}, fields ...LogField) {
  53. mw.lock.Lock()
  54. defer mw.lock.Unlock()
  55. output(&mw.builder, levelSlow, v, fields...)
  56. }
  57. func (mw *mockWriter) Stack(v interface{}) {
  58. mw.lock.Lock()
  59. defer mw.lock.Unlock()
  60. output(&mw.builder, levelError, v)
  61. }
  62. func (mw *mockWriter) Stat(v interface{}, fields ...LogField) {
  63. mw.lock.Lock()
  64. defer mw.lock.Unlock()
  65. output(&mw.builder, levelStat, v, fields...)
  66. }
  67. func (mw *mockWriter) Close() error {
  68. return nil
  69. }
  70. func (mw *mockWriter) Contains(text string) bool {
  71. mw.lock.Lock()
  72. defer mw.lock.Unlock()
  73. return strings.Contains(mw.builder.String(), text)
  74. }
  75. func (mw *mockWriter) Reset() {
  76. mw.lock.Lock()
  77. defer mw.lock.Unlock()
  78. mw.builder.Reset()
  79. }
  80. func (mw *mockWriter) String() string {
  81. mw.lock.Lock()
  82. defer mw.lock.Unlock()
  83. return mw.builder.String()
  84. }
  85. func TestField(t *testing.T) {
  86. tests := []struct {
  87. name string
  88. f LogField
  89. want map[string]interface{}
  90. }{
  91. {
  92. name: "error",
  93. f: Field("foo", errors.New("bar")),
  94. want: map[string]interface{}{
  95. "foo": "bar",
  96. },
  97. },
  98. {
  99. name: "errors",
  100. f: Field("foo", []error{errors.New("bar"), errors.New("baz")}),
  101. want: map[string]interface{}{
  102. "foo": []interface{}{"bar", "baz"},
  103. },
  104. },
  105. {
  106. name: "strings",
  107. f: Field("foo", []string{"bar", "baz"}),
  108. want: map[string]interface{}{
  109. "foo": []interface{}{"bar", "baz"},
  110. },
  111. },
  112. {
  113. name: "duration",
  114. f: Field("foo", time.Second),
  115. want: map[string]interface{}{
  116. "foo": "1s",
  117. },
  118. },
  119. {
  120. name: "durations",
  121. f: Field("foo", []time.Duration{time.Second, 2 * time.Second}),
  122. want: map[string]interface{}{
  123. "foo": []interface{}{"1s", "2s"},
  124. },
  125. },
  126. {
  127. name: "times",
  128. f: Field("foo", []time.Time{
  129. time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC),
  130. time.Date(2020, time.January, 2, 0, 0, 0, 0, time.UTC),
  131. }),
  132. want: map[string]interface{}{
  133. "foo": []interface{}{"2020-01-01 00:00:00 +0000 UTC", "2020-01-02 00:00:00 +0000 UTC"},
  134. },
  135. },
  136. {
  137. name: "stringer",
  138. f: Field("foo", ValStringer{val: "bar"}),
  139. want: map[string]interface{}{
  140. "foo": "bar",
  141. },
  142. },
  143. {
  144. name: "stringers",
  145. f: Field("foo", []fmt.Stringer{ValStringer{val: "bar"}, ValStringer{val: "baz"}}),
  146. want: map[string]interface{}{
  147. "foo": []interface{}{"bar", "baz"},
  148. },
  149. },
  150. }
  151. for _, test := range tests {
  152. test := test
  153. t.Run(test.name, func(t *testing.T) {
  154. w := new(mockWriter)
  155. old := writer.Swap(w)
  156. defer writer.Store(old)
  157. Infow("foo", test.f)
  158. validateFields(t, w.String(), test.want)
  159. })
  160. }
  161. }
  162. func TestFileLineFileMode(t *testing.T) {
  163. w := new(mockWriter)
  164. old := writer.Swap(w)
  165. defer writer.Store(old)
  166. file, line := getFileLine()
  167. Error("anything")
  168. assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1)))
  169. file, line = getFileLine()
  170. Errorf("anything %s", "format")
  171. assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1)))
  172. }
  173. func TestFileLineConsoleMode(t *testing.T) {
  174. w := new(mockWriter)
  175. old := writer.Swap(w)
  176. defer writer.Store(old)
  177. file, line := getFileLine()
  178. Error("anything")
  179. assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1)))
  180. w.Reset()
  181. file, line = getFileLine()
  182. Errorf("anything %s", "format")
  183. assert.True(t, w.Contains(fmt.Sprintf("%s:%d", file, line+1)))
  184. }
  185. func TestStructedLogAlert(t *testing.T) {
  186. w := new(mockWriter)
  187. old := writer.Swap(w)
  188. defer writer.Store(old)
  189. doTestStructedLog(t, levelAlert, w, func(v ...interface{}) {
  190. Alert(fmt.Sprint(v...))
  191. })
  192. }
  193. func TestStructedLogDebug(t *testing.T) {
  194. w := new(mockWriter)
  195. old := writer.Swap(w)
  196. defer writer.Store(old)
  197. doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
  198. Debug(v...)
  199. })
  200. }
  201. func TestStructedLogDebugf(t *testing.T) {
  202. w := new(mockWriter)
  203. old := writer.Swap(w)
  204. defer writer.Store(old)
  205. doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
  206. Debugf(fmt.Sprint(v...))
  207. })
  208. }
  209. func TestStructedLogDebugv(t *testing.T) {
  210. w := new(mockWriter)
  211. old := writer.Swap(w)
  212. defer writer.Store(old)
  213. doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
  214. Debugv(fmt.Sprint(v...))
  215. })
  216. }
  217. func TestStructedLogDebugw(t *testing.T) {
  218. w := new(mockWriter)
  219. old := writer.Swap(w)
  220. defer writer.Store(old)
  221. doTestStructedLog(t, levelDebug, w, func(v ...interface{}) {
  222. Debugw(fmt.Sprint(v...), Field("foo", time.Second))
  223. })
  224. }
  225. func TestStructedLogError(t *testing.T) {
  226. w := new(mockWriter)
  227. old := writer.Swap(w)
  228. defer writer.Store(old)
  229. doTestStructedLog(t, levelError, w, func(v ...interface{}) {
  230. Error(v...)
  231. })
  232. }
  233. func TestStructedLogErrorf(t *testing.T) {
  234. w := new(mockWriter)
  235. old := writer.Swap(w)
  236. defer writer.Store(old)
  237. doTestStructedLog(t, levelError, w, func(v ...interface{}) {
  238. Errorf("%s", fmt.Sprint(v...))
  239. })
  240. }
  241. func TestStructedLogErrorv(t *testing.T) {
  242. w := new(mockWriter)
  243. old := writer.Swap(w)
  244. defer writer.Store(old)
  245. doTestStructedLog(t, levelError, w, func(v ...interface{}) {
  246. Errorv(fmt.Sprint(v...))
  247. })
  248. }
  249. func TestStructedLogErrorw(t *testing.T) {
  250. w := new(mockWriter)
  251. old := writer.Swap(w)
  252. defer writer.Store(old)
  253. doTestStructedLog(t, levelError, w, func(v ...interface{}) {
  254. Errorw(fmt.Sprint(v...), Field("foo", "bar"))
  255. })
  256. }
  257. func TestStructedLogInfo(t *testing.T) {
  258. w := new(mockWriter)
  259. old := writer.Swap(w)
  260. defer writer.Store(old)
  261. doTestStructedLog(t, levelInfo, w, func(v ...interface{}) {
  262. Info(v...)
  263. })
  264. }
  265. func TestStructedLogInfof(t *testing.T) {
  266. w := new(mockWriter)
  267. old := writer.Swap(w)
  268. defer writer.Store(old)
  269. doTestStructedLog(t, levelInfo, w, func(v ...interface{}) {
  270. Infof("%s", fmt.Sprint(v...))
  271. })
  272. }
  273. func TestStructedLogInfov(t *testing.T) {
  274. w := new(mockWriter)
  275. old := writer.Swap(w)
  276. defer writer.Store(old)
  277. doTestStructedLog(t, levelInfo, w, func(v ...interface{}) {
  278. Infov(fmt.Sprint(v...))
  279. })
  280. }
  281. func TestStructedLogInfow(t *testing.T) {
  282. w := new(mockWriter)
  283. old := writer.Swap(w)
  284. defer writer.Store(old)
  285. doTestStructedLog(t, levelInfo, w, func(v ...interface{}) {
  286. Infow(fmt.Sprint(v...), Field("foo", "bar"))
  287. })
  288. }
  289. func TestStructedLogInfoConsoleAny(t *testing.T) {
  290. w := new(mockWriter)
  291. old := writer.Swap(w)
  292. defer writer.Store(old)
  293. doTestStructedLogConsole(t, w, func(v ...interface{}) {
  294. old := atomic.LoadUint32(&encoding)
  295. atomic.StoreUint32(&encoding, plainEncodingType)
  296. defer func() {
  297. atomic.StoreUint32(&encoding, old)
  298. }()
  299. Infov(v)
  300. })
  301. }
  302. func TestStructedLogInfoConsoleAnyString(t *testing.T) {
  303. w := new(mockWriter)
  304. old := writer.Swap(w)
  305. defer writer.Store(old)
  306. doTestStructedLogConsole(t, w, func(v ...interface{}) {
  307. old := atomic.LoadUint32(&encoding)
  308. atomic.StoreUint32(&encoding, plainEncodingType)
  309. defer func() {
  310. atomic.StoreUint32(&encoding, old)
  311. }()
  312. Infov(fmt.Sprint(v...))
  313. })
  314. }
  315. func TestStructedLogInfoConsoleAnyError(t *testing.T) {
  316. w := new(mockWriter)
  317. old := writer.Swap(w)
  318. defer writer.Store(old)
  319. doTestStructedLogConsole(t, w, func(v ...interface{}) {
  320. old := atomic.LoadUint32(&encoding)
  321. atomic.StoreUint32(&encoding, plainEncodingType)
  322. defer func() {
  323. atomic.StoreUint32(&encoding, old)
  324. }()
  325. Infov(errors.New(fmt.Sprint(v...)))
  326. })
  327. }
  328. func TestStructedLogInfoConsoleAnyStringer(t *testing.T) {
  329. w := new(mockWriter)
  330. old := writer.Swap(w)
  331. defer writer.Store(old)
  332. doTestStructedLogConsole(t, w, func(v ...interface{}) {
  333. old := atomic.LoadUint32(&encoding)
  334. atomic.StoreUint32(&encoding, plainEncodingType)
  335. defer func() {
  336. atomic.StoreUint32(&encoding, old)
  337. }()
  338. Infov(ValStringer{
  339. val: fmt.Sprint(v...),
  340. })
  341. })
  342. }
  343. func TestStructedLogInfoConsoleText(t *testing.T) {
  344. w := new(mockWriter)
  345. old := writer.Swap(w)
  346. defer writer.Store(old)
  347. doTestStructedLogConsole(t, w, func(v ...interface{}) {
  348. old := atomic.LoadUint32(&encoding)
  349. atomic.StoreUint32(&encoding, plainEncodingType)
  350. defer func() {
  351. atomic.StoreUint32(&encoding, old)
  352. }()
  353. Info(fmt.Sprint(v...))
  354. })
  355. }
  356. func TestStructedLogSlow(t *testing.T) {
  357. w := new(mockWriter)
  358. old := writer.Swap(w)
  359. defer writer.Store(old)
  360. doTestStructedLog(t, levelSlow, w, func(v ...interface{}) {
  361. Slow(v...)
  362. })
  363. }
  364. func TestStructedLogSlowf(t *testing.T) {
  365. w := new(mockWriter)
  366. old := writer.Swap(w)
  367. defer writer.Store(old)
  368. doTestStructedLog(t, levelSlow, w, func(v ...interface{}) {
  369. Slowf(fmt.Sprint(v...))
  370. })
  371. }
  372. func TestStructedLogSlowv(t *testing.T) {
  373. w := new(mockWriter)
  374. old := writer.Swap(w)
  375. defer writer.Store(old)
  376. doTestStructedLog(t, levelSlow, w, func(v ...interface{}) {
  377. Slowv(fmt.Sprint(v...))
  378. })
  379. }
  380. func TestStructedLogSloww(t *testing.T) {
  381. w := new(mockWriter)
  382. old := writer.Swap(w)
  383. defer writer.Store(old)
  384. doTestStructedLog(t, levelSlow, w, func(v ...interface{}) {
  385. Sloww(fmt.Sprint(v...), Field("foo", time.Second))
  386. })
  387. }
  388. func TestStructedLogStat(t *testing.T) {
  389. w := new(mockWriter)
  390. old := writer.Swap(w)
  391. defer writer.Store(old)
  392. doTestStructedLog(t, levelStat, w, func(v ...interface{}) {
  393. Stat(v...)
  394. })
  395. }
  396. func TestStructedLogStatf(t *testing.T) {
  397. w := new(mockWriter)
  398. old := writer.Swap(w)
  399. defer writer.Store(old)
  400. doTestStructedLog(t, levelStat, w, func(v ...interface{}) {
  401. Statf(fmt.Sprint(v...))
  402. })
  403. }
  404. func TestStructedLogSevere(t *testing.T) {
  405. w := new(mockWriter)
  406. old := writer.Swap(w)
  407. defer writer.Store(old)
  408. doTestStructedLog(t, levelSevere, w, func(v ...interface{}) {
  409. Severe(v...)
  410. })
  411. }
  412. func TestStructedLogSeveref(t *testing.T) {
  413. w := new(mockWriter)
  414. old := writer.Swap(w)
  415. defer writer.Store(old)
  416. doTestStructedLog(t, levelSevere, w, func(v ...interface{}) {
  417. Severef(fmt.Sprint(v...))
  418. })
  419. }
  420. func TestStructedLogWithDuration(t *testing.T) {
  421. const message = "hello there"
  422. w := new(mockWriter)
  423. old := writer.Swap(w)
  424. defer writer.Store(old)
  425. WithDuration(time.Second).Info(message)
  426. var entry map[string]interface{}
  427. if err := json.Unmarshal([]byte(w.String()), &entry); err != nil {
  428. t.Error(err)
  429. }
  430. assert.Equal(t, levelInfo, entry[levelKey])
  431. assert.Equal(t, message, entry[contentKey])
  432. assert.Equal(t, "1000.0ms", entry[durationKey])
  433. }
  434. func TestSetLevel(t *testing.T) {
  435. SetLevel(ErrorLevel)
  436. const message = "hello there"
  437. w := new(mockWriter)
  438. old := writer.Swap(w)
  439. defer writer.Store(old)
  440. Info(message)
  441. assert.Equal(t, 0, w.builder.Len())
  442. }
  443. func TestSetLevelTwiceWithMode(t *testing.T) {
  444. testModes := []string{
  445. "mode",
  446. "console",
  447. "volumn",
  448. }
  449. w := new(mockWriter)
  450. old := writer.Swap(w)
  451. defer writer.Store(old)
  452. for _, mode := range testModes {
  453. testSetLevelTwiceWithMode(t, mode, w)
  454. }
  455. }
  456. func TestSetLevelWithDuration(t *testing.T) {
  457. SetLevel(ErrorLevel)
  458. const message = "hello there"
  459. w := new(mockWriter)
  460. old := writer.Swap(w)
  461. defer writer.Store(old)
  462. WithDuration(time.Second).Info(message)
  463. assert.Equal(t, 0, w.builder.Len())
  464. }
  465. func TestErrorfWithWrappedError(t *testing.T) {
  466. SetLevel(ErrorLevel)
  467. const message = "there"
  468. w := new(mockWriter)
  469. old := writer.Swap(w)
  470. defer writer.Store(old)
  471. Errorf("hello %w", errors.New(message))
  472. assert.True(t, strings.Contains(w.String(), "hello there"))
  473. }
  474. func TestMustNil(t *testing.T) {
  475. Must(nil)
  476. }
  477. func TestSetup(t *testing.T) {
  478. defer func() {
  479. SetLevel(InfoLevel)
  480. atomic.StoreUint32(&encoding, jsonEncodingType)
  481. }()
  482. MustSetup(LogConf{
  483. ServiceName: "any",
  484. Mode: "console",
  485. TimeFormat: timeFormat,
  486. })
  487. MustSetup(LogConf{
  488. ServiceName: "any",
  489. Mode: "file",
  490. Path: os.TempDir(),
  491. })
  492. MustSetup(LogConf{
  493. ServiceName: "any",
  494. Mode: "volume",
  495. Path: os.TempDir(),
  496. })
  497. MustSetup(LogConf{
  498. ServiceName: "any",
  499. Mode: "console",
  500. TimeFormat: timeFormat,
  501. })
  502. MustSetup(LogConf{
  503. ServiceName: "any",
  504. Mode: "console",
  505. Encoding: plainEncoding,
  506. })
  507. defer os.RemoveAll("CD01CB7D-2705-4F3F-889E-86219BF56F10")
  508. assert.NotNil(t, setupWithVolume(LogConf{}))
  509. assert.Nil(t, setupWithVolume(LogConf{
  510. ServiceName: "CD01CB7D-2705-4F3F-889E-86219BF56F10",
  511. }))
  512. assert.Nil(t, setupWithVolume(LogConf{
  513. ServiceName: "CD01CB7D-2705-4F3F-889E-86219BF56F10",
  514. Rotation: sizeRotationRule,
  515. }))
  516. assert.NotNil(t, setupWithFiles(LogConf{}))
  517. assert.Nil(t, setupWithFiles(LogConf{
  518. ServiceName: "any",
  519. Path: os.TempDir(),
  520. Compress: true,
  521. KeepDays: 1,
  522. }))
  523. setupLogLevel(LogConf{
  524. Level: levelInfo,
  525. })
  526. setupLogLevel(LogConf{
  527. Level: levelError,
  528. })
  529. setupLogLevel(LogConf{
  530. Level: levelSevere,
  531. })
  532. _, err := createOutput("")
  533. assert.NotNil(t, err)
  534. Disable()
  535. SetLevel(InfoLevel)
  536. atomic.StoreUint32(&encoding, jsonEncodingType)
  537. }
  538. func TestDisable(t *testing.T) {
  539. Disable()
  540. var opt logOptions
  541. WithKeepDays(1)(&opt)
  542. WithGzip()(&opt)
  543. WithMaxBackups(1)(&opt)
  544. WithMaxSize(1024)(&opt)
  545. assert.Nil(t, Close())
  546. assert.Nil(t, Close())
  547. }
  548. func TestDisableStat(t *testing.T) {
  549. DisableStat()
  550. const message = "hello there"
  551. w := new(mockWriter)
  552. old := writer.Swap(w)
  553. defer writer.Store(old)
  554. Stat(message)
  555. assert.Equal(t, 0, w.builder.Len())
  556. }
  557. func TestSetWriter(t *testing.T) {
  558. atomic.StoreUint32(&disableLog, 0)
  559. Reset()
  560. SetWriter(nopWriter{})
  561. assert.NotNil(t, writer.Load())
  562. assert.True(t, writer.Load() == nopWriter{})
  563. mocked := new(mockWriter)
  564. SetWriter(mocked)
  565. assert.Equal(t, mocked, writer.Load())
  566. }
  567. func TestWithGzip(t *testing.T) {
  568. fn := WithGzip()
  569. var opt logOptions
  570. fn(&opt)
  571. assert.True(t, opt.gzipEnabled)
  572. }
  573. func TestWithKeepDays(t *testing.T) {
  574. fn := WithKeepDays(1)
  575. var opt logOptions
  576. fn(&opt)
  577. assert.Equal(t, 1, opt.keepDays)
  578. }
  579. func BenchmarkCopyByteSliceAppend(b *testing.B) {
  580. for i := 0; i < b.N; i++ {
  581. var buf []byte
  582. buf = append(buf, getTimestamp()...)
  583. buf = append(buf, ' ')
  584. buf = append(buf, s...)
  585. _ = buf
  586. }
  587. }
  588. func BenchmarkCopyByteSliceAllocExactly(b *testing.B) {
  589. for i := 0; i < b.N; i++ {
  590. now := []byte(getTimestamp())
  591. buf := make([]byte, len(now)+1+len(s))
  592. n := copy(buf, now)
  593. buf[n] = ' '
  594. copy(buf[n+1:], s)
  595. }
  596. }
  597. func BenchmarkCopyByteSlice(b *testing.B) {
  598. var buf []byte
  599. for i := 0; i < b.N; i++ {
  600. buf = make([]byte, len(s))
  601. copy(buf, s)
  602. }
  603. fmt.Fprint(io.Discard, buf)
  604. }
  605. func BenchmarkCopyOnWriteByteSlice(b *testing.B) {
  606. var buf []byte
  607. for i := 0; i < b.N; i++ {
  608. size := len(s)
  609. buf = s[:size:size]
  610. }
  611. fmt.Fprint(io.Discard, buf)
  612. }
  613. func BenchmarkCacheByteSlice(b *testing.B) {
  614. for i := 0; i < b.N; i++ {
  615. dup := fetch()
  616. copy(dup, s)
  617. put(dup)
  618. }
  619. }
  620. func BenchmarkLogs(b *testing.B) {
  621. b.ReportAllocs()
  622. log.SetOutput(io.Discard)
  623. for i := 0; i < b.N; i++ {
  624. Info(i)
  625. }
  626. }
  627. func fetch() []byte {
  628. select {
  629. case b := <-pool:
  630. return b
  631. default:
  632. }
  633. return make([]byte, 4096)
  634. }
  635. func getFileLine() (string, int) {
  636. _, file, line, _ := runtime.Caller(1)
  637. short := file
  638. for i := len(file) - 1; i > 0; i-- {
  639. if file[i] == '/' {
  640. short = file[i+1:]
  641. break
  642. }
  643. }
  644. return short, line
  645. }
  646. func put(b []byte) {
  647. select {
  648. case pool <- b:
  649. default:
  650. }
  651. }
  652. func doTestStructedLog(t *testing.T, level string, w *mockWriter, write func(...interface{})) {
  653. const message = "hello there"
  654. write(message)
  655. var entry map[string]interface{}
  656. if err := json.Unmarshal([]byte(w.String()), &entry); err != nil {
  657. t.Error(err)
  658. }
  659. assert.Equal(t, level, entry[levelKey])
  660. val, ok := entry[contentKey]
  661. assert.True(t, ok)
  662. assert.True(t, strings.Contains(val.(string), message))
  663. }
  664. func doTestStructedLogConsole(t *testing.T, w *mockWriter, write func(...interface{})) {
  665. const message = "hello there"
  666. write(message)
  667. assert.True(t, strings.Contains(w.String(), message))
  668. }
  669. func testSetLevelTwiceWithMode(t *testing.T, mode string, w *mockWriter) {
  670. writer.Store(nil)
  671. SetUp(LogConf{
  672. Mode: mode,
  673. Level: "error",
  674. Path: "/dev/null",
  675. })
  676. SetUp(LogConf{
  677. Mode: mode,
  678. Level: "info",
  679. Path: "/dev/null",
  680. })
  681. const message = "hello there"
  682. Info(message)
  683. assert.Equal(t, 0, w.builder.Len())
  684. Infof(message)
  685. assert.Equal(t, 0, w.builder.Len())
  686. ErrorStack(message)
  687. assert.Equal(t, 0, w.builder.Len())
  688. ErrorStackf(message)
  689. assert.Equal(t, 0, w.builder.Len())
  690. }
  691. type ValStringer struct {
  692. val string
  693. }
  694. func (v ValStringer) String() string {
  695. return v.val
  696. }
  697. func validateFields(t *testing.T, content string, fields map[string]interface{}) {
  698. var m map[string]interface{}
  699. if err := json.Unmarshal([]byte(content), &m); err != nil {
  700. t.Error(err)
  701. }
  702. for k, v := range fields {
  703. if reflect.TypeOf(v).Kind() == reflect.Slice {
  704. assert.EqualValues(t, v, m[k])
  705. } else {
  706. assert.Equal(t, v, m[k], content)
  707. }
  708. }
  709. }