internal/logger/logger_test.go

package logger

import (
	"honeypot/internal/database"
	"honeypot/internal/types"
	"log/slog"
	"net/http"
	"os"
	"testing"
)

type mockMetricsCollector struct {
	events []types.LogEvent
}

func (m *mockMetricsCollector) RecordEvent(e types.LogEvent) {
	m.events = append(m.events, e)
}

func (m *mockMetricsCollector) GetHandler() http.Handler {
	return nil
}

func (m *mockMetricsCollector) SetDatabase(db *database.Database) {}

type mockEventSink struct {
	events []types.LogEvent
}

func (m *mockEventSink) EmitEvent(e types.LogEvent) {
	m.events = append(m.events, e)
}

func TestLogEvent(t *testing.T) {
	logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))

	metrics := &mockMetricsCollector{}
	sink := &mockEventSink{}

	RegisterMetricsCollector(metrics)
	RegisterEventSink(sink)

	e := types.LogEvent{
		Type:       "test",
		Event:      "unit_test",
		RemoteAddr: "1.2.3.4",
		Fields:     map[string]interface{}{"foo": "bar"},
	}

	LogEvent(logger, e)

	if len(metrics.events) != 1 {
		t.Errorf("expected 1 event in metrics, got %v", len(metrics.events))
	}
	if len(sink.events) != 1 {
		t.Errorf("expected 1 event in sink, got %v", len(sink.events))
	}

	if metrics.events[0].Type != "test" {
		t.Errorf("expected type 'test', got %v", metrics.events[0].Type)
	}
}

func TestSetup(t *testing.T) {
	logFile := "test.log"
	defer os.Remove(logFile)

	logger, err := Setup(logFile)
	if err != nil {
		t.Fatalf("Setup failed: %v", err)
	}
	if logger == nil {
		t.Fatal("Setup returned nil logger")
	}

	if _, err := os.Stat(logFile); os.IsNotExist(err) {
		t.Error("log file was not created")
	}
}

func TestRegisterDatabase(t *testing.T) {
	db := &database.Database{}
	RegisterDatabase(db)
	if globalDatabase.DB != db.DB {
		t.Error("database was not registered correctly")
	}
}

func TestLogError(t *testing.T) {
	logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
	LogError(logger, "test", "error_event", os.ErrNotExist, []any{"extra", "info"})
	// Primarily verifying it doesn't panic and prints to stderr
}

func TestLogInfo(t *testing.T) {
	logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
	LogInfo(logger, "test", "info message", []any{"extra", "info"})
	// Primarily verifying it doesn't panic and prints to stdout
}

type topNMock struct {
	mockMetricsCollector
	registeredType  string
	registeredField string
}

func (m *topNMock) RegisterTopNField(honeypotType, fieldName string) {
	m.registeredType = honeypotType
	m.registeredField = fieldName
}

func TestRegisterTopNField(t *testing.T) {
	mock := &topNMock{}
	RegisterMetricsCollector(mock)
	RegisterTopNField("ssh", "username")

	if mock.registeredType != "ssh" || mock.registeredField != "username" {
		t.Errorf("expected ssh/username, got %v/%v", mock.registeredType, mock.registeredField)
	}
}