Source file
src/log/log_test.go
Documentation: log
1
2
3
4
5 package log
6
7
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):`
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
32 }
33
34 var tests = []tester{
35
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 + " "},
43 {Llongfile, "", Rlongfile + " "},
44 {Lshortfile, "", Rshortfile + " "},
45 {Llongfile | Lshortfile, "", Rshortfile + " "},
46
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
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
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
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
158
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)
187 itoa(&dst, 1, 2)
188 itoa(&dst, 30, 2)
189 itoa(&dst, 12, 2)
190 itoa(&dst, 56, 2)
191 itoa(&dst, 0, 2)
192 itoa(&dst, 987654, 6)
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 }
215
View as plain text