From 480e6ea18d0bd6d1ee65165632bf8a395c628e3a Mon Sep 17 00:00:00 2001 From: David Young Date: Sun, 8 Nov 2026 11:43:51 -0700 Subject: [PATCH] Report receiver: fix a race in its tests, and log Gitea's reasons The first test checked that a report was no longer pending as soon as its log reached the fake Gitea, a moment before the receiver marks it filed, so it could fail; wait for the mark instead. The tests now close their servers and error responses. When Gitea refuses an issue or attachment, the receiver closes the reply and logs Gitea's reason, such as a token without the right permission. Co-Authored-By: Claude Opus 5.5 --- server/report-receiver/receiver.py | 10 ++++++++-- server/report-receiver/test_receiver.py | 9 +++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/server/report-receiver/receiver.py b/server/report-receiver/receiver.py index 730b0e1..967bf10 100644 --- a/server/report-receiver/receiver.py +++ b/server/report-receiver/receiver.py @@ -191,8 +191,14 @@ class Gitea: "Content-Type": content_type, "Accept": "application/json", }) - with urllib.request.urlopen(request, timeout=self.timeout) as response: - return json.load(response) + try: + with urllib.request.urlopen(request, timeout=self.timeout) as response: + return json.load(response) + except urllib.error.HTTPError as error: + # Gitea's reason, e.g. a token without the right permission, for the journal + with error: + detail = error.read(500).decode("utf-8", errors="replace").strip() + raise OSError(f"Gitea answered {error.code}: {detail or error.reason}") from None def create_issue(self, title, body): """The new issue's number.""" diff --git a/server/report-receiver/test_receiver.py b/server/report-receiver/test_receiver.py index 8e9f3de..bb67c56 100644 --- a/server/report-receiver/test_receiver.py +++ b/server/report-receiver/test_receiver.py @@ -61,6 +61,7 @@ class FakeGitea: def close(self): self.server.shutdown() + self.server.server_close() class ReceiverTest(unittest.TestCase): @@ -85,6 +86,7 @@ class ReceiverTest(unittest.TestCase): def tearDown(self): self.server.shutdown() + self.server.server_close() self.gitea.close() shutil.rmtree(self.tmp) @@ -109,7 +111,8 @@ class ReceiverTest(unittest.TestCase): output = self.send("--offer", str(self.log), "71-siblings.sh", "46-neovim.sh") self.assertIn("Your report's ID is CD-", output) report_id = output.split("Your report's ID is ")[1].split(";")[0] - self.wait_for(lambda: self.gitea.attachments) + # Filed means attached and no longer pending, which happens just after + self.wait_for(lambda: not (self.tmp / "state" / report_id / "pending").exists()) issue = self.gitea.issues[0] self.assertEqual(issue["path"], "/api/v1/repos/Federated_Computer/coredesktop-reports/issues") @@ -154,7 +157,8 @@ class ReceiverTest(unittest.TestCase): with urllib.request.urlopen(request) as response: return response.status, response.read().decode() except urllib.error.HTTPError as error: - return error.code, error.read().decode() + with error: + return error.code, error.read().decode() def test_things_that_arent_reports_are_turned_away(self): self.assertEqual(self.post(b"hello", "text/plain")[0], 400) @@ -180,6 +184,7 @@ class ReceiverTest(unittest.TestCase): request = urllib.request.Request(self.url.replace("/report", "/other"), data=b"x", method="POST") with self.assertRaises(urllib.error.HTTPError) as caught: urllib.request.urlopen(request) + caught.exception.close() self.assertEqual(caught.exception.code, 404)