From 976de36ba75334b6c4ac018698d719ac34548ea9 Mon Sep 17 00:00:00 2001 From: Daniel McCoy Stephenson Date: Wed, 21 Oct 2026 03:58:02 -0600 Subject: [PATCH] Test the opt-out mapping, delivery order and the queue-full log Co-Authored-By: Claude Opus 5.5 --- tests/test_trace_client.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/test_trace_client.py b/tests/test_trace_client.py index 4962ed9..c78b044 100644 --- a/tests/test_trace_client.py +++ b/tests/test_trace_client.py @@ -262,6 +262,15 @@ def test_environment_opts_out_accepts_an_explicit_mapping(self): self.assertFalse(environment_opts_out({})) self.assertFalse(environment_opts_out({"DO_NOT_TRACK": "0", "TRACE_USAGE_REPORTING": "on"})) + def test_environment_opts_out_reads_only_the_mapping_it_is_given(self): + with mock.patch.dict(os.environ, {"DO_NOT_TRACK": "1"}): + self.assertTrue(environment_opts_out(), "no mapping means the process environment") + self.assertTrue(environment_opts_out(None), "None means the process environment") + self.assertFalse(environment_opts_out({}), "an explicit mapping replaces the environment") + self.assertTrue(environment_opts_out({"DO_NOT_TRACK": " TRUE "}), + "a mapping's values are trimmed and compared without case, like the environment's") + self.assertTrue(environment_opts_out({"TRACE_USAGE_REPORTING": " No "})) + def test_user_agent_names_the_client_version(self): from trace_client import __version__ self.assertEqual("0.4.1", __version__) @@ -501,6 +510,31 @@ def test_queue_is_bounded_and_drops_rather_than_grows(self): self.capture.release.set() client.close() + def test_a_dropped_report_is_logged_at_debug_with_its_name(self): + self.capture.release.clear() # hold the sender on the first report + client = TraceClient(self.base_url, "MyGame", "1.2.3", key="k") + # The queue holds QUEUE_CAPACITY and the sender at most one more, so + # the next report has nowhere to go whatever the sender has picked up. + for _ in range(TraceClient.QUEUE_CAPACITY + 1): + client.report("filler") + client.report("overflow-event") + dropped = [r for r in self.log if r.getMessage() == "[trace] queue full, dropped overflow-event"] + self.assertEqual(1, len(dropped), + "a drop names the event it dropped: %r" % [r.getMessage() for r in self.log]) + self.assertTrue(all(r.levelno == logging.DEBUG for r in self.log), "drops are logged at DEBUG only") + self.capture.release.set() + client.close() + + def test_reports_are_delivered_in_the_order_they_were_made(self): + # One sender thread, one request at a time: the server sees events in + # the order the program reported them. + client = TraceClient(self.base_url, "MyGame", "1.2.3", key="k") + for i in range(20): + client.report("step", tags={"n": str(i)}) + client.close() + self.assertEqual([str(i) for i in range(20)], + [json.loads(r["body"])["tags"]["n"] for r in self.capture.requests]) + def test_close_sends_what_was_just_queued_before_stopping(self): # A CLI reports once and exits at once. Without draining, the event # races the sender thread and is lost a good fraction of the time;