377 lines
8.1 KiB
Go
377 lines
8.1 KiB
Go
package hlog
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
func TestNewLogger(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cfg *Config
|
|
writer io.Writer
|
|
wantErr bool
|
|
errMsg string
|
|
}{
|
|
{
|
|
name: "console output only",
|
|
cfg: &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "console",
|
|
LogDir: "",
|
|
LogFileName: "",
|
|
LogAppend: true,
|
|
},
|
|
writer: bytes.NewBuffer(nil),
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "nil config",
|
|
cfg: nil,
|
|
writer: bytes.NewBuffer(nil),
|
|
wantErr: true,
|
|
errMsg: "No config provided",
|
|
},
|
|
{
|
|
name: "nil writer for both output",
|
|
cfg: &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "both",
|
|
},
|
|
writer: nil,
|
|
wantErr: true,
|
|
errMsg: "No Writer provided",
|
|
},
|
|
{
|
|
name: "file output without LogDir",
|
|
cfg: &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "file",
|
|
LogDir: "",
|
|
LogFileName: "test.log",
|
|
LogAppend: true,
|
|
},
|
|
writer: nil,
|
|
wantErr: true,
|
|
errMsg: "LOG_DIR must be set",
|
|
},
|
|
{
|
|
name: "file output without LogFileName",
|
|
cfg: &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "file",
|
|
LogDir: "/tmp",
|
|
LogFileName: "",
|
|
LogAppend: true,
|
|
},
|
|
writer: nil,
|
|
wantErr: true,
|
|
errMsg: "LOG_FILE_NAME must be set",
|
|
},
|
|
{
|
|
name: "both output without LogDir",
|
|
cfg: &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "both",
|
|
LogDir: "",
|
|
LogFileName: "test.log",
|
|
LogAppend: true,
|
|
},
|
|
writer: bytes.NewBuffer(nil),
|
|
wantErr: true,
|
|
errMsg: "LOG_DIR must be set",
|
|
},
|
|
{
|
|
name: "both output without LogFileName",
|
|
cfg: &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "both",
|
|
LogDir: "/tmp",
|
|
LogFileName: "",
|
|
LogAppend: true,
|
|
},
|
|
writer: bytes.NewBuffer(nil),
|
|
wantErr: true,
|
|
errMsg: "LOG_FILE_NAME must be set",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
logger, err := NewLogger(tt.cfg, tt.writer)
|
|
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Errorf("NewLogger() expected error but got nil")
|
|
return
|
|
}
|
|
if tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) {
|
|
t.Errorf("NewLogger() error = %v, should contain %v", err, tt.errMsg)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("NewLogger() unexpected error = %v", err)
|
|
return
|
|
}
|
|
|
|
if logger == nil {
|
|
t.Errorf("NewLogger() returned nil logger")
|
|
return
|
|
}
|
|
|
|
if logger.Logger == nil {
|
|
t.Errorf("NewLogger() returned logger with nil zerolog.Logger")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewLogger_FileOutput(t *testing.T) {
|
|
// Create temporary directory for test logs
|
|
tempDir := t.TempDir()
|
|
|
|
tests := []struct {
|
|
name string
|
|
cfg *Config
|
|
writer io.Writer
|
|
wantErr bool
|
|
checkFile bool
|
|
logMessage string
|
|
}{
|
|
{
|
|
name: "file output with append",
|
|
cfg: &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "file",
|
|
LogDir: tempDir,
|
|
LogFileName: "append_test.log",
|
|
LogAppend: true,
|
|
},
|
|
writer: nil,
|
|
wantErr: false,
|
|
checkFile: true,
|
|
logMessage: "test append message",
|
|
},
|
|
{
|
|
name: "file output with overwrite",
|
|
cfg: &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "file",
|
|
LogDir: tempDir,
|
|
LogFileName: "overwrite_test.log",
|
|
LogAppend: false,
|
|
},
|
|
writer: nil,
|
|
wantErr: false,
|
|
checkFile: true,
|
|
logMessage: "test overwrite message",
|
|
},
|
|
{
|
|
name: "both output modes",
|
|
cfg: &Config{
|
|
LogLevel: zerolog.DebugLevel,
|
|
LogOutput: "both",
|
|
LogDir: tempDir,
|
|
LogFileName: "both_test.log",
|
|
LogAppend: true,
|
|
},
|
|
writer: bytes.NewBuffer(nil),
|
|
wantErr: false,
|
|
checkFile: true,
|
|
logMessage: "test both message",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
logger, err := NewLogger(tt.cfg, tt.writer)
|
|
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Errorf("NewLogger() expected error but got nil")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("NewLogger() unexpected error = %v", err)
|
|
return
|
|
}
|
|
|
|
if logger == nil {
|
|
t.Errorf("NewLogger() returned nil logger")
|
|
return
|
|
}
|
|
|
|
// Log a test message
|
|
logger.Info().Msg(tt.logMessage)
|
|
|
|
// Close the log file to flush
|
|
err = logger.CloseLogFile()
|
|
if err != nil {
|
|
t.Errorf("CloseLogFile() error = %v", err)
|
|
}
|
|
|
|
// Check if file exists and contains message
|
|
if tt.checkFile {
|
|
logPath := filepath.Join(tt.cfg.LogDir, tt.cfg.LogFileName)
|
|
content, err := os.ReadFile(logPath)
|
|
if err != nil {
|
|
t.Errorf("Failed to read log file: %v", err)
|
|
return
|
|
}
|
|
|
|
if !strings.Contains(string(content), tt.logMessage) {
|
|
t.Errorf("Log file doesn't contain expected message. Got: %s", string(content))
|
|
}
|
|
}
|
|
|
|
// Check console output for "both" mode
|
|
if tt.cfg.LogOutput == "both" && tt.writer != nil {
|
|
if buf, ok := tt.writer.(*bytes.Buffer); ok {
|
|
consoleOutput := buf.String()
|
|
if !strings.Contains(consoleOutput, tt.logMessage) {
|
|
t.Errorf("Console output doesn't contain expected message. Got: %s", consoleOutput)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewLogger_AppendVsOverwrite(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
logFileName := "append_vs_overwrite.log"
|
|
|
|
// First logger - write initial content
|
|
cfg1 := &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "file",
|
|
LogDir: tempDir,
|
|
LogFileName: logFileName,
|
|
LogAppend: true,
|
|
}
|
|
|
|
logger1, err := NewLogger(cfg1, nil)
|
|
if err != nil {
|
|
t.Fatalf("NewLogger() error = %v", err)
|
|
}
|
|
|
|
logger1.Info().Msg("first message")
|
|
logger1.CloseLogFile()
|
|
|
|
// Second logger - append mode
|
|
cfg2 := &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "file",
|
|
LogDir: tempDir,
|
|
LogFileName: logFileName,
|
|
LogAppend: true,
|
|
}
|
|
|
|
logger2, err := NewLogger(cfg2, nil)
|
|
if err != nil {
|
|
t.Fatalf("NewLogger() error = %v", err)
|
|
}
|
|
|
|
logger2.Info().Msg("second message")
|
|
logger2.CloseLogFile()
|
|
|
|
// Check both messages exist
|
|
logPath := filepath.Join(tempDir, logFileName)
|
|
content, err := os.ReadFile(logPath)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read log file: %v", err)
|
|
}
|
|
|
|
contentStr := string(content)
|
|
if !strings.Contains(contentStr, "first message") {
|
|
t.Errorf("Log file missing 'first message' after append")
|
|
}
|
|
if !strings.Contains(contentStr, "second message") {
|
|
t.Errorf("Log file missing 'second message' after append")
|
|
}
|
|
|
|
// Third logger - overwrite mode
|
|
cfg3 := &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "file",
|
|
LogDir: tempDir,
|
|
LogFileName: logFileName,
|
|
LogAppend: false,
|
|
}
|
|
|
|
logger3, err := NewLogger(cfg3, nil)
|
|
if err != nil {
|
|
t.Fatalf("NewLogger() error = %v", err)
|
|
}
|
|
|
|
logger3.Info().Msg("third message")
|
|
logger3.CloseLogFile()
|
|
|
|
// Check only third message exists
|
|
content, err = os.ReadFile(logPath)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read log file: %v", err)
|
|
}
|
|
|
|
contentStr = string(content)
|
|
if strings.Contains(contentStr, "first message") {
|
|
t.Errorf("Log file still contains 'first message' after overwrite")
|
|
}
|
|
if strings.Contains(contentStr, "second message") {
|
|
t.Errorf("Log file still contains 'second message' after overwrite")
|
|
}
|
|
if !strings.Contains(contentStr, "third message") {
|
|
t.Errorf("Log file missing 'third message' after overwrite")
|
|
}
|
|
}
|
|
|
|
func TestLogger_CloseLogFile(t *testing.T) {
|
|
t.Run("close with file", func(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
cfg := &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "file",
|
|
LogDir: tempDir,
|
|
LogFileName: "close_test.log",
|
|
LogAppend: true,
|
|
}
|
|
|
|
logger, err := NewLogger(cfg, nil)
|
|
if err != nil {
|
|
t.Fatalf("NewLogger() error = %v", err)
|
|
}
|
|
|
|
err = logger.CloseLogFile()
|
|
if err != nil {
|
|
t.Errorf("CloseLogFile() error = %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("close without file", func(t *testing.T) {
|
|
cfg := &Config{
|
|
LogLevel: zerolog.InfoLevel,
|
|
LogOutput: "console",
|
|
}
|
|
|
|
logger, err := NewLogger(cfg, bytes.NewBuffer(nil))
|
|
if err != nil {
|
|
t.Fatalf("NewLogger() error = %v", err)
|
|
}
|
|
|
|
err = logger.CloseLogFile()
|
|
if err != nil {
|
|
t.Errorf("CloseLogFile() should not error when no file is open, got: %v", err)
|
|
}
|
|
})
|
|
}
|