Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit f114556

Browse files
author
David Robertson
authored
Extra type annotations in test_server (#13124)
1 parent 6b99a66 commit f114556

File tree

3 files changed

+48
-37
lines changed

3 files changed

+48
-37
lines changed

changelog.d/13124.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add type annotations to `tests.test_server`.

mypy.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ disallow_untyped_defs = False
113113
[mypy-tests.handlers.test_user_directory]
114114
disallow_untyped_defs = True
115115

116+
[mypy-tests.test_server]
117+
disallow_untyped_defs = True
118+
116119
[mypy-tests.state.test_profile]
117120
disallow_untyped_defs = True
118121

tests/test_server.py

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import re
1616
from http import HTTPStatus
17-
from typing import Tuple
17+
from typing import Awaitable, Callable, Dict, NoReturn, Optional, Tuple
1818

1919
from twisted.internet.defer import Deferred
2020
from twisted.web.resource import Resource
@@ -36,6 +36,7 @@
3636
from tests import unittest
3737
from tests.http.server._base import test_disconnect
3838
from tests.server import (
39+
FakeChannel,
3940
FakeSite,
4041
ThreadedMemoryReactorClock,
4142
make_request,
@@ -44,7 +45,7 @@
4445

4546

4647
class JsonResourceTests(unittest.TestCase):
47-
def setUp(self):
48+
def setUp(self) -> None:
4849
self.reactor = ThreadedMemoryReactorClock()
4950
self.hs_clock = Clock(self.reactor)
5051
self.homeserver = setup_test_homeserver(
@@ -54,15 +55,17 @@ def setUp(self):
5455
reactor=self.reactor,
5556
)
5657

57-
def test_handler_for_request(self):
58+
def test_handler_for_request(self) -> None:
5859
"""
5960
JsonResource.handler_for_request gives correctly decoded URL args to
6061
the callback, while Twisted will give the raw bytes of URL query
6162
arguments.
6263
"""
6364
got_kwargs = {}
6465

65-
def _callback(request, **kwargs):
66+
def _callback(
67+
request: SynapseRequest, **kwargs: object
68+
) -> Tuple[int, Dict[str, object]]:
6669
got_kwargs.update(kwargs)
6770
return 200, kwargs
6871

@@ -83,13 +86,13 @@ def _callback(request, **kwargs):
8386

8487
self.assertEqual(got_kwargs, {"room_id": "\N{SNOWMAN}"})
8588

86-
def test_callback_direct_exception(self):
89+
def test_callback_direct_exception(self) -> None:
8790
"""
8891
If the web callback raises an uncaught exception, it will be translated
8992
into a 500.
9093
"""
9194

92-
def _callback(request, **kwargs):
95+
def _callback(request: SynapseRequest, **kwargs: object) -> NoReturn:
9396
raise Exception("boo")
9497

9598
res = JsonResource(self.homeserver)
@@ -103,17 +106,17 @@ def _callback(request, **kwargs):
103106

104107
self.assertEqual(channel.result["code"], b"500")
105108

106-
def test_callback_indirect_exception(self):
109+
def test_callback_indirect_exception(self) -> None:
107110
"""
108111
If the web callback raises an uncaught exception in a Deferred, it will
109112
be translated into a 500.
110113
"""
111114

112-
def _throw(*args):
115+
def _throw(*args: object) -> NoReturn:
113116
raise Exception("boo")
114117

115-
def _callback(request, **kwargs):
116-
d = Deferred()
118+
def _callback(request: SynapseRequest, **kwargs: object) -> "Deferred[None]":
119+
d: "Deferred[None]" = Deferred()
117120
d.addCallback(_throw)
118121
self.reactor.callLater(0.5, d.callback, True)
119122
return make_deferred_yieldable(d)
@@ -129,13 +132,13 @@ def _callback(request, **kwargs):
129132

130133
self.assertEqual(channel.result["code"], b"500")
131134

132-
def test_callback_synapseerror(self):
135+
def test_callback_synapseerror(self) -> None:
133136
"""
134137
If the web callback raises a SynapseError, it returns the appropriate
135138
status code and message set in it.
136139
"""
137140

138-
def _callback(request, **kwargs):
141+
def _callback(request: SynapseRequest, **kwargs: object) -> NoReturn:
139142
raise SynapseError(403, "Forbidden!!one!", Codes.FORBIDDEN)
140143

141144
res = JsonResource(self.homeserver)
@@ -151,12 +154,12 @@ def _callback(request, **kwargs):
151154
self.assertEqual(channel.json_body["error"], "Forbidden!!one!")
152155
self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
153156

154-
def test_no_handler(self):
157+
def test_no_handler(self) -> None:
155158
"""
156159
If there is no handler to process the request, Synapse will return 400.
157160
"""
158161

159-
def _callback(request, **kwargs):
162+
def _callback(request: SynapseRequest, **kwargs: object) -> None:
160163
"""
161164
Not ever actually called!
162165
"""
@@ -175,14 +178,16 @@ def _callback(request, **kwargs):
175178
self.assertEqual(channel.json_body["error"], "Unrecognized request")
176179
self.assertEqual(channel.json_body["errcode"], "M_UNRECOGNIZED")
177180

178-
def test_head_request(self):
181+
def test_head_request(self) -> None:
179182
"""
180183
JsonResource.handler_for_request gives correctly decoded URL args to
181184
the callback, while Twisted will give the raw bytes of URL query
182185
arguments.
183186
"""
184187

185-
def _callback(request, **kwargs):
188+
def _callback(
189+
request: SynapseRequest, **kwargs: object
190+
) -> Tuple[int, Dict[str, object]]:
186191
return 200, {"result": True}
187192

188193
res = JsonResource(self.homeserver)
@@ -203,20 +208,21 @@ def _callback(request, **kwargs):
203208

204209

205210
class OptionsResourceTests(unittest.TestCase):
206-
def setUp(self):
211+
def setUp(self) -> None:
207212
self.reactor = ThreadedMemoryReactorClock()
208213

209214
class DummyResource(Resource):
210215
isLeaf = True
211216

212-
def render(self, request):
213-
return request.path
217+
def render(self, request: SynapseRequest) -> bytes:
218+
# Type-ignore: mypy thinks request.path is Optional[Any], not bytes.
219+
return request.path # type: ignore[return-value]
214220

215221
# Setup a resource with some children.
216222
self.resource = OptionsResource()
217223
self.resource.putChild(b"res", DummyResource())
218224

219-
def _make_request(self, method, path):
225+
def _make_request(self, method: bytes, path: bytes) -> FakeChannel:
220226
"""Create a request from the method/path and return a channel with the response."""
221227
# Create a site and query for the resource.
222228
site = SynapseSite(
@@ -233,7 +239,7 @@ def _make_request(self, method, path):
233239
channel = make_request(self.reactor, site, method, path, shorthand=False)
234240
return channel
235241

236-
def test_unknown_options_request(self):
242+
def test_unknown_options_request(self) -> None:
237243
"""An OPTIONS requests to an unknown URL still returns 204 No Content."""
238244
channel = self._make_request(b"OPTIONS", b"/foo/")
239245
self.assertEqual(channel.result["code"], b"204")
@@ -253,7 +259,7 @@ def test_unknown_options_request(self):
253259
"has CORS Headers header",
254260
)
255261

256-
def test_known_options_request(self):
262+
def test_known_options_request(self) -> None:
257263
"""An OPTIONS requests to an known URL still returns 204 No Content."""
258264
channel = self._make_request(b"OPTIONS", b"/res/")
259265
self.assertEqual(channel.result["code"], b"204")
@@ -273,12 +279,12 @@ def test_known_options_request(self):
273279
"has CORS Headers header",
274280
)
275281

276-
def test_unknown_request(self):
282+
def test_unknown_request(self) -> None:
277283
"""A non-OPTIONS request to an unknown URL should 404."""
278284
channel = self._make_request(b"GET", b"/foo/")
279285
self.assertEqual(channel.result["code"], b"404")
280286

281-
def test_known_request(self):
287+
def test_known_request(self) -> None:
282288
"""A non-OPTIONS request to an known URL should query the proper resource."""
283289
channel = self._make_request(b"GET", b"/res/")
284290
self.assertEqual(channel.result["code"], b"200")
@@ -287,16 +293,17 @@ def test_known_request(self):
287293

288294
class WrapHtmlRequestHandlerTests(unittest.TestCase):
289295
class TestResource(DirectServeHtmlResource):
290-
callback = None
296+
callback: Optional[Callable[..., Awaitable[None]]]
291297

292-
async def _async_render_GET(self, request):
298+
async def _async_render_GET(self, request: SynapseRequest) -> None:
299+
assert self.callback is not None
293300
await self.callback(request)
294301

295-
def setUp(self):
302+
def setUp(self) -> None:
296303
self.reactor = ThreadedMemoryReactorClock()
297304

298-
def test_good_response(self):
299-
async def callback(request):
305+
def test_good_response(self) -> None:
306+
async def callback(request: SynapseRequest) -> None:
300307
request.write(b"response")
301308
request.finish()
302309

@@ -311,13 +318,13 @@ async def callback(request):
311318
body = channel.result["body"]
312319
self.assertEqual(body, b"response")
313320

314-
def test_redirect_exception(self):
321+
def test_redirect_exception(self) -> None:
315322
"""
316323
If the callback raises a RedirectException, it is turned into a 30x
317324
with the right location.
318325
"""
319326

320-
async def callback(request, **kwargs):
327+
async def callback(request: SynapseRequest, **kwargs: object) -> None:
321328
raise RedirectException(b"/look/an/eagle", 301)
322329

323330
res = WrapHtmlRequestHandlerTests.TestResource()
@@ -332,13 +339,13 @@ async def callback(request, **kwargs):
332339
location_headers = [v for k, v in headers if k == b"Location"]
333340
self.assertEqual(location_headers, [b"/look/an/eagle"])
334341

335-
def test_redirect_exception_with_cookie(self):
342+
def test_redirect_exception_with_cookie(self) -> None:
336343
"""
337344
If the callback raises a RedirectException which sets a cookie, that is
338345
returned too
339346
"""
340347

341-
async def callback(request, **kwargs):
348+
async def callback(request: SynapseRequest, **kwargs: object) -> NoReturn:
342349
e = RedirectException(b"/no/over/there", 304)
343350
e.cookies.append(b"session=yespls")
344351
raise e
@@ -357,10 +364,10 @@ async def callback(request, **kwargs):
357364
cookies_headers = [v for k, v in headers if k == b"Set-Cookie"]
358365
self.assertEqual(cookies_headers, [b"session=yespls"])
359366

360-
def test_head_request(self):
367+
def test_head_request(self) -> None:
361368
"""A head request should work by being turned into a GET request."""
362369

363-
async def callback(request):
370+
async def callback(request: SynapseRequest) -> None:
364371
request.write(b"response")
365372
request.finish()
366373

@@ -410,7 +417,7 @@ async def _async_render_POST(self, request: SynapseRequest) -> Tuple[int, bytes]
410417
class DirectServeJsonResourceCancellationTests(unittest.TestCase):
411418
"""Tests for `DirectServeJsonResource` cancellation."""
412419

413-
def setUp(self):
420+
def setUp(self) -> None:
414421
self.reactor = ThreadedMemoryReactorClock()
415422
self.clock = Clock(self.reactor)
416423
self.resource = CancellableDirectServeJsonResource(self.clock)
@@ -444,7 +451,7 @@ def test_uncancellable_disconnect(self) -> None:
444451
class DirectServeHtmlResourceCancellationTests(unittest.TestCase):
445452
"""Tests for `DirectServeHtmlResource` cancellation."""
446453

447-
def setUp(self):
454+
def setUp(self) -> None:
448455
self.reactor = ThreadedMemoryReactorClock()
449456
self.clock = Clock(self.reactor)
450457
self.resource = CancellableDirectServeHtmlResource(self.clock)

0 commit comments

Comments
 (0)