Repository navigation
test(core): fix the NetMonitorCore runner crash and DST-dependent expiry test (#330) - #368
Conversation
…endent expiry test (#330) - Nest the nine suites that share MockURLProtocol's global requestHandler under one serialized parent (GlobalMockURLProtocolSuites). Separate .serialized suites ran in parallel, and each test's init() cleared the handler another suite was using mid-request. - With no handler, MockURLProtocol now fails the request instead of finishing without a response, which made URLSession.data(for:) trap (SIGTRAP, signal 5) and end the whole run. - The SSL expiry-calculation tests use a fixed date and a UTC calendar; 60 x 86400 s from Date() counts 59 days across a DST change. The six test files are reindented only; review with `git diff -w`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012SGbgc2WtUFjD4SKcoa2bt
There was a problem hiding this comment.
🔍 Devin Review: 1 flag
Not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The change is a large, CI-critical reindentation of shared test infrastructure whose runtime correctness depends on Swift Testing serialization behavior that cannot be executed in this review environment, so a human should confirm before approval.
Review effort: Balanced
Findings: None
What changed in this PR
This test-only PR fixes two pre-existing failures in the NetMonitorCore package's full swift test run (issue #330): a signal 5 runner crash and a DST-sensitive SSL-expiry test. No application code changes.
The runner crash was caused by nine .serialized suites that share MockURLProtocol's global requestHandler: separate serialized suites still run in parallel, and each test's init() reset the handler while another suite's request was mid-flight, leaving a request with no handler that finished without a response and trapped inside URLSession.data(for:). The fix serializes all nine suites under a single @Suite(.serialized) parent and hardens the no-handler path.
Changes:
- Introduce a
@Suite(.serialized) enum GlobalMockURLProtocolSuitesand nest all nine global-handler suites under it (via extensions) so they run one at a time. - Make
MockURLProtocolfail a handler-less request withURLError(.resourceUnavailable)instead of finishing empty (which trapped the run). - Make the two expiry-calculation tests deterministic using a fixed
2026-10-15 00:00 UTCdate and a UTC Gregorian calendar.
| File | Description |
|---|---|
Helpers/MockURLProtocol.swift |
Adds the GlobalMockURLProtocolSuites serialized parent; fails handler-less requests instead of trapping; updates doc comments. |
ContractTests.swift |
Nests the suite (and its inner contract sub-suites) under GlobalMockURLProtocolSuites; reindent only. |
GeoLocationServiceTests.swift |
Nests the suite under GlobalMockURLProtocolSuites; reindent only. |
WorldPingServiceErrorTests.swift |
Nests the suite under GlobalMockURLProtocolSuites; reindent only. |
WorldPingRegressionTests.swift |
Nests both suites under GlobalMockURLProtocolSuites; reindent only. |
SpeedTestServiceSessionTests.swift |
Nests three suites under GlobalMockURLProtocolSuites; reindent only. |
SpeedTestServiceErrorRecoveryTests.swift |
Nests the suite under GlobalMockURLProtocolSuites; reindent only. |
SSLCertificateContractTests.swift |
Replaces Date()/Calendar.current with a fixed UTC date and calendar in the two expiry tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Problem
The full
swift testin NetMonitorCore failed onmainin two ways (reproduced on mini-pro-2 at 5f002e3):swiftpm-testing-helper-2026-09-28-233146.ips) traps inside Foundation'sURLSession.data(for:)completion. Nine suites shareMockURLProtocol's globalrequestHandler. Each is.serialized, but separate serialized suites still run in parallel, and every test'sinit()sets the handler tonil. A test in one suite cleared the handler another suite's request was using; the mock then finished the load with no response, anddata(for:)trapped. Only 926 of about 1,464 tests had finished when the runner died.Date()crosses the 1 Nov DST change in the local zone.Fix (tests only; no app code changes)
GlobalMockURLProtocolSuitesis a serialized parent suite, and the nine global-handler suites are nested under it in extensions, so they run one at a time..serializedcovers nested suites.MockURLProtocolnow fails the request withURLError(.resourceUnavailable)instead of finishing without a response, so a future race fails one test rather than ending the run.The six suite files are reindented only; review with
git diff -w(48+/9−).Verification (mini-pro-2, under
lockf /tmp/nm-node-test.lock)exited with unexpected signal code 5✔ Test run with 1464 tests in 187 suites passedboth timesNot part of 2.2.1 build 16. Only tests change, so no new build is needed.
Closes #330
🤖 Generated with Claude Code
https://claude.ai/code/session_012SGbgc2WtUFjD4SKcoa2bt