def inject_event(hs: synapse.server.HomeServer, room_version: Optional[str] = None, prev_event_ids: Optional[Collection[str]] = None, **kwargs) -> EventBase: """Inject a generic event into a room Args: hs: the homeserver under test room_version: the version of the room we're inserting into. if not specified, will be looked up prev_event_ids: prev_events for the event. If not specified, will be looked up kwargs: fields for the event to be created """ test_reactor = hs.get_reactor() if room_version is None: d = hs.get_datastore().get_room_version_id(kwargs["room_id"]) test_reactor.advance(0) room_version = get_awaitable_result(d) builder = hs.get_event_builder_factory().for_room_version( KNOWN_ROOM_VERSIONS[room_version], kwargs) d = hs.get_event_creation_handler().create_new_client_event( builder, prev_event_ids=prev_event_ids) test_reactor.advance(0) event, context = get_awaitable_result(d) d = hs.get_storage().persistence.persist_event(event, context) test_reactor.advance(0) get_awaitable_result(d) return event
def test_unexpected_auth_events(self): """Events with excess auth_events should be rejected https://spec.matrix.org/v1.3/rooms/v9/#authorization-rules 2. Reject if event has auth_events that: 2. have entries whose type and state_key don’t match those specified by the auth events selection algorithm described in the server specification. """ creator = "@creator:example.com" create_event = _create_event(RoomVersions.V9, creator) join_event = _join_event(RoomVersions.V9, creator) pl_event = _power_levels_event( RoomVersions.V9, creator, { "state_default": 30, "users": { "creator": 100 } }, ) join_rules_event = _join_rules_event(RoomVersions.V9, creator, "public") event_store = _StubEventSourceStore() event_store.add_events( [create_event, join_event, pl_event, join_rules_event]) good_event = _random_state_event(RoomVersions.V9, creator, [create_event, join_event, pl_event]) # join rules should *not* be included in the auth events. bad_event = _random_state_event( RoomVersions.V9, creator, [create_event, join_event, pl_event, join_rules_event], ) get_awaitable_result( event_auth.check_state_independent_auth_rules( event_store, good_event)) with self.assertRaises(AuthError): get_awaitable_result( event_auth.check_state_independent_auth_rules( event_store, bad_event))
def create_event(hs: synapse.server.HomeServer, room_version: Optional[str] = None, prev_event_ids: Optional[Collection[str]] = None, **kwargs) -> Tuple[EventBase, EventContext]: test_reactor = hs.get_reactor() if room_version is None: d = hs.get_datastore().get_room_version_id(kwargs["room_id"]) test_reactor.advance(0) room_version = get_awaitable_result(d) builder = hs.get_event_builder_factory().for_room_version( KNOWN_ROOM_VERSIONS[room_version], kwargs) d = hs.get_event_creation_handler().create_new_client_event( builder, prev_event_ids=prev_event_ids) test_reactor.advance(0) event, context = get_awaitable_result(d) return event, context
def test_fast_call(self): """ Test the behaviour when the underlying function completes immediately """ async def f(): return 12 fast_call = Mock(side_effect=f) cached_call = CachedCall(fast_call) # the mock should not yet have been called fast_call.assert_not_called() # run the call a couple of times, which should complete immediately self.assertEqual(get_awaitable_result(cached_call.get()), 12) self.assertEqual(get_awaitable_result(cached_call.get()), 12) # the mock should have been called once fast_call.assert_called_once_with()
def test_create_event_with_prev_events(self): """A create event with prev_events should be rejected https://spec.matrix.org/v1.3/rooms/v9/#authorization-rules 1: If type is m.room.create: 1. If it has any previous events, reject. """ creator = f"@creator:{TEST_DOMAIN}" # we make both a good event and a bad event, to check that we are rejecting # the bad event for the reason we think we are. good_event = make_event_from_dict( { "room_id": TEST_ROOM_ID, "type": "m.room.create", "state_key": "", "sender": creator, "content": { "creator": creator, "room_version": RoomVersions.V9.identifier, }, "auth_events": [], "prev_events": [], }, room_version=RoomVersions.V9, ) bad_event = make_event_from_dict( { **good_event.get_dict(), "prev_events": ["$fakeevent"] }, room_version=RoomVersions.V9, ) event_store = _StubEventSourceStore() get_awaitable_result( event_auth.check_state_independent_auth_rules( event_store, good_event)) with self.assertRaises(AuthError): get_awaitable_result( event_auth.check_state_independent_auth_rules( event_store, bad_event))
def inject_event(hs: synapse.server.HomeServer, room_version: Optional[str] = None, prev_event_ids: Optional[Collection[str]] = None, **kwargs) -> EventBase: """Inject a generic event into a room Args: hs: the homeserver under test room_version: the version of the room we're inserting into. if not specified, will be looked up prev_event_ids: prev_events for the event. If not specified, will be looked up kwargs: fields for the event to be created """ test_reactor = hs.get_reactor() event, context = create_event(hs, room_version, prev_event_ids, **kwargs) d = hs.get_storage().persistence.persist_event(event, context) test_reactor.advance(0) get_awaitable_result(d) return event
def test_get(self): """ Happy-path test case: makes a couple of calls and makes sure they behave correctly """ d = Deferred() async def f(): return await d slow_call = Mock(side_effect=f) cached_call = CachedCall(slow_call) # the mock should not yet have been called slow_call.assert_not_called() # now fire off a couple of calls completed_results = [] async def r(): res = await cached_call.get() completed_results.append(res) r1 = defer.ensureDeferred(r()) r2 = defer.ensureDeferred(r()) # neither result should be complete yet self.assertNoResult(r1) self.assertNoResult(r2) # and the mock should have been called *once*, with no params slow_call.assert_called_once_with() # allow the deferred to complete, which should complete both the pending results d.callback(123) self.assertEqual(completed_results, [123, 123]) self.successResultOf(r1) self.successResultOf(r2) # another call to the getter should complete immediately slow_call.reset_mock() r3 = get_awaitable_result(cached_call.get()) self.assertEqual(r3, 123) slow_call.assert_not_called()
def test_duplicate_auth_events(self): """Events with duplicate auth_events should be rejected https://spec.matrix.org/v1.3/rooms/v9/#authorization-rules 2. Reject if event has auth_events that: 1. have duplicate entries for a given type and state_key pair """ creator = "@creator:example.com" create_event = _create_event(RoomVersions.V9, creator) join_event1 = _join_event(RoomVersions.V9, creator) pl_event = _power_levels_event( RoomVersions.V9, creator, { "state_default": 30, "users": { "creator": 100 } }, ) # create a second join event, so that we can make a duplicate join_event2 = _join_event(RoomVersions.V9, creator) event_store = _StubEventSourceStore() event_store.add_events( [create_event, join_event1, join_event2, pl_event]) good_event = _random_state_event(RoomVersions.V9, creator, [create_event, join_event2, pl_event]) bad_event = _random_state_event( RoomVersions.V9, creator, [create_event, join_event1, join_event2, pl_event]) # a variation: two instances of the *same* event bad_event2 = _random_state_event( RoomVersions.V9, creator, [create_event, join_event2, join_event2, pl_event]) get_awaitable_result( event_auth.check_state_independent_auth_rules( event_store, good_event)) with self.assertRaises(AuthError): get_awaitable_result( event_auth.check_state_independent_auth_rules( event_store, bad_event)) with self.assertRaises(AuthError): get_awaitable_result( event_auth.check_state_independent_auth_rules( event_store, bad_event2))
def test_rejected_auth_events(self): """ Events that refer to rejected events in their auth events are rejected """ creator = "@creator:example.com" auth_events = [ _create_event(RoomVersions.V9, creator), _join_event(RoomVersions.V9, creator), ] event_store = _StubEventSourceStore() event_store.add_events(auth_events) # creator should be able to send state event = _random_state_event(RoomVersions.V9, creator, auth_events) get_awaitable_result( event_auth.check_state_independent_auth_rules(event_store, event)) event_auth.check_state_dependent_auth_rules(event, auth_events) # ... but a rejected join_rules event should cause it to be rejected rejected_join_rules = _join_rules_event( RoomVersions.V9, creator, "public", ) rejected_join_rules.rejected_reason = "stinky" auth_events.append(rejected_join_rules) event_store.add_event(rejected_join_rules) with self.assertRaises(AuthError): get_awaitable_result( event_auth.check_state_independent_auth_rules( event_store, _random_state_event(RoomVersions.V9, creator), )) # ... even if there is *also* a good join rules auth_events.append( _join_rules_event(RoomVersions.V9, creator, "public")) event_store.add_event(rejected_join_rules) with self.assertRaises(AuthError): get_awaitable_result( event_auth.check_state_independent_auth_rules( event_store, _random_state_event(RoomVersions.V9, creator), ))
def test_invalidate_cascade(self): """Invalidations should cascade up through cache contexts""" class Cls: @cached(cache_context=True) async def func1(self, key, cache_context): return await self.func2(key, on_invalidate=cache_context.invalidate) @cached(cache_context=True) async def func2(self, key, cache_context): return self.func3(key, on_invalidate=cache_context.invalidate) @lru_cache(cache_context=True) def func3(self, key, cache_context): self.invalidate = cache_context.invalidate return 42 obj = Cls() top_invalidate = mock.Mock() r = get_awaitable_result(obj.func1("k1", on_invalidate=top_invalidate)) self.assertEqual(r, 42) obj.invalidate() top_invalidate.assert_called_once()
def test_skip_verification(self): """Provider metadata validation can be disabled by config.""" with self.metadata_edit({"issuer": "http://insecure"}): # This should not throw get_awaitable_result(self.provider.load_metadata())
def force_load_metadata(): async def force_load(): return await h.load_metadata(force=True) return get_awaitable_result(force_load())
def test_get(self): # set up the RetryOnExceptionCachedCall around a function which will fail # (after a while) d = Deferred() async def f1(): await d raise ValueError("moo") slow_call = Mock(side_effect=f1) cached_call = RetryOnExceptionCachedCall(slow_call) # the mock should not yet have been called slow_call.assert_not_called() # now fire off a couple of calls completed_results = [] async def r(): try: await cached_call.get() except Exception as e1: completed_results.append(e1) r1 = defer.ensureDeferred(r()) r2 = defer.ensureDeferred(r()) # neither result should be complete yet self.assertNoResult(r1) self.assertNoResult(r2) # and the mock should have been called *once*, with no params slow_call.assert_called_once_with() # complete the deferred, which should make the pending calls fail d.callback(0) self.assertEqual(len(completed_results), 2) for e in completed_results: self.assertIsInstance(e, ValueError) self.assertEqual(e.args, ("moo", )) # reset the mock to return a successful result, and make another pair of calls # to the getter d = Deferred() async def f2(): return await d slow_call.reset_mock() slow_call.side_effect = f2 r3 = defer.ensureDeferred(cached_call.get()) r4 = defer.ensureDeferred(cached_call.get()) self.assertNoResult(r3) self.assertNoResult(r4) slow_call.assert_called_once_with() # let that call complete, and check the results d.callback(123) self.assertEqual(self.successResultOf(r3), 123) self.assertEqual(self.successResultOf(r4), 123) # and now more calls to the getter should complete immediately slow_call.reset_mock() self.assertEqual(get_awaitable_result(cached_call.get()), 123) slow_call.assert_not_called()