diff --git a/tests/handlers/test_profile.py b/tests/handlers/test_profile.py
index 80da1c8954..d60c124eec 100644
--- a/tests/handlers/test_profile.py
+++ b/tests/handlers/test_profile.py
@@ -55,11 +55,11 @@ class ProfileTestCase(unittest.TestCase):
federation_client=self.mock_federation,
federation_server=Mock(),
federation_registry=self.mock_registry,
- ratelimiter=NonCallableMock(spec_set=["send_message"]),
+ ratelimiter=NonCallableMock(spec_set=["can_do_action"]),
)
self.ratelimiter = hs.get_ratelimiter()
- self.ratelimiter.send_message.return_value = (True, 0)
+ self.ratelimiter.can_do_action.return_value = (True, 0)
self.store = hs.get_datastore()
diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py
index 36e136cded..13486930fb 100644
--- a/tests/handlers/test_typing.py
+++ b/tests/handlers/test_typing.py
@@ -24,13 +24,17 @@ from synapse.api.errors import AuthError
from synapse.types import UserID
from tests import unittest
+from tests.utils import register_federation_servlets
-from ..utils import (
- DeferredMockCallable,
- MockClock,
- MockHttpResource,
- setup_test_homeserver,
-)
+# Some local users to test with
+U_APPLE = UserID.from_string("@apple:test")
+U_BANANA = UserID.from_string("@banana:test")
+
+# Remote user
+U_ONION = UserID.from_string("@onion:farm")
+
+# Test room id
+ROOM_ID = "a-room"
def _expect_edu_transaction(edu_type, content, origin="test"):
@@ -46,30 +50,21 @@ def _make_edu_transaction_json(edu_type, content):
return json.dumps(_expect_edu_transaction(edu_type, content)).encode('utf8')
-class TypingNotificationsTestCase(unittest.TestCase):
- """Tests typing notifications to rooms."""
-
- @defer.inlineCallbacks
- def setUp(self):
- self.clock = MockClock()
+class TypingNotificationsTestCase(unittest.HomeserverTestCase):
+ servlets = [register_federation_servlets]
- self.mock_http_client = Mock(spec=[])
- self.mock_http_client.put_json = DeferredMockCallable()
+ def make_homeserver(self, reactor, clock):
+ # we mock out the keyring so as to skip the authentication check on the
+ # federation API call.
+ mock_keyring = Mock(spec=["verify_json_for_server"])
+ mock_keyring.verify_json_for_server.return_value = defer.succeed(True)
- self.mock_federation_resource = MockHttpResource()
-
- mock_notifier = Mock()
- self.on_new_event = mock_notifier.on_new_event
+ # we mock out the federation client too
+ mock_federation_client = Mock(spec=["put_json"])
+ mock_federation_client.put_json.return_value = defer.succeed((200, "OK"))
- self.auth = Mock(spec=[])
- self.state_handler = Mock()
-
- hs = yield setup_test_homeserver(
- self.addCleanup,
- "test",
- auth=self.auth,
- clock=self.clock,
- datastore=Mock(
+ hs = self.setup_test_homeserver(
+ datastore=(Mock(
spec=[
# Bits that Federation needs
"prep_send_transaction",
@@ -82,16 +77,21 @@ class TypingNotificationsTestCase(unittest.TestCase):
"get_user_directory_stream_pos",
"get_current_state_deltas",
]
- ),
- state_handler=self.state_handler,
- handlers=Mock(),
- notifier=mock_notifier,
- resource_for_client=Mock(),
- resource_for_federation=self.mock_federation_resource,
- http_client=self.mock_http_client,
- keyring=Mock(),
+ )),
+ notifier=Mock(),
+ http_client=mock_federation_client,
+ keyring=mock_keyring,
)
+ return hs
+
+ def prepare(self, reactor, clock, hs):
+ # the tests assume that we are starting at unix time 1000
+ reactor.pump((1000, ))
+
+ mock_notifier = hs.get_notifier()
+ self.on_new_event = mock_notifier.on_new_event
+
self.handler = hs.get_typing_handler()
self.event_source = hs.get_event_sources().sources["typing"]
@@ -109,13 +109,12 @@ class TypingNotificationsTestCase(unittest.TestCase):
self.datastore.get_received_txn_response = get_received_txn_response
- self.room_id = "a-room"
-
self.room_members = []
def check_joined_room(room_id, user_id):
if user_id not in [u.to_string() for u in self.room_members]:
raise AuthError(401, "User is not in the room")
+ hs.get_auth().check_joined_room = check_joined_room
def get_joined_hosts_for_room(room_id):
return set(member.domain for member in self.room_members)
@@ -124,8 +123,7 @@ class TypingNotificationsTestCase(unittest.TestCase):
def get_current_user_in_room(room_id):
return set(str(u) for u in self.room_members)
-
- self.state_handler.get_current_user_in_room = get_current_user_in_room
+ hs.get_state_handler().get_current_user_in_room = get_current_user_in_room
self.datastore.get_user_directory_stream_pos.return_value = (
# we deliberately return a non-None stream pos to avoid doing an initial_spam
@@ -134,230 +132,208 @@ class TypingNotificationsTestCase(unittest.TestCase):
self.datastore.get_current_state_deltas.return_value = None
- self.auth.check_joined_room = check_joined_room
-
self.datastore.get_to_device_stream_token = lambda: 0
self.datastore.get_new_device_msgs_for_remote = lambda *args, **kargs: ([], 0)
self.datastore.delete_device_msgs_for_remote = lambda *args, **kargs: None
- # Some local users to test with
- self.u_apple = UserID.from_string("@apple:test")
- self.u_banana = UserID.from_string("@banana:test")
-
- # Remote user
- self.u_onion = UserID.from_string("@onion:farm")
-
- @defer.inlineCallbacks
def test_started_typing_local(self):
- self.room_members = [self.u_apple, self.u_banana]
+ self.room_members = [U_APPLE, U_BANANA]
self.assertEquals(self.event_source.get_current_key(), 0)
- yield self.handler.started_typing(
- target_user=self.u_apple,
- auth_user=self.u_apple,
- room_id=self.room_id,
+ self.successResultOf(self.handler.started_typing(
+ target_user=U_APPLE,
+ auth_user=U_APPLE,
+ room_id=ROOM_ID,
timeout=20000,
- )
+ ))
self.on_new_event.assert_has_calls(
- [call('typing_key', 1, rooms=[self.room_id])]
+ [call('typing_key', 1, rooms=[ROOM_ID])]
)
self.assertEquals(self.event_source.get_current_key(), 1)
- events = yield self.event_source.get_new_events(
- room_ids=[self.room_id], from_key=0
+ events = self.event_source.get_new_events(
+ room_ids=[ROOM_ID], from_key=0
)
self.assertEquals(
events[0],
[
{
"type": "m.typing",
- "room_id": self.room_id,
- "content": {"user_ids": [self.u_apple.to_string()]},
+ "room_id": ROOM_ID,
+ "content": {"user_ids": [U_APPLE.to_string()]},
}
],
)
- @defer.inlineCallbacks
def test_started_typing_remote_send(self):
- self.room_members = [self.u_apple, self.u_onion]
-
- put_json = self.mock_http_client.put_json
- put_json.expect_call_and_return(
- call(
- "farm",
- path="/_matrix/federation/v1/send/1000000/",
- data=_expect_edu_transaction(
- "m.typing",
- content={
- "room_id": self.room_id,
- "user_id": self.u_apple.to_string(),
- "typing": True,
- },
- ),
- json_data_callback=ANY,
- long_retries=True,
- backoff_on_404=True,
- ),
- defer.succeed((200, "OK")),
- )
+ self.room_members = [U_APPLE, U_ONION]
- yield self.handler.started_typing(
- target_user=self.u_apple,
- auth_user=self.u_apple,
- room_id=self.room_id,
+ self.successResultOf(self.handler.started_typing(
+ target_user=U_APPLE,
+ auth_user=U_APPLE,
+ room_id=ROOM_ID,
timeout=20000,
- )
+ ))
- yield put_json.await_calls()
+ put_json = self.hs.get_http_client().put_json
+ put_json.assert_called_once_with(
+ "farm",
+ path="/_matrix/federation/v1/send/1000000/",
+ data=_expect_edu_transaction(
+ "m.typing",
+ content={
+ "room_id": ROOM_ID,
+ "user_id": U_APPLE.to_string(),
+ "typing": True,
+ },
+ ),
+ json_data_callback=ANY,
+ long_retries=True,
+ backoff_on_404=True,
+ )
- @defer.inlineCallbacks
def test_started_typing_remote_recv(self):
- self.room_members = [self.u_apple, self.u_onion]
+ self.room_members = [U_APPLE, U_ONION]
self.assertEquals(self.event_source.get_current_key(), 0)
- (code, response) = yield self.mock_federation_resource.trigger(
+ (request, channel) = self.make_request(
"PUT",
"/_matrix/federation/v1/send/1000000/",
_make_edu_transaction_json(
"m.typing",
content={
- "room_id": self.room_id,
- "user_id": self.u_onion.to_string(),
+ "room_id": ROOM_ID,
+ "user_id": U_ONION.to_string(),
"typing": True,
},
),
federation_auth_origin=b'farm',
)
+ self.render(request)
+ self.assertEqual(channel.code, 200)
self.on_new_event.assert_has_calls(
- [call('typing_key', 1, rooms=[self.room_id])]
+ [call('typing_key', 1, rooms=[ROOM_ID])]
)
self.assertEquals(self.event_source.get_current_key(), 1)
- events = yield self.event_source.get_new_events(
- room_ids=[self.room_id], from_key=0
+ events = self.event_source.get_new_events(
+ room_ids=[ROOM_ID], from_key=0
)
self.assertEquals(
events[0],
[
{
"type": "m.typing",
- "room_id": self.room_id,
- "content": {"user_ids": [self.u_onion.to_string()]},
+ "room_id": ROOM_ID,
+ "content": {"user_ids": [U_ONION.to_string()]},
}
],
)
- @defer.inlineCallbacks
def test_stopped_typing(self):
- self.room_members = [self.u_apple, self.u_banana, self.u_onion]
-
- put_json = self.mock_http_client.put_json
- put_json.expect_call_and_return(
- call(
- "farm",
- path="/_matrix/federation/v1/send/1000000/",
- data=_expect_edu_transaction(
- "m.typing",
- content={
- "room_id": self.room_id,
- "user_id": self.u_apple.to_string(),
- "typing": False,
- },
- ),
- json_data_callback=ANY,
- long_retries=True,
- backoff_on_404=True,
- ),
- defer.succeed((200, "OK")),
- )
+ self.room_members = [U_APPLE, U_BANANA, U_ONION]
# Gut-wrenching
from synapse.handlers.typing import RoomMember
- member = RoomMember(self.room_id, self.u_apple.to_string())
+ member = RoomMember(ROOM_ID, U_APPLE.to_string())
self.handler._member_typing_until[member] = 1002000
- self.handler._room_typing[self.room_id] = set([self.u_apple.to_string()])
+ self.handler._room_typing[ROOM_ID] = set([U_APPLE.to_string()])
self.assertEquals(self.event_source.get_current_key(), 0)
- yield self.handler.stopped_typing(
- target_user=self.u_apple, auth_user=self.u_apple, room_id=self.room_id
- )
+ self.successResultOf(self.handler.stopped_typing(
+ target_user=U_APPLE, auth_user=U_APPLE, room_id=ROOM_ID
+ ))
self.on_new_event.assert_has_calls(
- [call('typing_key', 1, rooms=[self.room_id])]
+ [call('typing_key', 1, rooms=[ROOM_ID])]
)
- yield put_json.await_calls()
+ put_json = self.hs.get_http_client().put_json
+ put_json.assert_called_once_with(
+ "farm",
+ path="/_matrix/federation/v1/send/1000000/",
+ data=_expect_edu_transaction(
+ "m.typing",
+ content={
+ "room_id": ROOM_ID,
+ "user_id": U_APPLE.to_string(),
+ "typing": False,
+ },
+ ),
+ json_data_callback=ANY,
+ long_retries=True,
+ backoff_on_404=True,
+ )
self.assertEquals(self.event_source.get_current_key(), 1)
- events = yield self.event_source.get_new_events(
- room_ids=[self.room_id], from_key=0
+ events = self.event_source.get_new_events(
+ room_ids=[ROOM_ID], from_key=0
)
self.assertEquals(
events[0],
[
{
"type": "m.typing",
- "room_id": self.room_id,
+ "room_id": ROOM_ID,
"content": {"user_ids": []},
}
],
)
- @defer.inlineCallbacks
def test_typing_timeout(self):
- self.room_members = [self.u_apple, self.u_banana]
+ self.room_members = [U_APPLE, U_BANANA]
self.assertEquals(self.event_source.get_current_key(), 0)
- yield self.handler.started_typing(
- target_user=self.u_apple,
- auth_user=self.u_apple,
- room_id=self.room_id,
+ self.successResultOf(self.handler.started_typing(
+ target_user=U_APPLE,
+ auth_user=U_APPLE,
+ room_id=ROOM_ID,
timeout=10000,
- )
+ ))
self.on_new_event.assert_has_calls(
- [call('typing_key', 1, rooms=[self.room_id])]
+ [call('typing_key', 1, rooms=[ROOM_ID])]
)
self.on_new_event.reset_mock()
self.assertEquals(self.event_source.get_current_key(), 1)
- events = yield self.event_source.get_new_events(
- room_ids=[self.room_id], from_key=0
+ events = self.event_source.get_new_events(
+ room_ids=[ROOM_ID], from_key=0
)
self.assertEquals(
events[0],
[
{
"type": "m.typing",
- "room_id": self.room_id,
- "content": {"user_ids": [self.u_apple.to_string()]},
+ "room_id": ROOM_ID,
+ "content": {"user_ids": [U_APPLE.to_string()]},
}
],
)
- self.clock.advance_time(16)
+ self.reactor.pump([16, ])
self.on_new_event.assert_has_calls(
- [call('typing_key', 2, rooms=[self.room_id])]
+ [call('typing_key', 2, rooms=[ROOM_ID])]
)
self.assertEquals(self.event_source.get_current_key(), 2)
- events = yield self.event_source.get_new_events(
- room_ids=[self.room_id], from_key=1
+ events = self.event_source.get_new_events(
+ room_ids=[ROOM_ID], from_key=1
)
self.assertEquals(
events[0],
[
{
"type": "m.typing",
- "room_id": self.room_id,
+ "room_id": ROOM_ID,
"content": {"user_ids": []},
}
],
@@ -365,29 +341,29 @@ class TypingNotificationsTestCase(unittest.TestCase):
# SYN-230 - see if we can still set after timeout
- yield self.handler.started_typing(
- target_user=self.u_apple,
- auth_user=self.u_apple,
- room_id=self.room_id,
+ self.successResultOf(self.handler.started_typing(
+ target_user=U_APPLE,
+ auth_user=U_APPLE,
+ room_id=ROOM_ID,
timeout=10000,
- )
+ ))
self.on_new_event.assert_has_calls(
- [call('typing_key', 3, rooms=[self.room_id])]
+ [call('typing_key', 3, rooms=[ROOM_ID])]
)
self.on_new_event.reset_mock()
self.assertEquals(self.event_source.get_current_key(), 3)
- events = yield self.event_source.get_new_events(
- room_ids=[self.room_id], from_key=0
+ events = self.event_source.get_new_events(
+ room_ids=[ROOM_ID], from_key=0
)
self.assertEquals(
events[0],
[
{
"type": "m.typing",
- "room_id": self.room_id,
- "content": {"user_ids": [self.u_apple.to_string()]},
+ "room_id": ROOM_ID,
+ "content": {"user_ids": [U_APPLE.to_string()]},
}
],
)
diff --git a/tests/handlers/test_user_directory.py b/tests/handlers/test_user_directory.py
index 11f2bae698..aefe11ac28 100644
--- a/tests/handlers/test_user_directory.py
+++ b/tests/handlers/test_user_directory.py
@@ -14,78 +14,306 @@
# limitations under the License.
from mock import Mock
-from twisted.internet import defer
-
from synapse.api.constants import UserTypes
-from synapse.handlers.user_directory import UserDirectoryHandler
+from synapse.rest.client.v1 import admin, login, room
from synapse.storage.roommember import ProfileInfo
from tests import unittest
-from tests.utils import setup_test_homeserver
-class UserDirectoryHandlers(object):
- def __init__(self, hs):
- self.user_directory_handler = UserDirectoryHandler(hs)
+class UserDirectoryTestCase(unittest.HomeserverTestCase):
+ """
+ Tests the UserDirectoryHandler.
+ """
+ servlets = [
+ login.register_servlets,
+ admin.register_servlets,
+ room.register_servlets,
+ ]
-class UserDirectoryTestCase(unittest.TestCase):
- """ Tests the UserDirectoryHandler. """
+ def make_homeserver(self, reactor, clock):
- @defer.inlineCallbacks
- def setUp(self):
- hs = yield setup_test_homeserver(self.addCleanup)
- self.store = hs.get_datastore()
- hs.handlers = UserDirectoryHandlers(hs)
+ config = self.default_config()
+ config.update_user_directory = True
+ return self.setup_test_homeserver(config=config)
- self.handler = hs.get_handlers().user_directory_handler
+ def prepare(self, reactor, clock, hs):
+ self.store = hs.get_datastore()
+ self.handler = hs.get_user_directory_handler()
- @defer.inlineCallbacks
def test_handle_local_profile_change_with_support_user(self):
support_user_id = "@support:test"
- yield self.store.register(
- user_id=support_user_id,
- token="123",
- password_hash=None,
- user_type=UserTypes.SUPPORT
+ self.get_success(
+ self.store.register(
+ user_id=support_user_id,
+ token="123",
+ password_hash=None,
+ user_type=UserTypes.SUPPORT,
+ )
)
- yield self.handler.handle_local_profile_change(support_user_id, None)
- profile = yield self.store.get_user_in_directory(support_user_id)
+ self.get_success(
+ self.handler.handle_local_profile_change(support_user_id, None)
+ )
+ profile = self.get_success(self.store.get_user_in_directory(support_user_id))
self.assertTrue(profile is None)
display_name = 'display_name'
- profile_info = ProfileInfo(
- avatar_url='avatar_url',
- display_name=display_name,
- )
+ profile_info = ProfileInfo(avatar_url='avatar_url', display_name=display_name)
regular_user_id = '@regular:test'
- yield self.handler.handle_local_profile_change(regular_user_id, profile_info)
- profile = yield self.store.get_user_in_directory(regular_user_id)
+ self.get_success(
+ self.handler.handle_local_profile_change(regular_user_id, profile_info)
+ )
+ profile = self.get_success(self.store.get_user_in_directory(regular_user_id))
self.assertTrue(profile['display_name'] == display_name)
- @defer.inlineCallbacks
def test_handle_user_deactivated_support_user(self):
s_user_id = "@support:test"
- self.store.register(
- user_id=s_user_id,
- token="123",
- password_hash=None,
- user_type=UserTypes.SUPPORT
+ self.get_success(
+ self.store.register(
+ user_id=s_user_id,
+ token="123",
+ password_hash=None,
+ user_type=UserTypes.SUPPORT,
+ )
)
self.store.remove_from_user_dir = Mock()
self.store.remove_from_user_in_public_room = Mock()
- yield self.handler.handle_user_deactivated(s_user_id)
+ self.get_success(self.handler.handle_user_deactivated(s_user_id))
self.store.remove_from_user_dir.not_called()
self.store.remove_from_user_in_public_room.not_called()
- @defer.inlineCallbacks
def test_handle_user_deactivated_regular_user(self):
r_user_id = "@regular:test"
- self.store.register(user_id=r_user_id, token="123", password_hash=None)
+ self.get_success(
+ self.store.register(user_id=r_user_id, token="123", password_hash=None)
+ )
self.store.remove_from_user_dir = Mock()
- self.store.remove_from_user_in_public_room = Mock()
- yield self.handler.handle_user_deactivated(r_user_id)
+ self.get_success(self.handler.handle_user_deactivated(r_user_id))
self.store.remove_from_user_dir.called_once_with(r_user_id)
- self.store.remove_from_user_in_public_room.assert_called_once_with(r_user_id)
+
+ def test_private_room(self):
+ """
+ A user can be searched for only by people that are either in a public
+ room, or that share a private chat.
+ """
+ u1 = self.register_user("user1", "pass")
+ u1_token = self.login(u1, "pass")
+ u2 = self.register_user("user2", "pass")
+ u2_token = self.login(u2, "pass")
+ u3 = self.register_user("user3", "pass")
+
+ # We do not add users to the directory until they join a room.
+ s = self.get_success(self.handler.search_users(u1, "user2", 10))
+ self.assertEqual(len(s["results"]), 0)
+
+ room = self.helper.create_room_as(u1, is_public=False, tok=u1_token)
+ self.helper.invite(room, src=u1, targ=u2, tok=u1_token)
+ self.helper.join(room, user=u2, tok=u2_token)
+
+ # Check we have populated the database correctly.
+ shares_private = self.get_users_who_share_private_rooms()
+ public_users = self.get_users_in_public_rooms()
+
+ self.assertEqual(
+ self._compress_shared(shares_private), set([(u1, u2, room), (u2, u1, room)])
+ )
+ self.assertEqual(public_users, [])
+
+ # We get one search result when searching for user2 by user1.
+ s = self.get_success(self.handler.search_users(u1, "user2", 10))
+ self.assertEqual(len(s["results"]), 1)
+
+ # We get NO search results when searching for user2 by user3.
+ s = self.get_success(self.handler.search_users(u3, "user2", 10))
+ self.assertEqual(len(s["results"]), 0)
+
+ # We get NO search results when searching for user3 by user1.
+ s = self.get_success(self.handler.search_users(u1, "user3", 10))
+ self.assertEqual(len(s["results"]), 0)
+
+ # User 2 then leaves.
+ self.helper.leave(room, user=u2, tok=u2_token)
+
+ # Check we have removed the values.
+ shares_private = self.get_users_who_share_private_rooms()
+ public_users = self.get_users_in_public_rooms()
+
+ self.assertEqual(self._compress_shared(shares_private), set())
+ self.assertEqual(public_users, [])
+
+ # User1 now gets no search results for any of the other users.
+ s = self.get_success(self.handler.search_users(u1, "user2", 10))
+ self.assertEqual(len(s["results"]), 0)
+
+ s = self.get_success(self.handler.search_users(u1, "user3", 10))
+ self.assertEqual(len(s["results"]), 0)
+
+ def _compress_shared(self, shared):
+ """
+ Compress a list of users who share rooms dicts to a list of tuples.
+ """
+ r = set()
+ for i in shared:
+ r.add((i["user_id"], i["other_user_id"], i["room_id"]))
+ return r
+
+ def get_users_in_public_rooms(self):
+ r = self.get_success(
+ self.store._simple_select_list(
+ "users_in_public_rooms", None, ("user_id", "room_id")
+ )
+ )
+ retval = []
+ for i in r:
+ retval.append((i["user_id"], i["room_id"]))
+ return retval
+
+ def get_users_who_share_private_rooms(self):
+ return self.get_success(
+ self.store._simple_select_list(
+ "users_who_share_private_rooms",
+ None,
+ ["user_id", "other_user_id", "room_id"],
+ )
+ )
+
+ def _add_background_updates(self):
+ """
+ Add the background updates we need to run.
+ """
+ # Ugh, have to reset this flag
+ self.store._all_done = False
+
+ self.get_success(
+ self.store._simple_insert(
+ "background_updates",
+ {
+ "update_name": "populate_user_directory_createtables",
+ "progress_json": "{}",
+ },
+ )
+ )
+ self.get_success(
+ self.store._simple_insert(
+ "background_updates",
+ {
+ "update_name": "populate_user_directory_process_rooms",
+ "progress_json": "{}",
+ "depends_on": "populate_user_directory_createtables",
+ },
+ )
+ )
+ self.get_success(
+ self.store._simple_insert(
+ "background_updates",
+ {
+ "update_name": "populate_user_directory_process_users",
+ "progress_json": "{}",
+ "depends_on": "populate_user_directory_process_rooms",
+ },
+ )
+ )
+ self.get_success(
+ self.store._simple_insert(
+ "background_updates",
+ {
+ "update_name": "populate_user_directory_cleanup",
+ "progress_json": "{}",
+ "depends_on": "populate_user_directory_process_users",
+ },
+ )
+ )
+
+ def test_initial(self):
+ """
+ The user directory's initial handler correctly updates the search tables.
+ """
+ u1 = self.register_user("user1", "pass")
+ u1_token = self.login(u1, "pass")
+ u2 = self.register_user("user2", "pass")
+ u2_token = self.login(u2, "pass")
+ u3 = self.register_user("user3", "pass")
+ u3_token = self.login(u3, "pass")
+
+ room = self.helper.create_room_as(u1, is_public=True, tok=u1_token)
+ self.helper.invite(room, src=u1, targ=u2, tok=u1_token)
+ self.helper.join(room, user=u2, tok=u2_token)
+
+ private_room = self.helper.create_room_as(u1, is_public=False, tok=u1_token)
+ self.helper.invite(private_room, src=u1, targ=u3, tok=u1_token)
+ self.helper.join(private_room, user=u3, tok=u3_token)
+
+ self.get_success(self.store.update_user_directory_stream_pos(None))
+ self.get_success(self.store.delete_all_from_user_dir())
+
+ shares_private = self.get_users_who_share_private_rooms()
+ public_users = self.get_users_in_public_rooms()
+
+ # Nothing updated yet
+ self.assertEqual(shares_private, [])
+ self.assertEqual(public_users, [])
+
+ # Do the initial population of the user directory via the background update
+ self._add_background_updates()
+
+ while not self.get_success(self.store.has_completed_background_updates()):
+ self.get_success(self.store.do_next_background_update(100), by=0.1)
+
+ shares_private = self.get_users_who_share_private_rooms()
+ public_users = self.get_users_in_public_rooms()
+
+ # User 1 and User 2 are in the same public room
+ self.assertEqual(set(public_users), set([(u1, room), (u2, room)]))
+
+ # User 1 and User 3 share private rooms
+ self.assertEqual(
+ self._compress_shared(shares_private),
+ set([(u1, u3, private_room), (u3, u1, private_room)]),
+ )
+
+ def test_initial_share_all_users(self):
+ """
+ Search all users = True means that a user does not have to share a
+ private room with the searching user or be in a public room to be search
+ visible.
+ """
+ self.handler.search_all_users = True
+ self.hs.config.user_directory_search_all_users = True
+
+ u1 = self.register_user("user1", "pass")
+ self.register_user("user2", "pass")
+ u3 = self.register_user("user3", "pass")
+
+ # Wipe the user dir
+ self.get_success(self.store.update_user_directory_stream_pos(None))
+ self.get_success(self.store.delete_all_from_user_dir())
+
+ # Do the initial population of the user directory via the background update
+ self._add_background_updates()
+
+ while not self.get_success(self.store.has_completed_background_updates()):
+ self.get_success(self.store.do_next_background_update(100), by=0.1)
+
+ shares_private = self.get_users_who_share_private_rooms()
+ public_users = self.get_users_in_public_rooms()
+
+ # No users share rooms
+ self.assertEqual(public_users, [])
+ self.assertEqual(self._compress_shared(shares_private), set([]))
+
+ # Despite not sharing a room, search_all_users means we get a search
+ # result.
+ s = self.get_success(self.handler.search_users(u1, u3, 10))
+ self.assertEqual(len(s["results"]), 1)
+
+ # We can find the other two users
+ s = self.get_success(self.handler.search_users(u1, "user", 10))
+ self.assertEqual(len(s["results"]), 2)
+
+ # Registering a user and then searching for them works.
+ u4 = self.register_user("user4", "pass")
+ s = self.get_success(self.handler.search_users(u1, u4, 10))
+ self.assertEqual(len(s["results"]), 1)
|