summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorErik Johnston <erik@matrix.org>2024-07-18 15:01:51 +0100
committerErik Johnston <erik@matrix.org>2024-07-18 15:01:51 +0100
commit37c4463c8ed5af357f66c89bbfda2430fe45384f (patch)
tree439977addc6d53e6d1f3574ee67d242f4d5fceb4 /tests
parentRefactor to avoid SyncConfig.connection_id() (diff)
downloadsynapse-37c4463c8ed5af357f66c89bbfda2430fe45384f.tar.xz
Add some unit tests for 'get_room_sync_data'
Diffstat (limited to 'tests')
-rw-r--r--tests/handlers/test_sliding_sync.py399
1 files changed, 396 insertions, 3 deletions
diff --git a/tests/handlers/test_sliding_sync.py b/tests/handlers/test_sliding_sync.py
index a7aa9bb8af..6c63719ca5 100644
--- a/tests/handlers/test_sliding_sync.py
+++ b/tests/handlers/test_sliding_sync.py
@@ -19,8 +19,8 @@
 #
 import logging
 from copy import deepcopy
-from typing import Dict, Optional
-from unittest.mock import patch
+from typing import Dict, Optional, Tuple
+from unittest.mock import Mock, patch
 
 from parameterized import parameterized
 
@@ -46,7 +46,13 @@ from synapse.rest import admin
 from synapse.rest.client import knock, login, room
 from synapse.server import HomeServer
 from synapse.storage.util.id_generators import MultiWriterIdGenerator
-from synapse.types import JsonDict, StreamToken, UserID
+from synapse.types import (
+    JsonDict,
+    SlidingSyncStreamToken,
+    StreamToken,
+    UserID,
+    create_requester,
+)
 from synapse.types.handlers import SlidingSyncConfig
 from synapse.util import Clock
 
@@ -3759,3 +3765,390 @@ class SortRoomsTestCase(HomeserverTestCase):
             # We only care about the *latest* event in the room.
             [room_id1, room_id2],
         )
