mirror of
https://github.com/element-hq/synapse.git
synced 2026-08-28 05:04:38 +00:00
Add test that required state is immediately returned
This commit is contained in:
@@ -2245,3 +2245,69 @@ class SlidingSyncRoomsRequiredStateTestCase(SlidingSyncBase):
|
||||
response_body["rooms"][room_id]["required_state"][0]["event_id"],
|
||||
first_event_id,
|
||||
)
|
||||
|
||||
def test_changing_required_state_returns_immediately(self) -> None:
|
||||
"""Test that if we change the required state, then we return immediately
|
||||
with the new required state."""
|
||||
|
||||
user1_id = self.register_user("user1", "pass")
|
||||
user1_tok = self.login(user1_id, "pass")
|
||||
|
||||
room_id1 = self.helper.create_room_as(user1_id, tok=user1_tok)
|
||||
|
||||
# Make an initial sync request with no required state
|
||||
sync_body = {
|
||||
"lists": {
|
||||
"foo-list": {
|
||||
"ranges": [[0, 1]],
|
||||
"required_state": [],
|
||||
"timeline_limit": 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
response_body, from_token = self.do_sync(sync_body, tok=user1_tok)
|
||||
|
||||
# We should see no required state
|
||||
self.assertIsNone(response_body["rooms"][room_id1].get("required_state"))
|
||||
|
||||
# Get the state_map before we change the state as this is the final state we
|
||||
# expect to see when we update the required state.
|
||||
state_map = self.get_success(
|
||||
self.storage_controllers.state.get_current_state(room_id1)
|
||||
)
|
||||
|
||||
# There is no new data, and so making another sync request will block.
|
||||
channel = self.make_sync_request(
|
||||
sync_body,
|
||||
since=from_token,
|
||||
tok=user1_tok,
|
||||
timeout_ms=10_000,
|
||||
await_result=False,
|
||||
)
|
||||
self.reactor.advance(0.1) # Allow the request to start processing
|
||||
self.reactor.advance(9.5)
|
||||
self.assertFalse(channel.is_finished())
|
||||
|
||||
# Advance past the timeout to make sure the request finishes. (We do this
|
||||
# to ensure log contexts don't leak between tests).
|
||||
self.reactor.advance(1)
|
||||
self.assertTrue(channel.is_finished())
|
||||
|
||||
# Now update the sliding sync requests to include a required state
|
||||
# event, and make another sync request.
|
||||
sync_body["lists"]["foo-list"]["required_state"] = [
|
||||
[EventTypes.Create, ""],
|
||||
]
|
||||
|
||||
response_body, _ = self.do_sync(
|
||||
sync_body, since=from_token, tok=user1_tok, timeout_ms=10_000
|
||||
)
|
||||
|
||||
# We should see the new required state immediately without waiting.
|
||||
self._assertRequiredStateIncludes(
|
||||
response_body["rooms"][room_id1]["required_state"],
|
||||
{
|
||||
state_map[(EventTypes.Create, "")],
|
||||
},
|
||||
exact=True,
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||
#
|
||||
import logging
|
||||
import urllib.parse
|
||||
from typing import Any, Iterable, Literal
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
@@ -81,7 +82,13 @@ class SlidingSyncBase(unittest.HomeserverTestCase):
|
||||
return config
|
||||
|
||||
def make_sync_request(
|
||||
self, sync_body: JsonDict, *, since: str | None = None, tok: str
|
||||
self,
|
||||
sync_body: JsonDict,
|
||||
*,
|
||||
since: str | None = None,
|
||||
tok: str,
|
||||
timeout_ms: int | None = None,
|
||||
await_result: bool = True,
|
||||
) -> FakeChannel:
|
||||
"""Make a sliding sync request with given body.
|
||||
|
||||
@@ -89,25 +96,40 @@ class SlidingSyncBase(unittest.HomeserverTestCase):
|
||||
sync_body: The full request body to use
|
||||
since: Optional since token
|
||||
tok: Access token to use
|
||||
|
||||
timeout_ms: Optional timeout in milliseconds to use for the request.
|
||||
await_result: Whether to block and wait for the result before returning.
|
||||
Returns:
|
||||
A tuple of the response body and the `pos` field.
|
||||
"""
|
||||
|
||||
sync_path = self.sync_endpoint
|
||||
|
||||
query_params: dict[str, Any] = {}
|
||||
if since:
|
||||
sync_path += f"?pos={since}"
|
||||
query_params["pos"] = since
|
||||
if timeout_ms is not None:
|
||||
query_params["timeout"] = timeout_ms
|
||||
|
||||
if query_params:
|
||||
query_str = urllib.parse.urlencode(query_params)
|
||||
sync_path += f"?{query_str}"
|
||||
|
||||
channel = self.make_request(
|
||||
method="POST",
|
||||
path=sync_path,
|
||||
content=sync_body,
|
||||
access_token=tok,
|
||||
await_result=await_result,
|
||||
)
|
||||
return channel
|
||||
|
||||
def do_sync(
|
||||
self, sync_body: JsonDict, *, since: str | None = None, tok: str
|
||||
self,
|
||||
sync_body: JsonDict,
|
||||
*,
|
||||
since: str | None = None,
|
||||
tok: str,
|
||||
timeout_ms: int | None = None,
|
||||
) -> tuple[JsonDict, str]:
|
||||
"""Do a sliding sync request with given body.
|
||||
|
||||
@@ -117,11 +139,14 @@ class SlidingSyncBase(unittest.HomeserverTestCase):
|
||||
sync_body: The full request body to use
|
||||
since: Optional since token
|
||||
tok: Access token to use
|
||||
timeout_ms: Optional timeout in milliseconds to use for the request.
|
||||
|
||||
Returns:
|
||||
A tuple of the response body and the `pos` field.
|
||||
"""
|
||||
channel = self.make_sync_request(sync_body, since=since, tok=tok)
|
||||
channel = self.make_sync_request(
|
||||
sync_body, since=since, tok=tok, timeout_ms=timeout_ms
|
||||
)
|
||||
self.assertEqual(channel.code, 200, channel.json_body)
|
||||
|
||||
return channel.json_body, channel.json_body["pos"]
|
||||
|
||||
Reference in New Issue
Block a user