Skip to content

Commit 3ca79f0

Browse files
committed
test(sdk/go): cover EOF on abandoned setup
Signed-off-by: Eric Curtin <[email protected]>
1 parent 001749e commit 3ca79f0

1 file changed

Lines changed: 41 additions & 2 deletions

File tree

‎sdk/go/openshell/v1/tcp_client_test.go‎

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

12361257
func 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

Comments
 (0)