fix: logging module test coverage
This commit is contained in:
@@ -64,7 +64,7 @@ var (
|
|||||||
ErrMissingFilePath = errors.New("file path missing in destination config for file logging")
|
ErrMissingFilePath = errors.New("file path missing in destination config for file logging")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (config *Config) validate() error {
|
func (config *Config) Validate() error {
|
||||||
if _, exists := logLevels[config.level]; !exists {
|
if _, exists := logLevels[config.level]; !exists {
|
||||||
return ErrInvalidLogLevel
|
return ErrInvalidLogLevel
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ func getLogger(config Config) (zerolog.Logger, error) {
|
|||||||
func InitLogger(c Config) error {
|
func InitLogger(c Config) error {
|
||||||
var initErr error
|
var initErr error
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
if err := c.validate(); err != nil {
|
if err := c.Validate(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,301 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,20 +3,16 @@ package log
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
// "bytes"
|
|
||||||
// "fmt"
|
|
||||||
// "net/http"
|
|
||||||
// "time"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const testLogFilePath = "./test_logs/test.log"
|
const testLogFilePath = "./test_logs/test.log"
|
||||||
@@ -49,12 +45,10 @@ func setupLogger(t *testing.T, l Level) string {
|
|||||||
},
|
},
|
||||||
contextKeys: []any{"userID", "requestID"},
|
contextKeys: []any{"userID", "requestID"},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = InitLogger(config)
|
err = InitLogger(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to initialize logger: %v", err)
|
t.Fatalf("failed to initialize logger: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return testLogFilePath
|
return testLogFilePath
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,13 +58,11 @@ func readLogFile(t *testing.T, logPath string) []string {
|
|||||||
t.Fatalf("failed to open log file: %v", err)
|
t.Fatalf("failed to open log file: %v", err)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
var lines []string
|
var lines []string
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
lines = append(lines, scanner.Text())
|
lines = append(lines, scanner.Text())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
t.Fatalf("failed to read log file: %v", err)
|
t.Fatalf("failed to read log file: %v", err)
|
||||||
}
|
}
|
||||||
@@ -92,7 +84,6 @@ func TestDebug(t *testing.T) {
|
|||||||
ctx := context.WithValue(context.Background(), userID, "12345")
|
ctx := context.WithValue(context.Background(), userID, "12345")
|
||||||
Debug(ctx, "Debug message")
|
Debug(ctx, "Debug message")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -114,7 +105,6 @@ func TestInfo(t *testing.T) {
|
|||||||
ctx := context.WithValue(context.Background(), userID, "12345")
|
ctx := context.WithValue(context.Background(), userID, "12345")
|
||||||
Info(ctx, "Info message")
|
Info(ctx, "Info message")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -137,7 +127,6 @@ func TestWarn(t *testing.T) {
|
|||||||
ctx := context.WithValue(context.Background(), userID, "12345")
|
ctx := context.WithValue(context.Background(), userID, "12345")
|
||||||
Warn(ctx, "Warning message")
|
Warn(ctx, "Warning message")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -149,7 +138,6 @@ func TestWarn(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected Warning message, but it was not found in logs")
|
t.Errorf("expected Warning message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
@@ -160,7 +148,6 @@ func TestError(t *testing.T) {
|
|||||||
ctx := context.WithValue(context.Background(), userID, "12345")
|
ctx := context.WithValue(context.Background(), userID, "12345")
|
||||||
Error(ctx, fmt.Errorf("test error"), "Error message")
|
Error(ctx, fmt.Errorf("test error"), "Error message")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -172,7 +159,6 @@ func TestError(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected Error message, but it was not found in logs")
|
t.Errorf("expected Error message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
@@ -185,7 +171,6 @@ func TestRequest(t *testing.T) {
|
|||||||
req.RemoteAddr = "127.0.0.1:8080"
|
req.RemoteAddr = "127.0.0.1:8080"
|
||||||
Request(ctx, req, []byte(`{"key":"value"}`))
|
Request(ctx, req, []byte(`{"key":"value"}`))
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -200,7 +185,6 @@ func TestRequest(t *testing.T) {
|
|||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected formatted debug message, but it was not found in logs")
|
t.Errorf("expected formatted debug message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResponse(t *testing.T) {
|
func TestResponse(t *testing.T) {
|
||||||
@@ -209,7 +193,6 @@ func TestResponse(t *testing.T) {
|
|||||||
req, _ := http.NewRequest("GET", "/api/test", nil)
|
req, _ := http.NewRequest("GET", "/api/test", nil)
|
||||||
Response(ctx, req, 200, time.Millisecond*123)
|
Response(ctx, req, 200, time.Millisecond*123)
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -217,18 +200,15 @@ func TestResponse(t *testing.T) {
|
|||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
logEntry := parseLogLine(t, line)
|
logEntry := parseLogLine(t, line)
|
||||||
if logEntry["message"] == "HTTP Response" {
|
if logEntry["message"] == "HTTP Response" {
|
||||||
|
|
||||||
if logEntry["message"] == "HTTP Response" {
|
if logEntry["message"] == "HTTP Response" {
|
||||||
value, ok := logEntry["statusCode"]
|
value, ok := logEntry["statusCode"]
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("Expected key 'statusCode' not found in log entry")
|
t.Fatalf("Expected key 'statusCode' not found in log entry")
|
||||||
}
|
}
|
||||||
|
|
||||||
statusCode, ok := value.(float64)
|
statusCode, ok := value.(float64)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("Value for 'statusCode' is not a float64, found: %T", value)
|
t.Fatalf("Value for 'statusCode' is not a float64, found: %T", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if statusCode == 200 {
|
if statusCode == 200 {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
@@ -239,7 +219,6 @@ func TestResponse(t *testing.T) {
|
|||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected message, but it was not found in logs")
|
t.Errorf("expected message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFatal(t *testing.T) {
|
func TestFatal(t *testing.T) {
|
||||||
@@ -247,7 +226,6 @@ func TestFatal(t *testing.T) {
|
|||||||
ctx := context.WithValue(context.Background(), userID, "12345")
|
ctx := context.WithValue(context.Background(), userID, "12345")
|
||||||
Fatal(ctx, fmt.Errorf("fatal error"), "Fatal message")
|
Fatal(ctx, fmt.Errorf("fatal error"), "Fatal message")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -259,7 +237,6 @@ func TestFatal(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected Fatal message, but it was not found in logs")
|
t.Errorf("expected Fatal message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
@@ -270,7 +247,6 @@ func TestPanic(t *testing.T) {
|
|||||||
ctx := context.WithValue(context.Background(), userID, "12345")
|
ctx := context.WithValue(context.Background(), userID, "12345")
|
||||||
Panic(ctx, fmt.Errorf("panic error"), "Panic message")
|
Panic(ctx, fmt.Errorf("panic error"), "Panic message")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -282,7 +258,6 @@ func TestPanic(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected Panic message, but it was not found in logs")
|
t.Errorf("expected Panic message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
@@ -293,7 +268,6 @@ func TestDebugf(t *testing.T) {
|
|||||||
ctx := context.WithValue(context.Background(), userID, "12345")
|
ctx := context.WithValue(context.Background(), userID, "12345")
|
||||||
Debugf(ctx, "Debugf message: %s", "test")
|
Debugf(ctx, "Debugf message: %s", "test")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -305,7 +279,6 @@ func TestDebugf(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected formatted debug message, but it was not found in logs")
|
t.Errorf("expected formatted debug message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
@@ -316,7 +289,6 @@ func TestInfof(t *testing.T) {
|
|||||||
ctx := context.WithValue(context.Background(), userID, "12345")
|
ctx := context.WithValue(context.Background(), userID, "12345")
|
||||||
Infof(ctx, "Infof message: %s", "test")
|
Infof(ctx, "Infof message: %s", "test")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -328,7 +300,6 @@ func TestInfof(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected Infof message, but it was not found in logs")
|
t.Errorf("expected Infof message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
@@ -339,7 +310,6 @@ func TestWarnf(t *testing.T) {
|
|||||||
ctx := context.WithValue(context.Background(), userID, "12345")
|
ctx := context.WithValue(context.Background(), userID, "12345")
|
||||||
Warnf(ctx, "Warnf message: %s", "test")
|
Warnf(ctx, "Warnf message: %s", "test")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -351,7 +321,6 @@ func TestWarnf(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected Warnf message, but it was not found in logs")
|
t.Errorf("expected Warnf message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
@@ -363,7 +332,6 @@ func TestErrorf(t *testing.T) {
|
|||||||
err := fmt.Errorf("error message")
|
err := fmt.Errorf("error message")
|
||||||
Errorf(ctx, err, "Errorf message: %s", "test")
|
Errorf(ctx, err, "Errorf message: %s", "test")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -375,7 +343,6 @@ func TestErrorf(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected Errorf message, but it was not found in logs")
|
t.Errorf("expected Errorf message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
@@ -387,7 +354,6 @@ func TestFatalf(t *testing.T) {
|
|||||||
err := fmt.Errorf("fatal error")
|
err := fmt.Errorf("fatal error")
|
||||||
Fatalf(ctx, err, "Fatalf message: %s", "test")
|
Fatalf(ctx, err, "Fatalf message: %s", "test")
|
||||||
lines := readLogFile(t, logPath)
|
lines := readLogFile(t, logPath)
|
||||||
|
|
||||||
if len(lines) == 0 {
|
if len(lines) == 0 {
|
||||||
t.Fatal("No logs were written.")
|
t.Fatal("No logs were written.")
|
||||||
}
|
}
|
||||||
@@ -399,7 +365,6 @@ func TestFatalf(t *testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("expected Fatalf message, but it was not found in logs")
|
t.Errorf("expected Fatalf message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
@@ -428,3 +393,143 @@ func TestPanicf(t *testing.T) {
|
|||||||
t.Errorf("expected Panicf message, but it was not found in logs")
|
t.Errorf("expected Panicf message, but it was not found in logs")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateConfig(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config Config
|
||||||
|
wantErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Valid config with Stdout",
|
||||||
|
config: Config{
|
||||||
|
level: InfoLevel,
|
||||||
|
destinations: []Destination{
|
||||||
|
{Type: Stdout},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Valid config with File destination and valid path",
|
||||||
|
config: Config{
|
||||||
|
level: InfoLevel,
|
||||||
|
destinations: []Destination{
|
||||||
|
{
|
||||||
|
Type: File,
|
||||||
|
Config: map[string]string{
|
||||||
|
"path": "./logs/app.log",
|
||||||
|
"maxSize": "10",
|
||||||
|
"maxBackups": "5",
|
||||||
|
"maxAge": "7",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error: Invalid log level",
|
||||||
|
config: Config{
|
||||||
|
level: "invalid",
|
||||||
|
destinations: []Destination{
|
||||||
|
{Type: Stdout},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: ErrInvalidLogLevel,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error: No destinations provided",
|
||||||
|
config: Config{
|
||||||
|
level: InfoLevel,
|
||||||
|
destinations: []Destination{},
|
||||||
|
},
|
||||||
|
wantErr: ErrLogDestinationNil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error: Invalid destination type",
|
||||||
|
config: Config{
|
||||||
|
level: InfoLevel,
|
||||||
|
destinations: []Destination{
|
||||||
|
{Type: "unknown"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: fmt.Errorf("invalid destination type 'unknown'"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error: Missing file path for file destination",
|
||||||
|
config: Config{
|
||||||
|
level: InfoLevel,
|
||||||
|
destinations: []Destination{
|
||||||
|
{
|
||||||
|
Type: File,
|
||||||
|
Config: map[string]string{
|
||||||
|
"maxSize": "10",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: ErrMissingFilePath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error: Invalid maxSize value in file destination",
|
||||||
|
config: Config{
|
||||||
|
level: InfoLevel,
|
||||||
|
destinations: []Destination{
|
||||||
|
{
|
||||||
|
Type: File,
|
||||||
|
Config: map[string]string{
|
||||||
|
"path": "./logs/app.log",
|
||||||
|
"maxSize": "invalid",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: errors.New(`invalid maxSize: strconv.Atoi: parsing "invalid": invalid syntax`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error: Invalid maxBackups value in file destination",
|
||||||
|
config: Config{
|
||||||
|
level: InfoLevel,
|
||||||
|
destinations: []Destination{
|
||||||
|
{
|
||||||
|
Type: File,
|
||||||
|
Config: map[string]string{
|
||||||
|
"path": "./logs/app.log",
|
||||||
|
"maxBackups": "invalid",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: errors.New(`invalid maxBackups: strconv.Atoi: parsing "invalid": invalid syntax`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Error: Invalid maxAge value in file destination",
|
||||||
|
config: Config{
|
||||||
|
level: InfoLevel,
|
||||||
|
destinations: []Destination{
|
||||||
|
{
|
||||||
|
Type: File,
|
||||||
|
Config: map[string]string{
|
||||||
|
"path": "./logs/app.log",
|
||||||
|
"maxAge": "invalid",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: errors.New(`invalid maxAge: strconv.Atoi: parsing "invalid": invalid syntax`),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
err := tt.config.Validate()
|
||||||
|
if (err == nil) != (tt.wantErr == nil) {
|
||||||
|
t.Errorf("validate() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
if err != nil && tt.wantErr != nil && err.Error() != tt.wantErr.Error() {
|
||||||
|
t.Errorf("validate() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user