diff --git a/tests/handlers/test_profile.py b/tests/handlers/test_profile.py index b0cc77c7ce..7367ee4f30 100644 --- a/tests/handlers/test_profile.py +++ b/tests/handlers/test_profile.py @@ -23,6 +23,7 @@ from unittest.mock import AsyncMock, Mock, patch from parameterized import parameterized +from twisted.internet.defer import ensureDeferred from twisted.internet.testing import MemoryReactor import synapse.types @@ -749,60 +750,9 @@ class ProfileTestCase(unittest.HomeserverTestCase): """Test that room membership updates triggered by changing the avatar or the display name are resumed after a restart.""" initial_displayname = "Frank" updated_displayname = "Frank Jr." - self.get_success( - self.handler.set_field( - target_user=self.frank, - requester=synapse.types.create_requester(self.frank), - field_name=ProfileFields.DISPLAYNAME, - new_value=initial_displayname, - ) - ) - room_id_1 = self.helper.create_room_as( - self.frank.to_string(), tok=self.frank_token - ) - - room_id_2 = self.helper.create_room_as( - self.frank.to_string(), tok=self.frank_token - ) - room_id_3 = self.helper.create_room_as( - self.frank.to_string(), tok=self.frank_token - ) - - # Set read receipts with different timestamps (simulate different read times) - # Room 1 should be most recent, then room 2, then room 3 - event_3 = self.helper.send(room_id_3, "Hello 3", tok=self.frank_token) - event_2 = self.helper.send(room_id_2, "Hello 2", tok=self.frank_token) - event_1 = self.helper.send(room_id_1, "Hello 1", tok=self.frank_token) - self.get_success( - self.store.insert_receipt( - room_id_3, - ReceiptTypes.READ, - user_id=self.frank.to_string(), - event_ids=[event_3["event_id"]], - thread_id=None, - data={"ts": 100}, - ) - ) - self.get_success( - self.store.insert_receipt( - room_id_2, - ReceiptTypes.READ, - user_id=self.frank.to_string(), - event_ids=[event_2["event_id"]], - thread_id=None, - data={"ts": 200}, - ) - ) - self.get_success( - self.store.insert_receipt( - room_id_1, - ReceiptTypes.READ, - user_id=self.frank.to_string(), - event_ids=[event_1["event_id"]], - thread_id=None, - data={"ts": 300}, - ) + room_id_1, room_id_2, room_id_3 = self._setup_displayname_and_rooms( + initial_displayname ) original_update_membership = self.hs.get_room_member_handler().update_membership @@ -907,62 +857,8 @@ class ProfileTestCase(unittest.HomeserverTestCase): """Test that rooms are updated in order of most recent read receipt.""" initial_displayname = "Frank" updated_displayname = "Frank Jr." - self.get_success( - self.handler.set_displayname( - self.frank, - synapse.types.create_requester(self.frank), - initial_displayname, - ) - ) - # Create three rooms - room_id_1 = self.helper.create_room_as( - self.frank.to_string(), tok=self.frank_token - ) - room_id_2 = self.helper.create_room_as( - self.frank.to_string(), tok=self.frank_token - ) - room_id_3 = self.helper.create_room_as( - self.frank.to_string(), tok=self.frank_token - ) - - # Send an event in each room to create something to mark as read - event_1 = self.helper.send(room_id_1, "Hello 1", tok=self.frank_token) - event_2 = self.helper.send(room_id_2, "Hello 2", tok=self.frank_token) - event_3 = self.helper.send(room_id_3, "Hello 3", tok=self.frank_token) - - # Set read receipts with different timestamps (simulate different read times) - # Room 3 is the most recent, then room 2, then room 1 - self.get_success( - self.store.insert_receipt( - room_id_1, - ReceiptTypes.READ, - user_id=self.frank.to_string(), - event_ids=[event_1["event_id"]], - thread_id=None, - data={"ts": 100}, - ) - ) - self.get_success( - self.store.insert_receipt( - room_id_2, - ReceiptTypes.READ, - user_id=self.frank.to_string(), - event_ids=[event_2["event_id"]], - thread_id=None, - data={"ts": 200}, - ) - ) - self.get_success( - self.store.insert_receipt( - room_id_3, - ReceiptTypes.READ, - user_id=self.frank.to_string(), - event_ids=[event_3["event_id"]], - thread_id=None, - data={"ts": 300}, - ) - ) + self._setup_displayname_and_rooms(initial_displayname) # Track the order in which rooms are updated room_update_order = [] @@ -979,15 +875,19 @@ class ProfileTestCase(unittest.HomeserverTestCase): side_effect=track_update_membership, ): self.get_success( - self.handler.set_displayname( - self.frank, - synapse.types.create_requester(self.frank), - updated_displayname, + self.handler.set_field( + target_user=self.frank, + requester=synapse.types.create_requester(self.frank), + field_name=ProfileFields.DISPLAYNAME, + new_value=updated_displayname, ) ) - # Wait for background task to complete - self.get_success(self.clock.sleep(Duration(milliseconds=50)), by=1) + # Wait for background task to complete. `get_success` no longer advances the + # reactor itself, so drive the clock forward while it waits. + wait_d = ensureDeferred(self.clock.sleep(Duration(milliseconds=50))) + self.reactor.advance(Duration(milliseconds=50).as_secs()) + self.get_success(wait_d) # Get receipts to understand the actual stream ordering user_receipts = self.get_success( @@ -1007,11 +907,76 @@ class ProfileTestCase(unittest.HomeserverTestCase): self.assertEqual(len(room_update_order), 3) self.assertEqual(room_update_order, rooms_by_stream_ordering) + def _setup_displayname_and_rooms( + self, initial_displayname: str + ) -> tuple[str, str, str]: + """Helper to set up initial displayname and create three rooms. + Returns tuples of (room_id_1, room_id_2, room_id_3) where room_id_1 + is the room with the most recent read receipt, then room_id_2, then room_id_3.""" + self.get_success( + self.handler.set_field( + target_user=self.frank, + requester=synapse.types.create_requester(self.frank), + field_name=ProfileFields.DISPLAYNAME, + new_value=initial_displayname, + ) + ) + + # Create three rooms + room_id_1 = self.helper.create_room_as( + self.frank.to_string(), tok=self.frank_token + ) + room_id_2 = self.helper.create_room_as( + self.frank.to_string(), tok=self.frank_token + ) + room_id_3 = self.helper.create_room_as( + self.frank.to_string(), tok=self.frank_token + ) + # Set read receipts with different timestamps (simulate different read times) + # Room 1 should be most recent, then room 2, then room 3 + event_3 = self.helper.send(room_id_3, "Hello 3", tok=self.frank_token) + event_2 = self.helper.send(room_id_2, "Hello 2", tok=self.frank_token) + event_1 = self.helper.send(room_id_1, "Hello 1", tok=self.frank_token) + self.get_success( + self.store.insert_receipt( + room_id_3, + ReceiptTypes.READ, + user_id=self.frank.to_string(), + event_ids=[event_3["event_id"]], + thread_id=None, + data={"ts": 100}, + ) + ) + self.get_success( + self.store.insert_receipt( + room_id_2, + ReceiptTypes.READ, + user_id=self.frank.to_string(), + event_ids=[event_2["event_id"]], + thread_id=None, + data={"ts": 200}, + ) + ) + self.get_success( + self.store.insert_receipt( + room_id_1, + ReceiptTypes.READ, + user_id=self.frank.to_string(), + event_ids=[event_1["event_id"]], + thread_id=None, + data={"ts": 300}, + ) + ) + return room_id_1, room_id_2, room_id_3 + def test_room_update_ordering_with_no_receipts_fallback(self) -> None: """Test that rooms without read receipts fall back to alphabetical ordering.""" self.get_success( - self.handler.set_displayname( - self.frank, synapse.types.create_requester(self.frank), "Frank" + self.handler.set_field( + target_user=self.frank, + requester=synapse.types.create_requester(self.frank), + field_name=ProfileFields.DISPLAYNAME, + new_value="Frank", ) ) @@ -1044,15 +1009,19 @@ class ProfileTestCase(unittest.HomeserverTestCase): side_effect=track_update_membership, ): self.get_success( - self.handler.set_displayname( - self.frank, - synapse.types.create_requester(self.frank), - "Frank Updated", + self.handler.set_field( + target_user=self.frank, + requester=synapse.types.create_requester(self.frank), + field_name=ProfileFields.DISPLAYNAME, + new_value="Frank Updated", ) ) - # Wait for background task to complete - self.get_success(self.clock.sleep(Duration(milliseconds=50)), by=1) + # Wait for background task to complete. `get_success` no longer advances the + # reactor itself, so drive the clock forward while it waits. + wait_d = ensureDeferred(self.clock.sleep(Duration(milliseconds=50))) + self.reactor.advance(Duration(milliseconds=50).as_secs()) + self.get_success(wait_d) # Verify rooms were updated in alphabetical order self.assertEqual(len(room_update_order), 2) @@ -1062,8 +1031,11 @@ class ProfileTestCase(unittest.HomeserverTestCase): def test_room_update_ordering_mixed_receipts_and_no_receipts(self) -> None: """Test ordering when some rooms have receipts and others don't.""" self.get_success( - self.handler.set_displayname( - self.frank, synapse.types.create_requester(self.frank), "Frank" + self.handler.set_field( + target_user=self.frank, + requester=synapse.types.create_requester(self.frank), + field_name=ProfileFields.DISPLAYNAME, + new_value="Frank", ) ) @@ -1113,15 +1085,19 @@ class ProfileTestCase(unittest.HomeserverTestCase): side_effect=track_update_membership, ): self.get_success( - self.handler.set_displayname( - self.frank, - synapse.types.create_requester(self.frank), - "Frank Updated", + self.handler.set_field( + target_user=self.frank, + requester=synapse.types.create_requester(self.frank), + field_name=ProfileFields.DISPLAYNAME, + new_value="Frank Updated", ) ) - # Wait for background task to complete - self.get_success(self.clock.sleep(Duration(milliseconds=50)), by=1) + # Wait for background task to complete. `get_success` no longer advances the + # reactor itself, so drive the clock forward while it waits. + wait_d = ensureDeferred(self.clock.sleep(Duration(milliseconds=50))) + self.reactor.advance(Duration(milliseconds=50).as_secs()) + self.get_success(wait_d) # Verify ordering: room with receipt first, then others alphabetically self.assertEqual(len(room_update_order), 3)