diff --git a/helpers/waiter.go b/helpers/waiter.go index 8ee6fa73..59d066f4 100644 --- a/helpers/waiter.go +++ b/helpers/waiter.go @@ -47,6 +47,13 @@ func (w *Waiter) Waitf(t ct.TestLike, timeout time.Duration, errFormat string, a } } +// Done returns a channel which is closed when Finish is called. It can be used +// in `select` statements where failing the test on a timeout (as Wait does) is +// not appropriate. Prefer `Wait`/`Waitf` otherwise. +func (w *Waiter) Done() <-chan bool { + return w.ch +} + // Finish will cause all goroutines waiting via Wait to stop waiting and return. // Once this function has been called, subsequent calls to Wait will return immediately. // To begin waiting again, make a new Waiter. diff --git a/tests/msc3902/federation_room_join_partial_state_test.go b/tests/msc3902/federation_room_join_partial_state_test.go index 3313aa4e..6cd7e6fd 100644 --- a/tests/msc3902/federation_room_join_partial_state_test.go +++ b/tests/msc3902/federation_room_join_partial_state_test.go @@ -302,7 +302,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) t.Log("2. Have Alice lazy-sync until she sees (1).") lazySyncToken = alice.MustSyncUntil( @@ -407,7 +406,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) t.Log("Alice eager-syncs. The response should not contain the remote room.") response, nextBatch := alice.MustSync(t, client.SyncReq{}) @@ -470,8 +468,7 @@ func TestPartialStateJoin(t *testing.T) { cancel := server.Listen() defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) alice.MustSyncUntil(t, client.SyncReq{ @@ -492,8 +489,7 @@ func TestPartialStateJoin(t *testing.T) { cancel := server.Listen() defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) pdusChannel := make(chan gomatrixserverlib.PDU) removePDUHandler := server.AddPDUHandler( @@ -536,7 +532,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // Derek starts typing in the room. derekUserId := psjResult.Server.UserID("derek") @@ -606,7 +601,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) derekUserId := psjResult.Server.UserID("derek") @@ -653,7 +647,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // Send a to-device message from Derek to Alice. derekUserId := psjResult.Server.UserID("derek") @@ -703,7 +696,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) derekUserId := psjResult.Server.UserID("derek") @@ -756,7 +748,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) derekUserId := psjResult.Server.UserID("derek") @@ -806,7 +797,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) derekUserId := psjResult.Server.UserID("derek") @@ -835,7 +825,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // the HS will make an /event_auth request for the event federation.HandleEventAuthRequests()(server.Server) @@ -859,7 +848,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // we construct the following event graph: // ... <-- M <-- A <-- B @@ -899,7 +887,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // we construct the following event graph: // +---------+ @@ -942,7 +929,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // we construct the following event graph: // +---------+ @@ -988,7 +974,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // the HS will make an /event_auth request for the event federation.HandleEventAuthRequests()(server.Server) @@ -1030,7 +1015,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) syncToken = alice.MustSyncUntil(t, client.SyncReq{ @@ -1102,7 +1086,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) syncToken = alice.MustSyncUntil(t, client.SyncReq{ @@ -1151,7 +1134,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // we need a sync token to pass to the `at` param. syncToken := alice.MustSyncUntil(t, @@ -1213,7 +1195,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // Alice has now joined the room, and the server is syncing the state in the background. @@ -1284,7 +1265,29 @@ func TestPartialStateJoin(t *testing.T) { queryParams := req.URL.Query() t.Logf("Incoming state_ids request for event %s in room %s", queryParams["event_id"], roomID) fedStateIdsRequestReceivedWaiter.Finish() - fedStateIdsSendResponseWaiter.Wait(t, 60*time.Second) + + // Wait for `fedStateIdsSendResponseWaiter` + select { + case <-fedStateIdsSendResponseWaiter.Done(): + // Happy-path now that we're done waiting, continue serving the request now + case <-req.Context().Done(): + // The request was cancelled (the Complement server is probably shutting down) + // which means nobody wants this response any more (just bail out without + // doing any more work). + // + // Also as a note: although the cancellation itself happens while the test is + // still running, `srv.Close()` cancels any if-flight requests but does not + // wait for this goroutine, so by the time we wake up here the test may have + // already completed and touching `t` after that panics. + return + case <-time.After(60 * time.Second): + // Sanity check so a wedged test fails loudly instead of blocking forever. + t.Fatalf( + "Timed out waiting for the test to finish the `sendResponseWaiter` while trying"+ + "to serve /state_ids response for event %s", queryParams["event_id"], + ) + } + t.Logf("Replying to /state_ids request with invalid response") w.WriteHeader(200) @@ -1340,7 +1343,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // get a sync token before state syncing finishes. syncToken := alice.MustSyncUntil(t, @@ -1437,7 +1439,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // Alice has now joined the room, and the server is syncing the state in the background. @@ -1551,7 +1552,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // the HS will make an /event_auth request for the event federation.HandleEventAuthRequests()(server.Server) @@ -1646,7 +1646,6 @@ func TestPartialStateJoin(t *testing.T) { serverRoom.AddEvent(derekLeaveEvent) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // derek now sends a state event with auth_events that say he was in the room. It will be // accepted during the faster join, but should then ultimately be rejected. @@ -1731,7 +1730,6 @@ func TestPartialStateJoin(t *testing.T) { serverRoom.AddEvent(elsieJoinEvent) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // Derek now kicks Elsie, with auth_events that say he was in the room. It will be // accepted during the faster join, but should then ultimately be rejected. @@ -1828,8 +1826,7 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, testServer1, alice.GetDefaultRoomVersion(t)) roomID := serverRoom.RoomID - psjResult := beginPartialStateJoin(t, testServer1, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, testServer1, serverRoom, alice) // The partial join is now in progress. // Let's have a new test server rock up and ask to join the room by making a @@ -1878,8 +1875,7 @@ func TestPartialStateJoin(t *testing.T) { cancel := testServer1.Listen() defer cancel() serverRoom := createTestRoom(t, testServer1, alice.GetDefaultRoomVersion(t)) - psjResult := beginPartialStateJoin(t, testServer1, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, testServer1, serverRoom, alice) // hs1's partial join is now in progress. // Let's have a test server rock up and ask to /send_join in the room via hs1. @@ -1939,7 +1935,6 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) // Alice has now joined the room, and the server is syncing the state in the background. @@ -2006,8 +2001,7 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, testServer1, alice.GetDefaultRoomVersion(t)) roomID := serverRoom.RoomID - psjResult := beginPartialStateJoin(t, testServer1, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, testServer1, serverRoom, alice) // The partial join is now in progress. // Let's have a new test server rock up and ask to join the room by making a @@ -2056,8 +2050,7 @@ func TestPartialStateJoin(t *testing.T) { cancel := testServer1.Listen() defer cancel() serverRoom := createTestRoom(t, testServer1, alice.GetDefaultRoomVersion(t)) - psjResult := beginPartialStateJoin(t, testServer1, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, testServer1, serverRoom, alice) // hs1's partial join is now in progress. // Let's have a test server rock up and ask to /send_knock in the room via hs1. @@ -2265,7 +2258,6 @@ func TestPartialStateJoin(t *testing.T) { // The room starts with @charlie:server1 and @derek:server1 in it. // @t24alice:hs1 joins the room. psjResult := beginPartialStateJoin(t, server1, room, alice) - defer psjResult.Destroy(t) // Only server1 should receive device list updates. renameDevice(t, alice, "A new device name 1") @@ -2324,7 +2316,6 @@ func TestPartialStateJoin(t *testing.T) { // @t25alice:hs1 joins the room. psjResult := beginPartialStateJoin(t, server1, room, alice) - defer psjResult.Destroy(t) // @elsie:server2 leaves the room. // Create and send the event to the homeserver using server1, since the test setup did @@ -2531,7 +2522,6 @@ func TestPartialStateJoin(t *testing.T) { // @t27alice:hs1 joins the room, followed by @elsie:server2. // @elsie:server2 is kicked with an invalid event. syncToken, _, psjResult := setupIncorrectlyAcceptedKick(t, deployment, alice, server1, server2, deviceListUpdateChannel1, deviceListUpdateChannel2, room) - defer psjResult.Destroy(t) // @t27alice:hs1 sends out a device list update which is missed by @elsie:server2. // @elsie:server2 joins another room shared with @t27alice:hs1 and leaves the partial state room. @@ -2600,7 +2590,6 @@ func TestPartialStateJoin(t *testing.T) { federation.WithPartialState(), ) psjResult := beginPartialStateJoin(t, server1, room, alice) - defer psjResult.Destroy(t) // @t29alice:hs1 sends out a device list update which is missed by @elsie:server2. // @elsie:server2 joins another room shared with @t29alice:hs1 and leaves the partial state room. @@ -2896,7 +2885,6 @@ func TestPartialStateJoin(t *testing.T) { // @t30alice:hs1 joins the room. psjResult := beginPartialStateJoin(t, server, room, alice) - defer psjResult.Destroy(t) // @charlie and @derek's device list ought to not be cached. mustQueryKeysWithFederationRequest(t, alice, userDevicesChannel, server.UserID("charlie")) @@ -2946,7 +2934,6 @@ func TestPartialStateJoin(t *testing.T) { // @t31alice:hs1 joins the room. psjResult := beginPartialStateJoin(t, server, room, alice) - defer psjResult.Destroy(t) // @charlie sends a message. // Depending on the homeserver implementation, @t31alice:hs1 may be told that @charlie's devices are being tracked. @@ -2989,7 +2976,6 @@ func TestPartialStateJoin(t *testing.T) { // @t32alice:hs1 joins the room. psjResult := beginPartialStateJoin(t, server, room, alice) - defer psjResult.Destroy(t) syncToken := getSyncToken(t, alice) @@ -3037,8 +3023,7 @@ func TestPartialStateJoin(t *testing.T) { // The room starts with @charlie and @derek in it. // @t33alice:hs1 joins the room. - psjResult := beginPartialStateJoin(t, server, room, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, room, alice) syncToken := getSyncToken(t, alice) @@ -3082,8 +3067,7 @@ func TestPartialStateJoin(t *testing.T) { // The room starts with @charlie and @derek in it. // @t34alice:hs1 joins the room. - psjResult := beginPartialStateJoin(t, server, room, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, room, alice) syncToken := getSyncToken(t, alice) @@ -3125,7 +3109,6 @@ func TestPartialStateJoin(t *testing.T) { // @t35alice:hs1 joins the room. psjResult := beginPartialStateJoin(t, server, room, alice) - defer psjResult.Destroy(t) syncToken := getSyncToken(t, alice) @@ -3263,7 +3246,6 @@ func TestPartialStateJoin(t *testing.T) { // @charlie "kicks" @derek, which the homeserver under test incorrectly accepts. // @derek kicks @elsie, which the homeserver under test incorrectly rejects. _, psjResult := setupUserIncorrectlyInRoom(t, deployment, alice, server, room) - defer psjResult.Destroy(t) // @elsie is now incorrectly believed to be in the room. // The homeserver under test incorrectly thinks it is subscribed to @elsie's device list updates. @@ -3297,7 +3279,6 @@ func TestPartialStateJoin(t *testing.T) { // @charlie "kicks" @derek, which the homeserver under test incorrectly accepts. // @derek kicks @elsie, which the homeserver under test incorrectly rejects. syncToken, psjResult := setupUserIncorrectlyInRoom(t, deployment, alice, server, room) - defer psjResult.Destroy(t) // @elsie is now incorrectly believed to be in the room. // The homeserver under test incorrectly thinks it is subscribed to @elsie's device list updates. @@ -3339,7 +3320,6 @@ func TestPartialStateJoin(t *testing.T) { // @charlie "kicks" @derek, which the homeserver under test incorrectly accepts. // @derek kicks @elsie, which the homeserver under test incorrectly rejects. syncToken, psjResult := setupUserIncorrectlyInRoom(t, deployment, alice, server, room) - defer psjResult.Destroy(t) // @elsie is now incorrectly believed to be in the room. // The homeserver under test incorrectly thinks it is subscribed to @elsie's device list updates. @@ -3379,7 +3359,6 @@ func TestPartialStateJoin(t *testing.T) { // @charlie "kicks" @derek, which the homeserver under test incorrectly accepts. // @derek kicks @elsie, which the homeserver under test incorrectly rejects. syncToken, psjResult := setupUserIncorrectlyInRoom(t, deployment, alice, server, room) - defer psjResult.Destroy(t) // @elsie is now incorrectly believed to be in the room. // The homeserver under test incorrectly thinks it is subscribed to @elsie's device list updates. @@ -3429,8 +3408,7 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) // Alice creates an alias for the room aliasName := "#t40alice-room:hs1" @@ -3482,8 +3460,7 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) // Alice creates an alias for the room aliasName := "#t41alice-room:hs1" @@ -3525,8 +3502,7 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) server.AddPDUHandler(func(e gomatrixserverlib.PDU) bool { return true }) bob.MustJoinRoom(t, serverRoom.RoomID, []spec.ServerName{server.ServerName()}) @@ -3559,8 +3535,7 @@ func TestPartialStateJoin(t *testing.T) { defer cancel() serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) pdusChannel := make(chan gomatrixserverlib.PDU) removePDUHandler := server.AddPDUHandler( @@ -3604,7 +3579,6 @@ func TestPartialStateJoin(t *testing.T) { serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) t.Log("Alice partial-joins her room") psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) t.Log("Alice waits to see her join") aliceNextBatch := alice.MustSyncUntil( @@ -3646,8 +3620,7 @@ func TestPartialStateJoin(t *testing.T) { serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) t.Log("Alice begins a partial join to a room") - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) t.Log("Alice waits to see her join") aliceNextBatch := alice.MustSyncUntil( @@ -3709,11 +3682,7 @@ func TestPartialStateJoin(t *testing.T) { serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) t.Log("Alice partial-joins her room") - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - // At the end of the test, keep Bob in the room. Have him make a /members - // call to ensure the resync has completed. - psjResult.User = bob - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) t.Log("Alice sees her join") aliceNextBatch := alice.MustSyncUntil( @@ -3761,8 +3730,7 @@ func TestPartialStateJoin(t *testing.T) { serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) t.Log("Alice partial-joins her room") - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) t.Log("Alice waits to see her join") aliceNextBatch := alice.MustSyncUntil( @@ -3806,11 +3774,7 @@ func TestPartialStateJoin(t *testing.T) { serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) t.Log("Alice partial-joins her room") - psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - // At the end of the test, keep Bob in the room. Have him make a /members - // call to ensure the resync has completed. - psjResult.User = bob - defer psjResult.Destroy(t) + beginPartialStateJoin(t, server, serverRoom, alice) t.Log("Alice waits to see her join") aliceNextBatch := alice.MustSyncUntil( @@ -3852,8 +3816,6 @@ func TestPartialStateJoin(t *testing.T) { serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) t.Log("Alice partial-joins her room") psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - // Alice is not joined to the room at the end of the test, so we do not - // `defer psjResult.Destroy(t)`. t.Log("Alice waits to see her join") aliceNextBatch := alice.MustSyncUntil( @@ -3906,8 +3868,6 @@ func TestPartialStateJoin(t *testing.T) { serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) t.Log("Alice partial-joins her room") psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - // Alice is not joined to the room at the end of the test, so we do not - // `defer psjResult.Destroy(t)`. t.Log("Alice waits to see her join") aliceNextBatch := alice.MustSyncUntil( @@ -3971,7 +3931,6 @@ func TestPartialStateJoin(t *testing.T) { // start a partial state join psjResult := beginPartialStateJoin(t, server, serverRoom, terry) - defer psjResult.Destroy(t) // make the remote room visible in the local room list reqBody := client.WithJSONBody(t, map[string]interface{}{ @@ -4024,7 +3983,6 @@ func TestPartialStateJoin(t *testing.T) { // start a partial state join psjResult := beginPartialStateJoin(t, server, serverRoom, rocky) - defer psjResult.Destroy(t) assertUserInDirectory := func(t *testing.T, localpart string, userID string) { reqBody := client.WithJSONBody(t, map[string]interface{}{ @@ -4087,9 +4045,6 @@ func TestPartialStateJoin(t *testing.T) { serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t)) psjResult := beginPartialStateJoin(t, server, serverRoom, alice) - // NB: because we do not end up joined to this room at the end of the test, - // we do not `defer psjResult.Destroy(t)` as usual; see the comments below - // about races. t.Log("Alice waits to see her join") alice.MustSyncUntil( @@ -4315,14 +4270,13 @@ func buildLazyLoadingSyncFilter(timelineOptions map[string]interface{}) string { type partialStateJoinResult struct { Server *server ServerRoom *federation.ServerRoom - User *client.CSAPI fedStateIdsRequestReceivedWaiter *helpers.Waiter fedStateIdsSendResponseWaiter *helpers.Waiter } // beginPartialStateJoin has a test user attempt to join the given room. // -// It returns a partialStateJoinResult, which must be Destroy'd on completion. +// It returns a partialStateJoinResult. // // When this method completes, the /join request will have completed, but the // state has not yet been re-synced. To allow the re-sync to proceed, call @@ -4332,14 +4286,7 @@ func beginPartialStateJoin(t *testing.T, server *server, serverRoom *federation. result := partialStateJoinResult{ Server: server, ServerRoom: serverRoom, - User: joiningUser, } - success := false - defer func() { - if !success { - result.Destroy(t) - } - }() // some things for orchestration result.fedStateIdsRequestReceivedWaiter = helpers.NewWaiter() @@ -4367,22 +4314,9 @@ func beginPartialStateJoin(t *testing.T, server *server, serverRoom *federation. joiningUser.MustJoinRoom(t, serverRoom.RoomID, []spec.ServerName{server.ServerName()}) t.Logf("/join request completed") - success = true return result } -// Destroy cleans up the resources associated with the join attempt. -// It is idempotent and must be called once the test is finished. -func (psj *partialStateJoinResult) Destroy(t *testing.T) { - if psj.fedStateIdsSendResponseWaiter != nil { - psj.fedStateIdsSendResponseWaiter.Finish() - } - - if psj.fedStateIdsRequestReceivedWaiter != nil { - psj.fedStateIdsRequestReceivedWaiter.Finish() - } -} - // send a message into the room without letting the homeserver under test know about it. func (psj *partialStateJoinResult) CreateMessageEvent(t *testing.T, senderLocalpart string, prevEventIDs []string) gomatrixserverlib.PDU { var prevEvents interface{} @@ -4436,7 +4370,26 @@ func handleStateIdsRequests( requestReceivedWaiter.Finish() } if sendResponseWaiter != nil { - sendResponseWaiter.Waitf(t, 60*time.Second, "Waiting for /state_ids request") + select { + case <-sendResponseWaiter.Done(): + // Happy-path now that we're done waiting, continue serving the request now + case <-req.Context().Done(): + // The request was cancelled (the Complement server is probably shutting down) + // which means nobody wants this response any more (just bail out without + // doing any more work). + // + // Also as a note: although the cancellation itself happens while the test is + // still running, `srv.Close()` cancels any if-flight requests but does not + // wait for this goroutine, so by the time we wake up here the test may have + // already completed and touching `t` after that panics. + return + case <-time.After(60 * time.Second): + // Sanity check so a wedged test fails loudly instead of blocking forever. + t.Fatalf( + "Timed out waiting for the test to finish the `sendResponseWaiter` while trying"+ + "to serve /state_ids response for event %s", queryParams["event_id"], + ) + } } t.Logf("Replying to /state_ids request for event %s", queryParams["event_id"]) @@ -4476,7 +4429,27 @@ func handleStateRequests( requestReceivedWaiter.Finish() } if sendResponseWaiter != nil { - sendResponseWaiter.Waitf(t, 60*time.Second, "Waiting for /state request") + + select { + case <-sendResponseWaiter.Done(): + // Happy-path now that we're done waiting, continue serving the request now + case <-req.Context().Done(): + // The request was cancelled (the Complement server is probably shutting down) + // which means nobody wants this response any more (just bail out without + // doing any more work). + // + // Also as a note: although the cancellation itself happens while the test is + // still running, `srv.Close()` cancels any if-flight requests but does not + // wait for this goroutine, so by the time we wake up here the test may have + // already completed and touching `t` after that panics. + return + case <-time.After(60 * time.Second): + // Sanity check so a wedged test fails loudly instead of blocking forever. + t.Fatalf( + "Timed out waiting for the test to finish the `sendResponseWaiter` while trying"+ + "to serve /state response for event %s", queryParams["event_id"], + ) + } } t.Logf("Replying to /state request for event %s", queryParams["event_id"])