-
Notifications
You must be signed in to change notification settings - Fork 64
Add MSC4222 /sync state_after test for initial sync lazy-loading room members
#842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
aa81ebc
158656a
8e85ad2
c373332
b3c058e
7a77aa7
c4149a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package tests | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/matrix-org/complement" | ||
| ) | ||
|
|
||
| func TestMain(m *testing.M) { | ||
| complement.TestMain(m, "msc4222") | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| package tests | ||
|
|
||
| import ( | ||
| "maps" | ||
| "slices" | ||
| "testing" | ||
|
|
||
| "github.com/matrix-org/complement" | ||
| "github.com/matrix-org/complement/client" | ||
| "github.com/matrix-org/complement/helpers" | ||
| "github.com/matrix-org/complement/should" | ||
| "github.com/tidwall/gjson" | ||
| ) | ||
|
|
||
| func TestSync(t *testing.T) { | ||
| deployment := complement.Deploy(t, 1) | ||
| defer deployment.Destroy(t) | ||
| alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{LocalpartSuffix: "alice"}) | ||
| bob := deployment.Register(t, "hs1", helpers.RegistrationOpts{LocalpartSuffix: "bob"}) | ||
|
|
||
| t.Run("parallel", func(t *testing.T) { | ||
| // When lazy-loading room members is enabled, for a public room, the `state_after` | ||
| // in an initial sync request should include membership from every `sender` in the | ||
| // `timeline` | ||
| // | ||
| // We're specifically testing the scenario where a new "DM" is created and the other person | ||
| // joins without speaking yet. | ||
| t.Run("Initial sync with lazy-loading room members -> public room `state_after` includes all members from timeline", func(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // Alice creates a room | ||
| roomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"}) | ||
| alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID)) | ||
|
|
||
| // Bob joins the room | ||
| bob.MustJoinRoom(t, roomID, nil) | ||
|
|
||
| // Make double sure that bob is joined to the room | ||
| alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) | ||
|
|
||
| // Ensure `state_after` looks correct | ||
| expectedSendersFromTimeline := []string{ alice.UserID, bob.UserID } | ||
| syncFilter := `{ | ||
| "room": { | ||
| "timeline": { "limit": 20 }, | ||
| "state": { "lazy_load_members": true } | ||
| } | ||
| }` | ||
| testInitialSyncStateAfterIncludesTimelineSenders(t, alice, roomID, expectedSendersFromTimeline, syncFilter) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For public rooms, things appear to work fine in Synapse ✅ : Example {"timeline":{"events":[{"type":"m.room.create","sender":"@user-1-alice:hs1","content":{"room_version":"10","creator":"@user-1-alice:hs1"},"state_key":"","origin_server_ts":1770930300664,"unsigned":{"membership":"leave","age":618},"event_id":"$qp-zP4IHGRfkc0IVa_kN6tX_sBJyV0ffkTF3RaWey4c"},{"type":"m.room.member","sender":"@user-1-alice:hs1","content":{"displayname":"user-1-alice","membership":"join"},"state_key":"@user-1-alice:hs1","origin_server_ts":1770930300805,"unsigned":{"membership":"join","age":477},"event_id":"$59iC8AUKcjIZHIxjq7HglPsxDZBzGcKy1WP5g48FSRI"},{"type":"m.room.power_levels","sender":"@user-1-alice:hs1","content":{"users":{"@user-1-alice:hs1":100},"users_default":0,"events":{"m.room.name":50,"m.room.power_levels":100,"m.room.history_visibility":100,"m.room.canonical_alias":50,"m.room.avatar":50,"m.room.tombstone":100,"m.room.server_acl":100,"m.room.encryption":100},"events_default":0,"state_default":50,"ban":50,"kick":50,"redact":50,"invite":50,"historical":100,"m.call.invite":50},"state_key":"","origin_server_ts":1770930300916,"unsigned":{"membership":"join","age":366},"event_id":"$gbu10XtbHx4qEN0Zwho3k248Sho2n5SWlR29ISc5FKw"},{"type":"m.room.join_rules","sender":"@user-1-alice:hs1","content":{"join_rule":"public"},"state_key":"","origin_server_ts":1770930300921,"unsigned":{"membership":"join","age":361},"event_id":"$dWnerY4XQ-eVhLmGmy9prqMgRwIF5E8n5TOYkAmAT4k"},{"type":"m.room.history_visibility","sender":"@user-1-alice:hs1","content":{"history_visibility":"shared"},"state_key":"","origin_server_ts":1770930300921,"unsigned":{"membership":"join","age":361},"event_id":"$3fe6abisM3FkfrWK9CDRlV32dOzmk2kb9FaG8wEDOjs"},{"type":"m.room.member","sender":"@user-2-bob:hs1","content":{"displayname":"user-2-bob","membership":"join"},"state_key":"@user-2-bob:hs1","origin_server_ts":1770930301142,"unsigned":{"membership":"join","age":140},"event_id":"$Ug1lAQ7BCQANKhBtSfPrRnImxzaZOyFyi6P2qVjtfok"}],"prev_batch":"s7_2_0_1_1_1_1_3_0_1_1_1","limited":false},"org.matrix.msc4222.state_after":{"events":[{"type":"m.room.create","sender":"@user-1-alice:hs1","content":{"room_version":"10","creator":"@user-1-alice:hs1"},"state_key":"","origin_server_ts":1770930300664,"unsigned":{"age":618},"event_id":"$qp-zP4IHGRfkc0IVa_kN6tX_sBJyV0ffkTF3RaWey4c"},{"type":"m.room.history_visibility","sender":"@user-1-alice:hs1","content":{"history_visibility":"shared"},"state_key":"","origin_server_ts":1770930300921,"unsigned":{"age":361},"event_id":"$3fe6abisM3FkfrWK9CDRlV32dOzmk2kb9FaG8wEDOjs"},{"type":"m.room.join_rules","sender":"@user-1-alice:hs1","content":{"join_rule":"public"},"state_key":"","origin_server_ts":1770930300921,"unsigned":{"age":361},"event_id":"$dWnerY4XQ-eVhLmGmy9prqMgRwIF5E8n5TOYkAmAT4k"},{"type":"m.room.member","sender":"@user-1-alice:hs1","content":{"displayname":"user-1-alice","membership":"join"},"state_key":"@user-1-alice:hs1","origin_server_ts":1770930300805,"unsigned":{"age":477},"event_id":"$59iC8AUKcjIZHIxjq7HglPsxDZBzGcKy1WP5g48FSRI"},{"type":"m.room.member","sender":"@user-2-bob:hs1","content":{"displayname":"user-2-bob","membership":"join"},"state_key":"@user-2-bob:hs1","origin_server_ts":1770930301142,"unsigned":{"age":140},"event_id":"$Ug1lAQ7BCQANKhBtSfPrRnImxzaZOyFyi6P2qVjtfok"},{"type":"m.room.power_levels","sender":"@user-1-alice:hs1","content":{"users":{"@user-1-alice:hs1":100},"users_default":0,"events":{"m.room.name":50,"m.room.power_levels":100,"m.room.history_visibility":100,"m.room.canonical_alias":50,"m.room.avatar":50,"m.room.tombstone":100,"m.room.server_acl":100,"m.room.encryption":100},"events_default":0,"state_default":50,"ban":50,"kick":50,"redact":50,"invite":50,"historical":100,"m.call.invite":50},"state_key":"","origin_server_ts":1770930300916,"unsigned":{"age":366},"event_id":"$gbu10XtbHx4qEN0Zwho3k248Sho2n5SWlR29ISc5FKw"}]},"account_data":{"events":[]},"ephemeral":{"events":[]},"unread_notifications":{"notification_count":0,"highlight_count":0},"summary":{"m.joined_member_count":2,"m.invited_member_count":0,"m.heroes":["@user-2-bob:hs1"]}} |
||
| }) | ||
|
|
||
| // When lazy-loading room members is enabled, for a private room, the `state_after` | ||
| // in an initial sync request should include membership from every `sender` in the | ||
| // `timeline` | ||
| // | ||
| // We're specifically testing the scenario where a new "DM" is created and the other person | ||
| // joins without speaking yet. | ||
| t.Run("Initial sync with lazy-loading room members -> private room `state_after` includes all members from timeline", func(t *testing.T) { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I've updated things so we have both tests (for public and private) |
||
| t.Parallel() | ||
|
|
||
| // Alice creates a room | ||
| roomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "private_chat"}) | ||
| alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID)) | ||
|
|
||
| // Alice invites Bob | ||
| alice.MustInviteRoom(t, roomID, bob.UserID) | ||
|
|
||
| // Bob must get the invite | ||
| bob.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID)) | ||
|
|
||
| // Bob joins the room | ||
| bob.MustJoinRoom(t, roomID, nil) | ||
|
|
||
| // Make double sure that bob is joined to the room | ||
| alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) | ||
|
|
||
| // Ensure `state_after` looks correct | ||
| expectedSendersFromTimeline := []string{ alice.UserID, bob.UserID } | ||
| syncFilter := `{ | ||
| "room": { | ||
| "timeline": { "limit": 20 }, | ||
| "state": { "lazy_load_members": true } | ||
| } | ||
| }` | ||
| testInitialSyncStateAfterIncludesTimelineSenders(t, alice, roomID, expectedSendersFromTimeline, syncFilter) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For private rooms, things currently fail in Synapse ❌. Reproduces element-hq/synapse#19455 Example {"next_batch":"s9_3_0_1_1_1_1_3_0_1_1_1","account_data":{"events":[{"type":"m.push_rules","content":{"global":{"underride":[{"conditions":[{"kind":"event_match","key":"type","pattern":"m.call.invite"}],"actions":["notify",{"set_tweak":"sound","value":"ring"},{"set_tweak":"highlight","value":false}],"rule_id":".m.rule.call","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"m.room.encrypted"},{"kind":"room_member_count","is":"2"}],"actions":["notify",{"set_tweak":"sound","value":"default"},{"set_tweak":"highlight","value":false}],"rule_id":".m.rule.encrypted_room_one_to_one","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"m.room.message"},{"kind":"room_member_count","is":"2"}],"actions":["notify",{"set_tweak":"sound","value":"default"},{"set_tweak":"highlight","value":false}],"rule_id":".m.rule.room_one_to_one","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"m.room.message"}],"actions":["notify",{"set_tweak":"highlight","value":false}],"rule_id":".m.rule.message","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"m.room.encrypted"}],"actions":["notify",{"set_tweak":"highlight","value":false}],"rule_id":".m.rule.encrypted","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"im.vector.modular.widgets"},{"kind":"event_match","key":"content.type","pattern":"jitsi"},{"kind":"event_match","key":"state_key","pattern":"*"}],"actions":["notify",{"set_tweak":"highlight","value":false}],"rule_id":".im.vector.jitsi","default":true,"enabled":true},{"conditions":[{"kind":"room_member_count","is":"2"},{"kind":"event_match","key":"type","pattern":"org.matrix.msc3381.poll.start"}],"actions":["notify",{"set_tweak":"sound","value":"default"}],"rule_id":".org.matrix.msc3930.rule.poll_start_one_to_one","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"org.matrix.msc3381.poll.start"}],"actions":["notify"],"rule_id":".org.matrix.msc3930.rule.poll_start","default":true,"enabled":true},{"conditions":[{"kind":"room_member_count","is":"2"},{"kind":"event_match","key":"type","pattern":"org.matrix.msc3381.poll.end"}],"actions":["notify",{"set_tweak":"sound","value":"default"}],"rule_id":".org.matrix.msc3930.rule.poll_end_one_to_one","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"org.matrix.msc3381.poll.end"}],"actions":["notify"],"rule_id":".org.matrix.msc3930.rule.poll_end","default":true,"enabled":true}],"sender":[],"room":[],"postcontent":[{"conditions":[{"kind":"io.element.msc4306.thread_subscription","subscribed":false}],"actions":[],"rule_id":".io.element.msc4306.rule.unsubscribed_thread","default":true,"enabled":true},{"conditions":[{"kind":"io.element.msc4306.thread_subscription","subscribed":true}],"actions":["notify",{"set_tweak":"sound","value":"default"}],"rule_id":".io.element.msc4306.rule.subscribed_thread","default":true,"enabled":true}],"content":[{"actions":["notify",{"set_tweak":"highlight"},{"set_tweak":"sound","value":"default"}],"rule_id":".m.rule.contains_user_name","default":true,"pattern":"user-1-alice","enabled":true}],"override":[{"conditions":[],"actions":[],"rule_id":".m.rule.master","default":true,"enabled":false},{"conditions":[{"kind":"event_match","key":"content.msgtype","pattern":"m.notice"}],"actions":[],"rule_id":".m.rule.suppress_notices","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"m.room.member"},{"kind":"event_match","key":"content.membership","pattern":"invite"},{"kind":"event_match","key":"state_key","pattern":"@user-1-alice:hs1"}],"actions":["notify",{"set_tweak":"highlight","value":false},{"set_tweak":"sound","value":"default"}],"rule_id":".m.rule.invite_for_me","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"m.room.member"}],"actions":[],"rule_id":".m.rule.member_event","default":true,"enabled":true},{"conditions":[{"kind":"event_property_contains","key":"content.m\\.mentions.user_ids","value":"@user-1-alice:hs1"}],"actions":["notify",{"set_tweak":"highlight"},{"set_tweak":"sound","value":"default"}],"rule_id":".m.rule.is_user_mention","default":true,"enabled":true},{"conditions":[{"kind":"contains_display_name"}],"actions":["notify",{"set_tweak":"highlight"},{"set_tweak":"sound","value":"default"}],"rule_id":".m.rule.contains_display_name","default":true,"enabled":true},{"conditions":[{"kind":"event_property_is","key":"content.m\\.mentions.room","value":true},{"kind":"sender_notification_permission","key":"room"}],"actions":["notify",{"set_tweak":"highlight"}],"rule_id":".m.rule.is_room_mention","default":true,"enabled":true},{"conditions":[{"kind":"sender_notification_permission","key":"room"},{"kind":"event_match","key":"content.body","pattern":"@room"}],"actions":["notify",{"set_tweak":"highlight"}],"rule_id":".m.rule.roomnotif","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"m.room.tombstone"},{"kind":"event_match","key":"state_key","pattern":""}],"actions":["notify",{"set_tweak":"highlight"}],"rule_id":".m.rule.tombstone","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"m.reaction"}],"actions":[],"rule_id":".m.rule.reaction","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"m.room.server_acl"},{"kind":"event_match","key":"state_key","pattern":""}],"actions":[],"rule_id":".m.rule.room.server_acl","default":true,"enabled":true},{"conditions":[{"kind":"event_property_is","key":"content.m\\.relates_to.rel_type","value":"m.replace"}],"actions":[],"rule_id":".m.rule.suppress_edits","default":true,"enabled":true},{"conditions":[{"kind":"event_match","key":"type","pattern":"org.matrix.msc3381.poll.response"}],"actions":[],"rule_id":".org.matrix.msc3930.rule.poll_response","default":true,"enabled":true}]}}}]},"presence":{"events":[{"type":"m.presence","sender":"@user-1-alice:hs1","content":{"presence":"online","last_active_ago":3,"currently_active":true}},{"type":"m.presence","sender":"@user-2-bob:hs1","content":{"presence":"online","last_active_ago":179,"currently_active":true}}]},"device_one_time_keys_count":{"signed_curve25519":0},"device_unused_fallback_key_types":[],"rooms":{"join":{"!gdBDkMRnmIypMjFmBh:hs1":{"timeline":{"events":[{"type":"m.room.create","sender":"@user-1-alice:hs1","content":{"room_version":"10","creator":"@user-1-alice:hs1"},"state_key":"","origin_server_ts":1771007574475,"unsigned":{"membership":"leave","age":824},"event_id":"$y5d9TkIOmtx_Bgs6emLOkuAsMeKGF8BdBNTfb_MOyVQ"},{"type":"m.room.member","sender":"@user-1-alice:hs1","content":{"displayname":"user-1-alice","membership":"join"},"state_key":"@user-1-alice:hs1","origin_server_ts":1771007574619,"unsigned":{"membership":"join","age":680},"event_id":"$1_a1Y1rddZC9qQuILgeZymyTfGS9hQia5dYj82h1O_I"},{"type":"m.room.power_levels","sender":"@user-1-alice:hs1","content":{"users":{"@user-1-alice:hs1":100},"users_default":0,"events":{"m.room.name":50,"m.room.power_levels":100,"m.room.history_visibility":100,"m.room.canonical_alias":50,"m.room.avatar":50,"m.room.tombstone":100,"m.room.server_acl":100,"m.room.encryption":100},"events_default":0,"state_default":50,"ban":50,"kick":50,"redact":50,"invite":0,"historical":100},"state_key":"","origin_server_ts":1771007574733,"unsigned":{"membership":"join","age":566},"event_id":"$qc1MGLT23L35gJCnFGTV3QkL7SmvODwe6PSFqFo3x9I"},{"type":"m.room.join_rules","sender":"@user-1-alice:hs1","content":{"join_rule":"invite"},"state_key":"","origin_server_ts":1771007574738,"unsigned":{"membership":"join","age":561},"event_id":"$KVG2BvhxOJw3wN0iTdOmqV7jONh44dokydRrATbrCvI"},{"type":"m.room.history_visibility","sender":"@user-1-alice:hs1","content":{"history_visibility":"shared"},"state_key":"","origin_server_ts":1771007574738,"unsigned":{"membership":"join","age":561},"event_id":"$JdttXi3VDucYC7HcGAw0OTBwm2K6mJn_7GfkewcHEhc"},{"type":"m.room.guest_access","sender":"@user-1-alice:hs1","content":{"guest_access":"can_join"},"state_key":"","origin_server_ts":1771007574738,"unsigned":{"membership":"join","age":561},"event_id":"$cgkV_w3r4_piAlf4g1X8kg7ba6yh37eBdQuXLWWyxzE"},{"type":"m.room.member","sender":"@user-1-alice:hs1","content":{"displayname":"user-2-bob","membership":"invite"},"state_key":"@user-2-bob:hs1","origin_server_ts":1771007574962,"unsigned":{"membership":"join","age":337},"event_id":"$rzywv46JfX2c30FWTTRPBhEMDmnWwOrtabxycJPOHuE"},{"type":"m.room.member","sender":"@user-2-bob:hs1","content":{"displayname":"user-2-bob","membership":"join"},"state_key":"@user-2-bob:hs1","origin_server_ts":1771007575156,"unsigned":{"replaces_state":"$rzywv46JfX2c30FWTTRPBhEMDmnWwOrtabxycJPOHuE","prev_content":{"displayname":"user-2-bob","membership":"invite"},"prev_sender":"@user-1-alice:hs1","membership":"join","age":143},"event_id":"$iMb1zckAPk3WERBUuMNJRIS32F-q3nUbUK_TdYcNTv4"}],"prev_batch":"s9_3_0_1_1_1_1_3_0_1_1_1","limited":false},"org.matrix.msc4222.state_after":{"events":[{"type":"m.room.create","sender":"@user-1-alice:hs1","content":{"room_version":"10","creator":"@user-1-alice:hs1"},"state_key":"","origin_server_ts":1771007574475,"unsigned":{"age":824},"event_id":"$y5d9TkIOmtx_Bgs6emLOkuAsMeKGF8BdBNTfb_MOyVQ"},{"type":"m.room.guest_access","sender":"@user-1-alice:hs1","content":{"guest_access":"can_join"},"state_key":"","origin_server_ts":1771007574738,"unsigned":{"age":561},"event_id":"$cgkV_w3r4_piAlf4g1X8kg7ba6yh37eBdQuXLWWyxzE"},{"type":"m.room.history_visibility","sender":"@user-1-alice:hs1","content":{"history_visibility":"shared"},"state_key":"","origin_server_ts":1771007574738,"unsigned":{"age":561},"event_id":"$JdttXi3VDucYC7HcGAw0OTBwm2K6mJn_7GfkewcHEhc"},{"type":"m.room.join_rules","sender":"@user-1-alice:hs1","content":{"join_rule":"invite"},"state_key":"","origin_server_ts":1771007574738,"unsigned":{"age":561},"event_id":"$KVG2BvhxOJw3wN0iTdOmqV7jONh44dokydRrATbrCvI"},{"type":"m.room.member","sender":"@user-1-alice:hs1","content":{"displayname":"user-1-alice","membership":"join"},"state_key":"@user-1-alice:hs1","origin_server_ts":1771007574619,"unsigned":{"age":680},"event_id":"$1_a1Y1rddZC9qQuILgeZymyTfGS9hQia5dYj82h1O_I"},{"type":"m.room.power_levels","sender":"@user-1-alice:hs1","content":{"users":{"@user-1-alice:hs1":100},"users_default":0,"events":{"m.room.name":50,"m.room.power_levels":100,"m.room.history_visibility":100,"m.room.canonical_alias":50,"m.room.avatar":50,"m.room.tombstone":100,"m.room.server_acl":100,"m.room.encryption":100},"events_default":0,"state_default":50,"ban":50,"kick":50,"redact":50,"invite":0,"historical":100},"state_key":"","origin_server_ts":1771007574733,"unsigned":{"age":566},"event_id":"$qc1MGLT23L35gJCnFGTV3QkL7SmvODwe6PSFqFo3x9I"}]},"account_data":{"events":[]},"ephemeral":{"events":[]},"unread_notifications":{"notification_count":0,"highlight_count":0},"summary":{"m.joined_member_count":2,"m.invited_member_count":0,"m.heroes":["@user-2-bob:hs1"]}}}}} |
||
| }) | ||
| }) | ||
| } | ||
|
|
||
|
|
||
| // The `state_after` in an initial sync request should at-least include membership from | ||
| // every `sender` in the `timeline`. | ||
| func testInitialSyncStateAfterIncludesTimelineSenders( | ||
| t *testing.T, | ||
| syncingUser *client.CSAPI, | ||
| roomID string, | ||
| expectedSendersFromTimeline []string, | ||
| syncFilter string, | ||
| ) { | ||
| t.Helper() | ||
|
|
||
| // `syncingUser` makes an initial sync request with lazy-loading members enabled | ||
| // | ||
| // The spec says `lazy_load_members` is valid field for both `timeline` and | ||
| // `state` but as far as I can tell, only makes sense for `state` and that's | ||
| // what Synapse keys off of. | ||
| res, _ := syncingUser.MustSync(t, client.SyncReq{UseStateAfter: true, Filter: syncFilter}) | ||
| joinedRoomRes := res.Get("rooms.join." + client.GjsonEscape(roomID)) | ||
| if !joinedRoomRes.Exists() { | ||
| t.Fatalf("Unable to find roomID=%s in the join part of the sync response: %s", roomID, res) | ||
| } | ||
|
|
||
| // Collect the senders of all the time timeline events. | ||
| roomTimelineRes := joinedRoomRes.Get("timeline.events"); | ||
| if !roomTimelineRes.IsArray() { | ||
| t.Fatalf("Timeline events is not an array (found %s) %s", roomTimelineRes.Type.String(), res) | ||
| } | ||
| sendersFromTimeline := make(map[string]struct{}, 0) | ||
| for _, event := range roomTimelineRes.Array() { | ||
| sendersFromTimeline[event.Get("sender").Str] = struct{}{} | ||
| } | ||
| // We expect to see timeline events from `expectedSendersFromTimeline` | ||
| err := should.ContainSubset( | ||
| slices.Collect(maps.Keys(sendersFromTimeline)), | ||
| expectedSendersFromTimeline, | ||
| ) | ||
| if err != nil { | ||
| t.Fatalf( | ||
| "Expected to see timeline events from (%s) but only saw %s. " + | ||
| "Got error: %s. join part of the sync response: %s", | ||
| expectedSendersFromTimeline, | ||
| slices.Collect(maps.Keys(sendersFromTimeline)), | ||
| err.Error(), | ||
| res, | ||
| ) | ||
| } | ||
|
|
||
| // Collect the `m.room.membership` from `state_after` | ||
| // | ||
| // Try looking up the stable variant `state_after` first, then fallback to the | ||
| // unstable version | ||
| roomStateAfterResStable := joinedRoomRes.Get("state_after.events"); | ||
| roomStateAfterResUnstable := joinedRoomRes.Get("org\\.matrix\\.msc4222\\.state_after.events"); | ||
| var roomStateAfterRes gjson.Result | ||
| if roomStateAfterResStable.Exists() { | ||
| roomStateAfterRes = roomStateAfterResStable | ||
| } else if roomStateAfterResUnstable.Exists() { | ||
| roomStateAfterRes = roomStateAfterResUnstable | ||
| } | ||
|
Comment on lines
+140
to
+149
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a great piece of code but since we only do this in one spot I'm tempted to leave it rather than create a bad abstraction. And it's unclear how things like this should work once MSC's have stabilized but homeservers haven't yet. |
||
| // Sanity check syntax | ||
| if !roomStateAfterRes.IsArray() { | ||
| t.Fatalf("state_after events is not an array (found %s) %s", roomStateAfterRes.Type.String(), res) | ||
| } | ||
| membershipFromState := make(map[string]struct{}, 0) | ||
| for _, event := range roomStateAfterRes.Array() { | ||
| if event.Get("type").Str == "m.room.member" { | ||
| membershipFromState[event.Get("sender").Str] = struct{}{} | ||
| } | ||
| } | ||
| // We should see membership state from every `sender` in the `timeline`. | ||
| err = should.ContainSubset( | ||
| slices.Collect(maps.Keys(membershipFromState)), | ||
| slices.Collect(maps.Keys(sendersFromTimeline)), | ||
| ) | ||
| if err != nil { | ||
| t.Fatalf( | ||
| "Expected to see membership state (%s) from every sender in the timeline (%s). " + | ||
| "Got error: %s. join part of the sync response: %s", | ||
| slices.Collect(maps.Keys(membershipFromState)), | ||
| slices.Collect(maps.Keys(sendersFromTimeline)), | ||
| err.Error(), | ||
| res, | ||
| ) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See other discussion #842 (comment)