def __init__(self, id, sender, type, state_key, content): self.node_id = id self.event_id = EventID(id, "example.com").to_string() self.sender = sender self.type = type self.state_key = state_key self.content = content
def create_event_id(self): i = str(self.event_id_count) self.event_id_count += 1 local_part = str(int(self.clock.time())) + i + random_string(5) e_id = EventID(local_part, self.hostname) return e_id.to_string()
def __init__( self, id: str, sender: str, type: str, state_key: Optional[str], content: Mapping[str, object], ): self.node_id = id self.event_id = EventID(id, "example.com").to_string() self.sender = sender self.type = type self.state_key = state_key self.content = content self.room_id = ROOM_ID
def _create_event_id(clock, hostname): """Create a new event ID Args: clock (Clock) hostname (str): The server name for the event ID Returns: str """ global _event_id_counter i = str(_event_id_counter) _event_id_counter += 1 local_part = str(int(clock.time())) + i + random_string(5) e_id = EventID(local_part, hostname) return e_id.to_string()
def do_check(self, events, edges, expected_state_ids): """Take a list of events and edges and calculate the state of the graph at END, and asserts it matches `expected_state_ids` Args: events (list[FakeEvent]) edges (list[list[str]]): A list of chains of event edges, e.g. `[[A, B, C]]` are edges A->B and B->C. expected_state_ids (list[str]): The expected state at END, (excluding the keys that haven't changed since START). """ # We want to sort the events into topological order for processing. graph = {} # node_id -> FakeEvent fake_event_map = {} for ev in itertools.chain(INITIAL_EVENTS, events): graph[ev.node_id] = set() fake_event_map[ev.node_id] = ev for a, b in pairwise(INITIAL_EDGES): graph[a].add(b) for edge_list in edges: for a, b in pairwise(edge_list): graph[a].add(b) # event_id -> FrozenEvent event_map = {} # node_id -> state state_at_event = {} # We copy the map as the sort consumes the graph graph_copy = {k: set(v) for k, v in graph.items()} for node_id in lexicographical_topological_sort(graph_copy, key=lambda e: e): fake_event = fake_event_map[node_id] event_id = fake_event.event_id prev_events = list(graph[node_id]) if len(prev_events) == 0: state_before = {} elif len(prev_events) == 1: state_before = dict(state_at_event[prev_events[0]]) else: state_d = resolve_events_with_store( FakeClock(), ROOM_ID, RoomVersions.V2.identifier, [state_at_event[n] for n in prev_events], event_map=event_map, state_res_store=TestStateResolutionStore(event_map), ) state_before = self.successResultOf( defer.ensureDeferred(state_d)) state_after = dict(state_before) if fake_event.state_key is not None: state_after[(fake_event.type, fake_event.state_key)] = event_id auth_types = set(auth_types_for_event(fake_event)) auth_events = [] for key in auth_types: if key in state_before: auth_events.append(state_before[key]) event = fake_event.to_event(auth_events, prev_events) state_at_event[node_id] = state_after event_map[event_id] = event expected_state = {} for node_id in expected_state_ids: # expected_state_ids are node IDs rather than event IDs, # so we have to convert event_id = EventID(node_id, "example.com").to_string() event = event_map[event_id] key = (event.type, event.state_key) expected_state[key] = event_id start_state = state_at_event["START"] end_state = { key: value for key, value in state_at_event["END"].items() if key in expected_state or start_state.get(key) != value } self.assertEqual(expected_state, end_state)
def to_event_id(s): return EventID(s, SERVER_NAME).to_string()
def do_check( self, events: List[FakeEvent], edges: List[List[str]], expected_state_ids: List[str], ) -> None: """Take a list of events and edges and calculate the state of the graph at END, and asserts it matches `expected_state_ids` Args: events edges: A list of chains of event edges, e.g. `[[A, B, C]]` are edges A->B and B->C. expected_state_ids: The expected state at END, (excluding the keys that haven't changed since START). """ # We want to sort the events into topological order for processing. graph: Dict[str, Set[str]] = {} fake_event_map: Dict[str, FakeEvent] = {} for ev in itertools.chain(INITIAL_EVENTS, events): graph[ev.node_id] = set() fake_event_map[ev.node_id] = ev for a, b in pairwise(INITIAL_EDGES): graph[a].add(b) for edge_list in edges: for a, b in pairwise(edge_list): graph[a].add(b) event_map: Dict[str, EventBase] = {} state_at_event: Dict[str, StateMap[str]] = {} # We copy the map as the sort consumes the graph graph_copy = {k: set(v) for k, v in graph.items()} for node_id in lexicographical_topological_sort(graph_copy, key=lambda e: e): fake_event = fake_event_map[node_id] event_id = fake_event.event_id prev_events = list(graph[node_id]) state_before: StateMap[str] if len(prev_events) == 0: state_before = {} elif len(prev_events) == 1: state_before = dict(state_at_event[prev_events[0]]) else: state_d = resolve_events_with_store( FakeClock(), ROOM_ID, RoomVersions.V2, [state_at_event[n] for n in prev_events], event_map=event_map, state_res_store=TestStateResolutionStore(event_map), ) state_before = self.successResultOf( defer.ensureDeferred(state_d)) state_after = dict(state_before) if fake_event.state_key is not None: state_after[(fake_event.type, fake_event.state_key)] = event_id # This type ignore is a bit sad. Things we have tried: # 1. Define a `GenericEvent` Protocol satisfied by FakeEvent, EventBase and # EventBuilder. But this is Hard because the relevant attributes are # DictProperty[T] descriptors on EventBase but normal Ts on FakeEvent. # 2. Define a `GenericEvent` Protocol describing `FakeEvent` only, and # change this function to accept Union[Event, EventBase, EventBuilder]. # This seems reasonable to me, but mypy isn't happy. I think that's # a mypy bug, see https://github.com/python/mypy/issues/5570 # Instead, resort to a type-ignore. auth_types = set(auth_types_for_event( RoomVersions.V6, fake_event)) # type: ignore[arg-type] auth_events = [] for key in auth_types: if key in state_before: auth_events.append(state_before[key]) event = fake_event.to_event(auth_events, prev_events) state_at_event[node_id] = state_after event_map[event_id] = event expected_state = {} for node_id in expected_state_ids: # expected_state_ids are node IDs rather than event IDs, # so we have to convert event_id = EventID(node_id, "example.com").to_string() event = event_map[event_id] key = (event.type, event.state_key) expected_state[key] = event_id start_state = state_at_event["START"] end_state = { key: value for key, value in state_at_event["END"].items() if key in expected_state or start_state.get(key) != value } self.assertEqual(expected_state, end_state)