1 package lumberjack
2
3 import (
4 "bytes"
5 "compress/gzip"
6 "encoding/json"
7 "fmt"
8 "io/ioutil"
9 "os"
10 "path/filepath"
11 "testing"
12 "time"
13 )
14
15
16
17
18
19
20
21
22
23
24 var fakeCurrentTime = time.Now()
25
26 func fakeTime() time.Time {
27 return fakeCurrentTime
28 }
29
30 func TestNewFile(t *testing.T) {
31 currentTime = fakeTime
32
33 dir := makeTempDir("TestNewFile", t)
34 defer os.RemoveAll(dir)
35 l := &Logger{
36 Filename: logFile(dir),
37 }
38 defer l.Close()
39 b := []byte("boo!")
40 n, err := l.Write(b)
41 isNil(err, t)
42 equals(len(b), n, t)
43 existsWithContent(logFile(dir), b, t)
44 fileCount(dir, 1, t)
45 }
46
47 func TestOpenExisting(t *testing.T) {
48 currentTime = fakeTime
49 dir := makeTempDir("TestOpenExisting", t)
50 defer os.RemoveAll(dir)
51
52 filename := logFile(dir)
53 data := []byte("foo!")
54 err := ioutil.WriteFile(filename, data, 0644)
55 isNil(err, t)
56 existsWithContent(filename, data, t)
57
58 l := &Logger{
59 Filename: filename,
60 }
61 defer l.Close()
62 b := []byte("boo!")
63 n, err := l.Write(b)
64 isNil(err, t)
65 equals(len(b), n, t)
66
67
68 existsWithContent(filename, append(data, b...), t)
69
70
71 fileCount(dir, 1, t)
72 }
73
74 func TestWriteTooLong(t *testing.T) {
75 currentTime = fakeTime
76 megabyte = 1
77 dir := makeTempDir("TestWriteTooLong", t)
78 defer os.RemoveAll(dir)
79 l := &Logger{
80 Filename: logFile(dir),
81 MaxSize: 5,
82 }
83 defer l.Close()
84 b := []byte("booooooooooooooo!")
85 n, err := l.Write(b)
86 notNil(err, t)
87 equals(0, n, t)
88 equals(err.Error(),
89 fmt.Sprintf("write length %d exceeds maximum file size %d", len(b), l.MaxSize), t)
90 _, err = os.Stat(logFile(dir))
91 assert(os.IsNotExist(err), t, "File exists, but should not have been created")
92 }
93
94 func TestMakeLogDir(t *testing.T) {
95 currentTime = fakeTime
96 dir := time.Now().Format("TestMakeLogDir" + backupTimeFormat)
97 dir = filepath.Join(os.TempDir(), dir)
98 defer os.RemoveAll(dir)
99 filename := logFile(dir)
100 l := &Logger{
101 Filename: filename,
102 }
103 defer l.Close()
104 b := []byte("boo!")
105 n, err := l.Write(b)
106 isNil(err, t)
107 equals(len(b), n, t)
108 existsWithContent(logFile(dir), b, t)
109 fileCount(dir, 1, t)
110 }
111
112 func TestDefaultFilename(t *testing.T) {
113 currentTime = fakeTime
114 dir := os.TempDir()
115 filename := filepath.Join(dir, filepath.Base(os.Args[0])+"-lumberjack.log")
116 defer os.Remove(filename)
117 l := &Logger{}
118 defer l.Close()
119 b := []byte("boo!")
120 n, err := l.Write(b)
121
122 isNil(err, t)
123 equals(len(b), n, t)
124 existsWithContent(filename, b, t)
125 }
126
127 func TestAutoRotate(t *testing.T) {
128 currentTime = fakeTime
129 megabyte = 1
130
131 dir := makeTempDir("TestAutoRotate", t)
132 defer os.RemoveAll(dir)
133
134 filename := logFile(dir)
135 l := &Logger{
136 Filename: filename,
137 MaxSize: 10,
138 }
139 defer l.Close()
140 b := []byte("boo!")
141 n, err := l.Write(b)
142 isNil(err, t)
143 equals(len(b), n, t)
144
145 existsWithContent(filename, b, t)
146 fileCount(dir, 1, t)
147
148 newFakeTime()
149
150 b2 := []byte("foooooo!")
151 n, err = l.Write(b2)
152 isNil(err, t)
153 equals(len(b2), n, t)
154
155
156
157 existsWithContent(filename, b2, t)
158
159
160 existsWithContent(backupFile(dir), b, t)
161
162 fileCount(dir, 2, t)
163 }
164
165 func TestFirstWriteRotate(t *testing.T) {
166 currentTime = fakeTime
167 megabyte = 1
168 dir := makeTempDir("TestFirstWriteRotate", t)
169 defer os.RemoveAll(dir)
170
171 filename := logFile(dir)
172 l := &Logger{
173 Filename: filename,
174 MaxSize: 10,
175 }
176 defer l.Close()
177
178 start := []byte("boooooo!")
179 err := ioutil.WriteFile(filename, start, 0600)
180 isNil(err, t)
181
182 newFakeTime()
183
184
185 b := []byte("fooo!")
186 n, err := l.Write(b)
187 isNil(err, t)
188 equals(len(b), n, t)
189
190 existsWithContent(filename, b, t)
191 existsWithContent(backupFile(dir), start, t)
192
193 fileCount(dir, 2, t)
194 }
195
196 func TestMaxBackups(t *testing.T) {
197 currentTime = fakeTime
198 megabyte = 1
199 dir := makeTempDir("TestMaxBackups", t)
200 defer os.RemoveAll(dir)
201
202 filename := logFile(dir)
203 l := &Logger{
204 Filename: filename,
205 MaxSize: 10,
206 MaxBackups: 1,
207 }
208 defer l.Close()
209 b := []byte("boo!")
210 n, err := l.Write(b)
211 isNil(err, t)
212 equals(len(b), n, t)
213
214 existsWithContent(filename, b, t)
215 fileCount(dir, 1, t)
216
217 newFakeTime()
218
219
220 b2 := []byte("foooooo!")
221 n, err = l.Write(b2)
222 isNil(err, t)
223 equals(len(b2), n, t)
224
225
226 secondFilename := backupFile(dir)
227 existsWithContent(secondFilename, b, t)
228
229
230 existsWithContent(filename, b2, t)
231
232 fileCount(dir, 2, t)
233
234 newFakeTime()
235
236
237 b3 := []byte("baaaaaar!")
238 n, err = l.Write(b3)
239 isNil(err, t)
240 equals(len(b3), n, t)
241
242
243 thirdFilename := backupFile(dir)
244 existsWithContent(thirdFilename, b2, t)
245
246 existsWithContent(filename, b3, t)
247
248
249
250 <-time.After(time.Millisecond * 10)
251
252
253 fileCount(dir, 2, t)
254
255
256 existsWithContent(thirdFilename, b2, t)
257
258
259 notExist(secondFilename, t)
260
261
262
263 newFakeTime()
264
265
266
267 notlogfile := logFile(dir) + ".foo"
268 err = ioutil.WriteFile(notlogfile, []byte("data"), 0644)
269 isNil(err, t)
270
271
272
273 notlogfiledir := backupFile(dir)
274 err = os.Mkdir(notlogfiledir, 0700)
275 isNil(err, t)
276
277 newFakeTime()
278
279
280 fourthFilename := backupFile(dir)
281
282
283
284
285 compLogFile := fourthFilename + compressSuffix
286 err = ioutil.WriteFile(compLogFile, []byte("compress"), 0644)
287 isNil(err, t)
288
289
290 b4 := []byte("baaaaaaz!")
291 n, err = l.Write(b4)
292 isNil(err, t)
293 equals(len(b4), n, t)
294
295 existsWithContent(fourthFilename, b3, t)
296 existsWithContent(fourthFilename+compressSuffix, []byte("compress"), t)
297
298
299
300 <-time.After(time.Millisecond * 10)
301
302
303
304 fileCount(dir, 5, t)
305
306
307 existsWithContent(filename, b4, t)
308
309 existsWithContent(fourthFilename, b3, t)
310
311
312 notExist(thirdFilename, t)
313
314
315 exists(notlogfile, t)
316
317
318 exists(notlogfiledir, t)
319 }
320
321 func TestCleanupExistingBackups(t *testing.T) {
322
323
324
325 currentTime = fakeTime
326 megabyte = 1
327
328 dir := makeTempDir("TestCleanupExistingBackups", t)
329 defer os.RemoveAll(dir)
330
331
332
333 data := []byte("data")
334 backup := backupFile(dir)
335 err := ioutil.WriteFile(backup, data, 0644)
336 isNil(err, t)
337
338 newFakeTime()
339
340 backup = backupFile(dir)
341 err = ioutil.WriteFile(backup+compressSuffix, data, 0644)
342 isNil(err, t)
343
344 newFakeTime()
345
346 backup = backupFile(dir)
347 err = ioutil.WriteFile(backup, data, 0644)
348 isNil(err, t)
349
350
351 filename := logFile(dir)
352 err = ioutil.WriteFile(filename, data, 0644)
353 isNil(err, t)
354
355 l := &Logger{
356 Filename: filename,
357 MaxSize: 10,
358 MaxBackups: 1,
359 }
360 defer l.Close()
361
362 newFakeTime()
363
364 b2 := []byte("foooooo!")
365 n, err := l.Write(b2)
366 isNil(err, t)
367 equals(len(b2), n, t)
368
369
370
371 <-time.After(time.Millisecond * 10)
372
373
374 fileCount(dir, 2, t)
375 }
376
377 func TestMaxAge(t *testing.T) {
378 currentTime = fakeTime
379 megabyte = 1
380
381 dir := makeTempDir("TestMaxAge", t)
382 defer os.RemoveAll(dir)
383
384 filename := logFile(dir)
385 l := &Logger{
386 Filename: filename,
387 MaxSize: 10,
388 MaxAge: 1,
389 }
390 defer l.Close()
391 b := []byte("boo!")
392 n, err := l.Write(b)
393 isNil(err, t)
394 equals(len(b), n, t)
395
396 existsWithContent(filename, b, t)
397 fileCount(dir, 1, t)
398
399
400 newFakeTime()
401
402 b2 := []byte("foooooo!")
403 n, err = l.Write(b2)
404 isNil(err, t)
405 equals(len(b2), n, t)
406 existsWithContent(backupFile(dir), b, t)
407
408
409
410 <-time.After(10 * time.Millisecond)
411
412
413
414 fileCount(dir, 2, t)
415
416 existsWithContent(filename, b2, t)
417
418
419 existsWithContent(backupFile(dir), b, t)
420
421
422 newFakeTime()
423
424 b3 := []byte("baaaaar!")
425 n, err = l.Write(b3)
426 isNil(err, t)
427 equals(len(b3), n, t)
428 existsWithContent(backupFile(dir), b2, t)
429
430
431
432 <-time.After(10 * time.Millisecond)
433
434
435
436 fileCount(dir, 2, t)
437
438 existsWithContent(filename, b3, t)
439
440
441 existsWithContent(backupFile(dir), b2, t)
442 }
443
444 func TestOldLogFiles(t *testing.T) {
445 currentTime = fakeTime
446 megabyte = 1
447
448 dir := makeTempDir("TestOldLogFiles", t)
449 defer os.RemoveAll(dir)
450
451 filename := logFile(dir)
452 data := []byte("data")
453 err := ioutil.WriteFile(filename, data, 07)
454 isNil(err, t)
455
456
457
458 t1, err := time.Parse(backupTimeFormat, fakeTime().UTC().Format(backupTimeFormat))
459 isNil(err, t)
460
461 backup := backupFile(dir)
462 err = ioutil.WriteFile(backup, data, 07)
463 isNil(err, t)
464
465 newFakeTime()
466
467 t2, err := time.Parse(backupTimeFormat, fakeTime().UTC().Format(backupTimeFormat))
468 isNil(err, t)
469
470 backup2 := backupFile(dir)
471 err = ioutil.WriteFile(backup2, data, 07)
472 isNil(err, t)
473
474 l := &Logger{Filename: filename}
475 files, err := l.oldLogFiles()
476 isNil(err, t)
477 equals(2, len(files), t)
478
479
480 equals(t2, files[0].timestamp, t)
481 equals(t1, files[1].timestamp, t)
482 }
483
484 func TestTimeFromName(t *testing.T) {
485 l := &Logger{Filename: "/var/log/myfoo/foo.log"}
486 prefix, ext := l.prefixAndExt()
487
488 tests := []struct {
489 filename string
490 want time.Time
491 wantErr bool
492 }{
493 {"foo-2014-05-04T14-44-33.555.log", time.Date(2014, 5, 4, 14, 44, 33, 555000000, time.UTC), false},
494 {"foo-2014-05-04T14-44-33.555", time.Time{}, true},
495 {"2014-05-04T14-44-33.555.log", time.Time{}, true},
496 {"foo.log", time.Time{}, true},
497 }
498
499 for _, test := range tests {
500 got, err := l.timeFromName(test.filename, prefix, ext)
501 equals(got, test.want, t)
502 equals(err != nil, test.wantErr, t)
503 }
504 }
505
506 func TestLocalTime(t *testing.T) {
507 currentTime = fakeTime
508 megabyte = 1
509
510 dir := makeTempDir("TestLocalTime", t)
511 defer os.RemoveAll(dir)
512
513 l := &Logger{
514 Filename: logFile(dir),
515 MaxSize: 10,
516 LocalTime: true,
517 }
518 defer l.Close()
519 b := []byte("boo!")
520 n, err := l.Write(b)
521 isNil(err, t)
522 equals(len(b), n, t)
523
524 b2 := []byte("fooooooo!")
525 n2, err := l.Write(b2)
526 isNil(err, t)
527 equals(len(b2), n2, t)
528
529 existsWithContent(logFile(dir), b2, t)
530 existsWithContent(backupFileLocal(dir), b, t)
531 }
532
533 func TestRotate(t *testing.T) {
534 currentTime = fakeTime
535 dir := makeTempDir("TestRotate", t)
536 defer os.RemoveAll(dir)
537
538 filename := logFile(dir)
539
540 l := &Logger{
541 Filename: filename,
542 MaxBackups: 1,
543 MaxSize: 100,
544 }
545 defer l.Close()
546 b := []byte("boo!")
547 n, err := l.Write(b)
548 isNil(err, t)
549 equals(len(b), n, t)
550
551 existsWithContent(filename, b, t)
552 fileCount(dir, 1, t)
553
554 newFakeTime()
555
556 err = l.Rotate()
557 isNil(err, t)
558
559
560
561 <-time.After(10 * time.Millisecond)
562
563 filename2 := backupFile(dir)
564 existsWithContent(filename2, b, t)
565 existsWithContent(filename, []byte{}, t)
566 fileCount(dir, 2, t)
567 newFakeTime()
568
569 err = l.Rotate()
570 isNil(err, t)
571
572
573
574 <-time.After(10 * time.Millisecond)
575
576 filename3 := backupFile(dir)
577 existsWithContent(filename3, []byte{}, t)
578 existsWithContent(filename, []byte{}, t)
579 fileCount(dir, 2, t)
580
581 b2 := []byte("foooooo!")
582 n, err = l.Write(b2)
583 isNil(err, t)
584 equals(len(b2), n, t)
585
586
587 existsWithContent(filename, b2, t)
588 }
589
590 func TestCompressOnRotate(t *testing.T) {
591 currentTime = fakeTime
592 megabyte = 1
593
594 dir := makeTempDir("TestCompressOnRotate", t)
595 defer os.RemoveAll(dir)
596
597 filename := logFile(dir)
598 l := &Logger{
599 Compress: true,
600 Filename: filename,
601 MaxSize: 10,
602 }
603 defer l.Close()
604 b := []byte("boo!")
605 n, err := l.Write(b)
606 isNil(err, t)
607 equals(len(b), n, t)
608
609 existsWithContent(filename, b, t)
610 fileCount(dir, 1, t)
611
612 newFakeTime()
613
614 err = l.Rotate()
615 isNil(err, t)
616
617
618
619 existsWithContent(filename, []byte{}, t)
620
621
622
623 <-time.After(300 * time.Millisecond)
624
625
626
627 bc := new(bytes.Buffer)
628 gz := gzip.NewWriter(bc)
629 _, err = gz.Write(b)
630 isNil(err, t)
631 err = gz.Close()
632 isNil(err, t)
633 existsWithContent(backupFile(dir)+compressSuffix, bc.Bytes(), t)
634 notExist(backupFile(dir), t)
635
636 fileCount(dir, 2, t)
637 }
638
639 func TestCompressOnResume(t *testing.T) {
640 currentTime = fakeTime
641 megabyte = 1
642
643 dir := makeTempDir("TestCompressOnResume", t)
644 defer os.RemoveAll(dir)
645
646 filename := logFile(dir)
647 l := &Logger{
648 Compress: true,
649 Filename: filename,
650 MaxSize: 10,
651 }
652 defer l.Close()
653
654
655 filename2 := backupFile(dir)
656 b := []byte("foo!")
657 err := ioutil.WriteFile(filename2, b, 0644)
658 isNil(err, t)
659 err = ioutil.WriteFile(filename2+compressSuffix, []byte{}, 0644)
660 isNil(err, t)
661
662 newFakeTime()
663
664 b2 := []byte("boo!")
665 n, err := l.Write(b2)
666 isNil(err, t)
667 equals(len(b2), n, t)
668 existsWithContent(filename, b2, t)
669
670
671
672 <-time.After(300 * time.Millisecond)
673
674
675
676 bc := new(bytes.Buffer)
677 gz := gzip.NewWriter(bc)
678 _, err = gz.Write(b)
679 isNil(err, t)
680 err = gz.Close()
681 isNil(err, t)
682 existsWithContent(filename2+compressSuffix, bc.Bytes(), t)
683 notExist(filename2, t)
684
685 fileCount(dir, 2, t)
686 }
687
688 func TestJson(t *testing.T) {
689 data := []byte(`
690 {
691 "filename": "foo",
692 "maxsize": 5,
693 "maxage": 10,
694 "maxbackups": 3,
695 "localtime": true,
696 "compress": true
697 }`[1:])
698
699 l := Logger{}
700 err := json.Unmarshal(data, &l)
701 isNil(err, t)
702 equals("foo", l.Filename, t)
703 equals(5, l.MaxSize, t)
704 equals(10, l.MaxAge, t)
705 equals(3, l.MaxBackups, t)
706 equals(true, l.LocalTime, t)
707 equals(true, l.Compress, t)
708 }
709
710
711
712
713 func makeTempDir(name string, t testing.TB) string {
714 dir := time.Now().Format(name + backupTimeFormat)
715 dir = filepath.Join(os.TempDir(), dir)
716 isNilUp(os.Mkdir(dir, 0700), t, 1)
717 return dir
718 }
719
720
721 func existsWithContent(path string, content []byte, t testing.TB) {
722 info, err := os.Stat(path)
723 isNilUp(err, t, 1)
724 equalsUp(int64(len(content)), info.Size(), t, 1)
725
726 b, err := ioutil.ReadFile(path)
727 isNilUp(err, t, 1)
728 equalsUp(content, b, t, 1)
729 }
730
731
732
733 func logFile(dir string) string {
734 return filepath.Join(dir, "foobar.log")
735 }
736
737 func backupFile(dir string) string {
738 return filepath.Join(dir, "foobar-"+fakeTime().UTC().Format(backupTimeFormat)+".log")
739 }
740
741 func backupFileLocal(dir string) string {
742 return filepath.Join(dir, "foobar-"+fakeTime().Format(backupTimeFormat)+".log")
743 }
744
745
746
747 func logFileLocal(dir string) string {
748 return filepath.Join(dir, fakeTime().Format(backupTimeFormat))
749 }
750
751
752 func fileCount(dir string, exp int, t testing.TB) {
753 files, err := ioutil.ReadDir(dir)
754 isNilUp(err, t, 1)
755
756 equalsUp(exp, len(files), t, 1)
757 }
758
759
760 func newFakeTime() {
761 fakeCurrentTime = fakeCurrentTime.Add(time.Hour * 24 * 2)
762 }
763
764 func notExist(path string, t testing.TB) {
765 _, err := os.Stat(path)
766 assertUp(os.IsNotExist(err), t, 1, "expected to get os.IsNotExist, but instead got %v", err)
767 }
768
769 func exists(path string, t testing.TB) {
770 _, err := os.Stat(path)
771 assertUp(err == nil, t, 1, "expected file to exist, but got error from os.Stat: %v", err)
772 }
773
View as plain text