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.
 
 
 
 
 
 

128 lines
6.2 KiB

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)
}
}