Add a test for sticky TTL calculation and exposure to clients

This commit is contained in:
Olivier 'reivilibre
2026-01-16 09:00:00 +00:00
parent b099d228e0
commit be9809347d
+117
View File
@@ -0,0 +1,117 @@
#
# This file is licensed under the Affero General Public License (AGPL) version 3.
#
# Copyright (C) 2025 New Vector, 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 twisted.internet.testing import MemoryReactor
from synapse.api.constants import EventTypes, EventUnsignedContentFields
from synapse.rest import admin
from synapse.rest.client import login, register, room
from synapse.server import HomeServer
from synapse.types import JsonDict
from synapse.util.clock import Clock
from tests import unittest
class StickyEventsClientTestCase(unittest.HomeserverTestCase):
"""Tests sticky events retrieved via the /event/ endpoint."""
servlets = [
room.register_servlets,
login.register_servlets,
register.register_servlets,
admin.register_servlets,
]
def default_config(self) -> JsonDict:
config = super().default_config()
config["experimental_features"] = {"msc4354_enabled": True}
return config
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
# Arrange: Register an account
self.user_id = self.register_user("user1", "pass")
self.token = self.login(self.user_id, "pass")
# Arrange: Create a room
self.room_id = self.helper.create_room_as(self.user_id, tok=self.token)
def _assert_event_sticky_for(self, event_id: str, sticky_ttl: int) -> None:
channel = self.make_request(
"GET",
f"/rooms/{self.room_id}/event/{event_id}",
access_token=self.token,
)
self.assertEqual(
channel.code, 200, f"could not retrieve event {event_id}: {channel.result}"
)
event = channel.json_body
self.assertIn(
EventUnsignedContentFields.STICKY_TTL,
event["unsigned"],
f"No {EventUnsignedContentFields.STICKY_TTL} field in {event_id}; event not sticky: {event}",
)
self.assertEqual(
event["unsigned"][EventUnsignedContentFields.STICKY_TTL],
sticky_ttl,
f"{event_id} had an unexpected sticky TTL: {event}",
)
def _assert_event_not_sticky(self, event_id: str) -> None:
channel = self.make_request(
"GET",
f"/rooms/{self.room_id}/event/{event_id}",
access_token=self.token,
)
self.assertEqual(
channel.code, 200, f"could not retrieve event {event_id}: {channel.result}"
)
event = channel.json_body
self.assertNotIn(
EventUnsignedContentFields.STICKY_TTL,
event["unsigned"],
f"{EventUnsignedContentFields.STICKY_TTL} field unexpectedly found in {event_id}: {event}",
)
def test_sticky_event_via_event_endpoint(self) -> None:
# Arrange: Send a sticky event with a specific duration
sticky_event_response = self.helper.send_sticky_event(
self.room_id,
EventTypes.Message,
# sticky duration is 1 minute
duration_ms=60_000,
content={"body": "sticky message", "msgtype": "m.text"},
tok=self.token,
)
event_id = sticky_event_response["event_id"]
# If we request the event immediately, it will still have
# 1 minute of stickiness
# The other 100 ms is advanced in FakeChannel.await_result.
self._assert_event_sticky_for(event_id, 59_900)
# But if we advance time by 59.799 seconds...
# we will get the event on its last millisecond of stickiness
# The other 100 ms is advanced in FakeChannel.await_result.
self.reactor.advance(59.799)
self._assert_event_sticky_for(event_id, 1)
# Advancing time any more, the event is no longer sticky
self.reactor.advance(0.001)
self._assert_event_not_sticky(event_id)