1package clog 2 3import ( 4 "bytes" 5 "fmt" 6 "io/ioutil" 7 "log" 8 "os" 9 "strings" 10 "testing" 11) 12 13func TestLastComponent(t *testing.T) { 14 tests := map[string]string{ 15 "plain": "plain", 16 "/a/b/c": "c", 17 "\\a\\b\\c": "c", 18 "a/b/c": "c", 19 "a\\b\\c": "c", 20 } 21 22 for in, exp := range tests { 23 got := lastComponent(in) 24 if got != exp { 25 t.Errorf("Expected %q for %q, got %q", exp, in, got) 26 } 27 } 28} 29 30func TestFlags(t *testing.T) { 31 if Flags() != log.LstdFlags { 32 t.Errorf("Expected LstdFlags by default") 33 } 34 SetFlags(0x01234) 35 if Flags() != 0x01234 { 36 t.Errorf("Expected SetFlags() to work") 37 } 38 SetFlags(log.LstdFlags) // Leave clog as it was. 39} 40 41func TestParseLogFlags(t *testing.T) { 42 defer SetOutput(os.Stderr) 43 SetOutput(ioutil.Discard) 44 ParseLogFlag("parsetest1,parsetest2+,bw,notime") 45 exp := map[string]bool{"parsetest1": true, "parsetest1+": false, 46 "parsetest2": true, "parsetest2+": true, 47 "parsetest3": false, 48 "bw": false, 49 "notime": false} 50 for k, v := range exp { 51 if KeyEnabled(k) != v { 52 t.Errorf("Expected %v enabled=%v, was %v", 53 k, v, KeyEnabled(k)) 54 } 55 } 56} 57 58func TestParseLogFlagsEmpty(t *testing.T) { 59 defer SetOutput(os.Stderr) 60 SetOutput(ioutil.Discard) 61 ParseLogFlag("") 62} 63 64func TestGetCallersName(t *testing.T) { 65 cn := getCallersName(0) 66 if lastComponent(cn.filename) != "clog_test.go" { 67 t.Errorf("Expected fn=clog_test.go, got %q", 68 lastComponent(cn.filename)) 69 } 70 if lastComponent(cn.funcname) != "clog.TestGetCallersName" { 71 t.Errorf("Expected func=clog.TestGetCallersName, got %q", 72 lastComponent(cn.funcname)) 73 } 74 cn.String() // for side effect 75 if cn = getCallersName(19); cn.String() != "???" { 76 t.Errorf("Expected unknown call, got %q", cn.String()) 77 } 78} 79 80func TestKeyFlag(t *testing.T) { 81 EnableKey("x") 82 EnableKey("y") 83 DisableKey("y") 84 85 if !KeyEnabled("x") { 86 t.Errorf("x should be enabled, but isn't") 87 } 88 if KeyEnabled("y") { 89 t.Errorf("y should not be enabled, but is") 90 } 91 if KeyEnabled("z") { 92 t.Errorf("z should not be enabled, but is") 93 } 94} 95 96func TestOutput(t *testing.T) { 97 // reset the log when we're done 98 defer SetOutput(os.Stderr) 99 100 type niladic func() 101 tests := []struct { 102 f niladic 103 output string 104 exitVal int 105 panicked bool 106 }{ 107 { 108 func() { 109 Log("testing %s", "123") 110 }, 111 "testing 123", -1, false, 112 }, 113 { 114 func() { 115 EnableKey("private") 116 To("private", "testing %s", "123") 117 }, 118 fgYellow + "private: " + reset + "testing 123", -1, false, 119 }, 120 { 121 func() { 122 EnableKey("private") 123 DisableKey("private") 124 To("private", "testing %s", "123") 125 }, 126 "", -1, false, 127 }, 128 { 129 func() { 130 Printf("testing %s", "123") 131 }, 132 "testing 123", -1, false, 133 }, 134 { 135 func() { 136 Print("testing", "123") 137 }, 138 "testing123", -1, false, 139 }, 140 { 141 func() { 142 Error(fmt.Errorf("test error")) 143 }, 144 fgRed + "ERRO: " + "test error" + reset, -1, false, 145 }, 146 { 147 func() { 148 Errorf("TestOutput, err: %v", fmt.Errorf("test error")) 149 }, 150 fgRed + "ERRO: " + "TestOutput, err: test error" + reset, -1, false, 151 }, 152 { 153 func() { 154 Warnf("testing %s", "123") 155 }, 156 fgRed + "WARN: " + "testing 123" + reset, -1, false, 157 }, 158 { 159 func() { 160 Warn("testing", "123") 161 }, 162 fgRed + "WARN: " + "testing123" + reset, -1, false, 163 }, 164 { 165 func() { 166 TEMPf("testing %s", "123") 167 }, 168 fgYellow + "TEMP: " + "testing 123" + reset, -1, false, 169 }, 170 { 171 func() { 172 TEMP("testing", "123") 173 }, 174 fgYellow + "TEMP: " + "testing123" + reset, -1, false, 175 }, 176 { 177 func() { 178 Fatal("testing", "123") 179 }, 180 fgYellow + "FATA: " + "testing123" + reset, 1, false, 181 }, 182 { 183 func() { 184 Fatalf("testing12%d", 3) 185 }, 186 fgYellow + "FATA: " + "testing123" + reset, 1, false, 187 }, 188 { 189 func() { 190 Panic("testing", "123") 191 }, 192 fgYellow + "CRIT: " + "testing123" + reset, -1, true, 193 }, 194 { 195 func() { 196 Panicf("testing12%d", 3) 197 }, 198 fgYellow + "CRIT: " + "testing123" + reset, -1, true, 199 }, 200 } 201 202 exitVal := -1 203 exit = func(i int) { exitVal = i } 204 defer func() { exit = os.Exit }() 205 206 for _, test := range tests { 207 // reset our log buffer 208 buffer := &bytes.Buffer{} 209 SetOutput(buffer) 210 // disable time so we can more easily compare 211 DisableTime() 212 exitVal = -1 213 panicked := false 214 func() { 215 defer func() { panicked = recover() != nil }() 216 test.f() 217 }() 218 if panicked != test.panicked { 219 t.Errorf("Expected panic == %v, got %v", test.panicked, panicked) 220 } 221 if exitVal != test.exitVal { 222 t.Errorf("Expected exitVal == %v, but got %v", test.exitVal, exitVal) 223 } 224 if buffer.Len() > 0 { 225 usedBytes := buffer.Bytes()[:buffer.Len()-1] 226 output := string(usedBytes) 227 // strip off the caller info as we can't easily compare that 228 callerLocation := strings.LastIndex(output, dim+" -- ") 229 if callerLocation >= 0 { 230 output = output[:callerLocation] 231 } 232 if output != test.output { 233 t.Errorf("Expected '%s' got '%s'", test.output, output) 234 } 235 } else { 236 if test.output != "" { 237 t.Errorf("Expected output `%s`, got none", test.output) 238 } 239 } 240 } 241} 242 243func TestRedactions(t *testing.T) { 244 logCB := func(format string, args ...interface{}) string { 245 return fmt.Sprintf(format, args...) 246 } 247 248 str := logCB("test1: %s, key: %q, seq: %v", "error", 249 Tag(ContentCategory(100), []byte("k123")), 12312) 250 expect := "test1: error, key: \"k123\", seq: 12312" 251 if str != expect { 252 t.Errorf("Unexpected output: [%v != %v]", str, expect) 253 } 254 255 str = logCB("test2: %s, key: %q, seq: %v", "error", 256 Tag(UserData, "k123"), 12312) 257 expect = "test2: error, key: \"<ud>k123</ud>\", seq: 12312" 258 if str != expect { 259 t.Errorf("Unexpected output: [%v != %v]", str, expect) 260 } 261 262 str = logCB("test3: %s, key: %q, seq: %v", "error", 263 Tag(UserData, []byte("k123")), 12312) 264 expect = "test3: error, key: \"<ud>k123</ud>\", seq: 12312" 265 if str != expect { 266 t.Errorf("Unexpected output: [%v != %v]", str, expect) 267 } 268} 269 270func BenchmarkFlagLookupMiss(b *testing.B) { 271 for i := 0; i < b.N; i++ { 272 KeyEnabled("x") 273 } 274} 275 276func BenchmarkFlagLookupHit(b *testing.B) { 277 EnableKey("x") 278 b.ResetTimer() 279 for i := 0; i < b.N; i++ { 280 KeyEnabled("x") 281 } 282} 283 284func BenchmarkFlagSet(b *testing.B) { 285 for i := 0; i < b.N; i++ { 286 EnableKey("x") 287 } 288} 289 290func BenchmarkToDisabled(b *testing.B) { 291 defer SetOutput(os.Stderr) 292 SetOutput(ioutil.Discard) 293 DisableKey("btoe") 294 b.ResetTimer() 295 296 for i := 0; i < b.N; i++ { 297 To("btod", "thing") 298 } 299} 300 301func BenchmarkToEnabled(b *testing.B) { 302 defer SetOutput(os.Stderr) 303 SetOutput(ioutil.Discard) 304 EnableKey("btoe") 305 b.ResetTimer() 306 307 for i := 0; i < b.N; i++ { 308 To("btoe", "thing") 309 } 310} 311 312func BenchmarkToWithFmt(b *testing.B) { 313 defer SetOutput(os.Stderr) 314 SetOutput(ioutil.Discard) 315 EnableKey("btoe") 316 b.ResetTimer() 317 318 for i := 0; i < b.N; i++ { 319 To("btoe", "%s", "a string") 320 } 321} 322