grokkit/internal/logger/logger_test.go
Greg Gauthier 8b6449c947 feat(logging): implement structured logging with slog
- Refactor logger package to use Go's slog for JSON-structured logs
- Add configurable log levels (debug, info, warn, error) via config and flags
- Integrate logging across commands, git operations, and API client with metrics like timing and sizes
- Update README with logging documentation and usage examples
- Add global --debug and --verbose flags
- Enhance tests for logger initialization, levels, and structured output
2026-03-01 12:35:21 +00:00

124 lines
2.9 KiB
Go

package logger
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestInit(t *testing.T) {
// Create temp directory
tmpDir := t.TempDir()
oldHome := os.Getenv("HOME")
os.Setenv("HOME", tmpDir)
defer os.Setenv("HOME", oldHome)
tests := []struct {
name string
logLevel string
}{
{"default level", "info"},
{"debug level", "debug"},
{"warn level", "warn"},
{"error level", "error"},
{"invalid level defaults to info", "invalid"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := Init(tt.logLevel)
if err != nil {
t.Errorf("Init(%q) unexpected error: %v", tt.logLevel, err)
}
// Check log file was created
logFile := filepath.Join(tmpDir, ".config", "grokkit", "grokkit.log")
if _, err := os.Stat(logFile); os.IsNotExist(err) {
t.Errorf("Log file not created at %s", logFile)
}
})
}
}
func TestLogging(t *testing.T) {
tmpDir := t.TempDir()
oldHome := os.Getenv("HOME")
os.Setenv("HOME", tmpDir)
defer os.Setenv("HOME", oldHome)
if err := Init("debug"); err != nil {
t.Fatalf("Init() failed: %v", err)
}
// Test all log levels with structured fields
Debug("test debug message", "key", "value")
Info("test info message", "count", 42)
Warn("test warn message", "enabled", true)
Error("test error message", "error", "something went wrong")
// Verify log file has content
logFile := filepath.Join(tmpDir, ".config", "grokkit", "grokkit.log")
content, err := os.ReadFile(logFile)
if err != nil {
t.Errorf("Failed to read log file: %v", err)
}
if len(content) == 0 {
t.Errorf("Log file is empty")
}
// Check for JSON structure (slog uses JSON handler)
contentStr := string(content)
if !strings.Contains(contentStr, `"level"`) {
t.Errorf("Log content doesn't contain JSON level field")
}
if !strings.Contains(contentStr, `"msg"`) {
t.Errorf("Log content doesn't contain JSON msg field")
}
}
func TestSetLevel(t *testing.T) {
tmpDir := t.TempDir()
oldHome := os.Getenv("HOME")
os.Setenv("HOME", tmpDir)
defer os.Setenv("HOME", oldHome)
if err := Init("info"); err != nil {
t.Fatalf("Init() failed: %v", err)
}
// Change level to debug
SetLevel("debug")
// Log at debug level
Debug("debug after level change", "test", true)
// Verify log file has the debug message
logFile := filepath.Join(tmpDir, ".config", "grokkit", "grokkit.log")
content, err := os.ReadFile(logFile)
if err != nil {
t.Errorf("Failed to read log file: %v", err)
}
if !strings.Contains(string(content), "debug after level change") {
t.Errorf("Debug message not found after level change")
}
}
func TestWith(t *testing.T) {
tmpDir := t.TempDir()
oldHome := os.Getenv("HOME")
os.Setenv("HOME", tmpDir)
defer os.Setenv("HOME", oldHome)
if err := Init("info"); err != nil {
t.Fatalf("Init() failed: %v", err)
}
// Create logger with context
contextLogger := With("request_id", "123", "user", "testuser")
if contextLogger == nil {
t.Errorf("With() returned nil logger")
}
}