github.com/Ryan-Johnson-1315/socketlogger@v0.0.2/logger_test.go (about) 1 package socketlogger 2 3 import ( 4 "bufio" 5 "fmt" 6 "log" 7 "os" 8 "path/filepath" 9 "runtime" 10 "strconv" 11 "strings" 12 "testing" 13 "time" 14 ) 15 16 var ( 17 udpLoggerServer LoggerServer 18 udpLoggerClient LoggerClient 19 tcpLoggerServer LoggerServer 20 tcpLoggerClient LoggerClient 21 consoleOut chan string 22 inputLines []string 23 outputLines []string 24 reader, writer *os.File 25 longWait int 26 ) 27 28 const ( 29 NUM_LINES int = 5000 30 udpTimeout time.Duration = 10 * time.Millisecond 31 // Account that TCP is a much slower socket 32 tcpTimeout time.Duration = 30 * time.Millisecond 33 ) 34 35 func TestUDPLog(t *testing.T) { 36 capture() 37 failed := false 38 var now time.Time 39 for i := 0; i < NUM_LINES; i++ { 40 ticker := time.NewTicker(udpTimeout * time.Duration(longWait)) 41 input := fmt.Sprintf("This is a testing message #%d -> TestUDPLog", i) 42 inputLines[i] = formatInput(input) 43 udpLoggerClient.Log(input) 44 select { 45 case line := <-consoleOut: 46 outputLines[i] = line 47 if failed { 48 closeWriters() 49 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, udpTimeout, time.Since(now)+udpTimeout) 50 t.FailNow() 51 } 52 case <-ticker.C: 53 failed = true 54 now = time.Now() 55 } 56 } 57 closeWriters() 58 if correct, expected := checkOutput(); !correct { 59 t.Errorf("Lines did not match:%s", expected) 60 t.FailNow() 61 } 62 } 63 64 func TestUDPDbg(t *testing.T) { 65 capture() 66 failed := false 67 var now time.Time 68 for i := 0; i < NUM_LINES; i++ { 69 ticker := time.NewTicker(udpTimeout * time.Duration(longWait)) 70 input := fmt.Sprintf("This is a testing message #%d -> TestUDPDbg", i) 71 inputLines[i] = formatInput(input) 72 udpLoggerClient.Dbg(input) 73 select { 74 case line := <-consoleOut: 75 outputLines[i] = line 76 if failed { 77 closeWriters() 78 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, udpTimeout, time.Since(now)+udpTimeout) 79 t.FailNow() 80 } 81 case <-ticker.C: 82 failed = true 83 now = time.Now() 84 } 85 } 86 closeWriters() 87 if correct, expected := checkOutput(); !correct { 88 t.Errorf("Lines did not match:%s", expected) 89 t.FailNow() 90 } 91 } 92 93 func TestUDPWrn(t *testing.T) { 94 capture() 95 failed := false 96 var now time.Time 97 for i := 0; i < NUM_LINES; i++ { 98 ticker := time.NewTicker(udpTimeout * time.Duration(longWait)) 99 input := fmt.Sprintf("This is a testing message #%d -> TestUDPWrn", i) 100 inputLines[i] = formatInput(input) 101 udpLoggerClient.Wrn(input) 102 select { 103 case line := <-consoleOut: 104 outputLines[i] = line 105 if failed { 106 closeWriters() 107 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, udpTimeout, time.Since(now)+udpTimeout) 108 t.FailNow() 109 } 110 case <-ticker.C: 111 failed = true 112 now = time.Now() 113 } 114 } 115 closeWriters() 116 if correct, expected := checkOutput(); !correct { 117 t.Errorf("Lines did not match:%s", expected) 118 t.FailNow() 119 } 120 } 121 122 func TestUDPErr(t *testing.T) { 123 capture() 124 failed := false 125 var now time.Time 126 for i := 0; i < NUM_LINES; i++ { 127 ticker := time.NewTicker(udpTimeout * time.Duration(longWait)) 128 input := fmt.Sprintf("This is a testing message #%d -> TestUDPErr", i) 129 inputLines[i] = formatInput(input) 130 udpLoggerClient.Err(input) 131 select { 132 case line := <-consoleOut: 133 outputLines[i] = line 134 if failed { 135 closeWriters() 136 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, udpTimeout, time.Since(now)+udpTimeout) 137 t.FailNow() 138 } 139 case <-ticker.C: 140 failed = true 141 now = time.Now() 142 } 143 } 144 closeWriters() 145 if correct, expected := checkOutput(); !correct { 146 t.Errorf("Lines did not match:%s", expected) 147 t.FailNow() 148 } 149 } 150 151 func TestUDPSuccess(t *testing.T) { 152 capture() 153 failed := false 154 var now time.Time 155 for i := 0; i < NUM_LINES; i++ { 156 ticker := time.NewTicker(udpTimeout * time.Duration(longWait)) 157 input := fmt.Sprintf("This is a testing message #%d -> TestUDPSuccess", i) 158 inputLines[i] = formatInput(input) 159 udpLoggerClient.Success(input) 160 select { 161 case line := <-consoleOut: 162 outputLines[i] = line 163 if failed { 164 closeWriters() 165 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, udpTimeout, time.Since(now)+udpTimeout) 166 t.FailNow() 167 } 168 case <-ticker.C: 169 failed = true 170 now = time.Now() 171 } 172 } 173 closeWriters() 174 if correct, expected := checkOutput(); !correct { 175 t.Errorf("Lines did not match:%s", expected) 176 t.FailNow() 177 } 178 } 179 180 func TestTCPLog(t *testing.T) { 181 capture() 182 failed := false 183 var now time.Time 184 for i := 0; i < NUM_LINES; i++ { 185 ticker := time.NewTicker(tcpTimeout * time.Duration(longWait)) 186 input := fmt.Sprintf("This is a testing message #%d -> TestTCPLog", i) 187 inputLines[i] = formatInput(input) 188 tcpLoggerClient.Log(input) 189 select { 190 case line := <-consoleOut: 191 outputLines[i] = line 192 if failed { 193 closeWriters() 194 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, tcpTimeout, time.Since(now)+tcpTimeout) 195 t.FailNow() 196 } 197 case <-ticker.C: 198 failed = true 199 now = time.Now() 200 } 201 } 202 closeWriters() 203 if correct, expected := checkOutput(); !correct { 204 t.Errorf("Lines did not match:%s", expected) 205 t.FailNow() 206 } 207 } 208 209 func TestTCPDbg(t *testing.T) { 210 capture() 211 failed := false 212 var now time.Time 213 for i := 0; i < NUM_LINES; i++ { 214 ticker := time.NewTicker(tcpTimeout * time.Duration(longWait)) 215 input := fmt.Sprintf("This is a testing message #%d -> TestTCPDbg", i) 216 inputLines[i] = formatInput(input) 217 tcpLoggerClient.Dbg(input) 218 select { 219 case line := <-consoleOut: 220 outputLines[i] = line 221 if failed { 222 closeWriters() 223 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, tcpTimeout, time.Since(now)+tcpTimeout) 224 t.FailNow() 225 } 226 case <-ticker.C: 227 failed = true 228 now = time.Now() 229 } 230 } 231 closeWriters() 232 if correct, expected := checkOutput(); !correct { 233 t.Errorf("Lines did not match:%s", expected) 234 t.FailNow() 235 } 236 } 237 238 func TestTCPWrn(t *testing.T) { 239 capture() 240 failed := false 241 var now time.Time 242 for i := 0; i < NUM_LINES; i++ { 243 ticker := time.NewTicker(tcpTimeout * time.Duration(longWait)) 244 input := fmt.Sprintf("This is a testing message #%d -> TestTCPWrn", i) 245 inputLines[i] = formatInput(input) 246 tcpLoggerClient.Wrn(input) 247 select { 248 case line := <-consoleOut: 249 outputLines[i] = line 250 if failed { 251 closeWriters() 252 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, tcpTimeout, time.Since(now)+tcpTimeout) 253 t.FailNow() 254 } 255 case <-ticker.C: 256 failed = true 257 now = time.Now() 258 } 259 } 260 closeWriters() 261 if correct, expected := checkOutput(); !correct { 262 t.Errorf("Lines did not match:%s", expected) 263 t.FailNow() 264 } 265 } 266 267 func TestTCPErr(t *testing.T) { 268 capture() 269 failed := false 270 var now time.Time 271 for i := 0; i < NUM_LINES; i++ { 272 ticker := time.NewTicker(tcpTimeout * time.Duration(longWait)) 273 input := fmt.Sprintf("This is a testing message #%d -> TestTCPErr", i) 274 inputLines[i] = formatInput(input) 275 tcpLoggerClient.Err(input) 276 select { 277 case line := <-consoleOut: 278 outputLines[i] = line 279 if failed { 280 closeWriters() 281 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, tcpTimeout, time.Since(now)+tcpTimeout) 282 t.FailNow() 283 } 284 case <-ticker.C: 285 failed = true 286 now = time.Now() 287 } 288 } 289 closeWriters() 290 if correct, expected := checkOutput(); !correct { 291 t.Errorf("Lines did not match:%s", expected) 292 t.FailNow() 293 } 294 } 295 296 func TestTCPSuccess(t *testing.T) { 297 capture() 298 failed := false 299 var now time.Time 300 for i := 0; i < NUM_LINES; i++ { 301 ticker := time.NewTicker(tcpTimeout * time.Duration(longWait)) 302 input := fmt.Sprintf("This is a testing message #%d -> TestTCPSuccess", i) 303 inputLines[i] = formatInput(input) 304 tcpLoggerClient.Success(input) 305 select { 306 case line := <-consoleOut: 307 outputLines[i] = line 308 if failed { 309 closeWriters() 310 t.Errorf("Message %d did not log in timeout period of %v. Actual: %v", i, tcpTimeout, time.Since(now)+tcpTimeout) 311 t.FailNow() 312 } 313 case <-ticker.C: 314 failed = true 315 now = time.Now() 316 } 317 } 318 closeWriters() 319 if correct, expected := checkOutput(); !correct { 320 t.Errorf("Lines did not match:%s", expected) 321 t.FailNow() 322 } 323 } 324 325 func TestSetcpLoggerClientFile(t *testing.T) { 326 now := time.Now().Format("2006-01-02T15:04:05") + ".log" 327 dir := t.TempDir() 328 if err := logFile(NewUdpLoggerServer(), dir, now); err != "" { 329 t.Error(err) 330 } 331 332 if err := logFile(NewTcpLoggerServer(), dir, now); err != "" { 333 t.Error(err) 334 } 335 336 if err := logFile(NewTcpLoggerServer(), dir+"/not_there_yet", now); err != "" { 337 t.Error(err) 338 } 339 340 if err := logFile(NewUdpLoggerServer(), "/dev/should_fail", now); err == "" { 341 t.Error(err) 342 } 343 } 344 345 func TestMessageType(t *testing.T) { 346 if !checkMsgType(udpLoggerServer) { 347 t.Errorf("expected %T actual %T", &LogMessage{}, udpLoggerServer.getMessageType()) 348 } 349 350 if !checkMsgType(tcpLoggerServer) { 351 t.Errorf("expected %T actual %T", &LogMessage{}, tcpLoggerServer.getMessageType()) 352 } 353 } 354 355 func BenchmarkUDPLog(b *testing.B) { 356 for i := 0; i < NUM_LINES; i++ { 357 udpLoggerClient.Log("Benching with a long message %s", "***********************************************************************************") 358 } 359 } 360 361 func BenchmarkUDPDbg(b *testing.B) { 362 for i := 0; i < NUM_LINES; i++ { 363 udpLoggerClient.Dbg("Benching with a long message %s", "***********************************************************************************") 364 } 365 } 366 367 func BenchmarkUDPWrn(b *testing.B) { 368 for i := 0; i < NUM_LINES; i++ { 369 udpLoggerClient.Wrn("Benching with a long message %s", "***********************************************************************************") 370 } 371 } 372 373 func BenchmarkUDPErr(b *testing.B) { 374 for i := 0; i < NUM_LINES; i++ { 375 udpLoggerClient.Err("Benching with a long message %s", "***********************************************************************************") 376 } 377 } 378 379 func BenchmarkUDPSuccess(b *testing.B) { 380 for i := 0; i < NUM_LINES; i++ { 381 udpLoggerClient.Success("Benching with a long message %s", "***********************************************************************************") 382 } 383 } 384 385 func BenchmarkTCPLog(b *testing.B) { 386 for i := 0; i < NUM_LINES; i++ { 387 tcpLoggerClient.Log("Benching with a long message %s", "***********************************************************************************") 388 } 389 } 390 391 func BenchmarkTCPDbg(b *testing.B) { 392 for i := 0; i < NUM_LINES; i++ { 393 tcpLoggerClient.Dbg("Benching with a long message %s", "***********************************************************************************") 394 } 395 } 396 397 func BenchmarkTCPWrn(b *testing.B) { 398 for i := 0; i < NUM_LINES; i++ { 399 tcpLoggerClient.Wrn("Benching with a long message %s", "***********************************************************************************") 400 } 401 } 402 403 func BenchmarkTCPErr(b *testing.B) { 404 for i := 0; i < NUM_LINES; i++ { 405 tcpLoggerClient.Err("Benching with a long message %s", "***********************************************************************************") 406 } 407 } 408 409 func BenchmarkTCPSuccess(b *testing.B) { 410 for i := 0; i < NUM_LINES; i++ { 411 tcpLoggerClient.Success("Benching with a long message %s", "***********************************************************************************") 412 } 413 } 414 415 func TestTCPDisconnect(t *testing.T) { 416 server := NewTcpLoggerServer() 417 dir := t.TempDir() 418 server.SetLogFile(dir, "tcp_disconnect.log") 419 server.Bind(Connection{ 420 Addr: "127.0.0.1", 421 Port: 43000, 422 }) 423 424 logger := NewTcpLoggerClient() 425 logger.Connect(Connection{ 426 Addr: "127.0.0.1", 427 Port: 0, 428 }, Connection{ 429 Addr: "127.0.0.1", 430 Port: 43000, 431 }) 432 expectedLines := 250 433 for i := 0; i < expectedLines; i++ { 434 logger.Log("TCP disconnect %d", i) 435 } 436 437 logger.Disconnect() // Blocking 438 time.Sleep(500 * time.Millisecond) // Just enough to let the messages get to the server 439 server.Shutdown() // Blocking 440 441 dat, _ := os.ReadFile(filepath.Join(dir, "tcp_disconnect.log")) 442 lines := strings.Split(string(dat), "\n") 443 444 if len(lines) != expectedLines+4 { // +4 is the server and client and tcp disconnect output that gets written to the file, and the last newline after the split 445 t.Errorf("Output lines did not match expected. Expected: %d, Actual %d, %s", expectedLines+3, len(lines), filepath.Join(dir, "tcp_disconnect.log")) 446 } 447 } 448 449 func TestUDPDisconnect(t *testing.T) { 450 server := NewUdpLoggerServer() 451 dir := t.TempDir() 452 server.SetLogFile(dir, "udp_disconnect.log") 453 server.Bind(Connection{ 454 Addr: "127.0.0.1", 455 Port: 43000, 456 }) 457 458 logger := NewUdpLoggerClient() 459 logger.Connect(Connection{ 460 Addr: "127.0.0.1", 461 Port: 0, 462 }, Connection{ 463 Addr: "127.0.0.1", 464 Port: 43000, 465 }) 466 expectedLines := 250 467 for i := 0; i < expectedLines; i++ { 468 logger.Log("UDP disconnect %d", i) 469 } 470 471 logger.Disconnect() // Blocking 472 time.Sleep(500 * time.Millisecond) // Just enough to let the messages get to the server 473 server.Shutdown() // Blocking 474 475 dat, _ := os.ReadFile(filepath.Join(dir, "udp_disconnect.log")) 476 lines := strings.Split(string(dat), "\n") 477 478 if len(lines) != expectedLines+3 { // +3 is the server and client output that gets written to the file, and the last newline after the split 479 t.Errorf("Output lines did not match expected. Expected: %d, Actual %d, %s", expectedLines+3, len(lines), filepath.Join(dir, "udp_disconnect.log")) 480 } 481 } 482 483 func init() { 484 tcp := 60001 485 tcpLoggerServer = NewTcpLoggerServer() 486 tcpLoggerServer.SetTimeFlags(log.Ldate | log.Ltime | log.Lmicroseconds) 487 tcpLoggerServer.Bind(Connection{ 488 Addr: "127.0.0.1", 489 Port: tcp, 490 }) 491 492 tcpLoggerClient = NewTcpLoggerClient() 493 tcpLoggerClient.Connect(Connection{ 494 Addr: "127.0.0.1", 495 Port: 0, 496 }, Connection{ 497 Addr: "127.0.0.1", 498 Port: tcp, 499 }) 500 501 udp := 60000 502 udpLoggerServer = NewUdpLoggerServer() 503 udpLoggerServer.SetTimeFlags(log.Ldate | log.Ltime | log.Lmicroseconds) 504 udpLoggerServer.Bind(Connection{ 505 Addr: "127.0.0.1", 506 Port: udp, 507 }) 508 509 udpLoggerClient = NewUdpLoggerClient() 510 udpLoggerClient.Connect(Connection{ 511 Addr: "127.0.0.1", 512 Port: 0, 513 }, Connection{ 514 Addr: "127.0.0.1", 515 Port: udp, 516 }) 517 518 consoleOut = make(chan string, 25) 519 inputLines = make([]string, NUM_LINES) 520 outputLines = make([]string, NUM_LINES) 521 time.Sleep(100 * time.Millisecond) 522 log.Println("Multiplying wait time by", os.Getenv("LONG_WAIT")) 523 if env := os.Getenv("LONG_WAIT"); env != "" { 524 var err error 525 longWait, err = strconv.Atoi(env) 526 if err != nil { 527 log.Fatal(err) 528 } 529 } else { 530 longWait = 1 531 } 532 } 533 534 func capture() { 535 var err error 536 537 reader, writer, err = os.Pipe() 538 if err != nil { 539 panic(err) 540 } 541 542 stdout := os.Stdout 543 stderr := os.Stderr 544 545 os.Stderr = writer 546 os.Stdout = writer 547 log.SetOutput(writer) 548 549 go func() { 550 scanner := bufio.NewScanner(reader) 551 for scanner.Scan() { 552 consoleOut <- scanner.Text() 553 } 554 555 os.Stdout = stdout 556 os.Stderr = stderr 557 }() 558 time.Sleep(50 * time.Millisecond) // Reset everything 559 } 560 561 func closeWriters() { 562 writer.Close() 563 reader.Close() 564 } 565 566 func checkOutput() (bool, string) { 567 closeWriters() 568 success := true 569 expected := "" 570 for i, fullLine := range outputLines { 571 output := strings.Split(fullLine, "| ")[1] 572 if same := strings.Compare(output, inputLines[i]); same != 0 { 573 success = false 574 expected = fmt.Sprintf(` 575 Output: "%s" 576 Expected: "%s"`, strings.TrimSuffix(output, "\n"), inputLines[i]) 577 break 578 } 579 } 580 return success, expected 581 } 582 583 func formatInput(msg string) string { 584 _, file, line, _ := runtime.Caller(1) 585 paths := strings.Split(file, "/") 586 file = paths[len(paths)-1] 587 return fmt.Sprintf("%s:%d -- %s", file, line+1, msg) + string(reset) 588 } 589 590 func logFile(server LoggerServer, dir, fname string) string { 591 msg := "" 592 server.SetLogFile(dir, fname) 593 594 if !fileDirExists(dir, fname) { 595 msg = fmt.Sprintf("%s log file was not created", filepath.Join(dir, fname)) 596 } 597 return msg 598 } 599 600 func checkMsgType(server LoggerServer) bool { 601 switch server.getMessageType().(type) { 602 case *LogMessage: 603 return true 604 default: 605 return false 606 } 607 }