Skip to content

test: add coverage gate and chaos testing for retry policy - #361

Open
leofoxcode-oss wants to merge 4 commits into
ethos-protocol:mainfrom
leofoxcode-oss:fix/testing-and-parity-improvements
Open

test: add coverage gate and chaos testing for retry policy#361
leofoxcode-oss wants to merge 4 commits into
ethos-protocol:mainfrom
leofoxcode-oss:fix/testing-and-parity-improvements

Conversation

@leofoxcode-oss

Copy link
Copy Markdown

Summary

This PR implements comprehensive testing and quality improvements across both Android and iOS platforms:

Changes

Testing & Quality

  • iOS: 7 new chaos tests for RetryPolicy (truncated responses, connection resets, timeout handling, jitter bounds)
  • Android: 5 new chaos tests for RetryPolicy with packet-loss simulation
  • Coverage reporting: JaCoCo for Android (30% threshold), llvm-cov for iOS (40% threshold)
  • Snapshot tests: Verified Deposit/Withdraw screen snapshots match golden images (light + dark mode)

Documentation

  • PARITY.md: Updated offline check-in queue status from ❌ to ✅ for iOS (confirmed implementation in PendingCheckInStore.swift)
  • PARITY.md: Updated offline queue badge/notification status from ❌ to ✅ for iOS
  • Audit date: Updated "Last audited" from 2026-07-27 to 2026-08-31
  • Known gaps: Removed iOS offline queue items (now implemented)

Test Plan

  • Android unit tests with chaos scenarios pass
  • iOS unit tests with chaos scenarios pass
  • Coverage reports generate successfully (JaCoCo and llvm-cov)
  • Coverage thresholds are reasonable (30% Android, 40% iOS - ratchetable over time)
  • Snapshot tests verify against golden images
  • PARITY.md reflects current feature implementation

Closes #297
Closes #296
Closes #298
Closes #299

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y1T7r23DQ7C9dWJ6xd74xn

Re-audited feature matrix against current source. Confirmed that
PendingCheckInStore, CheckInSyncTask, and queuedCheckInCount in Stores
indicate iOS offline check-in queue support was implemented to match
Android (closing ethos-protocol#105ethos-protocol#108). Updated "Offline check-in queue" and
"Offline queue badge / notification" rows from ❌ to ✅ for iOS,
updated "Last audited" date, and removed these items from "Known gaps".

Closes ethos-protocol#299
…ary screens

Updated ScreenshotTest to document the snapshot coverage for Deposit,
Withdraw, and Manage-Beneficiary screens. Both DepositScreen and
WithdrawScreen tests are implemented with light and dark mode coverage
(via ScreenshotLightTest and ScreenshotDarkTest), reconciled against
pre-existing golden snapshot images (depositScreen_light/dark.png,
withdrawScreen_light/dark.png). ManageBeneficiaryScreen snapshot tests
will be added once the screen is implemented in ethos-protocol#87.

Verified via ./gradlew verifyPaparazziDebug that current snapshots match
the golden images.

Closes ethos-protocol#296
Added comprehensive chaos tests simulating real-world packet-loss failure
modes (truncated responses, connection resets, socket timeouts) for both
iOS and Android retry policies.

iOS (RetryPolicyTests.swift):
- testRetryPolicyHandlesTruncatedResponse: verifies recovery from partial
  response bodies
- testRetryPolicyHandlesConnectionReset: verifies recovery from peer resets
- testRetryPolicyBackoffIncreasesExponentially: validates exponential
  backoff with jitter bounds
- testRetryPolicyDoesNotRetryTimeoutMoreThanMaxAttempts: confirms max
  attempt limits on persistent errors
- testRetryPolicyJitterStaysBelowExponentialBackoff: verifies jitter never
  exceeds exponential ceiling across multiple seeds
- testRetryPolicyDoesNotDoubleSubmitMutatingRequests: confirms no mutation
  double-submission via nonce/timestamp anti-replay
- testMultipleConcurrentRetriesProduceDifferentJitter: validates independent
  random sources for concurrent retries

Android (RetryPolicyTest.kt):
- withRetry handles truncated response and recovers on retry
- withRetry handles connection reset and recovers on retry
- withRetry does not retry non-transient network errors (SocketTimeout)
- withRetry does not double-submit mutating requests
- withRetry respects max attempts on persistent socket timeouts

Closes ethos-protocol#298
Implemented code coverage measurement and reporting for both Android and iOS
platforms to enforce a minimum coverage threshold and prevent coverage erosion.

Android (JaCoCo):
- Added JaCoCo gradle plugin and configuration to app/build.gradle.kts
- Created jacocoTestReport task that generates HTML and XML coverage reports
  after testDebugUnitTest
- Added coverage extraction step in CI that parses the JaCoCo HTML report
  and extracts the coverage percentage
- Set initial threshold at 30% (below current coverage to avoid blocking
  unrelated PRs; can be ratcheted up incrementally as tests are added)
- Surfaces coverage delta as a GitHub Actions warning annotation (non-blocking)
- Uploads coverage report as a build artifact for PR review

iOS (llvm-cov):
- Enabled code coverage data collection via xcodebuild -enableCodeCoverage YES
  in EthosProtocol-Package test invocation
- Added llvm-cov export step to extract coverage data from profdata to JSON
- Set initial threshold at 40% (accommodates current SPM test coverage)
- Surfaces coverage delta as a warning annotation, non-blocking
- Includes graceful fallback if profdata/coverage data is unavailable

Both implementations:
- Start with conservative thresholds to avoid blocking existing PRs
- Report coverage as warnings (non-blocking) to allow gradual improvement
- Provide actionable feedback when coverage falls below threshold
- Artifact uploads enable detailed review via CI

Closes ethos-protocol#297
@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@leofoxcode-oss Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant