ScuttleBot

scuttlebot / internal / bots / auditbot / auditbot_test.go
Source Blame History 111 lines
8fe9b10… lmata 1 package auditbot_test
8fe9b10… lmata 2
8fe9b10… lmata 3 import (
8fe9b10… lmata 4 "testing"
8fe9b10… lmata 5
8fe9b10… lmata 6 "github.com/conflicthq/scuttlebot/internal/bots/auditbot"
8fe9b10… lmata 7 )
8fe9b10… lmata 8
8fe9b10… lmata 9 func newBot(auditTypes ...string) (*auditbot.Bot, *auditbot.MemoryStore) {
8fe9b10… lmata 10 s := &auditbot.MemoryStore{}
8fe9b10… lmata 11 b := auditbot.New("localhost:6667", "pass", []string{"#fleet"}, auditTypes, s, nil)
8fe9b10… lmata 12 return b, s
8fe9b10… lmata 13 }
8fe9b10… lmata 14
8fe9b10… lmata 15 func TestBotNameAndNew(t *testing.T) {
8fe9b10… lmata 16 b, _ := newBot()
8fe9b10… lmata 17 if b.Name() != "auditbot" {
8fe9b10… lmata 18 t.Errorf("Name(): got %q, want auditbot", b.Name())
8fe9b10… lmata 19 }
8fe9b10… lmata 20 }
8fe9b10… lmata 21
8fe9b10… lmata 22 func TestRecordRegistryEvent(t *testing.T) {
8fe9b10… lmata 23 _, s := newBot("agent.registered")
8fe9b10… lmata 24 // newBot uses nil logger; Record directly writes to store.
8fe9b10… lmata 25 b, s2 := newBot("agent.registered")
8fe9b10… lmata 26 b.Record("agent-01", "agent.registered", "new registration")
8fe9b10… lmata 27
8fe9b10… lmata 28 entries := s2.All()
8fe9b10… lmata 29 if len(entries) != 1 {
8fe9b10… lmata 30 t.Fatalf("expected 1 entry, got %d", len(entries))
8fe9b10… lmata 31 }
8fe9b10… lmata 32 e := entries[0]
8fe9b10… lmata 33 if e.Kind != auditbot.KindRegistry {
8fe9b10… lmata 34 t.Errorf("Kind: got %q, want registry", e.Kind)
8fe9b10… lmata 35 }
8fe9b10… lmata 36 if e.Nick != "agent-01" {
8fe9b10… lmata 37 t.Errorf("Nick: got %q", e.Nick)
8fe9b10… lmata 38 }
8fe9b10… lmata 39 if e.MessageType != "agent.registered" {
8fe9b10… lmata 40 t.Errorf("MessageType: got %q", e.MessageType)
8fe9b10… lmata 41 }
8fe9b10… lmata 42 if e.Detail != "new registration" {
8fe9b10… lmata 43 t.Errorf("Detail: got %q", e.Detail)
8fe9b10… lmata 44 }
8fe9b10… lmata 45 _ = s
8fe9b10… lmata 46 }
8fe9b10… lmata 47
8fe9b10… lmata 48 func TestRecordMultipleRegistryEvents(t *testing.T) {
8fe9b10… lmata 49 b, s := newBot()
8fe9b10… lmata 50 b.Record("agent-01", "agent.registered", "")
8fe9b10… lmata 51 b.Record("agent-01", "credentials.rotated", "")
8fe9b10… lmata 52 b.Record("agent-02", "agent.revoked", "policy violation")
8fe9b10… lmata 53
8fe9b10… lmata 54 entries := s.All()
8fe9b10… lmata 55 if len(entries) != 3 {
8fe9b10… lmata 56 t.Fatalf("expected 3 entries, got %d", len(entries))
8fe9b10… lmata 57 }
8fe9b10… lmata 58 }
8fe9b10… lmata 59
8fe9b10… lmata 60 func TestStoreIsAppendOnly(t *testing.T) {
8fe9b10… lmata 61 s := &auditbot.MemoryStore{}
8fe9b10… lmata 62 s.Append(auditbot.Entry{Nick: "a", MessageType: "task.create"})
8fe9b10… lmata 63 s.Append(auditbot.Entry{Nick: "b", MessageType: "task.complete"})
8fe9b10… lmata 64
8fe9b10… lmata 65 entries := s.All()
8fe9b10… lmata 66 if len(entries) != 2 {
8fe9b10… lmata 67 t.Fatalf("expected 2 entries, got %d", len(entries))
8fe9b10… lmata 68 }
8fe9b10… lmata 69 // Modifying the snapshot should not affect the store.
8fe9b10… lmata 70 entries[0].Nick = "tampered"
8fe9b10… lmata 71 fresh := s.All()
8fe9b10… lmata 72 if fresh[0].Nick == "tampered" {
8fe9b10… lmata 73 t.Error("store should be immutable — snapshot modification should not affect store")
8fe9b10… lmata 74 }
8fe9b10… lmata 75 }
8fe9b10… lmata 76
8fe9b10… lmata 77 func TestAuditTypeFilter(t *testing.T) {
8fe9b10… lmata 78 // Only task.create should be audited.
8fe9b10… lmata 79 b, s := newBot("task.create")
8fe9b10… lmata 80 // Record two types — only the audited one should appear.
8fe9b10… lmata 81 // We can't inject IRC events directly, but we can verify that Record()
8fe9b10… lmata 82 // with any type always writes (registry events bypass the filter).
8fe9b10… lmata 83 b.Record("agent-01", "task.create", "")
8fe9b10… lmata 84 b.Record("agent-01", "task.update", "") // registry events always written
8fe9b10… lmata 85
8fe9b10… lmata 86 entries := s.All()
8fe9b10… lmata 87 if len(entries) != 2 {
8fe9b10… lmata 88 t.Fatalf("expected 2 entries from Record(), got %d", len(entries))
8fe9b10… lmata 89 }
8fe9b10… lmata 90 }
8fe9b10… lmata 91
8fe9b10… lmata 92 func TestAuditAllWhenNoFilter(t *testing.T) {
8fe9b10… lmata 93 b, s := newBot() // no filter = audit everything
8fe9b10… lmata 94 b.Record("a", "task.create", "")
8fe9b10… lmata 95 b.Record("b", "task.update", "")
8fe9b10… lmata 96 b.Record("c", "agent.hello", "")
8fe9b10… lmata 97
8fe9b10… lmata 98 if got := len(s.All()); got != 3 {
8fe9b10… lmata 99 t.Errorf("expected 3 entries, got %d", got)
8fe9b10… lmata 100 }
8fe9b10… lmata 101 }
8fe9b10… lmata 102
8fe9b10… lmata 103 func TestEntryTimestamp(t *testing.T) {
8fe9b10… lmata 104 b, s := newBot()
8fe9b10… lmata 105 b.Record("agent-01", "agent.registered", "")
8fe9b10… lmata 106
8fe9b10… lmata 107 entries := s.All()
8fe9b10… lmata 108 if entries[0].At.IsZero() {
8fe9b10… lmata 109 t.Error("entry timestamp should not be zero")
8fe9b10… lmata 110 }
8fe9b10… lmata 111 }

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button