github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/log/log_test.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package log 6 7 // These tests are too simple. 8 9 import ( 10 "bytes" 11 "fmt" 12 "os" 13 "regexp" 14 "strings" 15 "testing" 16 "time" 17 ) 18 19 const ( 20 Rdate = `[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]` 21 Rtime = `[0-9][0-9]:[0-9][0-9]:[0-9][0-9]` 22 Rmicroseconds = `\.[0-9][0-9][0-9][0-9][0-9][0-9]` 23 Rline = `(60|62):` // must update if the calls to l.Printf / l.Print below move 24 Rlongfile = `.*/[A-Za-z0-9_\-]+\.go:` + Rline 25 Rshortfile = `[A-Za-z0-9_\-]+\.go:` + Rline 26 ) 27 28 type tester struct { 29 flag int 30 prefix string 31 pattern string // regexp that log output must match; we add ^ and expected_text$ always 32 } 33 34 var tests = []tester{ 35 // individual pieces: 36 {0, "", ""}, 37 {0, "XXX", "XXX"}, 38 {Ldate, "", Rdate + " "}, 39 {Ltime, "", Rtime + " "}, 40 {Ltime | Lmsgprefix, "XXX", Rtime + " XXX"}, 41 {Ltime | Lmicroseconds, "", Rtime + Rmicroseconds + " "}, 42 {Lmicroseconds, "", Rtime + Rmicroseconds + " "}, // microsec implies time 43 {Llongfile, "", Rlongfile + " "}, 44 {Lshortfile, "", Rshortfile + " "}, 45 {Llongfile | Lshortfile, "", Rshortfile + " "}, // shortfile overrides longfile 46 // everything at once: 47 {Ldate | Ltime | Lmicroseconds | Llongfile, "XXX", "XXX" + Rdate + " " + Rtime + Rmicroseconds + " " + Rlongfile + " "}, 48 {Ldate | Ltime | Lmicroseconds | Lshortfile, "XXX", "XXX" + Rdate + " " + Rtime + Rmicroseconds + " " + Rshortfile + " "}, 49 {Ldate | Ltime | Lmicroseconds | Llongfile | Lmsgprefix, "XXX", Rdate + " " + Rtime + Rmicroseconds + " " + Rlongfile + " XXX"}, 50 {Ldate | Ltime | Lmicroseconds | Lshortfile | Lmsgprefix, "XXX", Rdate + " " + Rtime + Rmicroseconds + " " + Rshortfile + " XXX"}, 51 } 52 53 // Test using Println("hello", 23, "world") or using Printf("hello %d world", 23) 54 func testPrint(t *testing.T, flag int, prefix string, pattern string, useFormat bool) { 55 buf := new(bytes.Buffer) 56 SetOutput(buf) 57 SetFlags(flag) 58 SetPrefix(prefix) 59 if useFormat { 60 Printf("hello %d world", 23) 61 } else { 62 Println("hello", 23, "world") 63 } 64 line := buf.String() 65 line = line[0 : len(line)-1] 66 pattern = "^" + pattern + "hello 23 world$" 67 matched, err := regexp.MatchString(pattern, line) 68 if err != nil { 69 t.Fatal("pattern did not compile:", err) 70 } 71 if !matched { 72 t.Errorf("log output should match %q is %q", pattern, line) 73 } 74 SetOutput(os.Stderr) 75 } 76 77 func TestDefault(t *testing.T) { 78 if got := Default(); got != std { 79 t.Errorf("Default [%p] should be std [%p]", got, std) 80 } 81 } 82 83 func TestAll(t *testing.T) { 84 for _, testcase := range tests { 85 testPrint(t, testcase.flag, testcase.prefix, testcase.pattern, false) 86 testPrint(t, testcase.flag, testcase.prefix, testcase.pattern, true) 87 } 88 } 89 90 func TestOutput(t *testing.T) { 91 const testString = "test" 92 var b bytes.Buffer 93 l := New(&b, "", 0) 94 l.Println(testString) 95 if expect := testString + "\n"; b.String() != expect { 96 t.Errorf("log output should match %q is %q", expect, b.String()) 97 } 98 } 99 100 func TestOutputRace(t *testing.T) { 101 var b bytes.Buffer 102 l := New(&b, "", 0) 103 for i := 0; i < 100; i++ { 104 go func() { 105 l.SetFlags(0) 106 }() 107 l.Output(0, "") 108 } 109 } 110 111 func TestFlagAndPrefixSetting(t *testing.T) { 112 var b bytes.Buffer 113 l := New(&b, "Test:", LstdFlags) 114 f := l.Flags() 115 if f != LstdFlags { 116 t.Errorf("Flags 1: expected %x got %x", LstdFlags, f) 117 } 118 l.SetFlags(f | Lmicroseconds) 119 f = l.Flags() 120 if f != LstdFlags|Lmicroseconds { 121 t.Errorf("Flags 2: expected %x got %x", LstdFlags|Lmicroseconds, f) 122 } 123 p := l.Prefix() 124 if p != "Test:" { 125 t.Errorf(`Prefix: expected "Test:" got %q`, p) 126 } 127 l.SetPrefix("Reality:") 128 p = l.Prefix() 129 if p != "Reality:" { 130 t.Errorf(`Prefix: expected "Reality:" got %q`, p) 131 } 132 // Verify a log message looks right, with our prefix and microseconds present. 133 l.Print("hello") 134 pattern := "^Reality:" + Rdate + " " + Rtime + Rmicroseconds + " hello\n" 135 matched, err := regexp.Match(pattern, b.Bytes()) 136 if err != nil { 137 t.Fatalf("pattern %q did not compile: %s", pattern, err) 138 } 139 if !matched { 140 t.Error("message did not match pattern") 141 } 142 } 143 144 func TestUTCFlag(t *testing.T) { 145 var b bytes.Buffer 146 l := New(&b, "Test:", LstdFlags) 147 l.SetFlags(Ldate | Ltime | LUTC) 148 // Verify a log message looks right in the right time zone. Quantize to the second only. 149 now := time.Now().UTC() 150 l.Print("hello") 151 want := fmt.Sprintf("Test:%d/%.2d/%.2d %.2d:%.2d:%.2d hello\n", 152 now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second()) 153 got := b.String() 154 if got == want { 155 return 156 } 157 // It's possible we crossed a second boundary between getting now and logging, 158 // so add a second and try again. This should very nearly always work. 159 now = now.Add(time.Second) 160 want = fmt.Sprintf("Test:%d/%.2d/%.2d %.2d:%.2d:%.2d hello\n", 161 now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second()) 162 if got == want { 163 return 164 } 165 t.Errorf("got %q; want %q", got, want) 166 } 167 168 func TestEmptyPrintCreatesLine(t *testing.T) { 169 var b bytes.Buffer 170 l := New(&b, "Header:", LstdFlags) 171 l.Print() 172 l.Println("non-empty") 173 output := b.String() 174 if n := strings.Count(output, "Header"); n != 2 { 175 t.Errorf("expected 2 headers, got %d", n) 176 } 177 if n := strings.Count(output, "\n"); n != 2 { 178 t.Errorf("expected 2 lines, got %d", n) 179 } 180 } 181 182 func BenchmarkItoa(b *testing.B) { 183 dst := make([]byte, 0, 64) 184 for i := 0; i < b.N; i++ { 185 dst = dst[0:0] 186 itoa(&dst, 2015, 4) // year 187 itoa(&dst, 1, 2) // month 188 itoa(&dst, 30, 2) // day 189 itoa(&dst, 12, 2) // hour 190 itoa(&dst, 56, 2) // minute 191 itoa(&dst, 0, 2) // second 192 itoa(&dst, 987654, 6) // microsecond 193 } 194 } 195 196 func BenchmarkPrintln(b *testing.B) { 197 const testString = "test" 198 var buf bytes.Buffer 199 l := New(&buf, "", LstdFlags) 200 for i := 0; i < b.N; i++ { 201 buf.Reset() 202 l.Println(testString) 203 } 204 } 205 206 func BenchmarkPrintlnNoFlags(b *testing.B) { 207 const testString = "test" 208 var buf bytes.Buffer 209 l := New(&buf, "", 0) 210 for i := 0; i < b.N; i++ { 211 buf.Reset() 212 l.Println(testString) 213 } 214 }