@@ -2668,19 +2668,19 @@ func TestAgent_Dial(t *testing.T) {
2668
2668
2669
2669
cases := []struct {
2670
2670
name string
2671
- setup func (t * testing.T ) net.Listener
2671
+ setup func (t testing.TB ) net.Listener
2672
2672
}{
2673
2673
{
2674
2674
name : "TCP" ,
2675
- setup : func (t * testing.T ) net.Listener {
2675
+ setup : func (t testing.TB ) net.Listener {
2676
2676
l , err := net .Listen ("tcp" , "127.0.0.1:0" )
2677
2677
require .NoError (t , err , "create TCP listener" )
2678
2678
return l
2679
2679
},
2680
2680
},
2681
2681
{
2682
2682
name : "UDP" ,
2683
- setup : func (t * testing.T ) net.Listener {
2683
+ setup : func (t testing.TB ) net.Listener {
2684
2684
addr := net.UDPAddr {
2685
2685
IP : net .ParseIP ("127.0.0.1" ),
2686
2686
Port : 0 ,
@@ -2698,57 +2698,68 @@ func TestAgent_Dial(t *testing.T) {
2698
2698
2699
2699
// The purpose of this test is to ensure that a client can dial a
2700
2700
// listener in the workspace over tailnet.
2701
- l := c .setup (t )
2702
- done := make (chan struct {})
2703
- defer func () {
2704
- l .Close ()
2705
- <- done
2706
- }()
2707
-
2708
- ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
2709
- defer cancel ()
2710
-
2711
- go func () {
2712
- defer close (done )
2713
- for range 2 {
2714
- c , err := l .Accept ()
2715
- if assert .NoError (t , err , "accept connection" ) {
2716
- testAccept (ctx , t , c )
2717
- _ = c .Close ()
2701
+ //
2702
+ // The OS sometimes drops packets if the system can't keep up with
2703
+ // them. For TCP packets, it's typically fine due to
2704
+ // retransmissions, but for UDP packets, it can fail this test.
2705
+ //
2706
+ // The OS gets involved for the Wireguard traffic (either via DERP
2707
+ // or direct UDP), and also for the traffic between the agent and
2708
+ // the listener in the "workspace".
2709
+ //
2710
+ // To avoid this, we'll retry this test up to 3 times.
2711
+ testutil .RunRetry (t , 3 , func (t testing.TB ) {
2712
+ ctx := testutil .Context (t , testutil .WaitLong )
2713
+
2714
+ l := c .setup (t )
2715
+ done := make (chan struct {})
2716
+ defer func () {
2717
+ l .Close ()
2718
+ <- done
2719
+ }()
2720
+
2721
+ go func () {
2722
+ defer close (done )
2723
+ for range 2 {
2724
+ c , err := l .Accept ()
2725
+ if assert .NoError (t , err , "accept connection" ) {
2726
+ testAccept (ctx , t , c )
2727
+ _ = c .Close ()
2728
+ }
2718
2729
}
2719
- }
2720
- }()
2730
+ }()
2721
2731
2722
- agentID := uuid.UUID {0 , 0 , 0 , 0 , 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }
2723
- //nolint:dogsled
2724
- agentConn , _ , _ , _ , _ := setupAgent (t , agentsdk.Manifest {
2725
- AgentID : agentID ,
2726
- }, 0 )
2727
- require .True (t , agentConn .AwaitReachable (ctx ))
2728
- conn , err := agentConn .DialContext (ctx , l .Addr ().Network (), l .Addr ().String ())
2729
- require .NoError (t , err )
2730
- testDial (ctx , t , conn )
2731
- err = conn .Close ()
2732
- require .NoError (t , err )
2732
+ agentID := uuid.UUID {0 , 0 , 0 , 0 , 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }
2733
+ //nolint:dogsled
2734
+ agentConn , _ , _ , _ , _ := setupAgent (t , agentsdk.Manifest {
2735
+ AgentID : agentID ,
2736
+ }, 0 )
2737
+ require .True (t , agentConn .AwaitReachable (ctx ))
2738
+ conn , err := agentConn .DialContext (ctx , l .Addr ().Network (), l .Addr ().String ())
2739
+ require .NoError (t , err )
2740
+ testDial (ctx , t , conn )
2741
+ err = conn .Close ()
2742
+ require .NoError (t , err )
2733
2743
2734
- // also connect via the CoderServicePrefix, to test that we can reach the agent on this
2735
- // IP. This will be required for CoderVPN.
2736
- _ , rawPort , _ := net .SplitHostPort (l .Addr ().String ())
2737
- port , _ := strconv .ParseUint (rawPort , 10 , 16 )
2738
- ipp := netip .AddrPortFrom (tailnet .CoderServicePrefix .AddrFromUUID (agentID ), uint16 (port ))
2739
-
2740
- switch l .Addr ().Network () {
2741
- case "tcp" :
2742
- conn , err = agentConn .Conn .DialContextTCP (ctx , ipp )
2743
- case "udp" :
2744
- conn , err = agentConn .Conn .DialContextUDP (ctx , ipp )
2745
- default :
2746
- t .Fatalf ("unknown network: %s" , l .Addr ().Network ())
2747
- }
2748
- require .NoError (t , err )
2749
- testDial (ctx , t , conn )
2750
- err = conn .Close ()
2751
- require .NoError (t , err )
2744
+ // also connect via the CoderServicePrefix, to test that we can reach the agent on this
2745
+ // IP. This will be required for CoderVPN.
2746
+ _ , rawPort , _ := net .SplitHostPort (l .Addr ().String ())
2747
+ port , _ := strconv .ParseUint (rawPort , 10 , 16 )
2748
+ ipp := netip .AddrPortFrom (tailnet .CoderServicePrefix .AddrFromUUID (agentID ), uint16 (port ))
2749
+
2750
+ switch l .Addr ().Network () {
2751
+ case "tcp" :
2752
+ conn , err = agentConn .Conn .DialContextTCP (ctx , ipp )
2753
+ case "udp" :
2754
+ conn , err = agentConn .Conn .DialContextUDP (ctx , ipp )
2755
+ default :
2756
+ t .Fatalf ("unknown network: %s" , l .Addr ().Network ())
2757
+ }
2758
+ require .NoError (t , err )
2759
+ testDial (ctx , t , conn )
2760
+ err = conn .Close ()
2761
+ require .NoError (t , err )
2762
+ })
2752
2763
})
2753
2764
}
2754
2765
}
@@ -3251,7 +3262,7 @@ func setupSSHSessionOnPort(
3251
3262
return session
3252
3263
}
3253
3264
3254
- func setupAgent (t * testing.T , metadata agentsdk.Manifest , ptyTimeout time.Duration , opts ... func (* agenttest.Client , * agent.Options )) (
3265
+ func setupAgent (t testing.TB , metadata agentsdk.Manifest , ptyTimeout time.Duration , opts ... func (* agenttest.Client , * agent.Options )) (
3255
3266
* workspacesdk.AgentConn ,
3256
3267
* agenttest.Client ,
3257
3268
<- chan * proto.Stats ,
@@ -3349,7 +3360,7 @@ func setupAgent(t *testing.T, metadata agentsdk.Manifest, ptyTimeout time.Durati
3349
3360
3350
3361
var dialTestPayload = []byte ("dean-was-here123" )
3351
3362
3352
- func testDial (ctx context.Context , t * testing.T , c net.Conn ) {
3363
+ func testDial (ctx context.Context , t testing.TB , c net.Conn ) {
3353
3364
t .Helper ()
3354
3365
3355
3366
if deadline , ok := ctx .Deadline (); ok {
@@ -3365,7 +3376,7 @@ func testDial(ctx context.Context, t *testing.T, c net.Conn) {
3365
3376
assertReadPayload (t , c , dialTestPayload )
3366
3377
}
3367
3378
3368
- func testAccept (ctx context.Context , t * testing.T , c net.Conn ) {
3379
+ func testAccept (ctx context.Context , t testing.TB , c net.Conn ) {
3369
3380
t .Helper ()
3370
3381
defer c .Close ()
3371
3382
@@ -3382,7 +3393,7 @@ func testAccept(ctx context.Context, t *testing.T, c net.Conn) {
3382
3393
assertWritePayload (t , c , dialTestPayload )
3383
3394
}
3384
3395
3385
- func assertReadPayload (t * testing.T , r io.Reader , payload []byte ) {
3396
+ func assertReadPayload (t testing.TB , r io.Reader , payload []byte ) {
3386
3397
t .Helper ()
3387
3398
b := make ([]byte , len (payload )+ 16 )
3388
3399
n , err := r .Read (b )
@@ -3391,11 +3402,11 @@ func assertReadPayload(t *testing.T, r io.Reader, payload []byte) {
3391
3402
assert .Equal (t , payload , b [:n ])
3392
3403
}
3393
3404
3394
- func assertWritePayload (t * testing.T , w io.Writer , payload []byte ) {
3405
+ func assertWritePayload (t testing.TB , w io.Writer , payload []byte ) {
3395
3406
t .Helper ()
3396
3407
n , err := w .Write (payload )
3397
3408
assert .NoError (t , err , "write payload" )
3398
- assert .Equal (t , len (payload ), n , "payload length does not match" )
3409
+ assert .Equal (t , len (payload ), n , "written payload length does not match" )
3399
3410
}
3400
3411
3401
3412
func testSessionOutput (t * testing.T , session * ssh.Session , expected , unexpected []string , expectedRe * regexp.Regexp ) {
0 commit comments