1
0
Files
synapse/tests/replication/http/test__base.py
Olivier 'reivilibre 4500652459 Rename the test_disconnect test helper so that pytest doesn't see it as a test. (#19486)
This fixes one of the 2 blockers to using pytest instead of Trial (which
is not formally-motivated, but sometimes seems like an interesting idea
because
pytest has seen a lot of developer experience features that Trial
hasn't. It would also removes one more coupling to the Twisted
framework.)

---

The `test_` prefix to this test helper makes it appear as a test to
pytest.

We *can* set a `__test__ = False` attribute on the test, but it felt
cleaner to just rename it (as I also thought it would be a test from
that name!).

This was previously reported as:
https://github.com/element-hq/synapse/issues/18665

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-02-20 15:37:34 +00:00

114 lines
3.8 KiB
Python

#
# This file is licensed under the Affero General Public License (AGPL) version 3.
#
# Copyright 2022 The Matrix.org Foundation C.I.C.
# Copyright (C) 2023 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>.
#
# Originally licensed under the Apache License, Version 2.0:
# <http://www.apache.org/licenses/LICENSE-2.0>.
#
# [This file includes modifications made by New Vector Limited]
#
#
from http import HTTPStatus
from twisted.web.server import Request
from synapse.api.errors import Codes
from synapse.http.server import JsonResource
from synapse.replication.http import REPLICATION_PREFIX
from synapse.replication.http._base import ReplicationEndpoint
from synapse.server import HomeServer
from synapse.types import JsonDict
from synapse.util.cancellation import cancellable
from synapse.util.duration import Duration
from tests import unittest
from tests.http.server._base import disconnect_and_assert
class CancellableReplicationEndpoint(ReplicationEndpoint):
NAME = "cancellable_sleep"
PATH_ARGS = ()
CACHE = False
def __init__(self, hs: HomeServer):
super().__init__(hs)
self.clock = hs.get_clock()
@staticmethod
async def _serialize_payload(**kwargs: ReplicationEndpoint) -> JsonDict:
return {}
@cancellable
async def _handle_request( # type: ignore[override]
self, request: Request, content: JsonDict
) -> tuple[int, JsonDict]:
await self.clock.sleep(Duration(seconds=1))
return HTTPStatus.OK, {"result": True}
class UncancellableReplicationEndpoint(ReplicationEndpoint):
NAME = "uncancellable_sleep"
PATH_ARGS = ()
CACHE = False
WAIT_FOR_STREAMS = False
def __init__(self, hs: HomeServer):
super().__init__(hs)
self.clock = hs.get_clock()
@staticmethod
async def _serialize_payload(**kwargs: ReplicationEndpoint) -> JsonDict:
return {}
async def _handle_request( # type: ignore[override]
self, request: Request, content: JsonDict
) -> tuple[int, JsonDict]:
await self.clock.sleep(Duration(seconds=1))
return HTTPStatus.OK, {"result": True}
class ReplicationEndpointCancellationTestCase(unittest.HomeserverTestCase):
"""Tests for `ReplicationEndpoint` cancellation."""
def create_test_resource(self) -> JsonResource:
"""Overrides `HomeserverTestCase.create_test_resource`."""
resource = JsonResource(self.hs)
CancellableReplicationEndpoint(self.hs).register(resource)
UncancellableReplicationEndpoint(self.hs).register(resource)
return resource
def test_cancellable_disconnect(self) -> None:
"""Test that handlers with the `@cancellable` flag can be cancelled."""
path = f"{REPLICATION_PREFIX}/{CancellableReplicationEndpoint.NAME}/"
channel = self.make_request("POST", path, await_result=False, content={})
disconnect_and_assert(
self.reactor,
channel,
expect_cancellation=True,
expected_body={"error": "Request cancelled", "errcode": Codes.UNKNOWN},
)
def test_uncancellable_disconnect(self) -> None:
"""Test that handlers without the `@cancellable` flag cannot be cancelled."""
path = f"{REPLICATION_PREFIX}/{UncancellableReplicationEndpoint.NAME}/"
channel = self.make_request("POST", path, await_result=False, content={})
disconnect_and_assert(
self.reactor,
channel,
expect_cancellation=False,
expected_body={"result": True},
)