Files
onix/pkg/log/log_tes1.go
2025-03-23 17:06:44 +05:30

302 lines
8.6 KiB
Go

package log
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"strings"
"testing"
"time"
"github.com/rs/zerolog"
)
func TestLogFunctions(t *testing.T) {
testConfig := Config{
level: DebugLevel,
destinations: []Destination{
{Type: Stdout},
},
contextKeys: []any{"userID", "requestID"},
}
err := InitLogger(testConfig)
if err != nil {
t.Fatalf("Failed to initialize logger: %v", err)
}
tests := []struct {
name string
logFunc func(ctx context.Context)
expectedOutput string
}{
{
name: "Debug log with context",
logFunc: func(ctx context.Context) {
type ctxKey any
var requestID ctxKey = "requestID"
ctx = context.WithValue(ctx, requestID, "12345")
Debug(ctx, "debug message")
},
expectedOutput: `{"level":"debug","requestID":"12345","message":"debug message"}`,
},
{
name: "Debugf with context",
logFunc: func(ctx context.Context) {
type ctxKey any
var requestID ctxKey = "requestID"
ctx = context.WithValue(ctx, requestID, "12345")
Debugf(ctx, "formatted %s", "debug message")
},
expectedOutput: `{"level":"debug","requestID":"12345","message":"formatted debug message"}`,
},
{
name: "Info log with message",
logFunc: func(ctx context.Context) {
type ctxKey any
var requestID ctxKey = "requestID"
ctx = context.WithValue(ctx, requestID, "12345")
Info(ctx, "info message")
},
expectedOutput: `{"level":"info","requestID":"12345","message":"info message"}`,
},
{
name: "Info log with formatted message",
logFunc: func(ctx context.Context) {
Infof(ctx, "formatted %s", "info message")
},
expectedOutput: `{"level":"info","message":"formatted info message"}`,
},
{
name: "Warn log with context",
logFunc: func(ctx context.Context) {
type ctxKey any
var requestID ctxKey = "requestID"
ctx = context.WithValue(ctx, requestID, "12345")
Warn(ctx, "warning message")
},
expectedOutput: `{"level":"warn","requestID":"12345","message":"warning message"}`,
},
{
name: "Warnf with context",
logFunc: func(ctx context.Context) {
type ctxKey any
var requestID ctxKey = "requestID"
ctx = context.WithValue(ctx, requestID, "12345")
Warnf(ctx, "formatted %s", "warning message")
},
expectedOutput: `{"level":"warn","requestID":"12345","message":"formatted warning message"}`,
},
{
name: "Error log with error and context",
logFunc: func(ctx context.Context) {
type ctxKey any
var userID ctxKey = "userID"
ctx = context.WithValue(ctx, userID, "67890")
Error(ctx, errors.New("something went wrong"), "error message")
},
expectedOutput: `{"level":"error","userID":"67890","error":"something went wrong","message":"error message"}`,
},
{
name: "Errorf with error and context",
logFunc: func(ctx context.Context) {
type ctxKey any
var userID ctxKey = "userID"
ctx = context.WithValue(ctx, userID, "67890")
Errorf(ctx, errors.New("something went wrong"), "formatted %s", "error message")
},
expectedOutput: `{"level":"error","userID":"67890","error":"something went wrong","message":"formatted error message"}`,
},
{
name: "Fatal log with error and context",
logFunc: func(ctx context.Context) {
type ctxKey any
var requestID ctxKey = "requestID"
ctx = context.WithValue(ctx, requestID, "12345")
Fatal(ctx, errors.New("fatal error"), "fatal message")
},
expectedOutput: `{"level":"fatal","requestID":"12345","error":"fatal error","message":"fatal message"}`,
},
{
name: "Fatalf with error and context",
logFunc: func(ctx context.Context) {
type ctxKey any
var requestID ctxKey = "requestID"
ctx = context.WithValue(ctx, requestID, "12345")
Fatalf(ctx, errors.New("fatal error"), "formatted %s", "fatal message")
},
expectedOutput: `{"level":"fatal","requestID":"12345","error":"fatal error","message":"formatted fatal message"}`,
},
{
name: "Panic log with error and context",
logFunc: func(ctx context.Context) {
type ctxKey any
var userID ctxKey = "userID"
ctx = context.WithValue(ctx, userID, "67890")
Panic(ctx, errors.New("panic error"), "panic message")
},
expectedOutput: `{"level":"panic","userID":"67890","error":"panic error","message":"panic message"}`,
},
{
name: "Panicf with error and context",
logFunc: func(ctx context.Context) {
type ctxKey any
var userID ctxKey = "userID"
ctx = context.WithValue(ctx, userID, "67890")
Panicf(ctx, errors.New("panic error"), "formatted %s", "panic message")
},
expectedOutput: `{"level":"panic","userID":"67890","error":"panic error","message":"formatted panic message"}`,
},
{
name: "Request log",
logFunc: func(ctx context.Context) {
req, _ := http.NewRequest("GET", "http://example.com", nil)
req.RemoteAddr = "127.0.0.1:8080"
Request(ctx, req, []byte("request body"))
},
expectedOutput: `{"level":"info","method":"GET","url":"http://example.com","body":"request body","remoteAddr":"127.0.0.1:8080","message":"HTTP Request"}`,
},
{
name: "Response log",
logFunc: func(ctx context.Context) {
req, _ := http.NewRequest("GET", "http://example.com", nil)
Response(ctx, req, 200, 100*time.Millisecond)
},
expectedOutput: `{"level":"info","method":"GET","url":"http://example.com","statusCode":200,"responseTime":100,"message":"HTTP Response"}`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var buf bytes.Buffer
logger = zerolog.New(&buf).With().Timestamp().Logger()
tt.logFunc(context.Background())
output := buf.String()
t.Logf("Log output: %s", output)
lines := strings.Split(strings.TrimSpace(output), "\n")
if len(lines) == 0 {
t.Fatal("No log output found")
}
lastLine := lines[len(lines)-1]
var logOutput map[string]interface{}
if err := json.Unmarshal([]byte(lastLine), &logOutput); err != nil {
t.Fatalf("Failed to unmarshal log output: %v", err)
}
delete(logOutput, "time")
delete(logOutput, "caller")
var expectedOutput map[string]interface{}
if err := json.Unmarshal([]byte(tt.expectedOutput), &expectedOutput); err != nil {
t.Fatalf("Failed to unmarshal expected output: %v", err)
}
for key, expectedValue := range expectedOutput {
actualValue, ok := logOutput[key]
if !ok {
t.Errorf("Expected key %q not found in log output", key)
continue
}
if actualValue != expectedValue {
t.Errorf("Mismatch for key %q: expected %v, got %v", key, expectedValue, actualValue)
}
}
})
}
}
func TestDestinationValidation(t *testing.T) {
tests := []struct {
name string
config Config
expectedError error
}{
// Missing `path` for File destination
{
name: "Missing file path",
config: Config{
level: InfoLevel,
destinations: []Destination{
{
Type: File,
Config: map[string]string{
"maxSize": "500",
"maxBackups": "15",
"maxAge": "30",
},
},
},
},
expectedError: ErrMissingFilePath,
},
{
name: "Invalid maxAge",
config: Config{
level: InfoLevel,
destinations: []Destination{
{
Type: File,
Config: map[string]string{
"path": "log/app.txt",
"maxSize": "500",
"maxBackups": "15",
"maxAge": "invalid",
},
},
},
},
expectedError: errors.New("invalid maxAge"),
},
{
name: "Valid file destination",
config: Config{
level: InfoLevel,
destinations: []Destination{
{
Type: File,
Config: map[string]string{
"path": "log/app.txt",
"maxSize": "500",
"maxBackups": "15",
"maxAge": "30",
},
},
},
},
expectedError: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fmt.Print(tt.config)
err := InitLogger(tt.config)
if (err == nil && tt.expectedError != nil) || (err != nil && tt.expectedError == nil) {
t.Errorf("Expected error: %v, got: %v", tt.expectedError, err)
} else if err != nil && tt.expectedError != nil && !strings.Contains(err.Error(), tt.expectedError.Error()) {
t.Errorf("Expected error to contain: %v, got: %v", tt.expectedError, err)
}
// ✅ Send a test log to verify file write
logger.Info().Msg("This is a test log message")
// ✅ Optional: Check if the file was created
filePath := tt.config.destinations[0].Config["path"]
if _, err := os.Stat(filePath); os.IsNotExist(err) {
t.Errorf("Log file was not created at %s", filePath)
} else {
fmt.Printf("Log file created at: %s\n", filePath)
}
})
}
}