ScuttleBot
| 8fe9b10… | lmata | 1 | package herald_test |
| 8fe9b10… | lmata | 2 | |
| 8fe9b10… | lmata | 3 | import ( |
| 8fe9b10… | lmata | 4 | "testing" |
| 8fe9b10… | lmata | 5 | "time" |
| 8fe9b10… | lmata | 6 | |
| 8fe9b10… | lmata | 7 | "github.com/conflicthq/scuttlebot/internal/bots/herald" |
| 8fe9b10… | lmata | 8 | ) |
| 8fe9b10… | lmata | 9 | |
| 8fe9b10… | lmata | 10 | func newBot(routes herald.RouteConfig) *herald.Bot { |
| 3420a83… | lmata | 11 | return herald.New("localhost:6667", "pass", nil, routes, 100, 100, nil) |
| 8fe9b10… | lmata | 12 | } |
| 8fe9b10… | lmata | 13 | |
| 8fe9b10… | lmata | 14 | func TestBotName(t *testing.T) { |
| 8fe9b10… | lmata | 15 | b := newBot(herald.RouteConfig{}) |
| 8fe9b10… | lmata | 16 | if b.Name() != "herald" { |
| 8fe9b10… | lmata | 17 | t.Errorf("Name(): got %q", b.Name()) |
| 8fe9b10… | lmata | 18 | } |
| 8fe9b10… | lmata | 19 | } |
| 8fe9b10… | lmata | 20 | |
| 8fe9b10… | lmata | 21 | func TestEmitNonBlocking(t *testing.T) { |
| 8fe9b10… | lmata | 22 | b := newBot(herald.RouteConfig{DefaultChannel: "#fleet"}) |
| 8fe9b10… | lmata | 23 | // Fill queue past capacity — should not block. |
| 8fe9b10… | lmata | 24 | for i := 0; i < 300; i++ { |
| 8fe9b10… | lmata | 25 | b.Emit(herald.Event{Type: "ci.build", Message: "build done"}) |
| 8fe9b10… | lmata | 26 | } |
| 8fe9b10… | lmata | 27 | } |
| 8fe9b10… | lmata | 28 | |
| 8fe9b10… | lmata | 29 | func TestRateLimiterAllows(t *testing.T) { |
| 8fe9b10… | lmata | 30 | // High rate + high burst: all should be allowed immediately. |
| 8fe9b10… | lmata | 31 | b := newBot(herald.RouteConfig{DefaultChannel: "#fleet"}) |
| 8fe9b10… | lmata | 32 | // Emit() just queues; actual rate limiting happens in deliver(). |
| 8fe9b10… | lmata | 33 | // We test that Emit is non-blocking and the bot is constructible. |
| 8fe9b10… | lmata | 34 | b.Emit(herald.Event{Type: "ci.build", Message: "ok"}) |
| 8fe9b10… | lmata | 35 | } |
| 8fe9b10… | lmata | 36 | |
| 8fe9b10… | lmata | 37 | func TestRouteConfig(t *testing.T) { |
| 8fe9b10… | lmata | 38 | // Verify routing logic by checking bot construction accepts route maps. |
| 8fe9b10… | lmata | 39 | routes := herald.RouteConfig{ |
| 8fe9b10… | lmata | 40 | Routes: map[string]string{ |
| 8fe9b10… | lmata | 41 | "ci.": "#builds", |
| 8fe9b10… | lmata | 42 | "ci.build.": "#builds", |
| 8fe9b10… | lmata | 43 | "deploy.": "#deploys", |
| 8fe9b10… | lmata | 44 | }, |
| 8fe9b10… | lmata | 45 | DefaultChannel: "#alerts", |
| 8fe9b10… | lmata | 46 | } |
| 3420a83… | lmata | 47 | b := herald.New("localhost:6667", "pass", nil, routes, 5, 20, nil) |
| 8fe9b10… | lmata | 48 | if b == nil { |
| 8fe9b10… | lmata | 49 | t.Fatal("expected non-nil bot") |
| 8fe9b10… | lmata | 50 | } |
| 8fe9b10… | lmata | 51 | } |
| 8fe9b10… | lmata | 52 | |
| 8fe9b10… | lmata | 53 | func TestEmitDropsWhenQueueFull(t *testing.T) { |
| 8fe9b10… | lmata | 54 | b := newBot(herald.RouteConfig{}) |
| 8fe9b10… | lmata | 55 | // Emit 1000 events — excess should be dropped without panic or block. |
| 8fe9b10… | lmata | 56 | done := make(chan struct{}) |
| 8fe9b10… | lmata | 57 | go func() { |
| 8fe9b10… | lmata | 58 | for i := 0; i < 1000; i++ { |
| 8fe9b10… | lmata | 59 | b.Emit(herald.Event{Type: "x", Message: "y"}) |
| 8fe9b10… | lmata | 60 | } |
| 8fe9b10… | lmata | 61 | close(done) |
| 8fe9b10… | lmata | 62 | }() |
| 8fe9b10… | lmata | 63 | select { |
| 8fe9b10… | lmata | 64 | case <-done: |
| 8fe9b10… | lmata | 65 | case <-time.After(2 * time.Second): |
| 8fe9b10… | lmata | 66 | t.Error("Emit blocked or deadlocked") |
| 8fe9b10… | lmata | 67 | } |
| 8fe9b10… | lmata | 68 | } |