You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
6.2 KiB
129 lines
6.2 KiB
|
2 months ago
|
package logpolicy
|
||
|
|
|
||
|
|
import (
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestSanitizeRedactsSecretsAndBoundsUnicode(t *testing.T) {
|
||
|
|
value, redacted := Sanitize("config auth.radius.key radius-secret configure password=hunter2\r\nAuthorization: Bearer abc.def "+strings.Repeat("가", 20), 70)
|
||
|
|
if !redacted {
|
||
|
|
t.Fatal("Sanitize() redacted = false, want true")
|
||
|
|
}
|
||
|
|
if strings.Contains(value, "radius-secret") || strings.Contains(value, "hunter2") || strings.Contains(value, "abc.def") || strings.ContainsAny(value, "\r\n") {
|
||
|
|
t.Fatalf("Sanitize() leaked unsafe text: %q", value)
|
||
|
|
}
|
||
|
|
if !strings.Contains(value, "[REDACTED]") || !strings.Contains(value, "[truncated]") {
|
||
|
|
t.Fatalf("Sanitize() = %q, want redaction and truncation markers", value)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObservedDefaultStatusCadences(t *testing.T) {
|
||
|
|
if DefaultLinkPollInterval != time.Minute {
|
||
|
|
t.Fatalf("DefaultLinkPollInterval = %s, want 1m", DefaultLinkPollInterval)
|
||
|
|
}
|
||
|
|
if DefaultKeepaliveInterval != 3*time.Minute {
|
||
|
|
t.Fatalf("DefaultKeepaliveInterval = %s, want 3m", DefaultKeepaliveInterval)
|
||
|
|
}
|
||
|
|
if DefaultSnapshotInterval != 30*time.Minute {
|
||
|
|
t.Fatalf("DefaultSnapshotInterval = %s, want 30m", DefaultSnapshotInterval)
|
||
|
|
}
|
||
|
|
|
||
|
|
tracker := NewLinkTracker(0)
|
||
|
|
start := time.Date(2026, 7, 29, 0, 0, 0, 0, time.UTC)
|
||
|
|
first, err := tracker.Observe(LinkObservation{Kind: "ethernet", Resource: "Interface-1", State: "down", Signal: "carrier", ObservedAt: start})
|
||
|
|
if err != nil || first == nil || first.EventType != "snapshot" || first.AlarmTriggered {
|
||
|
|
t.Fatalf("first observation = %+v, err=%v", first, err)
|
||
|
|
}
|
||
|
|
quiet, err := tracker.Observe(LinkObservation{Kind: "ethernet", Resource: "Interface-1", State: "down", Signal: "carrier", ObservedAt: start.Add(29 * time.Minute)})
|
||
|
|
if err != nil || quiet != nil {
|
||
|
|
t.Fatalf("quiet observation = %+v, err=%v", quiet, err)
|
||
|
|
}
|
||
|
|
periodic, err := tracker.Observe(LinkObservation{Kind: "ethernet", Resource: "Interface-1", State: "down", Signal: "carrier", ObservedAt: start.Add(30 * time.Minute)})
|
||
|
|
if err != nil || periodic == nil || periodic.EventType != "snapshot" || periodic.AlarmTriggered {
|
||
|
|
t.Fatalf("periodic observation = %+v, err=%v", periodic, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMatchCommandUsesCommandOnlyAndStableRuleIDs(t *testing.T) {
|
||
|
|
matches := MatchCommand("show LOGIN FAILED counters", []KeywordRule{
|
||
|
|
{RuleID: "z_rule", Keyword: "login failed"},
|
||
|
|
{RuleID: "a_rule", Keyword: "SHOW"},
|
||
|
|
{RuleID: "a_rule", Keyword: "counters"},
|
||
|
|
})
|
||
|
|
if strings.Join(matches, ",") != "a_rule,z_rule" {
|
||
|
|
t.Fatalf("MatchCommand() = %v", matches)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLinkTrackerSnapshotsTransitionsAndAlarms(t *testing.T) {
|
||
|
|
tracker := NewLinkTracker(5 * time.Minute)
|
||
|
|
start := time.Date(2026, 7, 28, 0, 0, 0, 0, time.UTC)
|
||
|
|
first, err := tracker.Observe(LinkObservation{Kind: "serial", Resource: "CH01", State: "down", Signal: "dcd", ObservedAt: start})
|
||
|
|
if err != nil || first == nil || first.EventType != "snapshot" || first.AlarmTriggered {
|
||
|
|
t.Fatalf("first observation = %+v, err=%v", first, err)
|
||
|
|
}
|
||
|
|
quiet, err := tracker.Observe(LinkObservation{Kind: "serial", Resource: "CH01", State: "down", Signal: "dcd", ObservedAt: start.Add(time.Minute)})
|
||
|
|
if err != nil || quiet != nil {
|
||
|
|
t.Fatalf("quiet observation = %+v, err=%v", quiet, err)
|
||
|
|
}
|
||
|
|
up, err := tracker.Observe(LinkObservation{Kind: "serial", Resource: "CH01", State: "up", Signal: "dcd", ObservedAt: start.Add(2 * time.Minute)})
|
||
|
|
if err != nil || up == nil || up.EventType != "transition" || up.AlarmTriggered {
|
||
|
|
t.Fatalf("up observation = %+v, err=%v", up, err)
|
||
|
|
}
|
||
|
|
down, err := tracker.Observe(LinkObservation{Kind: "serial", Resource: "CH01", State: "down", Signal: "dcd", ObservedAt: start.Add(3 * time.Minute)})
|
||
|
|
if err != nil || down == nil || !down.AlarmTriggered || down.PreviousState != "up" {
|
||
|
|
t.Fatalf("down observation = %+v, err=%v", down, err)
|
||
|
|
}
|
||
|
|
periodic, err := tracker.Observe(LinkObservation{Kind: "serial", Resource: "CH01", State: "down", Signal: "dcd", ObservedAt: start.Add(9 * time.Minute)})
|
||
|
|
if err != nil || periodic == nil || periodic.EventType != "snapshot" || periodic.AlarmTriggered {
|
||
|
|
t.Fatalf("periodic observation = %+v, err=%v", periodic, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLinkTrackerRejectsUnverifiablePhysicalState(t *testing.T) {
|
||
|
|
tracker := NewLinkTracker(time.Minute)
|
||
|
|
now := time.Date(2026, 7, 28, 0, 0, 0, 0, time.UTC)
|
||
|
|
for _, observation := range []LinkObservation{
|
||
|
|
{Kind: "serial", Resource: "CH99", State: "up", Signal: "dcd", ObservedAt: now},
|
||
|
|
{Kind: "serial", Resource: "CH01", State: "up", Signal: "unknown", ObservedAt: now},
|
||
|
|
{Kind: "ethernet", Resource: "Interface-1", State: "up", Signal: "dcd", ObservedAt: now},
|
||
|
|
} {
|
||
|
|
if event, err := tracker.Observe(observation); err == nil || event != nil {
|
||
|
|
t.Fatalf("Observe(%+v) = %+v, %v; want rejection", observation, event, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLinkTrackerAcceptsUnifiedSerialSignals(t *testing.T) {
|
||
|
|
tracker := NewLinkTracker(time.Minute)
|
||
|
|
now := time.Date(2026, 8, 22, 0, 0, 0, 0, time.UTC)
|
||
|
|
for _, signal := range []string{"cts", "cr"} {
|
||
|
|
event, err := tracker.Observe(LinkObservation{
|
||
|
|
Kind: "serial", Resource: "CH06", State: "up", Signal: signal, ObservedAt: now,
|
||
|
|
})
|
||
|
|
if err != nil || event == nil || event.Signal != signal {
|
||
|
|
t.Fatalf("%s observation = %+v, %v", signal, event, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLinkTrackerCanDisableSnapshotsWithoutLosingTransitions(t *testing.T) {
|
||
|
|
tracker := NewLinkTracker(time.Minute)
|
||
|
|
tracker.SetSnapshotsEnabled(false)
|
||
|
|
start := time.Date(2026, 7, 29, 0, 0, 0, 0, time.UTC)
|
||
|
|
first, err := tracker.Observe(LinkObservation{Kind: "ethernet", Resource: "Interface-1", State: "up", Signal: "carrier", ObservedAt: start})
|
||
|
|
if err != nil || first != nil {
|
||
|
|
t.Fatalf("disabled first snapshot = %+v, %v", first, err)
|
||
|
|
}
|
||
|
|
repeated, err := tracker.Observe(LinkObservation{Kind: "ethernet", Resource: "Interface-1", State: "up", Signal: "carrier", ObservedAt: start.Add(5 * time.Minute)})
|
||
|
|
if err != nil || repeated != nil {
|
||
|
|
t.Fatalf("disabled periodic snapshot = %+v, %v", repeated, err)
|
||
|
|
}
|
||
|
|
transition, err := tracker.Observe(LinkObservation{Kind: "ethernet", Resource: "Interface-1", State: "down", Signal: "carrier", ObservedAt: start.Add(6 * time.Minute)})
|
||
|
|
if err != nil || transition == nil || transition.EventType != "transition" || !transition.AlarmTriggered {
|
||
|
|
t.Fatalf("transition = %+v, %v", transition, err)
|
||
|
|
}
|
||
|
|
}
|