+
+
+class GetRoomSyncDataTestCase(HomeserverTestCase):
+    """
+    Tests for Sliding Sync handler `get_room_sync_data()`
+    """
+
+    servlets = [
+        admin.register_servlets,
+        knock.register_servlets,
+        login.register_servlets,
+        room.register_servlets,
+    ]
+
+    def default_config(self) -> JsonDict:
+        config = super().default_config()
+        # Enable sliding sync
+        config["experimental_features"] = {"msc3575_enabled": True}
+        return config
+
+    def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
+        self.sliding_sync_handler = self.hs.get_sliding_sync_handler()
+        self.store = self.hs.get_datastores().main
+        self.event_sources = hs.get_event_sources()
+
+    def _create_sync_configs(
+        self,
+        user_id,
+        room_id,
+        timeline_limit=5,
+    ) -> Tuple[SlidingSyncConfig, RoomSyncConfig, _RoomMembershipForUser]:
+        """Create the configs necessary to call `get_room_sync_data`"""
+        requester = create_requester(user_id, device_id="foo_device")
+        sync_config = SlidingSyncConfig(
+            user=requester.user,
+            requester=requester,
+            conn_id="conn_id",
+            lists={
+                "list": SlidingSyncConfig.SlidingSyncList(
+                    timeline_limit=timeline_limit,
+                    required_state=[
+                        (EventTypes.Name, ""),
+                    ],
+                ),
+            },
+            room_subscriptions={},
+            extensions=None,
+        )
+
+        room_sync_config = RoomSyncConfig(timeline_limit, {EventTypes.Name: {""}})
+
+        rooms = self.get_success(
+            self.store.get_rooms_for_local_user_where_membership_is(
+                user_id, membership_list=[Membership.JOIN]
+            )
+        )
+        room_for_user = rooms[0]
+        assert room_for_user.room_id == room_id
+
+        room_membership_for_user_at_to_token = _RoomMembershipForUser(
+            room_id=room_id,
+            event_id=room_for_user.event_id,
+            event_pos=room_for_user.event_pos,
+            membership=Membership.JOIN,
+            sender=user_id,
+            newly_joined=False,
+            newly_left=False,
+            is_dm=False,
+        )
+
+        return (sync_config, room_sync_config, room_membership_for_user_at_to_token)
+
+    def test_room_sync_data_initial(self) -> None:
+        """Tests getting room sync data with no from token"""
+
+        user1_id = self.register_user("user1", "pass")
+        user1_tok = self.login(user1_id, "pass")
+
+        room_id1 = self.helper.create_room_as(
+            user1_id,
+            tok=user1_tok,
+        )
+
+        sync_config, room_sync_config, room_membership_for_user_at_to_token = (
+            self._create_sync_configs(user1_id, room_id1, timeline_limit=5)
+        )
+
+        # Timeline limit is 5 so let's send 5 messages that we'll expect to get
+        # back.
+        expected_timeline = []
+        for _ in range(5):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+            expected_timeline.append(r["event_id"])
+
+        to_token = self.event_sources.get_current_token()
+
+        result = self.get_success(
+            self.sliding_sync_handler.get_room_sync_data(
+                sync_config,
+                room_id=room_id1,
+                room_sync_config=room_sync_config,
+                room_membership_for_user_at_to_token=room_membership_for_user_at_to_token,
+                from_token=None,
+                to_token=to_token,
+            )
+        )
+
+        self.assertTrue(result.initial)
+        self.assertTrue(result.limited)
+        self.assertEqual(
+            [e.event_id for e in result.timeline_events], expected_timeline
+        )
+
+    def test_room_sync_data_incremental_live(self) -> None:
+        """Test getting room data where we have previously sent down the room
+        and its state is considered LIVE"""
+        user1_id = self.register_user("user1", "pass")
+        user1_tok = self.login(user1_id, "pass")
+
+        room_id1 = self.helper.create_room_as(
+            user1_id,
+            tok=user1_tok,
+        )
+
+        sync_config, room_sync_config, room_membership_for_user_at_to_token = (
+            self._create_sync_configs(user1_id, room_id1)
+        )
+
+        # These messages are sent before the `from_token`, so we don't expect to
+        # see these messages.
+        for _ in range(5):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+
+        # Mark the room as having been sent down, and create an appropriate
+        # `from_token`.
+        connection_token = self.get_success(
+            self.sliding_sync_handler.connection_store.record_rooms(
+                sync_config, None, sent_room_ids=[room_id1], unsent_room_ids=[]
+            )
+        )
+        from_token = SlidingSyncStreamToken(
+            self.event_sources.get_current_token(), connection_token
+        )
+
+        # These messages are sent after the `from_token`, so we expect to only
+        # see these messages.
+        expected_timeline = []
+        for _ in range(2):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+            expected_timeline.append(r["event_id"])
+
+        to_token = self.event_sources.get_current_token()
+
+        result = self.get_success(
+            self.sliding_sync_handler.get_room_sync_data(
+                sync_config,
+                room_id=room_id1,
+                room_sync_config=room_sync_config,
+                room_membership_for_user_at_to_token=room_membership_for_user_at_to_token,
+                from_token=from_token,
+                to_token=to_token,
+            )
+        )
+
+        self.assertFalse(result.initial)
+        self.assertFalse(result.limited)
+        self.assertEqual(
+            [e.event_id for e in result.timeline_events], expected_timeline
+        )
+
+    def test_room_sync_data_incremental_previously_not_limited(self) -> None:
+        """Test getting room data where we have previously sent down the room,
+        but we missed sending down some data previously and so its state is
+        considered PREVIOUSLY.
+
+        In this case there has been more than timeline limit events.
+        """
+        user1_id = self.register_user("user1", "pass")
+        user1_tok = self.login(user1_id, "pass")
+
+        room_id1 = self.helper.create_room_as(
+            user1_id,
+            tok=user1_tok,
+        )
+
+        sync_config, room_sync_config, room_membership_for_user_at_to_token = (
+            self._create_sync_configs(user1_id, room_id1)
+        )
+
+        # These messages are sent before the initial `from_token`, so we don't
+        # expect to see these messages.
+        for _ in range(5):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+
+        # Mark the room as having been sent down, and create an appropriate
+        # `from_token`.
+        connection_token = self.get_success(
+            self.sliding_sync_handler.connection_store.record_rooms(
+                sync_config, None, sent_room_ids=[room_id1], unsent_room_ids=[]
+            )
+        )
+        from_token = SlidingSyncStreamToken(
+            self.event_sources.get_current_token(), connection_token
+        )
+
+        # These messages are sent after the initial `from_token`, so we expect
+        # to see these messages.
+        expected_timeline = []
+        for _ in range(2):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+            expected_timeline.append(r["event_id"])
+
+        # Mark the room as *not* having been sent down, and create a new
+        # `from_token`.
+        connection_token = self.get_success(
+            self.sliding_sync_handler.connection_store.record_rooms(
+                sync_config, from_token, sent_room_ids=[], unsent_room_ids=[room_id1]
+            )
+        )
+
+        from_token = SlidingSyncStreamToken(
+            self.event_sources.get_current_token(), connection_token
+        )
+
+        # We should also receive new messages
+        for _ in range(2):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+            expected_timeline.append(r["event_id"])
+
+        to_token = self.event_sources.get_current_token()
+
+        result = self.get_success(
+            self.sliding_sync_handler.get_room_sync_data(
+                sync_config,
+                room_id=room_id1,
+                room_sync_config=room_sync_config,
+                room_membership_for_user_at_to_token=room_membership_for_user_at_to_token,
+                from_token=from_token,
+                to_token=to_token,
+            )
+        )
+
+        self.assertFalse(result.initial)
+        self.assertFalse(result.limited)
+        self.assertEqual(
+            [e.event_id for e in result.timeline_events], expected_timeline
+        )
+
+    def test_room_sync_data_incremental_previously_limited(self) -> None:
+        """Test getting room data where we have previously sent down the room,
+        but we missed sending down some data previously and so its state is
+        considered PREVIOUSLY.
+
+        In this case there has been fewer than timeline limit events.
+        """
+        user1_id = self.register_user("user1", "pass")
+        user1_tok = self.login(user1_id, "pass")
+
+        room_id1 = self.helper.create_room_as(
+            user1_id,
+            tok=user1_tok,
+        )
+
+        sync_config, room_sync_config, room_membership_for_user_at_to_token = (
+            self._create_sync_configs(user1_id, room_id1)
+        )
+
+        # These messages are sent before the initial `from_token`, so we don't
+        # expect to see these messages.
+        for _ in range(5):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+
+        # Mark the room as having been sent down, and create an appropriate
+        # `from_token`.
+        connection_token = self.get_success(
+            self.sliding_sync_handler.connection_store.record_rooms(
+                sync_config, None, sent_room_ids=[room_id1], unsent_room_ids=[]
+            )
+        )
+        from_token = SlidingSyncStreamToken(
+            self.event_sources.get_current_token(), connection_token
+        )
+
+        # These messages are sent after the initial `from_token`, but are before
+        # the timeline limit, so we don't expect to see these messages.
+        for _ in range(5):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+
+        # ... but these messages are within the timeline limit, so we do expect
+        # to see them
+        expected_timeline = []
+        for _ in range(3):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+            expected_timeline.append(r["event_id"])
+
+        # Mark the room as *not* having been sent down, and create a new
+        # `from_token`.
+        connection_token = self.get_success(
+            self.sliding_sync_handler.connection_store.record_rooms(
+                sync_config, from_token, sent_room_ids=[], unsent_room_ids=[room_id1]
+            )
+        )
+
+        from_token = SlidingSyncStreamToken(
+            self.event_sources.get_current_token(), connection_token
+        )
+
+        # We should also receive new messages
+        for _ in range(2):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+            expected_timeline.append(r["event_id"])
+
+        to_token = self.event_sources.get_current_token()
+
+        result = self.get_success(
+            self.sliding_sync_handler.get_room_sync_data(
+                sync_config,
+                room_id=room_id1,
+                room_sync_config=room_sync_config,
+                room_membership_for_user_at_to_token=room_membership_for_user_at_to_token,
+                from_token=from_token,
+                to_token=to_token,
+            )
+        )
+
+        self.assertFalse(result.initial)
+        self.assertTrue(result.limited)
+        self.assertEqual(
+            [e.event_id for e in result.timeline_events], expected_timeline
+        )
+
+    def test_room_sync_data_incremental_never(self) -> None:
+        """Test getting room data where we have not previously sent down the room,
+        so its state is considered NEVER.
+        """
+        user1_id = self.register_user("user1", "pass")
+        user1_tok = self.login(user1_id, "pass")
+
+        room_id1 = self.helper.create_room_as(
+            user1_id,
+            tok=user1_tok,
+        )
+
+        sync_config, room_sync_config, room_membership_for_user_at_to_token = (
+            self._create_sync_configs(user1_id, room_id1)
+        )
+
+        # We expect to see these messages even though they're before the
+        # `from_token`, as the room has not been sent down.
+        expected_timeline = []
+        for _ in range(2):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+            expected_timeline.append(r["event_id"])
+
+        # Create a new `from_token`.
+        connection_token = self.get_success(
+            self.sliding_sync_handler.connection_store.record_rooms(
+                sync_config, None, sent_room_ids=[], unsent_room_ids=[]
+            )
+        )
+        from_token = SlidingSyncStreamToken(
+            self.event_sources.get_current_token(), connection_token
+        )
+
+        # We should also receive new messages
+        for _ in range(3):
+            r = self.helper.send(room_id1, "message", tok=user1_tok)
+            expected_timeline.append(r["event_id"])
+
+        to_token = self.event_sources.get_current_token()
+
+        result = self.get_success(
+            self.sliding_sync_handler.get_room_sync_data(
+                sync_config,
+                room_id=room_id1,
+                room_sync_config=room_sync_config,
+                room_membership_for_user_at_to_token=room_membership_for_user_at_to_token,
+                from_token=from_token,
+                to_token=to_token,
+            )
+        )
+
+        self.assertTrue(result.initial)
+        self.assertTrue(result.limited)
+        self.assertEqual(
+            [e.event_id for e in result.timeline_events], expected_timeline
+        )