from __future__ import annotations
import tempfile
import unittest
import uuid
from contextlib import ExitStack
from http.client import HTTPConnection
from pathlib import Path
from unittest.mock import patch
from moli_benchmark.wpt_cross.case_set import enumerate_cases
from moli_benchmark.wpt_cross.server import NAVIGATION_SECOND_VISIT_PATH, WptFixtureServer
CASE_DIRECTORY = "navigation-api/navigation-methods/return-value"
class NavigationResponseFixtureTests(unittest.TestCase):
def setUp(self) -> None:
self.stack = ExitStack()
self.addCleanup(self.stack.close)
self.root = Path(self.stack.enter_context(tempfile.TemporaryDirectory()))
(self.root / "resources").mkdir()
(self.root / "resources/testharness.js").write_text("// testharness")
resource = self.root / NAVIGATION_SECOND_VISIT_PATH.lstrip("/")
resource.parent.mkdir(parents=True)
resource.write_text("# Python source must not be served")
self.stack.enter_context(patch(
"moli_benchmark.wpt_cross.server._global_ipv6_address", return_value=None,
))
self.server = self.stack.enter_context(WptFixtureServer(self.root))
def request(self, query: str, *, method: str = "GET", port: int | None = None,
path: str = NAVIGATION_SECOND_VISIT_PATH):
connection = HTTPConnection("127.0.0.1", port or self.server.port, timeout=2)
try:
connection.request(method, path + "?" + query,
body=b"ignored request body" if method == "POST" else None)
response = connection.getresponse()
return response.status, response.headers, response.read()
finally:
connection.close()
def assert_initial_page(self, query: str, *, port: int | None = None) -> None:
status, headers, body = self.request(query, port=port)
self.assertEqual((status, headers["Content-Type"], body),
(200, "text/html", b"initial page"))
self.assertEqual(headers["Cache-Control"], "no-store")
self.assertIsNone(headers["Content-Disposition"])
def test_post_programs_one_get_response(self) -> None:
for action in ("204", "205", "download"):
with self.subTest(action=action):
key = uuid.uuid4()
query = f"id={key}"
self.assert_initial_page(query)
status, headers, body = self.request(query + f"&action={action}", method="POST")
self.assertEqual((status, body), (204, b""))
self.assertIsNone(headers["Content-Type"])
self.assertIsNone(headers["Cache-Control"])
status, headers, body = self.request(query)
if action == "download":
self.assertEqual((status, headers["Content-Type"], body),
(200, "text/plain", b"some text to download"))
self.assertEqual(headers["Content-Disposition"], "attachment")
else:
self.assertEqual((status, body), (int(action), b""))
self.assertIsNone(headers["Content-Type"])
self.assertIsNone(headers["Cache-Control"])
self.assert_initial_page(query)
def test_state_is_shared_across_origins_but_isolated_by_key_server_and_path(self) -> None:
key = uuid.uuid4()
query = f"id={key}"
self.assertEqual(self.request(query + "&action=205", method="POST")[0], 204)
self.assert_initial_page(f"id={uuid.uuid4()}")
other = self.stack.enter_context(WptFixtureServer(self.root))
self.assert_initial_page(query, port=other.port)
status, _, body = self.request(f"key={key}", path="/fetch/api/resources/stash-take.py")
self.assertEqual((status, body), (200, b"null"))
status, _, _ = self.request(f"id={str(key).upper()}", port=self.server.alternate_port)
self.assertEqual(status, 205)
self.assert_initial_page(f"id={key.hex}")
def test_unsupported_methods_do_not_consume_the_programmed_response(self) -> None:
query = f"id={uuid.uuid4()}"
self.assertEqual(self.request(query + "&action=204", method="POST")[0], 204)
for method in ("HEAD", "OPTIONS", "PUT", "PATCH", "DELETE", "YO", "CUSTOM"):
with self.subTest(method=method):
status, _, body = self.request(query, method=method)
self.assertEqual((status, body), (400, b""))
self.assertEqual(self.request(query)[0], 204)
self.assert_initial_page(query)
def test_unknown_actions_are_consumed_and_duplicate_posts_do_not_overwrite(self) -> None:
query = f"id={uuid.uuid4()}"
for action in ("unknown", ""):
self.assertEqual(self.request(query + f"&action={action}", method="POST")[0], 204)
self.assertEqual(self.request(query)[0], 400)
self.assert_initial_page(query)
self.assertEqual(self.request(query + "&action=205&action=204", method="POST")[0], 204)
self.assertEqual(self.request(query + "&action=204", method="POST")[0], 500)
self.assertEqual(self.request(query + "&id=ignored")[0], 205)
def test_invalid_parameters_report_errors(self) -> None:
for query, method in (("", "GET"), ("id=", "GET"), ("id=not-a-uuid", "GET"),
(f"id={uuid.uuid4()}", "POST"), ("id=%FF&action=204", "POST")):
with self.subTest(query=query, method=method):
self.assertEqual(self.request(query, method=method)[0], 500)
def test_discovery_accepts_only_supported_resource_locations(self) -> None:
resource = "resources/204-205-download-on-second-visit.py"
cases = {
"relative.html": (resource, True),
"dot.html": ("./" + resource, True),
"absolute.html": (NAVIGATION_SECOND_VISIT_PATH, True),
"wrong-directory.html": ("../" + resource, False),
"basename.html": (resource.rsplit("/", 1)[1], False),
"suffix.html": (resource + ".extra", False),
}
for name, (reference, _) in cases.items():
(self.root / CASE_DIRECTORY / name).write_text(
''
''
f''
)
discovered = enumerate_cases(self.root, dir_prefixes=(CASE_DIRECTORY,))
self.assertEqual(
sorted(case.case_path for case in discovered),
sorted(CASE_DIRECTORY + "/" + name for name, (_, allowed) in cases.items() if allowed),
)
if __name__ == "__main__":
unittest.main()