@@ -129,9 +129,67 @@ func TestDERP(t *testing.T) {
129
129
assert .True (t ,report .Healthy )
130
130
assert .Equal (t ,health .SeverityWarning ,report .Severity )
131
131
assert .True (t ,report .Dismissed )
132
- if assert .NotEmpty (t ,report .Warnings ) {
132
+ if assert .Len (t ,report .Warnings , 1 ) {
133
133
assert .Contains (t ,report .Warnings [0 ].Code ,health .CodeDERPOneNodeUnhealthy )
134
134
}
135
+ for _ ,region := range report .Regions {
136
+ assert .True (t ,region .Healthy )
137
+ assert .True (t ,region .NodeReports [0 ].Healthy )
138
+ assert .Empty (t ,region .NodeReports [0 ].Warnings )
139
+ assert .Equal (t ,health .SeverityOK ,region .NodeReports [0 ].Severity )
140
+ assert .False (t ,region .NodeReports [1 ].Healthy )
141
+ assert .Equal (t ,health .SeverityError ,region .NodeReports [1 ].Severity )
142
+ assert .Len (t ,region .Warnings ,1 )
143
+ }
144
+ })
145
+
146
+ t .Run ("HealthyWithNoSTUN" ,func (t * testing.T ) {
147
+ t .Parallel ()
148
+
149
+ healthyDerpSrv := derp .NewServer (key .NewNode (),func (format string ,args ... any ) {t .Logf (format ,args ... ) })
150
+ defer healthyDerpSrv .Close ()
151
+ healthySrv := httptest .NewServer (derphttp .Handler (healthyDerpSrv ))
152
+ defer healthySrv .Close ()
153
+
154
+ var (
155
+ ctx = context .Background ()
156
+ report = derphealth.Report {}
157
+ derpURL ,_ = url .Parse (healthySrv .URL )
158
+ opts = & derphealth.ReportOptions {
159
+ DERPMap :& tailcfg.DERPMap {Regions :map [int ]* tailcfg.DERPRegion {
160
+ 1 : {
161
+ EmbeddedRelay :true ,
162
+ RegionID :999 ,
163
+ Nodes : []* tailcfg.DERPNode {{
164
+ Name :"1a" ,
165
+ RegionID :999 ,
166
+ HostName :derpURL .Host ,
167
+ IPv4 :derpURL .Host ,
168
+ STUNPort :- 1 ,
169
+ InsecureForTests :true ,
170
+ ForceHTTP :true ,
171
+ }, {
172
+ Name :"badstun" ,
173
+ RegionID :999 ,
174
+ HostName :derpURL .Host ,
175
+ STUNPort :19302 ,
176
+ STUNOnly :true ,
177
+ InsecureForTests :true ,
178
+ ForceHTTP :true ,
179
+ }},
180
+ },
181
+ }},
182
+ }
183
+ )
184
+
185
+ report .Run (ctx ,opts )
186
+
187
+ assert .True (t ,report .Healthy )
188
+ assert .Equal (t ,health .SeverityWarning ,report .Severity )
189
+ if assert .Len (t ,report .Warnings ,2 ) {
190
+ assert .EqualValues (t ,report .Warnings [1 ].Code ,health .CodeSTUNNoNodes )
191
+ assert .EqualValues (t ,report .Warnings [0 ].Code ,health .CodeDERPOneNodeUnhealthy )
192
+ }
135
193
for _ ,region := range report .Regions {
136
194
assert .True (t ,region .Healthy )
137
195
assert .True (t ,region .NodeReports [0 ].Healthy )
@@ -291,8 +349,10 @@ func TestDERP(t *testing.T) {
291
349
report .Run (ctx ,opts )
292
350
293
351
assert .True (t ,report .Healthy )
352
+ assert .Equal (t ,health .SeverityOK ,report .Severity )
294
353
for _ ,region := range report .Regions {
295
354
assert .True (t ,region .Healthy )
355
+ assert .Equal (t ,health .SeverityOK ,region .Severity )
296
356
for _ ,node := range region .NodeReports {
297
357
assert .True (t ,node .Healthy )
298
358
assert .False (t ,node .CanExchangeMessages )
@@ -304,6 +364,107 @@ func TestDERP(t *testing.T) {
304
364
}
305
365
}
306
366
})
367
+
368
+ t .Run ("STUNOnly/OneBadOneGood" ,func (t * testing.T ) {
369
+ t .Parallel ()
370
+
371
+ var (
372
+ ctx = context .Background ()
373
+ report = derphealth.Report {}
374
+ opts = & derphealth.ReportOptions {
375
+ DERPMap :& tailcfg.DERPMap {
376
+ Regions :map [int ]* tailcfg.DERPRegion {
377
+ 1 : {
378
+ EmbeddedRelay :true ,
379
+ RegionID :999 ,
380
+ Nodes : []* tailcfg.DERPNode {{
381
+ Name :"badstun" ,
382
+ RegionID :999 ,
383
+ HostName :"badstun.example.com" ,
384
+ STUNPort :19302 ,
385
+ STUNOnly :true ,
386
+ InsecureForTests :true ,
387
+ ForceHTTP :true ,
388
+ }, {
389
+ Name :"goodstun" ,
390
+ RegionID :999 ,
391
+ HostName :"stun.l.google.com" ,
392
+ STUNPort :19302 ,
393
+ STUNOnly :true ,
394
+ InsecureForTests :true ,
395
+ ForceHTTP :true ,
396
+ }},
397
+ },
398
+ },
399
+ },
400
+ }
401
+ )
402
+
403
+ report .Run (ctx ,opts )
404
+ assert .True (t ,report .Healthy )
405
+ assert .Equal (t ,health .SeverityWarning ,report .Severity )
406
+ if assert .Len (t ,report .Warnings ,1 ) {
407
+ assert .Equal (t ,health .CodeDERPOneNodeUnhealthy ,report .Warnings [0 ].Code )
408
+ }
409
+ for _ ,region := range report .Regions {
410
+ assert .True (t ,region .Healthy )
411
+ assert .Equal (t ,health .SeverityWarning ,region .Severity )
412
+ // badstun
413
+ assert .False (t ,region .NodeReports [0 ].Healthy )
414
+ assert .True (t ,region .NodeReports [0 ].STUN .Enabled )
415
+ assert .False (t ,region .NodeReports [0 ].STUN .CanSTUN )
416
+ assert .NotNil (t ,region .NodeReports [0 ].STUN .Error )
417
+ // goodstun
418
+ assert .True (t ,region .NodeReports [1 ].Healthy )
419
+ assert .True (t ,region .NodeReports [1 ].STUN .Enabled )
420
+ assert .True (t ,region .NodeReports [1 ].STUN .CanSTUN )
421
+ assert .Nil (t ,region .NodeReports [1 ].STUN .Error )
422
+ }
423
+ })
424
+
425
+ t .Run ("STUNOnly/NoStun" ,func (t * testing.T ) {
426
+ t .Parallel ()
427
+
428
+ var (
429
+ ctx = context .Background ()
430
+ report = derphealth.Report {}
431
+ opts = & derphealth.ReportOptions {
432
+ DERPMap :& tailcfg.DERPMap {
433
+ Regions :map [int ]* tailcfg.DERPRegion {
434
+ 1 : {
435
+ EmbeddedRelay :true ,
436
+ RegionID :999 ,
437
+ Nodes : []* tailcfg.DERPNode {{
438
+ Name :"badstun" ,
439
+ RegionID :999 ,
440
+ HostName :"badstun.example.com" ,
441
+ STUNPort :19302 ,
442
+ STUNOnly :true ,
443
+ InsecureForTests :true ,
444
+ ForceHTTP :true ,
445
+ }},
446
+ },
447
+ },
448
+ },
449
+ }
450
+ )
451
+
452
+ report .Run (ctx ,opts )
453
+ assert .False (t ,report .Healthy )
454
+ assert .Equal (t ,health .SeverityError ,report .Severity )
455
+ for _ ,region := range report .Regions {
456
+ assert .False (t ,region .Healthy )
457
+ assert .Equal (t ,health .SeverityError ,region .Severity )
458
+ for _ ,node := range region .NodeReports {
459
+ assert .False (t ,node .Healthy )
460
+ assert .False (t ,node .CanExchangeMessages )
461
+ assert .Empty (t ,node .ClientLogs )
462
+ assert .True (t ,node .STUN .Enabled )
463
+ assert .False (t ,node .STUN .CanSTUN )
464
+ assert .NotNil (t ,node .STUN .Error )
465
+ }
466
+ }
467
+ })
307
468
}
308
469
309
470
func tsDERPMap (ctx context.Context ,t testing.TB )* tailcfg.DERPMap {