Files
synapse/tests/test_utils/event_builders.py
T
Jason LittleandPaul Chobert 7530874a12 Raise default room version to "12" (#20130)
Requires
* #19768 
* #19782 
* https://github.com/matrix-org/complement/pull/915

To meet the requirements for bumping Synapse to support [Matrix spec to
1.16](https://github.com/element-hq/synapse/issues/19414) the default
room version should be incremented to "12".

Other than the two separate Synapse PRs above(which are included here
but marked as "[diverted]" and should be removed prior to review) there
is only [one other real
change](https://github.com/element-hq/synapse/commit/c005e96c665b5a098a9b95d10f33faf224564be9)
to the code base itself to fix a `KeyError` during logging for a `/sync`
test against unknown room versions. Everything else should be on the
unit tests themselves.

Standard unit test running applies, should be nothing special to test
this outright.
`poetry run trial -jN tests` and similar for Postgresql.

Probably ok to review commit-by-commit

I took the liberty of writing a [room creating
helper](https://github.com/element-hq/synapse/commit/5ba81ad5d4a0a6787b7626bdb3293f633ea4097a)
for the two test series that try and test the sharding of the
`event_persister` workers. I'm not certain it stands up to scrutiny, but
at least does not do any funny mocking when producing room v12
appropriate room IDs.

I also took the liberty of writing an [assertion
helper](https://github.com/element-hq/synapse/pull/20130/commits/e408cef241d1b9c6a88f069eb5832de053790f9b)
for comparing lists of dicts for a select subset of keys/values. This is
used to compare stripped state selections while waiting on
https://github.com/element-hq/synapse/pull/19723 to be completed.

### Pull Request Checklist

<!-- Please read
https://element-hq.github.io/synapse/latest/development/contributing_guide.html
before submitting your pull request -->

* [x] Pull request is based on the develop branch
* [x] Pull request includes a [changelog
file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog).
The entry should:
- Be a short description of your change which makes sense to users.
"Fixed a bug that prevented receiving messages from other servers."
instead of "Moved X method from `EventStore` to `EventWorkerStore`.".
  - Use markdown where necessary, mostly for `code blocks`.
  - End with either a period (.) or an exclamation mark (!).
  - Start with a capital letter.
- Feel free to credit yourself, by adding a sentence "Contributed by
@github_username." or "Contributed by [Your Name]." to the end of the
entry.
* [x] [Code
style](https://element-hq.github.io/synapse/latest/code_style.html) is
correct (run the
[linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters))

---------

Co-authored-by: Paul Chobert <paul@chobert.fr>
2026-09-17 18:32:51 +00:00

146 lines
4.9 KiB
Python

#
# This file is licensed under the Affero General Public License (AGPL) version 3.
#
# Copyright (C) 2026 Element Creations Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# See the GNU Affero General Public License for more details:
# <https://www.gnu.org/licenses/agpl-3.0.html>.
#
from typing import TypedDict
from typing_extensions import NotRequired, Unpack
from synapse.api.room_versions import (
RoomVersion,
RoomVersions,
)
from synapse.events import EventBase, make_event_from_dict
from synapse.federation.federation_base import event_from_pdu_json
from synapse.types import JsonDict
def default_event_fields(room_version: RoomVersion) -> JsonDict:
"""Return default values for every field required by `room_version`."""
# We need to include entries for every required field for the room version.
# Note that they don't necessarily have to be valid values, just enough to
# allow us to construct the event class. (Ideally we'd build a fully valid
# event, but this is fine for now.)
defaults: JsonDict = {
"type": "m.test",
"sender": "@test:test",
"content": {},
"depth": 1,
"origin_server_ts": 1,
"hashes": {},
"prev_events": [],
"room_id": "!test:test",
}
# MSC4242 versions require prev_state_events but not auth_events.
if room_version.msc4242_state_dags:
defaults["prev_state_events"] = []
else:
defaults["auth_events"] = []
if room_version == RoomVersions.V1:
# V1 requires an event_id field, but later versions don't.
defaults["event_id"] = "$test_event_id:matrix.org"
return defaults
def make_test_event(
event_dict: JsonDict | None = None,
room_version: RoomVersion = RoomVersions.V1,
internal_metadata_dict: JsonDict | None = None,
rejected_reason: str | None = None,
**fields: Unpack["_EventFields"],
) -> EventBase:
"""Build an `EventBase` with defaults for the strict-required fields.
Pass an `event_dict` and/or `**fields` keyword arguments — both are
merged on top of the format-version defaults from
`default_event_fields`. Explicit values win over defaults, and
`**fields` wins over `event_dict` so call sites can override a
shared base dict with one-off tweaks.
"""
merged: JsonDict = {
**default_event_fields(room_version),
**(event_dict or {}),
**fields,
}
# For room versions where the create event's room_id is derived from its
# event ID (v11+ format), omit the default room_id on create events so each
# create event ends up with a distinct room_id.
#
# We can't do this in the `default_event_fields` as we don't know the event
# type at that point.
if (
room_version.msc4291_room_ids_as_hashes
and merged["type"] == "m.room.create"
and merged["state_key"] == ""
):
merged.pop("room_id", None)
return make_event_from_dict(
merged,
room_version=room_version,
internal_metadata_dict=internal_metadata_dict,
rejected_reason=rejected_reason,
)
def make_test_pdu_event(
pdu: JsonDict,
room_version: RoomVersion,
received_time: int | None = None,
) -> EventBase:
"""Wrapper around `event_from_pdu_json` for test PDU dicts.
Federation-side test fixtures often omit fields the strict Rust ctor
requires (e.g. `hashes`, `auth_events`, `prev_events`, `depth`)
because those tests focus on transport/auth flow rather than event
well-formedness. This helper layers in the same format-version
defaults as `make_test_event` before delegating.
"""
pdu = {**default_event_fields(room_version), **pdu}
# For room versions where the create event's room_id is derived from its
# event ID (v11+ format), omit the default room_id on create events so each
# create event ends up with a distinct room_id.
#
# We can't do this in the `default_event_fields` as we don't know the event
# type at that point.
if (
room_version.msc4291_room_ids_as_hashes
and pdu["type"] == "m.room.create"
and pdu["state_key"] == ""
):
pdu.pop("room_id", None)
return event_from_pdu_json(pdu, room_version, received_time=received_time)
class _EventFields(TypedDict):
"""Type for `kwargs` in `make_test_event`."""
event_id: NotRequired[str]
type: NotRequired[str]
sender: NotRequired[str]
content: NotRequired[JsonDict]
depth: NotRequired[int]
origin_server_ts: NotRequired[int]
hashes: NotRequired[dict[str, str]]
auth_events: NotRequired[list[str]]
prev_events: NotRequired[list[str]]
prev_state_events: NotRequired[list[str]]
room_id: NotRequired[str]