@@ -918,6 +918,95 @@ func TestImportHistoricalMessages(t *testing.T) {
918918 },
919919 })
920920 })
921+
922+ t .Run ("Historical messages show up for remote federated homeserver even the homeserver is missing the part of the timeline where the marker was sent and it paginates before it occured" , func (t * testing.T ) {
923+ t .Parallel ()
924+
925+ roomID := as .CreateRoom (t , createPublicRoomOpts )
926+ alice .JoinRoom (t , roomID , nil )
927+
928+ eventIDsBefore := createMessagesInRoom (t , alice , roomID , 1 , "eventIDsBefore" )
929+ eventIdBefore := eventIDsBefore [0 ]
930+ timeAfterEventBefore := time .Now ()
931+
932+ eventIDsAfter := createMessagesInRoom (t , alice , roomID , 3 , "eventIDsAfter" )
933+ eventIDAfter := eventIDsAfter [0 ]
934+
935+ // Join the room from a remote homeserver before the historical messages were sent
936+ remoteCharlie .JoinRoom (t , roomID , []string {"hs1" })
937+
938+ // Make sure all of the events have been backfilled for the remote user
939+ // before we leave the room
940+ fetchUntilMessagesResponseHas (t , remoteCharlie , roomID , func (ev gjson.Result ) bool {
941+ if ev .Get ("event_id" ).Str == eventIdBefore {
942+ return true
943+ }
944+
945+ return false
946+ })
947+
948+ // Leave before the historical messages are imported
949+ remoteCharlie .LeaveRoom (t , roomID )
950+
951+ batchSendRes := batchSendHistoricalMessages (
952+ t ,
953+ as ,
954+ roomID ,
955+ eventIdBefore ,
956+ "" ,
957+ createJoinStateEventsForBatchSendRequest ([]string {virtualUserID }, timeAfterEventBefore ),
958+ createMessageEventsForBatchSendRequest ([]string {virtualUserID }, timeAfterEventBefore , 2 ),
959+ // Status
960+ 200 ,
961+ )
962+ batchSendResBody := client .ParseJSON (t , batchSendRes )
963+ historicalEventIDs := client .GetJSONFieldStringArray (t , batchSendResBody , "event_ids" )
964+ baseInsertionEventID := client .GetJSONFieldStr (t , batchSendResBody , "base_insertion_event_id" )
965+
966+ // Send the marker event which lets remote homeservers know there are
967+ // some historical messages back at the given insertion event.
968+ sendMarkerAndEnsureBackfilled (t , as , alice , roomID , baseInsertionEventID )
969+
970+ // Add some events after the marker so that remoteCharlie doesn't see the marker
971+ createMessagesInRoom (t , alice , roomID , 3 , "eventIDFiller" )
972+
973+ // Join the room from a remote homeserver after the historical messages were sent
974+ remoteCharlie .JoinRoom (t , roomID , []string {"hs1" })
975+
976+ // Make a /context request for eventIDAfter to get pagination token before the marker event
977+ contextRes := remoteCharlie .MustDoFunc (t , "GET" , []string {"_matrix" , "client" , "r0" , "rooms" , roomID , "context" , eventIDAfter }, client .WithContentType ("application/json" ), client .WithQueries (url.Values {
978+ "limit" : []string {"0" },
979+ }))
980+ contextResResBody := client .ParseJSON (t , contextRes )
981+ paginationTokenBeforeMarker := client .GetJSONFieldStr (t , contextResResBody , "end" )
982+
983+ // Start /messages request from that pagination token which skips over
984+ // the marker event in the timeline.
985+ //
986+ // FIXME: In the future, we should probably replace the following logic
987+ // with `validateBatchSendRes` to re-use and have some more robust
988+ // assertion logic here. We're currently not using it because the
989+ // message order isn't quite perfect when a remote federated homeserver
990+ // gets backfilled. validateBatchSendRes(t, remoteCharlie, roomID,
991+ // batchSendRes, false)
992+ messagesRes := remoteCharlie .MustDoFunc (t , "GET" , []string {"_matrix" , "client" , "r0" , "rooms" , roomID , "messages" }, client .WithContentType ("application/json" ), client .WithQueries (url.Values {
993+ "dir" : []string {"b" },
994+ "limit" : []string {"100" },
995+ "from" : []string {paginationTokenBeforeMarker },
996+ }))
997+
998+ must .MatchResponse (t , messagesRes , match.HTTPResponse {
999+ JSON : []match.JSON {
1000+ match .JSONCheckOffAllowUnwanted ("chunk" , makeInterfaceSlice (historicalEventIDs ), func (r gjson.Result ) interface {} {
1001+ return r .Get ("event_id" ).Str
1002+ }, nil ),
1003+ },
1004+ })
1005+ })
1006+
1007+ t .Run ("TODO: do multiple marker events as state to see if homeserver can follow the state update chain and get all history" , func (t * testing.T ) {
1008+ t .Skip ("Skipping until I write this test" )
1009+ })
9211010 })
9221011
9231012 t .Run ("Existing room versions" , func (t * testing.T ) {
@@ -1170,8 +1259,7 @@ func sendMarkerAndEnsureBackfilled(t *testing.T, as *client.CSAPI, c *client.CSA
11701259 },
11711260 }
11721261 // We can't use as.SendEventSynced(...) because application services can't use the /sync API
1173- txnId := getTxnID ("sendMarkerAndEnsureBackfilled-txn" )
1174- markerSendRes := as .MustDoFunc (t , "PUT" , []string {"_matrix" , "client" , "r0" , "rooms" , roomID , "send" , markerEvent .Type , txnId }, client .WithJSONBody (t , markerEvent .Content ))
1262+ markerSendRes := as .MustDoFunc (t , "PUT" , []string {"_matrix" , "client" , "r0" , "rooms" , roomID , "state" , markerEvent .Type }, client .WithJSONBody (t , markerEvent .Content ))
11751263 markerSendBody := client .ParseJSON (t , markerSendRes )
11761264 markerEventID = client .GetJSONFieldStr (t , markerSendBody , "event_id" )
11771265
0 commit comments