package helper import ( "bytes" "io" "log" "os" "strings" "testing" ) func captureLogOutput(f func()) string { var buf bytes.Buffer log.SetOutput(&buf) defer log.SetOutput(os.Stderr) f() return buf.String() } func TestLogInfoDevelopment(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") output := captureLogOutput(func() { LogInfo("Test info message") }) if !strings.Contains(output, "INFO:") { t.Error("Expected INFO prefix in log output") } if !strings.Contains(output, "Test info message") { t.Error("Expected message to be logged") } } func TestLogInfoDebug(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "debug") output := captureLogOutput(func() { LogInfo("Debug info message") }) if !strings.Contains(output, "INFO:") { t.Error("Expected INFO prefix in log output") } if !strings.Contains(output, "Debug info message") { t.Error("Expected message to be logged") } } func TestLogInfoProduction(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "production") output := captureLogOutput(func() { LogInfo("Production info message") }) if !strings.Contains(output, "INFO:") { t.Error("Expected INFO prefix in log output") } if !strings.Contains(output, "Production info message") { t.Error("Expected message to be logged") } } func TestLogInfoNoEnv(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Unsetenv("GO_ENV") // LogInfo calls log.Fatal if GO_ENV not set, which exits the process // We can't easily test this without subprocess, so we'll skip this specific case // or test that it panics/exits t.Skip("Cannot test log.Fatal without subprocess") } func TestLogWarnDevelopment(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") output := captureLogOutput(func() { LogWarn("Test warning") }) if !strings.Contains(output, WarningLabel) { t.Error("Expected WARNING prefix in log output") } if !strings.Contains(output, "Test warning") { t.Error("Expected warning message to be logged") } } func TestLogWarnDebug(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "debug") output := captureLogOutput(func() { LogWarn("Debug warning") }) if !strings.Contains(output, WarningLabel) { t.Error("Expected WARNING prefix in log output") } } func TestLogErrorDevelopment(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") testErr := &testError{"test error"} output := captureLogOutput(func() { LogError(testErr, "Error occurred") }) if !strings.Contains(output, "ERROR:") { t.Error("Expected ERROR prefix in log output") } if !strings.Contains(output, "Error occurred") { t.Error("Expected error message to be logged") } if !strings.Contains(output, "test error") { t.Error("Expected error details to be logged") } } func TestLogErrorNilError(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") output := captureLogOutput(func() { LogError(nil, "Error message only") }) if !strings.Contains(output, "ERROR:") { t.Error("Expected ERROR prefix") } if !strings.Contains(output, "Error message only") { t.Error("Expected message to be logged") } } func TestLogErrorDebug(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "debug") testErr := &testError{"debug error"} output := captureLogOutput(func() { LogError(testErr, "Debug error occurred") }) if !strings.Contains(output, "ERROR:") { t.Error("Expected ERROR prefix") } if !strings.Contains(output, "Debug error occurred") { t.Error("Expected error message") } } type testError struct { msg string } func (e *testError) Error() string { return e.msg } func TestLogInfoEmptyMessage(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") output := captureLogOutput(func() { LogInfo("") }) if !strings.Contains(output, "INFO:") { t.Error("Expected INFO prefix even with empty message") } } func TestLogWarnEmptyMessage(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") output := captureLogOutput(func() { LogWarn("") }) if !strings.Contains(output, WarningLabel) { t.Error("Expected WARNING prefix even with empty message") } } func TestLogErrorEmptyMessage(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") output := captureLogOutput(func() { LogError(nil, "") }) if !strings.Contains(output, "ERROR:") { t.Error("Expected ERROR prefix even with empty message") } } func TestLogInfoLongMessage(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") longMessage := strings.Repeat("A", 1000) output := captureLogOutput(func() { LogInfo(longMessage) }) if !strings.Contains(output, longMessage) { t.Error("Expected long message to be logged completely") } } func TestLogWarnSpecialCharacters(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") specialMsg := "Warning: \n\t special characters & symbols!" output := captureLogOutput(func() { LogWarn(specialMsg) }) if !strings.Contains(output, WarningLabel) { t.Error("Expected WARNING prefix") } } func TestLogErrorMultilineMessage(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") multilineMsg := "Line 1\nLine 2\nLine 3" output := captureLogOutput(func() { LogError(nil, multilineMsg) }) if !strings.Contains(output, "ERROR:") { t.Error("Expected ERROR prefix") } } func TestLogInfoCanary(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "canary") output := captureLogOutput(func() { LogInfo("Canary info message") }) if !strings.Contains(output, "INFO:") { t.Error("Expected INFO prefix in canary environment") } if !strings.Contains(output, "Canary info message") { t.Error("Expected message to be logged in canary environment") } } func TestLogEnvironmentCheck(t *testing.T) { validEnvironments := []string{"development", "debug", "production", "canary"} originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) for _, env := range validEnvironments { t.Run(env, func(t *testing.T) { os.Setenv("GO_ENV", env) output := captureLogOutput(func() { LogInfo("Test message") }) if output == "" { t.Errorf("Expected log output for environment: %s", env) } }) } } func TestLogErrorWithAndWithoutError(t *testing.T) { originalEnv := os.Getenv("GO_ENV") defer os.Setenv("GO_ENV", originalEnv) os.Setenv("GO_ENV", "development") // With error output1 := captureLogOutput(func() { LogError(&testError{"actual error"}, "Context message") }) if !strings.Contains(output1, "actual error") { t.Error("Expected error details when error provided") } // Without error output2 := captureLogOutput(func() { LogError(nil, "Context message") }) if strings.Contains(output2, "") { t.Log("nil error is logged as ") } } func BenchmarkLogInfo(b *testing.B) { os.Setenv("GO_ENV", "development") defer os.Unsetenv("GO_ENV") // Discard log output for benchmarking log.SetOutput(io.Discard) defer log.SetOutput(os.Stderr) b.ResetTimer() for i := 0; i < b.N; i++ { LogInfo("Benchmark message") } } func BenchmarkLogWarn(b *testing.B) { os.Setenv("GO_ENV", "development") defer os.Unsetenv("GO_ENV") log.SetOutput(io.Discard) defer log.SetOutput(os.Stderr) b.ResetTimer() for i := 0; i < b.N; i++ { LogWarn("Benchmark warning") } } func BenchmarkLogError(b *testing.B) { os.Setenv("GO_ENV", "development") defer os.Unsetenv("GO_ENV") log.SetOutput(io.Discard) defer log.SetOutput(os.Stderr) testErr := &testError{"benchmark error"} b.ResetTimer() for i := 0; i < b.N; i++ { LogError(testErr, "Benchmark error message") } }