Files
2026-06-22 16:06:57 +02:00

108 lines
2.2 KiB
Go

package auditlog
import (
"path/filepath"
"testing"
"time"
)
func newTestStore(t *testing.T) *Store {
t.Helper()
s, err := New(filepath.Join(t.TempDir(), "audit.db"))
if err != nil {
t.Fatal(err)
}
return s
}
// eventually polls List until at least want entries are persisted (writes are
// async) or it times out.
func eventually(t *testing.T, s *Store, want int) []Entry {
t.Helper()
deadline := time.Now().Add(time.Second)
for {
got, err := s.List(100)
if err != nil {
t.Fatal(err)
}
if len(got) >= want {
return got
}
if time.Now().After(deadline) {
t.Fatalf("timed out waiting for %d entries, have %d", want, len(got))
}
time.Sleep(5 * time.Millisecond)
}
}
func TestRecordAndList(t *testing.T) {
s := newTestStore(t)
s.Record("alice", "POST", "/api/users", "users", 200)
s.Record("bob", "DELETE", "/api/users/x", "users", 403)
got := eventually(t, s, 2)
// Newest first.
if got[0].Username != "bob" || got[0].Status != 403 {
t.Errorf("newest entry wrong: %+v", got[0])
}
if got[1].Username != "alice" || got[1].Method != "POST" {
t.Errorf("oldest entry wrong: %+v", got[1])
}
if got[0].Time == "" {
t.Error("time not populated")
}
}
func TestListLimit(t *testing.T) {
s := newTestStore(t)
for range 5 {
s.Record("u", "POST", "/api/x", "system", 200)
}
eventually(t, s, 5)
got, err := s.List(3)
if err != nil {
t.Fatal(err)
}
if len(got) != 3 {
t.Errorf("limit not honored: got %d, want 3", len(got))
}
}
func TestCloseDrains(t *testing.T) {
path := filepath.Join(t.TempDir(), "audit.db")
s, err := New(path)
if err != nil {
t.Fatal(err)
}
for range 50 {
s.Record("u", "POST", "/api/x", "system", 200)
}
// Close must flush everything still buffered before returning.
if err := s.Close(); err != nil {
t.Fatal(err)
}
// Reopen and confirm all 50 made it to disk.
s2, err := New(path)
if err != nil {
t.Fatal(err)
}
got, err := s2.List(100)
if err != nil {
t.Fatal(err)
}
if len(got) != 50 {
t.Errorf("Close did not drain: got %d entries, want 50", len(got))
}
}
func TestListEmpty(t *testing.T) {
got, err := newTestStore(t).List(10)
if err != nil {
t.Fatal(err)
}
if len(got) != 0 {
t.Errorf("fresh store should be empty, got %d", len(got))
}
}