From bcb6d9f9f15d648dfd8cfed73e7fd82f82ff3a06 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 29 Mar 2022 19:58:12 -0500 Subject: [PATCH 1/3] Add test for non-member state events in /batch_send state_events_at_start Tests for https://github.com/matrix-org/synapse/issues/12110 --- tests/msc2716_test.go | 67 +++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/tests/msc2716_test.go b/tests/msc2716_test.go index 010dd8a5..f89ad108 100644 --- a/tests/msc2716_test.go +++ b/tests/msc2716_test.go @@ -305,6 +305,47 @@ func TestImportHistoricalMessages(t *testing.T) { } }) + t.Run("Non-member state events are allowed in state_events_at_start", func(t *testing.T) { + t.Parallel() + + roomID := as.CreateRoom(t, createPublicRoomOpts) + alice.JoinRoom(t, roomID, nil) + + // Create the "live" event we are going to insert our historical events next to + eventIDsBefore := createMessagesInRoom(t, alice, roomID, 1, "eventIDsBefore") + eventIdBefore := eventIDsBefore[0] + timeAfterEventBefore := time.Now() + + state_events_at_start := createJoinStateEventsForBatchSendRequest([]string{virtualUserID}, timeAfterEventBefore) + // Add the non-member state + state_events_at_start = append(state_events_at_start, map[string]interface{}{ + "type": "org.matrix.msc2716.foobarbaz", + "sender": as.UserID, + "origin_server_ts": uint64(timeAfterEventBefore.UnixNano() / int64(time.Millisecond)), + "content": map[string]interface{}{ + "foo": "bar", + }, + "state_key": "", + }) + + batchSendRes := batchSendHistoricalMessages( + t, + as, + roomID, + eventIdBefore, + "", + state_events_at_start, + createMessageEventsForBatchSendRequest([]string{virtualUserID}, timeAfterEventBefore, 1), + // Status + 200, + ) + validateBatchSendRes( + t, as, roomID, batchSendRes, + // Validate that the non-member state resolves + true, + ) + }) + t.Run("Unrecognised prev_event ID will throw an error", func(t *testing.T) { t.Parallel() @@ -1342,36 +1383,12 @@ func validateBatchSendRes(t *testing.T, c *client.CSAPI, roomID string, batchSen expectedEventIDOrder = append(expectedEventIDOrder, insertionEventID) if validateState { - // Get a pagination token for the newest-in-time event in the historical batch itself contextRes := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "context", expectedEventIDOrder[0]}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "limit": []string{"0"}, })) - contextResBody := client.ParseJSON(t, contextRes) - batchStartPaginationToken := client.GetJSONFieldStr(t, contextResBody, "end") - - // Fetch a chunk of `/messages` which only contains the historical batch. We - // want to do this because `/messages` only returns the state for the first - // message in the `chunk` and we want to be able assert that the historical - // state is able to be resolved. - messagesRes := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ - // Go backwards (newest -> oldest) (same direction as if you were using scrollback) - "dir": []string{"b"}, - // From the newest-in-time event in the historical batch - "from": []string{batchStartPaginationToken}, - // We are aiming to scrollback to the oldest-in-time event from the - // historical batch - "limit": []string{fmt.Sprintf("%d", len(expectedEventIDOrder))}, - // We add these options to the filter so we get member events in the state field - "filter": []string{"{\"lazy_load_members\":true,\"include_redundant_members\":true}"}, - })) - must.MatchResponse(t, messagesRes, match.HTTPResponse{ + must.MatchResponse(t, contextRes, match.HTTPResponse{ JSON: []match.JSON{ - // Double-check that we're in the right place of scrollback - matcherJSONEventIDArrayInOrder("chunk", - expectedEventIDOrder, - historicalEventFilter, - ), // Make sure the historical m.room.member join state event resolves // for the given chunk of messages in scrollback. The member event // will include the displayname and avatar. From aa984e7448e895c2e847bd5de92663801c02fcfa Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Fri, 1 Apr 2022 17:58:29 -0500 Subject: [PATCH 2/3] Use camelCase --- tests/msc2716_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/msc2716_test.go b/tests/msc2716_test.go index f89ad108..15d40946 100644 --- a/tests/msc2716_test.go +++ b/tests/msc2716_test.go @@ -316,9 +316,9 @@ func TestImportHistoricalMessages(t *testing.T) { eventIdBefore := eventIDsBefore[0] timeAfterEventBefore := time.Now() - state_events_at_start := createJoinStateEventsForBatchSendRequest([]string{virtualUserID}, timeAfterEventBefore) + stateEventsAtStart := createJoinStateEventsForBatchSendRequest([]string{virtualUserID}, timeAfterEventBefore) // Add the non-member state - state_events_at_start = append(state_events_at_start, map[string]interface{}{ + stateEventsAtStart = append(stateEventsAtStart, map[string]interface{}{ "type": "org.matrix.msc2716.foobarbaz", "sender": as.UserID, "origin_server_ts": uint64(timeAfterEventBefore.UnixNano() / int64(time.Millisecond)), @@ -334,7 +334,7 @@ func TestImportHistoricalMessages(t *testing.T) { roomID, eventIdBefore, "", - state_events_at_start, + stateEventsAtStart, createMessageEventsForBatchSendRequest([]string{virtualUserID}, timeAfterEventBefore, 1), // Status 200, From c1bf9cd9728b6596bf1928b2d483837a4e9caf8d Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Fri, 1 Apr 2022 18:02:21 -0500 Subject: [PATCH 3/3] Validate state (call /context) after we call /messages to backfill any potential gap See https://github.com/matrix-org/complement/pull/354#discussion_r840403997 --- tests/msc2716_test.go | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/tests/msc2716_test.go b/tests/msc2716_test.go index 15d40946..7ce5b7fb 100644 --- a/tests/msc2716_test.go +++ b/tests/msc2716_test.go @@ -1382,6 +1382,23 @@ func validateBatchSendRes(t *testing.T, c *client.CSAPI, roomID string, batchSen expectedEventIDOrder = append(expectedEventIDOrder, reversed(historicalEventIDs)...) expectedEventIDOrder = append(expectedEventIDOrder, insertionEventID) + // Make sure the historical events appear in scrollback without jumping back + // in time specifically. + fullMessagesRes := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + "dir": []string{"b"}, + "limit": []string{"100"}, + })) + must.MatchResponse(t, fullMessagesRes, match.HTTPResponse{ + JSON: []match.JSON{ + matcherJSONEventIDArrayInOrder("chunk", + expectedEventIDOrder, + historicalEventFilter, + ), + }, + }) + + // Validate state after we paginate `/messages` to avoid any potential 404 if + // the server hasn't backfilled here yet if validateState { contextRes := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "context", expectedEventIDOrder[0]}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "limit": []string{"0"}, @@ -1398,21 +1415,6 @@ func validateBatchSendRes(t *testing.T, c *client.CSAPI, roomID string, batchSen }, }) } - - // Make sure the historical events appear in scrollback without jumping back - // in time specifically. - fullMessagesRes := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ - "dir": []string{"b"}, - "limit": []string{"100"}, - })) - must.MatchResponse(t, fullMessagesRes, match.HTTPResponse{ - JSON: []match.JSON{ - matcherJSONEventIDArrayInOrder("chunk", - expectedEventIDOrder, - historicalEventFilter, - ), - }, - }) } // matcherJSONEventIDArrayInOrder loops through `jsonArrayKey` in the response