Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 87f2005

Browse files
Add some tests for propagation of device list changes between local users (#11972)
1 parent c4c98c7 commit 87f2005

File tree

4 files changed

+163
-3
lines changed

4 files changed

+163
-3
lines changed

changelog.d/11972.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add tests for device list changes between local users.

synapse/notifier.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def notify(
138138
self.current_token = self.current_token.copy_and_advance(stream_key, stream_id)
139139
self.last_notified_token = self.current_token
140140
self.last_notified_ms = time_now_ms
141-
noify_deferred = self.notify_deferred
141+
notify_deferred = self.notify_deferred
142142

143143
log_kv(
144144
{
@@ -153,7 +153,7 @@ def notify(
153153

154154
with PreserveLoggingContext():
155155
self.notify_deferred = ObservableDeferred(defer.Deferred())
156-
noify_deferred.callback(self.current_token)
156+
notify_deferred.callback(self.current_token)
157157

158158
def remove(self, notifier: "Notifier") -> None:
159159
"""Remove this listener from all the indexes in the Notifier
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Copyright 2022 The Matrix.org Foundation C.I.C.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
from synapse.rest import admin, devices, room, sync
15+
from synapse.rest.client import account, login, register
16+
17+
from tests import unittest
18+
19+
20+
class DeviceListsTestCase(unittest.HomeserverTestCase):
21+
"""Tests regarding device list changes."""
22+
23+
servlets = [
24+
admin.register_servlets_for_client_rest_resource,
25+
login.register_servlets,
26+
register.register_servlets,
27+
account.register_servlets,
28+
room.register_servlets,
29+
sync.register_servlets,
30+
devices.register_servlets,
31+
]
32+
33+
def test_receiving_local_device_list_changes(self):
34+
"""Tests that a local users that share a room receive each other's device list
35+
changes.
36+
"""
37+
# Register two users
38+
test_device_id = "TESTDEVICE"
39+
alice_user_id = self.register_user("alice", "correcthorse")
40+
alice_access_token = self.login(
41+
alice_user_id, "correcthorse", device_id=test_device_id
42+
)
43+
44+
bob_user_id = self.register_user("bob", "ponyponypony")
45+
bob_access_token = self.login(bob_user_id, "ponyponypony")
46+
47+
# Create a room for them to coexist peacefully in
48+
new_room_id = self.helper.create_room_as(
49+
alice_user_id, is_public=True, tok=alice_access_token
50+
)
51+
self.assertIsNotNone(new_room_id)
52+
53+
# Have Bob join the room
54+
self.helper.invite(
55+
new_room_id, alice_user_id, bob_user_id, tok=alice_access_token
56+
)
57+
self.helper.join(new_room_id, bob_user_id, tok=bob_access_token)
58+
59+
# Now have Bob initiate an initial sync (in order to get a since token)
60+
channel = self.make_request(
61+
"GET",
62+
"/sync",
63+
access_token=bob_access_token,
64+
)
65+
self.assertEqual(channel.code, 200, channel.json_body)
66+
next_batch_token = channel.json_body["next_batch"]
67+
68+
# ...and then an incremental sync. This should block until the sync stream is woken up,
69+
# which we hope will happen as a result of Alice updating their device list.
70+
bob_sync_channel = self.make_request(
71+
"GET",
72+
f"/sync?since={next_batch_token}&timeout=30000",
73+
access_token=bob_access_token,
74+
# Start the request, then continue on.
75+
await_result=False,
76+
)
77+
78+
# Have alice update their device list
79+
channel = self.make_request(
80+
"PUT",
81+
f"/devices/{test_device_id}",
82+
{
83+
"display_name": "New Device Name",
84+
},
85+
access_token=alice_access_token,
86+
)
87+
self.assertEqual(channel.code, 200, channel.json_body)
88+
89+
# Check that bob's incremental sync contains the updated device list.
90+
# If not, the client would only receive the device list update on the
91+
# *next* sync.
92+
bob_sync_channel.await_result()
93+
self.assertEqual(bob_sync_channel.code, 200, bob_sync_channel.json_body)
94+
95+
changed_device_lists = bob_sync_channel.json_body.get("device_lists", {}).get(
96+
"changed", []
97+
)
98+
self.assertIn(alice_user_id, changed_device_lists, bob_sync_channel.json_body)
99+
100+
def test_not_receiving_local_device_list_changes(self):
101+
"""Tests a local users DO NOT receive device updates from each other if they do not
102+
share a room.
103+
"""
104+
# Register two users
105+
test_device_id = "TESTDEVICE"
106+
alice_user_id = self.register_user("alice", "correcthorse")
107+
alice_access_token = self.login(
108+
alice_user_id, "correcthorse", device_id=test_device_id
109+
)
110+
111+
bob_user_id = self.register_user("bob", "ponyponypony")
112+
bob_access_token = self.login(bob_user_id, "ponyponypony")
113+
114+
# These users do not share a room. They are lonely.
115+
116+
# Have Bob initiate an initial sync (in order to get a since token)
117+
channel = self.make_request(
118+
"GET",
119+
"/sync",
120+
access_token=bob_access_token,
121+
)
122+
self.assertEqual(channel.code, 200, channel.json_body)
123+
next_batch_token = channel.json_body["next_batch"]
124+
125+
# ...and then an incremental sync. This should block until the sync stream is woken up,
126+
# which we hope will happen as a result of Alice updating their device list.
127+
bob_sync_channel = self.make_request(
128+
"GET",
129+
f"/sync?since={next_batch_token}&timeout=1000",
130+
access_token=bob_access_token,
131+
# Start the request, then continue on.
132+
await_result=False,
133+
)
134+
135+
# Have alice update their device list
136+
channel = self.make_request(
137+
"PUT",
138+
f"/devices/{test_device_id}",
139+
{
140+
"display_name": "New Device Name",
141+
},
142+
access_token=alice_access_token,
143+
)
144+
self.assertEqual(channel.code, 200, channel.json_body)
145+
146+
# Check that bob's incremental sync does not contain the updated device list.
147+
bob_sync_channel.await_result()
148+
self.assertEqual(bob_sync_channel.code, 200, bob_sync_channel.json_body)
149+
150+
changed_device_lists = bob_sync_channel.json_body.get("device_lists", {}).get(
151+
"changed", []
152+
)
153+
self.assertNotIn(
154+
alice_user_id, changed_device_lists, bob_sync_channel.json_body
155+
)

tests/rest/client/utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,13 @@ def create_room_as(
106106
default room version.
107107
tok: The access token to use in the request.
108108
expect_code: The expected HTTP response code.
109+
extra_content: Extra keys to include in the body of the /createRoom request.
110+
Note that if is_public is set, the "visibility" key will be overridden.
111+
If room_version is set, the "room_version" key will be overridden.
112+
custom_headers: HTTP headers to include in the request.
109113
110114
Returns:
111-
The ID of the newly created room.
115+
The ID of the newly created room, or None if the request failed.
112116
"""
113117
temp_id = self.auth_user_id
114118
self.auth_user_id = room_creator

0 commit comments

Comments
 (0)