@@ -4,17 +4,14 @@ import (
4
4
"context"
5
5
"testing"
6
6
7
- "github.com/google/uuid"
8
7
"github.com/stretchr/testify/require"
9
- "golang.org/x/exp/slices"
10
- "tailscale.com/types/key"
11
8
12
9
"cdr.dev/slog"
13
10
"cdr.dev/slog/sloggers/slogtest"
14
11
"github.com/coder/coder/v2/coderd/database/dbtestutil"
15
12
"github.com/coder/coder/v2/enterprise/tailnet"
16
13
agpl "github.com/coder/coder/v2/tailnet"
17
- "github.com/coder/coder/v2/tailnet/proto "
14
+ "github.com/coder/coder/v2/tailnet/tailnettest "
18
15
"github.com/coder/coder/v2/testutil"
19
16
)
20
17
@@ -42,25 +39,48 @@ func TestPGCoordinator_MultiAgent(t *testing.T) {
42
39
defer agent1 .close ()
43
40
agent1 .sendNode (& agpl.Node {PreferredDERP : 5 })
44
41
45
- ma1 := newTestMultiAgent (t , coord1 )
46
- defer ma1 .close ()
42
+ ma1 := tailnettest . NewTestMultiAgent (t , coord1 )
43
+ defer ma1 .Close ()
47
44
48
- ma1 .subscribeAgent (agent1 .id )
49
- ma1 .assertEventuallyHasDERPs (ctx , 5 )
45
+ ma1 .RequireSubscribeAgent (agent1 .id )
46
+ ma1 .RequireEventuallyHasDERPs (ctx , 5 )
50
47
51
48
agent1 .sendNode (& agpl.Node {PreferredDERP : 1 })
52
- ma1 .assertEventuallyHasDERPs (ctx , 1 )
49
+ ma1 .RequireEventuallyHasDERPs (ctx , 1 )
53
50
54
- ma1 .sendNodeWithDERP (3 )
51
+ ma1 .SendNodeWithDERP (3 )
55
52
assertEventuallyHasDERPs (ctx , t , agent1 , 3 )
56
53
57
- ma1 .close ()
54
+ ma1 .Close ()
58
55
require .NoError (t , agent1 .close ())
59
56
60
57
assertEventuallyNoClientsForAgent (ctx , t , store , agent1 .id )
61
58
assertEventuallyLost (ctx , t , store , agent1 .id )
62
59
}
63
60
61
+ func TestPGCoordinator_MultiAgent_CoordClose (t * testing.T ) {
62
+ t .Parallel ()
63
+ if ! dbtestutil .WillUsePostgres () {
64
+ t .Skip ("test only with postgres" )
65
+ }
66
+
67
+ logger := slogtest .Make (t , & slogtest.Options {IgnoreErrors : true }).Leveled (slog .LevelDebug )
68
+ store , ps := dbtestutil .NewDB (t )
69
+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
70
+ defer cancel ()
71
+ coord1 , err := tailnet .NewPGCoord (ctx , logger .Named ("coord1" ), ps , store )
72
+ require .NoError (t , err )
73
+ defer coord1 .Close ()
74
+
75
+ ma1 := tailnettest .NewTestMultiAgent (t , coord1 )
76
+ defer ma1 .Close ()
77
+
78
+ err = coord1 .Close ()
79
+ require .NoError (t , err )
80
+
81
+ ma1 .RequireEventuallyClosed (ctx )
82
+ }
83
+
64
84
// TestPGCoordinator_MultiAgent_UnsubscribeRace tests a single coordinator with
65
85
// a MultiAgent connecting to one agent. It tries to race a call to Unsubscribe
66
86
// with the MultiAgent closing.
@@ -86,20 +106,20 @@ func TestPGCoordinator_MultiAgent_UnsubscribeRace(t *testing.T) {
86
106
defer agent1 .close ()
87
107
agent1 .sendNode (& agpl.Node {PreferredDERP : 5 })
88
108
89
- ma1 := newTestMultiAgent (t , coord1 )
90
- defer ma1 .close ()
109
+ ma1 := tailnettest . NewTestMultiAgent (t , coord1 )
110
+ defer ma1 .Close ()
91
111
92
- ma1 .subscribeAgent (agent1 .id )
93
- ma1 .assertEventuallyHasDERPs (ctx , 5 )
112
+ ma1 .RequireSubscribeAgent (agent1 .id )
113
+ ma1 .RequireEventuallyHasDERPs (ctx , 5 )
94
114
95
115
agent1 .sendNode (& agpl.Node {PreferredDERP : 1 })
96
- ma1 .assertEventuallyHasDERPs (ctx , 1 )
116
+ ma1 .RequireEventuallyHasDERPs (ctx , 1 )
97
117
98
- ma1 .sendNodeWithDERP (3 )
118
+ ma1 .SendNodeWithDERP (3 )
99
119
assertEventuallyHasDERPs (ctx , t , agent1 , 3 )
100
120
101
- ma1 .unsubscribeAgent (agent1 .id )
102
- ma1 .close ()
121
+ ma1 .RequireUnsubscribeAgent (agent1 .id )
122
+ ma1 .Close ()
103
123
require .NoError (t , agent1 .close ())
104
124
105
125
assertEventuallyNoClientsForAgent (ctx , t , store , agent1 .id )
@@ -131,35 +151,35 @@ func TestPGCoordinator_MultiAgent_Unsubscribe(t *testing.T) {
131
151
defer agent1 .close ()
132
152
agent1 .sendNode (& agpl.Node {PreferredDERP : 5 })
133
153
134
- ma1 := newTestMultiAgent (t , coord1 )
135
- defer ma1 .close ()
154
+ ma1 := tailnettest . NewTestMultiAgent (t , coord1 )
155
+ defer ma1 .Close ()
136
156
137
- ma1 .subscribeAgent (agent1 .id )
138
- ma1 .assertEventuallyHasDERPs (ctx , 5 )
157
+ ma1 .RequireSubscribeAgent (agent1 .id )
158
+ ma1 .RequireEventuallyHasDERPs (ctx , 5 )
139
159
140
160
agent1 .sendNode (& agpl.Node {PreferredDERP : 1 })
141
- ma1 .assertEventuallyHasDERPs (ctx , 1 )
161
+ ma1 .RequireEventuallyHasDERPs (ctx , 1 )
142
162
143
- ma1 .sendNodeWithDERP (3 )
163
+ ma1 .SendNodeWithDERP (3 )
144
164
assertEventuallyHasDERPs (ctx , t , agent1 , 3 )
145
165
146
- ma1 .unsubscribeAgent (agent1 .id )
166
+ ma1 .RequireUnsubscribeAgent (agent1 .id )
147
167
assertEventuallyNoClientsForAgent (ctx , t , store , agent1 .id )
148
168
149
169
func () {
150
170
ctx , cancel := context .WithTimeout (ctx , testutil .IntervalSlow * 3 )
151
171
defer cancel ()
152
- ma1 .sendNodeWithDERP (9 )
172
+ ma1 .SendNodeWithDERP (9 )
153
173
assertNeverHasDERPs (ctx , t , agent1 , 9 )
154
174
}()
155
175
func () {
156
176
ctx , cancel := context .WithTimeout (ctx , testutil .IntervalSlow * 3 )
157
177
defer cancel ()
158
178
agent1 .sendNode (& agpl.Node {PreferredDERP : 8 })
159
- ma1 .assertNeverHasDERPs (ctx , 8 )
179
+ ma1 .RequireNeverHasDERPs (ctx , 8 )
160
180
}()
161
181
162
- ma1 .close ()
182
+ ma1 .Close ()
163
183
require .NoError (t , agent1 .close ())
164
184
165
185
assertEventuallyNoClientsForAgent (ctx , t , store , agent1 .id )
@@ -196,19 +216,19 @@ func TestPGCoordinator_MultiAgent_MultiCoordinator(t *testing.T) {
196
216
defer agent1 .close ()
197
217
agent1 .sendNode (& agpl.Node {PreferredDERP : 5 })
198
218
199
- ma1 := newTestMultiAgent (t , coord2 )
200
- defer ma1 .close ()
219
+ ma1 := tailnettest . NewTestMultiAgent (t , coord2 )
220
+ defer ma1 .Close ()
201
221
202
- ma1 .subscribeAgent (agent1 .id )
203
- ma1 .assertEventuallyHasDERPs (ctx , 5 )
222
+ ma1 .RequireSubscribeAgent (agent1 .id )
223
+ ma1 .RequireEventuallyHasDERPs (ctx , 5 )
204
224
205
225
agent1 .sendNode (& agpl.Node {PreferredDERP : 1 })
206
- ma1 .assertEventuallyHasDERPs (ctx , 1 )
226
+ ma1 .RequireEventuallyHasDERPs (ctx , 1 )
207
227
208
- ma1 .sendNodeWithDERP (3 )
228
+ ma1 .SendNodeWithDERP (3 )
209
229
assertEventuallyHasDERPs (ctx , t , agent1 , 3 )
210
230
211
- ma1 .close ()
231
+ ma1 .Close ()
212
232
require .NoError (t , agent1 .close ())
213
233
214
234
assertEventuallyNoClientsForAgent (ctx , t , store , agent1 .id )
@@ -246,19 +266,19 @@ func TestPGCoordinator_MultiAgent_MultiCoordinator_UpdateBeforeSubscribe(t *test
246
266
defer agent1 .close ()
247
267
agent1 .sendNode (& agpl.Node {PreferredDERP : 5 })
248
268
249
- ma1 := newTestMultiAgent (t , coord2 )
250
- defer ma1 .close ()
269
+ ma1 := tailnettest . NewTestMultiAgent (t , coord2 )
270
+ defer ma1 .Close ()
251
271
252
- ma1 .sendNodeWithDERP (3 )
272
+ ma1 .SendNodeWithDERP (3 )
253
273
254
- ma1 .subscribeAgent (agent1 .id )
255
- ma1 .assertEventuallyHasDERPs (ctx , 5 )
274
+ ma1 .RequireSubscribeAgent (agent1 .id )
275
+ ma1 .RequireEventuallyHasDERPs (ctx , 5 )
256
276
assertEventuallyHasDERPs (ctx , t , agent1 , 3 )
257
277
258
278
agent1 .sendNode (& agpl.Node {PreferredDERP : 1 })
259
- ma1 .assertEventuallyHasDERPs (ctx , 1 )
279
+ ma1 .RequireEventuallyHasDERPs (ctx , 1 )
260
280
261
- ma1 .close ()
281
+ ma1 .Close ()
262
282
require .NoError (t , agent1 .close ())
263
283
264
284
assertEventuallyNoClientsForAgent (ctx , t , store , agent1 .id )
@@ -305,129 +325,29 @@ func TestPGCoordinator_MultiAgent_TwoAgents(t *testing.T) {
305
325
defer agent1 .close ()
306
326
agent2 .sendNode (& agpl.Node {PreferredDERP : 6 })
307
327
308
- ma1 := newTestMultiAgent (t , coord3 )
309
- defer ma1 .close ()
328
+ ma1 := tailnettest . NewTestMultiAgent (t , coord3 )
329
+ defer ma1 .Close ()
310
330
311
- ma1 .subscribeAgent (agent1 .id )
312
- ma1 .assertEventuallyHasDERPs (ctx , 5 )
331
+ ma1 .RequireSubscribeAgent (agent1 .id )
332
+ ma1 .RequireEventuallyHasDERPs (ctx , 5 )
313
333
314
334
agent1 .sendNode (& agpl.Node {PreferredDERP : 1 })
315
- ma1 .assertEventuallyHasDERPs (ctx , 1 )
335
+ ma1 .RequireEventuallyHasDERPs (ctx , 1 )
316
336
317
- ma1 .subscribeAgent (agent2 .id )
318
- ma1 .assertEventuallyHasDERPs (ctx , 6 )
337
+ ma1 .RequireSubscribeAgent (agent2 .id )
338
+ ma1 .RequireEventuallyHasDERPs (ctx , 6 )
319
339
320
340
agent2 .sendNode (& agpl.Node {PreferredDERP : 2 })
321
- ma1 .assertEventuallyHasDERPs (ctx , 2 )
341
+ ma1 .RequireEventuallyHasDERPs (ctx , 2 )
322
342
323
- ma1 .sendNodeWithDERP (3 )
343
+ ma1 .SendNodeWithDERP (3 )
324
344
assertEventuallyHasDERPs (ctx , t , agent1 , 3 )
325
345
assertEventuallyHasDERPs (ctx , t , agent2 , 3 )
326
346
327
- ma1 .close ()
347
+ ma1 .Close ()
328
348
require .NoError (t , agent1 .close ())
329
349
require .NoError (t , agent2 .close ())
330
350
331
351
assertEventuallyNoClientsForAgent (ctx , t , store , agent1 .id )
332
352
assertEventuallyLost (ctx , t , store , agent1 .id )
333
353
}
334
-
335
- type testMultiAgent struct {
336
- t testing.TB
337
- id uuid.UUID
338
- a agpl.MultiAgentConn
339
- nodeKey []byte
340
- discoKey string
341
- }
342
-
343
- func newTestMultiAgent (t testing.TB , coord agpl.Coordinator ) * testMultiAgent {
344
- nk , err := key .NewNode ().Public ().MarshalBinary ()
345
- require .NoError (t , err )
346
- dk , err := key .NewDisco ().Public ().MarshalText ()
347
- require .NoError (t , err )
348
- m := & testMultiAgent {t : t , id : uuid .New (), nodeKey : nk , discoKey : string (dk )}
349
- m .a = coord .ServeMultiAgent (m .id )
350
- return m
351
- }
352
-
353
- func (m * testMultiAgent ) sendNodeWithDERP (derp int32 ) {
354
- m .t .Helper ()
355
- err := m .a .UpdateSelf (& proto.Node {
356
- Key : m .nodeKey ,
357
- Disco : m .discoKey ,
358
- PreferredDerp : derp ,
359
- })
360
- require .NoError (m .t , err )
361
- }
362
-
363
- func (m * testMultiAgent ) close () {
364
- m .t .Helper ()
365
- err := m .a .Close ()
366
- require .NoError (m .t , err )
367
- }
368
-
369
- func (m * testMultiAgent ) subscribeAgent (id uuid.UUID ) {
370
- m .t .Helper ()
371
- err := m .a .SubscribeAgent (id )
372
- require .NoError (m .t , err )
373
- }
374
-
375
- func (m * testMultiAgent ) unsubscribeAgent (id uuid.UUID ) {
376
- m .t .Helper ()
377
- err := m .a .UnsubscribeAgent (id )
378
- require .NoError (m .t , err )
379
- }
380
-
381
- func (m * testMultiAgent ) assertEventuallyHasDERPs (ctx context.Context , expected ... int ) {
382
- m .t .Helper ()
383
- for {
384
- resp , ok := m .a .NextUpdate (ctx )
385
- require .True (m .t , ok )
386
- nodes , err := agpl .OnlyNodeUpdates (resp )
387
- require .NoError (m .t , err )
388
- if len (nodes ) != len (expected ) {
389
- m .t .Logf ("expected %d, got %d nodes" , len (expected ), len (nodes ))
390
- continue
391
- }
392
-
393
- derps := make ([]int , 0 , len (nodes ))
394
- for _ , n := range nodes {
395
- derps = append (derps , n .PreferredDERP )
396
- }
397
- for _ , e := range expected {
398
- if ! slices .Contains (derps , e ) {
399
- m .t .Logf ("expected DERP %d to be in %v" , e , derps )
400
- continue
401
- }
402
- return
403
- }
404
- }
405
- }
406
-
407
- func (m * testMultiAgent ) assertNeverHasDERPs (ctx context.Context , expected ... int ) {
408
- m .t .Helper ()
409
- for {
410
- resp , ok := m .a .NextUpdate (ctx )
411
- if ! ok {
412
- return
413
- }
414
- nodes , err := agpl .OnlyNodeUpdates (resp )
415
- require .NoError (m .t , err )
416
- if len (nodes ) != len (expected ) {
417
- m .t .Logf ("expected %d, got %d nodes" , len (expected ), len (nodes ))
418
- continue
419
- }
420
-
421
- derps := make ([]int , 0 , len (nodes ))
422
- for _ , n := range nodes {
423
- derps = append (derps , n .PreferredDERP )
424
- }
425
- for _ , e := range expected {
426
- if ! slices .Contains (derps , e ) {
427
- m .t .Logf ("expected DERP %d to be in %v" , e , derps )
428
- continue
429
- }
430
- return
431
- }
432
- }
433
- }
0 commit comments