|
1
|
package client_test |
|
2
|
|
|
3
|
import ( |
|
4
|
"context" |
|
5
|
"testing" |
|
6
|
"time" |
|
7
|
|
|
8
|
"github.com/conflicthq/scuttlebot/pkg/client" |
|
9
|
) |
|
10
|
|
|
11
|
// TestDiscoveryNotConnected verifies all methods return an error when the |
|
12
|
// client is not connected to IRC. The full request→response path requires a |
|
13
|
// live Ergo instance (integration test). |
|
14
|
func TestDiscoveryNotConnected(t *testing.T) { |
|
15
|
c, _ := client.New(client.Options{ |
|
16
|
ServerAddr: "localhost:6667", |
|
17
|
Nick: "agent-01", |
|
18
|
Password: "secret", |
|
19
|
}) |
|
20
|
d := client.NewDiscovery(c, client.DiscoveryOptions{}) |
|
21
|
ctx := context.Background() |
|
22
|
|
|
23
|
t.Run("ListChannels", func(t *testing.T) { |
|
24
|
if _, err := d.ListChannels(ctx); err == nil { |
|
25
|
t.Error("expected error when not connected") |
|
26
|
} |
|
27
|
}) |
|
28
|
t.Run("ChannelMembers", func(t *testing.T) { |
|
29
|
if _, err := d.ChannelMembers(ctx, "#fleet"); err == nil { |
|
30
|
t.Error("expected error when not connected") |
|
31
|
} |
|
32
|
}) |
|
33
|
t.Run("GetTopic", func(t *testing.T) { |
|
34
|
if _, err := d.GetTopic(ctx, "#fleet"); err == nil { |
|
35
|
t.Error("expected error when not connected") |
|
36
|
} |
|
37
|
}) |
|
38
|
t.Run("WhoIs", func(t *testing.T) { |
|
39
|
if _, err := d.WhoIs(ctx, "someone"); err == nil { |
|
40
|
t.Error("expected error when not connected") |
|
41
|
} |
|
42
|
}) |
|
43
|
} |
|
44
|
|
|
45
|
func TestDiscoveryCancellation(t *testing.T) { |
|
46
|
c, _ := client.New(client.Options{ |
|
47
|
ServerAddr: "localhost:6667", |
|
48
|
Nick: "agent-01", |
|
49
|
Password: "secret", |
|
50
|
}) |
|
51
|
d := client.NewDiscovery(c, client.DiscoveryOptions{}) |
|
52
|
|
|
53
|
ctx, cancel := context.WithCancel(context.Background()) |
|
54
|
cancel() |
|
55
|
|
|
56
|
// All methods should return context.Canceled, not hang. |
|
57
|
_, err := d.ListChannels(ctx) |
|
58
|
// Either "not connected" (faster path) or context.Canceled is acceptable. |
|
59
|
if err == nil { |
|
60
|
t.Error("expected error on cancelled context") |
|
61
|
} |
|
62
|
} |
|
63
|
|
|
64
|
func TestDiscoveryCacheTTL(t *testing.T) { |
|
65
|
// Verify that cache entries expire after TTL. |
|
66
|
// We test the cache layer directly by setting a very short TTL. |
|
67
|
c, _ := client.New(client.Options{ |
|
68
|
ServerAddr: "localhost:6667", |
|
69
|
Nick: "agent-01", |
|
70
|
Password: "secret", |
|
71
|
}) |
|
72
|
|
|
73
|
// Zero TTL disables caching — discovery always hits the server. |
|
74
|
d := client.NewDiscovery(c, client.DiscoveryOptions{CacheTTL: 0}) |
|
75
|
if d == nil { |
|
76
|
t.Fatal("NewDiscovery returned nil") |
|
77
|
} |
|
78
|
} |
|
79
|
|
|
80
|
func TestDiscoveryDefaultOptions(t *testing.T) { |
|
81
|
c, _ := client.New(client.Options{ |
|
82
|
ServerAddr: "localhost:6667", |
|
83
|
Nick: "agent-01", |
|
84
|
Password: "secret", |
|
85
|
}) |
|
86
|
// Default TTL should be 30s — just verify it doesn't panic. |
|
87
|
d := client.NewDiscovery(c, client.DiscoveryOptions{}) |
|
88
|
if d == nil { |
|
89
|
t.Fatal("NewDiscovery returned nil") |
|
90
|
} |
|
91
|
} |
|
92
|
|
|
93
|
func TestDiscoveryInvalidate(t *testing.T) { |
|
94
|
c, _ := client.New(client.Options{ |
|
95
|
ServerAddr: "localhost:6667", |
|
96
|
Nick: "agent-01", |
|
97
|
Password: "secret", |
|
98
|
}) |
|
99
|
d := client.NewDiscovery(c, client.DiscoveryOptions{CacheTTL: 10 * time.Minute}) |
|
100
|
// Invalidate should not panic on unknown keys. |
|
101
|
d.Invalidate("list_channels") |
|
102
|
d.Invalidate("members:#fleet") |
|
103
|
d.Invalidate("topic:#fleet") |
|
104
|
d.Invalidate("whois:nobody") |
|
105
|
} |
|
106
|
|