fix: correction race conditions et amélioration robustesse
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled
- Correction race condition dans tlsparse avec mutex par ConnectionFlow - Fix fuite mémoire buffer HelloBuffer - Ajout rotation de fichiers logs (100MB, 3 backups) - Implémentation queue asynchrone avec reconnexion exponentielle (socket UNIX) - Validation BPF (caractères, longueur, parenthèses) - Augmentation snapLen pcap de 1600 à 65535 bytes - Permissions fichiers sécurisées (0600) - Ajout 46 tests unitaires (capture, output, logging) - Passage go test -race sans erreur Tests: go test -race ./... ✓ Build: go build ./... ✓ Lint: go vet ./... ✓ Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@ -2,9 +2,12 @@ package logging
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"ja4sentinel/api"
|
||||
)
|
||||
|
||||
func TestIsLogLevelEnabled(t *testing.T) {
|
||||
@ -22,6 +25,7 @@ func TestIsLogLevelEnabled(t *testing.T) {
|
||||
{name: "warn logger accepts error", loggerLevel: "warn", messageLevel: "error", want: true},
|
||||
{name: "error logger accepts only error", loggerLevel: "error", messageLevel: "error", want: true},
|
||||
{name: "error logger rejects warn", loggerLevel: "error", messageLevel: "warn", want: false},
|
||||
{name: "invalid level rejects all", loggerLevel: "invalid", messageLevel: "info", want: false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@ -57,3 +61,178 @@ func TestLog_UppercaseDebug_NotEmittedWhenLoggerLevelInfo(t *testing.T) {
|
||||
t.Fatalf("expected no output for uppercase DEBUG at info level, got: %s", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestInfo_EmitedWhenLoggerLevelInfo(t *testing.T) {
|
||||
logger := NewServiceLogger("info")
|
||||
var buf bytes.Buffer
|
||||
logger.out = log.New(&buf, "", 0)
|
||||
|
||||
logger.Info("service", "info message", map[string]string{"key": "value"})
|
||||
|
||||
if buf.Len() == 0 {
|
||||
t.Fatal("expected output for info at info level")
|
||||
}
|
||||
|
||||
// Verify JSON format
|
||||
var got map[string]interface{}
|
||||
if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
|
||||
t.Fatalf("output is not valid JSON: %v", err)
|
||||
}
|
||||
|
||||
if got["level"] != "INFO" {
|
||||
t.Errorf("level = %v, want INFO", got["level"])
|
||||
}
|
||||
if got["component"] != "service" {
|
||||
t.Errorf("component = %v, want service", got["component"])
|
||||
}
|
||||
if got["message"] != "info message" {
|
||||
t.Errorf("message = %v, want info message", got["message"])
|
||||
}
|
||||
if got["key"] != "value" {
|
||||
t.Errorf("key = %v, want value", got["key"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestWarn_EmitedWhenLoggerLevelWarn(t *testing.T) {
|
||||
logger := NewServiceLogger("warn")
|
||||
var buf bytes.Buffer
|
||||
logger.out = log.New(&buf, "", 0)
|
||||
|
||||
logger.Warn("service", "warn message", nil)
|
||||
|
||||
if buf.Len() == 0 {
|
||||
t.Fatal("expected output for warn at warn level")
|
||||
}
|
||||
}
|
||||
|
||||
func TestError_AlwaysEmitted(t *testing.T) {
|
||||
levels := []string{"debug", "info", "warn", "error"}
|
||||
for _, level := range levels {
|
||||
t.Run(level, func(t *testing.T) {
|
||||
logger := NewServiceLogger(level)
|
||||
var buf bytes.Buffer
|
||||
logger.out = log.New(&buf, "", 0)
|
||||
|
||||
logger.Error("service", "error message", map[string]string{"error": "test"})
|
||||
|
||||
if buf.Len() == 0 {
|
||||
t.Fatalf("expected output for error at %s level", level)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLog_EmptyDetails(t *testing.T) {
|
||||
logger := NewServiceLogger("debug")
|
||||
var buf bytes.Buffer
|
||||
logger.out = log.New(&buf, "", 0)
|
||||
|
||||
logger.Info("service", "test message", nil)
|
||||
|
||||
if buf.Len() == 0 {
|
||||
t.Fatal("expected output")
|
||||
}
|
||||
|
||||
var got map[string]interface{}
|
||||
if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
|
||||
t.Fatalf("output is not valid JSON: %v", err)
|
||||
}
|
||||
|
||||
// Details should not be present when nil/empty
|
||||
if _, ok := got["details"]; ok {
|
||||
t.Error("details should not be present when nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLog_WithDetails(t *testing.T) {
|
||||
logger := NewServiceLogger("debug")
|
||||
var buf bytes.Buffer
|
||||
logger.out = log.New(&buf, "", 0)
|
||||
|
||||
details := map[string]string{
|
||||
"error": "test error",
|
||||
"trace_id": "abc123",
|
||||
}
|
||||
logger.Info("service", "test message", details)
|
||||
|
||||
var got map[string]interface{}
|
||||
if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
|
||||
t.Fatalf("output is not valid JSON: %v", err)
|
||||
}
|
||||
|
||||
if got["error"] != "test error" {
|
||||
t.Errorf("error = %v, want test error", got["error"])
|
||||
}
|
||||
if got["trace_id"] != "abc123" {
|
||||
t.Errorf("trace_id = %v, want abc123", got["trace_id"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestLog_TimestampPresent(t *testing.T) {
|
||||
logger := NewServiceLogger("debug")
|
||||
var buf bytes.Buffer
|
||||
logger.out = log.New(&buf, "", 0)
|
||||
|
||||
logger.Info("service", "test", nil)
|
||||
|
||||
var got map[string]interface{}
|
||||
if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
|
||||
t.Fatalf("output is not valid JSON: %v", err)
|
||||
}
|
||||
|
||||
if _, ok := got["timestamp"]; !ok {
|
||||
t.Error("timestamp should be present")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoggerFactory(t *testing.T) {
|
||||
factory := &LoggerFactory{}
|
||||
|
||||
// Test NewLogger with different levels
|
||||
levels := []string{"debug", "info", "warn", "error"}
|
||||
for _, level := range levels {
|
||||
t.Run(level, func(t *testing.T) {
|
||||
logger := factory.NewLogger(level)
|
||||
if logger == nil {
|
||||
t.Fatalf("NewLogger(%q) returned nil", level)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Test NewDefaultLogger
|
||||
logger := factory.NewDefaultLogger()
|
||||
if logger == nil {
|
||||
t.Fatal("NewDefaultLogger() returned nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceLogger_ImplementsApiLogger(t *testing.T) {
|
||||
logger := NewServiceLogger("debug")
|
||||
|
||||
// Verify it implements the interface
|
||||
var _ api.Logger = logger
|
||||
}
|
||||
|
||||
func TestServiceLogger_ConcurrentLogging(t *testing.T) {
|
||||
logger := NewServiceLogger("debug")
|
||||
var buf bytes.Buffer
|
||||
logger.out = log.New(&buf, "", 0)
|
||||
|
||||
done := make(chan bool)
|
||||
for i := 0; i < 10; i++ {
|
||||
go func(id int) {
|
||||
logger.Info("service", "concurrent message", map[string]string{"id": string(rune(id))})
|
||||
done <- true
|
||||
}(i)
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
<-done
|
||||
}
|
||||
|
||||
// Should have 10 lines
|
||||
lines := strings.Split(strings.TrimSpace(buf.String()), "\n")
|
||||
if len(lines) != 10 {
|
||||
t.Errorf("expected 10 lines, got %d", len(lines))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user