sliding-sync/tests-e2e/gappy_state_test.go

139 lines
4.0 KiB
Go
Raw Permalink Normal View History

2023-04-13 18:47:15 +01:00
package syncv3_test
import (
"encoding/json"
2023-04-14 20:22:51 +01:00
"fmt"
2023-10-11 12:23:46 +01:00
"testing"
"github.com/matrix-org/complement/b"
2023-04-13 18:47:15 +01:00
"github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m"
)
2023-04-18 18:33:29 +01:00
// Test that state changes "missed" by a poller are injected back into the room when a
// future poller recieves a v2 incremental sync with a state block.
2023-04-13 18:47:15 +01:00
func TestGappyState(t *testing.T) {
t.Log("Alice registers on the homeserver.")
alice := registerNewUser(t)
t.Log("Alice creates a room")
2023-04-17 12:31:21 +01:00
firstRoomName := "Romeo Oscar Oscar Mike"
2023-10-11 12:23:46 +01:00
roomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": firstRoomName})
2023-04-13 18:47:15 +01:00
t.Log("Alice sends a message into that room")
2023-10-11 12:23:46 +01:00
firstMessageID := alice.SendEventSynced(t, roomID, b.Event{
2023-04-13 18:47:15 +01:00
Type: "m.room.message",
Content: map[string]interface{}{
"msgtype": "m.text",
"body": "Hello, world!",
},
})
2023-04-17 12:31:21 +01:00
t.Log("Alice requests an initial sliding sync on device 1.")
syncResp := alice.SlidingSync(t,
sync3.Request{
Lists: map[string]sync3.RequestList{
"a": {
Ranges: [][2]int64{{0, 20}},
2023-04-18 18:33:29 +01:00
RoomSubscription: sync3.RoomSubscription{
TimelineLimit: 10,
},
2023-04-17 12:31:21 +01:00
},
},
},
)
m.MatchResponse(
t,
syncResp,
2023-04-18 18:33:29 +01:00
m.MatchRoomSubscription(
roomID,
m.MatchRoomName(firstRoomName),
2023-04-19 13:05:01 +01:00
MatchRoomTimelineMostRecent(1, []Event{{ID: firstMessageID}}),
2023-04-18 18:33:29 +01:00
),
2023-04-17 12:31:21 +01:00
)
2023-04-13 18:47:15 +01:00
t.Log("Alice logs out of her first device.")
2023-10-11 12:23:46 +01:00
alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "logout"})
2023-04-13 18:47:15 +01:00
t.Log("Alice logs in again on her second device.")
alice.Login(t, "password", "device2")
2023-04-14 20:22:51 +01:00
t.Log("Alice changes the room name while the proxy isn't polling.")
2023-04-13 18:47:15 +01:00
nameContent := map[string]interface{}{"name": "potato"}
2023-10-11 12:23:46 +01:00
alice.Unsafe_SendEventUnsynced(t, roomID, b.Event{
Type: "m.room.name",
StateKey: ptr(""),
Content: nameContent,
})
2023-04-13 18:47:15 +01:00
t.Log("Alice sends lots of other state events.")
const numOtherState = 40
for i := 0; i < numOtherState; i++ {
alice.Unsafe_SendEventUnsynced(t, roomID, b.Event{
Type: "com.example.dummy",
StateKey: ptr(fmt.Sprintf("%d", i)),
Content: map[string]any{},
})
}
t.Log("Alice sends a batch of message events.")
const numMessages = 20
var lastMsgID string
for i := 0; i < numMessages; i++ {
lastMsgID = alice.Unsafe_SendEventUnsynced(t, roomID, b.Event{
2023-04-14 20:22:51 +01:00
Type: "m.room.message",
Content: map[string]interface{}{
"msgtype": "m.text",
"body": fmt.Sprintf("Message number %d", i),
},
})
}
2023-04-13 18:47:15 +01:00
t.Logf("The proxy is now %d events behind the HS, which should trigger a limited sync", 1+numOtherState+numMessages)
t.Log("Alice requests an initial sliding sync on device 2, with timeline limit big enough to see her first message at the start of the test.")
2023-04-17 12:31:21 +01:00
syncResp = alice.SlidingSync(t,
2023-04-13 18:47:15 +01:00
sync3.Request{
Lists: map[string]sync3.RequestList{
"a": {
Ranges: [][2]int64{{0, 20}},
2023-04-18 18:33:29 +01:00
RoomSubscription: sync3.RoomSubscription{
TimelineLimit: 100,
2023-04-18 18:33:29 +01:00
},
2023-04-13 18:47:15 +01:00
},
},
},
)
// We're testing here that the state events from the gappy poll are NOT injected
// into the timeline. The poll is only going to use timeline limit 1 because it's
// the first poll on a new device. See integration test for a "proper" gappy poll.
t.Log("She should see the updated room name, her most recent message, but NOT the state events in the gap nor messages from before the gap.")
2023-04-14 20:22:51 +01:00
m.MatchResponse(
t,
syncResp,
m.MatchRoomSubscription(
roomID,
m.MatchRoomName("potato"),
MatchRoomTimelineMostRecent(1, []Event{{ID: lastMsgID}}),
func(r sync3.Room) error {
for _, rawEv := range r.Timeline {
var ev Event
err := json.Unmarshal(rawEv, &ev)
if err != nil {
t.Fatal(err)
}
// Shouldn't see the state events, only messages
if ev.Type != "m.room.message" {
return fmt.Errorf("timeline contained event %s of type %s (expected m.room.message)", ev.ID, ev.Type)
}
if ev.ID == firstMessageID {
return fmt.Errorf("timeline contained first message from before the gap")
}
}
return nil
},
2023-04-14 20:22:51 +01:00
),
)
2023-04-13 18:47:15 +01:00
}