139 lines
4.2 KiB
Go
139 lines
4.2 KiB
Go
package logging
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestModulesMatchV1Taxonomy(t *testing.T) {
|
|
t.Parallel()
|
|
if got, want := len(Modules), 11; got != want {
|
|
t.Fatalf("Modules length = %d, want %d", got, want)
|
|
}
|
|
seen := make(map[Module]struct{}, len(Modules))
|
|
for _, module := range Modules {
|
|
if !module.Valid() {
|
|
t.Fatalf("listed module %q is invalid", module)
|
|
}
|
|
if _, duplicate := seen[module]; duplicate {
|
|
t.Fatalf("duplicate module %q", module)
|
|
}
|
|
seen[module] = struct{}{}
|
|
}
|
|
}
|
|
|
|
func TestLoggerWritesStructuredModuleAndClosesIdempotently(t *testing.T) {
|
|
t.Parallel()
|
|
path := filepath.Join(t.TempDir(), "remlink.log")
|
|
var console bytes.Buffer
|
|
config := DefaultConfig(path)
|
|
config.Console = &console
|
|
logger, err := New(config)
|
|
if err != nil {
|
|
t.Fatalf("New() error = %v", err)
|
|
}
|
|
core, err := logger.For(ModuleCore)
|
|
if err != nil {
|
|
t.Fatalf("For() error = %v", err)
|
|
}
|
|
core.Info("started", slog.String("version", "test"))
|
|
if err := logger.Close(); err != nil {
|
|
t.Fatalf("Close() error = %v", err)
|
|
}
|
|
if err := logger.Close(); err != nil {
|
|
t.Fatalf("second Close() error = %v", err)
|
|
}
|
|
|
|
contents, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("ReadFile() error = %v", err)
|
|
}
|
|
text := string(contents)
|
|
if !strings.Contains(text, `"module":"CORE"`) || !strings.Contains(text, `"msg":"started"`) {
|
|
t.Fatalf("structured log missing expected fields: %s", text)
|
|
}
|
|
if console.Len() == 0 {
|
|
t.Fatal("console writer received no log record")
|
|
}
|
|
}
|
|
|
|
func TestPacketSamplingDefaultsOffAndRateLimits(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := context.Background()
|
|
disabledConfig := DefaultConfig(filepath.Join(t.TempDir(), "disabled.log"))
|
|
disabledConfig.Console = nil
|
|
disabled, err := New(disabledConfig)
|
|
if err != nil {
|
|
t.Fatalf("New(disabled) error = %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = disabled.Close() })
|
|
logged, err := disabled.SamplePacketDebug(ctx, ModuleSubnet, "invalid-header", "packet rejected")
|
|
if err != nil || logged {
|
|
t.Fatalf("disabled SamplePacketDebug() = (%v, %v), want (false, nil)", logged, err)
|
|
}
|
|
|
|
enabledConfig := DefaultConfig(filepath.Join(t.TempDir(), "enabled.log"))
|
|
enabledConfig.Console = nil
|
|
enabledConfig.Level = slog.LevelDebug
|
|
enabledConfig.Packets.Enabled = true
|
|
enabledConfig.Packets.SampleInterval = time.Hour
|
|
enabled, err := New(enabledConfig)
|
|
if err != nil {
|
|
t.Fatalf("New(enabled) error = %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = enabled.Close() })
|
|
first, err := enabled.SamplePacketDebug(ctx, ModuleSubnet, "invalid-header", "packet rejected")
|
|
if err != nil || !first {
|
|
t.Fatalf("first SamplePacketDebug() = (%v, %v), want (true, nil)", first, err)
|
|
}
|
|
second, err := enabled.SamplePacketDebug(ctx, ModuleSubnet, "invalid-header", "packet rejected")
|
|
if err != nil || second {
|
|
t.Fatalf("second SamplePacketDebug() = (%v, %v), want (false, nil)", second, err)
|
|
}
|
|
different, err := enabled.SamplePacketDebug(ctx, ModuleSubnet, "source-mismatch", "packet rejected")
|
|
if err != nil || !different {
|
|
t.Fatalf("different-key SamplePacketDebug() = (%v, %v), want (true, nil)", different, err)
|
|
}
|
|
}
|
|
|
|
func TestSecurityWarningIsAlwaysRateLimited(t *testing.T) {
|
|
t.Parallel()
|
|
path := filepath.Join(t.TempDir(), "security.log")
|
|
config := DefaultConfig(path)
|
|
config.Console = nil
|
|
logger, err := New(config)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { _ = logger.Close() })
|
|
first, err := logger.SampleSecurityWarning(context.Background(), ModuleSubnet, "invalid-datagram", "packet rejected")
|
|
if err != nil || !first {
|
|
t.Fatalf("first warning = (%v, %v)", first, err)
|
|
}
|
|
second, err := logger.SampleSecurityWarning(context.Background(), ModuleSubnet, "invalid-datagram", "packet rejected")
|
|
if err != nil || second {
|
|
t.Fatalf("second warning = (%v, %v)", second, err)
|
|
}
|
|
}
|
|
|
|
func TestLoggerRejectsUnknownModule(t *testing.T) {
|
|
t.Parallel()
|
|
config := DefaultConfig(filepath.Join(t.TempDir(), "remlink.log"))
|
|
config.Console = nil
|
|
logger, err := New(config)
|
|
if err != nil {
|
|
t.Fatalf("New() error = %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = logger.Close() })
|
|
if _, err := logger.For(Module("PACKET")); !errors.Is(err, ErrInvalidModule) {
|
|
t.Fatalf("For() error = %v, want %v", err, ErrInvalidModule)
|
|
}
|
|
}
|