github.com/sereiner/library@v0.0.0-20200518095232-1fa3e640cc5f/log/logger_test.go (about) 1 package log 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "strings" 8 "sync" 9 "testing" 10 "time" 11 12 "github.com/sereiner/library/file" 13 ) 14 15 type TestType struct { 16 name string 17 age int 18 } 19 20 // TestDebug 测试记录Debug日志 21 func TestDebug(t *testing.T) { 22 // 清空数据统计 23 manager.factory = &testLoggerAppenderFactory{} 24 ResultClear() 25 26 log := New("key1") 27 28 // 写入字符串 29 log.Debug("content1") 30 31 // 写入nil 32 log.Debug(nil) 33 34 // 写入int 35 log.Debug(1) 36 37 // 写入sliens 38 log.Debug(make([]string, 2)) 39 40 // 写入数组 41 log.Debug([3]int{1, 2, 3}) 42 43 // 写入结构体 44 log.Debug(TestType{name: "test", age: 11}) 45 46 // 日志组件为空 47 log = New("") 48 log.Debug("hello world") 49 50 time.Sleep(time.Second * 2) 51 // 统计数据是否和预期的一致 52 if GetResult("debug") != 6 { 53 t.Errorf("test fail except : %d, actual : %d", 6, GetResult("debug")) 54 } 55 56 Close() 57 manager, _ = newLoggerManager() 58 } 59 60 // TestDebug 测试记录Debugf日志【format】 61 func TestDebugf(t *testing.T) { 62 // 清空数据统计 63 manager.factory = &testLoggerAppenderFactory{} 64 ResultClear() 65 66 log := New("key1") 67 // 参数正确 68 log.Debugf("%s %s", "hello", "world") 69 70 // format 为空字符串 71 log.Debugf("", "hello") 72 73 // format 不包含格式化参数 74 log.Debugf("hello", "world") 75 76 // format 格式化参数过多 77 log.Debugf("%s %s %s", "hello", "world") 78 79 // 内容为nil 80 log.Debugf("hello", nil) 81 82 // 内容和格式化参数类型不匹配 83 log.Debugf("%s %d", "hello", "world") 84 85 // 内容为结构体 86 log.Debugf("%+v", TestType{name: "test", age: 11}) 87 88 // 日志组件为空 89 log = New("") 90 log.Debugf("%s %s", "hello", "world") 91 92 time.Sleep(time.Second * 2) 93 // 统计数据是否和预期的一致 94 if GetResult("debug") != 7 { 95 t.Errorf("test fail except : %d, actual : %d", 7, GetResult("debug")) 96 } 97 98 Close() 99 manager, _ = newLoggerManager() 100 } 101 102 // TestInfo 测试记录Info日志 103 func TestInfo(t *testing.T) { 104 // 清空数据统计 105 manager.factory = &testLoggerAppenderFactory{} 106 ResultClear() 107 108 log := New("key1") 109 110 // 写入字符串 111 log.Info("content1") 112 // // 每秒钟写入文件一次 113 // time.Sleep(time.Second * 2) 114 115 // 写入nil 116 log.Info(nil) 117 118 // 写入int 119 log.Info(1) 120 121 // 写入sliens 122 log.Info(make([]string, 2)) 123 124 // 写入数组 125 log.Info([3]int{1, 2, 3}) 126 127 // 写入结构体 128 log.Info(TestType{name: "test", age: 11}) 129 130 // 日志组件为空 131 log = New("") 132 log.Info("hello world") 133 134 time.Sleep(time.Second * 2) 135 // 统计数据是否和预期的一致 136 if GetResult("info") != 6 { 137 t.Errorf("test fail except : %d, actual : %d", 6, GetResult("info")) 138 } 139 140 Close() 141 manager, _ = newLoggerManager() 142 } 143 144 // TestInfof 测试记录Info日志【format】 145 func TestInfof(t *testing.T) { 146 // 清空数据统计 147 manager.factory = &testLoggerAppenderFactory{} 148 ResultClear() 149 150 log := New("key1") 151 // 参数正确 152 log.Infof("%s %s", "hello", "world") 153 154 // format 为空字符串 155 log.Infof("", "hello") 156 157 // format 不包含格式化参数 158 log.Infof("hello", "world") 159 160 // format 格式化参数过多 161 log.Infof("%s %s %s", "hello", "world") 162 163 // 内容为nil 164 log.Infof("hello", nil) 165 166 // 内容和格式化参数类型不匹配 167 log.Infof("%s %d", "hello", "world") 168 169 // 内容为结构体 170 log.Infof("%+v", TestType{name: "test", age: 11}) 171 172 // 日志组件为空 173 log = New("") 174 log.Infof("%s %s", "hello", "world") 175 176 time.Sleep(time.Second * 2) 177 // 统计数据是否和预期的一致 178 if GetResult("info") != 7 { 179 t.Errorf("test fail except : %d, actual : %d", 7, GetResult("info")) 180 } 181 182 Close() 183 manager, _ = newLoggerManager() 184 } 185 186 // TestError 测试记录Error日志 187 func TestError(t *testing.T) { 188 // 清空数据统计 189 manager.factory = &testLoggerAppenderFactory{} 190 ResultClear() 191 192 log := New("key1") 193 194 // 写入字符串 195 log.Error("content1") 196 197 // 写入nil 198 log.Error(nil) 199 200 // 写入int 201 log.Error(1) 202 203 // 写入sliens 204 log.Error(make([]string, 2)) 205 206 // 写入数组 207 log.Error([3]int{1, 2, 3}) 208 209 // 写入结构体 210 log.Error(TestType{name: "test", age: 11}) 211 212 // 日志组件为空 213 log = New("") 214 log.Error("hello world") 215 216 time.Sleep(time.Second * 2) 217 // 统计数据是否和预期的一致 218 if GetResult("error") != 6 { 219 t.Errorf("test fail except : %d, actual : %d", 6, GetResult("error")) 220 } 221 222 Close() 223 manager, _ = newLoggerManager() 224 } 225 226 // TestErrorf 测试记录Error日志【format】 227 func TestErrorf(t *testing.T) { 228 // 清空数据统计 229 manager.factory = &testLoggerAppenderFactory{} 230 ResultClear() 231 232 log := New("key1") 233 // 参数正确 234 log.Errorf("%s %s", "hello", "world") 235 236 // format 为空字符串 237 log.Errorf("", "hello") 238 239 // format 不包含格式化参数 240 log.Errorf("hello", "world") 241 242 // format 格式化参数过多 243 log.Errorf("%s %s %s", "hello", "world") 244 245 // 内容为nil 246 log.Errorf("hello", nil) 247 248 // 内容为结构体 249 log.Errorf("%+v", TestType{name: "test", age: 11}) 250 251 // 内容和格式化参数类型不匹配 252 log.Errorf("%s %d", "hello", "world") 253 254 // 日志组件为空 255 log = New("") 256 log.Errorf("%s %s", "hello", "world") 257 258 time.Sleep(time.Second * 2) 259 // 统计数据是否和预期的一致 260 if GetResult("error") != 7 { 261 t.Errorf("test fail except : %d, actual : %d", 7, GetResult("error")) 262 } 263 264 Close() 265 manager, _ = newLoggerManager() 266 } 267 268 // TestWriteToBuffer 测试写入日志的时候,是否漏掉了日志记录,通过测试的testLoggerAppenderFactory来不进行真的日志记录 269 func TestWriteToBuffer(t *testing.T) { 270 manager.factory = &testLoggerAppenderFactory{} 271 // 清空结果 272 ResultClear() 273 totalCount := 10000 * 1 274 ch := make(chan int, totalCount) 275 lk := sync.WaitGroup{} 276 277 doWrite := func(ch chan int, lk *sync.WaitGroup) { 278 log := New("abc") 279 START: 280 for { 281 select { 282 case v, ok := <-ch: 283 if ok { 284 log.Debug(v) 285 log.Info(v) 286 log.Error(v) 287 } else { 288 break START 289 } 290 } 291 } 292 lk.Done() 293 } 294 295 for i := 0; i < 100; i++ { 296 lk.Add(1) 297 go doWrite(ch, &lk) 298 } 299 300 for i := 0; i < totalCount; i++ { 301 ch <- i 302 } 303 304 close(ch) 305 lk.Wait() 306 307 time.Sleep(time.Second * 2) 308 309 Close() 310 311 for i := 0; i < len(ACCOUNT); i++ { 312 fmt.Println(ACCOUNT[i].name, " ", ACCOUNT[i].count) 313 if strings.EqualFold(ACCOUNT[i].name, "debug") { 314 if ACCOUNT[i].count != totalCount { 315 t.Errorf("test fail, actual : %d", ACCOUNT[i].count) 316 } 317 } 318 if strings.EqualFold(ACCOUNT[i].name, "info") { 319 if ACCOUNT[i].count != totalCount { 320 t.Errorf("test fail, actual : %d", ACCOUNT[i].count) 321 } 322 } 323 // 测试不执行fatal日志记录 324 if strings.EqualFold(ACCOUNT[i].name, "fatal") { 325 if ACCOUNT[i].count != 0 { 326 t.Errorf("test fail, actual : %d", ACCOUNT[i].count) 327 } 328 } 329 if strings.EqualFold(ACCOUNT[i].name, "error") { 330 if ACCOUNT[i].count != totalCount { 331 t.Errorf("test fail, actual : %d", ACCOUNT[i].count) 332 } 333 } 334 } 335 336 manager, _ = newLoggerManager() 337 } 338 339 // TestLoggerToFile 测试输出到文件,并检验日志数量 340 func TestLoggerToFile(t *testing.T) { 341 // 把数据写入文件 342 totalAccount := 10000 * 1 343 lk := sync.WaitGroup{} 344 ch := make(chan int, totalAccount) 345 name := "ABC" 346 347 log := New(name) 348 349 doWriteToFile := func(ch chan int, lk *sync.WaitGroup) { 350 START: 351 for { 352 select { 353 case l, ok := <-ch: 354 if ok { 355 log.Debug(l) 356 log.Info(l) 357 log.Error(l) 358 } else { 359 break START 360 } 361 lk.Done() 362 } 363 } 364 } 365 366 for i := 0; i < 100; i++ { 367 go doWriteToFile(ch, &lk) 368 } 369 370 for i := 0; i < totalAccount; i++ { 371 lk.Add(1) 372 ch <- i 373 } 374 close(ch) 375 lk.Wait() 376 377 time.Sleep(time.Second * 1) 378 379 Close() 380 381 // 开始读取文件 382 path := fmt.Sprintf("../logs/%s/%d%d%d.log", name, time.Now().Year(), time.Now().Month(), time.Now().Day()) 383 filePath, _ := file.GetAbs(path) 384 data, err := ioutil.ReadFile(filePath) 385 if err != nil { 386 t.Errorf("test fail : %v", err) 387 } 388 count := len(strings.Split(string(data), "\n")) 389 if count != totalAccount*3+6 { 390 t.Errorf("test fail, actual:%d, except:%d", count, totalAccount*3+6) 391 } 392 393 // 删除日志防止下次进行测试的时候数据错误 394 os.Remove(filePath) 395 } 396 397 // TestLoggerToFileCheckOrder 测试写入到文件,然后判断输入的顺序 398 func TestLoggerToFileCheckOrder(tx *testing.T) { 399 // 写入日志到文件 400 manager, _ = newLoggerManager() 401 logger := GetSession("tofile", "12345678") 402 // t, err := time.Parse("2006/01/02 15:04:05", "2016/11/28 16:38:27") 403 // if err != nil { 404 // tx.Errorf("test fail, %+v", err) 405 // } 406 407 // 构建要测试的数据和预期数据 408 data := map[string]string{ 409 // LogEvent{Level: "Debug", Now: t, Name: "tofile", Session: "12345678", Content: "content1", Output: "output1"}: []string{"[d]", "content1"}, 410 // LogEvent{Level: "Debug", Now: t, Name: "tofile", Session: "12345678", Content: "content2", Output: "output2"}: []string{"[d]", "content2"}, 411 // LogEvent{Level: "Info", Now: t, Name: "tofile", Session: "12345678", Content: "content3", Output: "output3"}: []string{"[i]", "content3"}, 412 // LogEvent{Level: "Fatal", Now: t, Name: "tofile", Session: "12345678", Content: "content4", Output: "output4"}: []string{"[f]", "content4"}, 413 // LogEvent{Level: "Error", Now: t, Name: "tofile", Session: "12345678", Content: "content5", Output: "output5"}: []string{"[e]", "content5"}, 414 // LogEvent{Level: "Error", Now: t, Name: "tofile", Session: "12345678", Content: "content6", Output: "output6"}: []string{"[e]", "content6"}, 415 // LogEvent{Level: "Test", Now: t, Name: "tofile", Session: "12345678", Content: "content7", Output: "output6"}: []string{"[t]", "content7"}, 416 "content1": "content1", 417 "content2": "content2", 418 "content3": "content3", 419 "content4": "content4", 420 "content5": "content5", 421 "content6": "content6", 422 "content7": "content7", 423 } 424 425 // 获取日志文件的绝对路径 426 filePath, _ := file.GetAbs(fmt.Sprintf("../logs/tofile/%d%d%d.log", time.Now().Year(), time.Now().Month(), time.Now().Day())) 427 428 // 删除文件,多次测试前面的测试会覆盖掉结果 429 os.Remove(filePath) 430 431 excepts := []string{} 432 for event, except := range data { 433 // 写内容到buffer 434 // manager.Log(event) 435 logger.Info(event) 436 // 添加预期的结果【测试的时候map顺序不确定】 437 // excepts = append(excepts, fmt.Sprintf(`[2016/11/28 16:38:27]%s[12345678] %s`, "12345678", except)) 438 excepts = append(excepts, fmt.Sprintf(`][i][12345678] %s`, except)) 439 } 440 tx.Log(excepts) 441 time.Sleep(time.Second * 11) 442 443 // 读取文件中的类容 444 445 // 当前读取文件的行数 446 lineNow := 0 447 448 // 记录匹配的行数 449 actual := []int{} 450 451 // 循环预期结果 452 for _, except := range excepts { 453 fileData, err := ioutil.ReadFile(filePath) 454 if err != nil { 455 tx.Errorf("test fail : %v", err) 456 } 457 for line, lineData := range strings.Split(string(fileData), "\n") { 458 // 记录开始位置 459 if strings.Contains(lineData, "begin") && lineNow == 0 { 460 lineNow = line 461 } 462 463 // 有开始位置,开始匹配 464 if line > lineNow { 465 if strings.Contains(lineData, except) { 466 lineNow = line 467 actual = append(actual, line) 468 } 469 } 470 } 471 } 472 473 if len(actual) != len(excepts) { 474 tx.Errorf("test fail except: %d, actual: %d", len(excepts), len(actual)) 475 } 476 477 tx.Log(actual) 478 479 // 判断预期结果是否是连续的 480 for i := 0; i < len(actual); i++ { 481 if i != 0 { 482 if actual[i-1]+1 != actual[i] { 483 tx.Errorf("test fail, %+v", actual) 484 return 485 } 486 } 487 } 488 } 489 490 // Account 日志记录的对象 491 type Account struct { 492 name string 493 count int 494 } 495 496 // mutex 保证日志记录是原子操作 497 var mutex sync.Mutex 498 499 // ACCOUNT 记录日志的结果 500 var ACCOUNT []*Account 501 502 // SetResult 存放测试结果 503 func SetResult(name string, n int) { 504 for i := 0; i < len(ACCOUNT); i++ { 505 if strings.EqualFold(ACCOUNT[i].name, name) { 506 mutex.Lock() 507 ACCOUNT[i].count = ACCOUNT[i].count + n 508 mutex.Unlock() 509 return 510 } 511 } 512 513 mutex.Lock() 514 account := &Account{name: name, count: n} 515 ACCOUNT = append(ACCOUNT, account) 516 mutex.Unlock() 517 } 518 519 // GetResult 获取测试结果 520 func GetResult(name string) int { 521 for i := 0; i < len(ACCOUNT); i++ { 522 if strings.EqualFold(ACCOUNT[i].name, name) { 523 return ACCOUNT[i].count 524 } 525 } 526 return 0 527 } 528 529 // ResultClear 清空测试结果 530 func ResultClear() { 531 ACCOUNT = []*Account{} 532 }