@@ -1201,6 +1201,7 @@ func TestTCPListen_ConcurrentTunnelSetup(t *testing.T) {
12011201 const numConns = 4
12021202 var arrived atomic.Int32
12031203 allArrived := make (chan struct {})
1204+ gateErrs := make (chan error , numConns )
12041205
12051206 // Each setup waits for all the others, which only completes when the
12061207 // accept loop does not serialize tunnel setup.
@@ -1212,9 +1213,12 @@ func TestTCPListen_ConcurrentTunnelSetup(t *testing.T) {
12121213 case <- allArrived :
12131214 return nil
12141215 case <- ctx .Done ():
1216+ gateErrs <- ctx .Err ()
12151217 return ctx .Err ()
12161218 case <- time .After (2 * time .Second ):
1217- return errors .New ("tunnel setup was serialized" )
1219+ err := errors .New ("tunnel setup was serialized" )
1220+ gateErrs <- err
1221+ return err
12181222 }
12191223 }}
12201224 client , cleanup := setupTCPTestWithResolver (t , newMockTCPServer (), resolver )
@@ -1228,9 +1232,26 @@ func TestTCPListen_ConcurrentTunnelSetup(t *testing.T) {
12281232 for i := range numConns {
12291233 go func () { errCh <- echoOnce (ln .Addr ().String (), fmt .Sprintf ("msg-%d" , i )) }()
12301234 }
1235+ var echoErrs []error
12311236 for range numConns {
1232- require .NoError (t , <- errCh )
1237+ echoErrs = append (echoErrs , <- errCh )
1238+ }
1239+ select {
1240+ case err := <- gateErrs :
1241+ t .Fatalf ("gate failed: %v" , err )
1242+ default :
12331243 }
1244+ for _ , err := range echoErrs {
1245+ require .NoError (t , err )
1246+ }
1247+ }
1248+
1249+ // requireEOF requires that the next read on conn reports io.EOF.
1250+ func requireEOF (t * testing.T , conn net.Conn , timeout time.Duration ) {
1251+ t .Helper ()
1252+ require .NoError (t , conn .SetReadDeadline (time .Now ().Add (timeout )))
1253+ _ , err := conn .Read (make ([]byte , 1 ))
1254+ require .ErrorIs (t , err , io .EOF )
12341255}
12351256
12361257func TestTCPListen_HungSetupDoesNotBlockOthers (t * testing.T ) {
@@ -1264,4 +1285,22 @@ func TestTCPListen_HungSetupDoesNotBlockOthers(t *testing.T) {
12641285 case <- time .After (5 * time .Second ):
12651286 t .Fatal ("Close did not return while a tunnel setup was hung" )
12661287 }
1288+ requireEOF (t , hung , time .Second )
1289+ }
1290+
1291+ func TestTCPListen_FailedSetupClosesConn (t * testing.T ) {
1292+ resolver := & flippableResolver {
1293+ failErr : & StatusError {Code : ErrorUnavailable , Message : "sandbox unreachable" },
1294+ }
1295+ client , cleanup := setupTCPTestWithResolver (t , newMockTCPServer (), resolver )
1296+ defer cleanup ()
1297+
1298+ ln , err := client .Listen (context .Background (), "default" , "my-sandbox" , 8080 , 0 )
1299+ require .NoError (t , err )
1300+ defer func () { _ = ln .Close () }()
1301+
1302+ c , err := net .Dial ("tcp" , ln .Addr ().String ())
1303+ require .NoError (t , err )
1304+ defer func () { _ = c .Close () }()
1305+ requireEOF (t , c , 2 * time .Second )
12671306}
0 commit comments