Skip to content

[Integration] Integration test infrastructure and cross-system bug fixes#286

Merged
nemoshu merged 34 commits intointegration/network-testsfrom
integration/test-suit-bug-fix-ralphing
Mar 6, 2026
Merged

[Integration] Integration test infrastructure and cross-system bug fixes#286
nemoshu merged 34 commits intointegration/network-testsfrom
integration/test-suit-bug-fix-ralphing

Conversation

@WillStephenn
Copy link
Copy Markdown
Collaborator

@WillStephenn WillStephenn commented Mar 4, 2026

Summary

This PR resolves all integration test failures between the Android client and Windows server, bringing both test suites to green. Changes span the Android app, Android integration tests, Windows server controllers and services, Windows unit tests, and the Integration Test Contract documentation.

Changes

1. API URL prefix fix

Files: ApiService.java, ApiServiceTest.java

All 7 Retrofit endpoint annotations were missing the /api/v1/ prefix that the server expects (per API Contract §4). Added the prefix to every endpoint and updated the corresponding unit test URL assertions.

2. Test entity IDs -> valid UUIDs

Files: IntegrationTestConfig.java, AttachmentEndpointIntegrationTest.java, ResponseSubmissionIntegrationTest.java, TcpCommandIntegrationTest.java, Integration Test Contract.md

The server validates all device/entity IDs with Guid.TryParse(). Test IDs like "inttest-00000000-..." and "inttest-attachment-001" were being rejected as invalid GUIDs. All test IDs are now valid UUIDs (e.g., 00000001-0000-0000-0000-000000000001). The Integration Test Contract documentation was updated to use these valid UUIDs across all examples and seed data specifications.

3. MaterialDto serialisation fix

Files: MaterialDto.java

@SerializedName("Type") was changed to @SerializedName("MaterialType") to match the server's AndroidMaterialDto.cs and Validation Rules §2A(1)(a). Without this fix, the material type field deserialised as null.

4. Roboelectric compatibility fixes

Files: NetworkIntegrationHarness.java, PairingManager.java, TcpSocketManager.java

Three issues caused test failures under Roboelectric's PAUSED looper mode:

  • RetryInterceptor removed from harness — It internally calls ConnectivityManager.isConnected(), which always returns false under Roboelectric. Removing it allows HTTP requests to proceed normally in tests.
  • directHandler added to harness — TCP callbacks use Handler.post(), but runnables never execute in PAUSED mode. The harness now creates a Handler that overrides sendMessageAtTime to dispatch runnables immediately.
  • Volatile currentStateSnapshot in PairingManagerLiveData.getValue() returns stale/null values under Roboelectric because observers don't dispatch. A volatile field is now written alongside LiveData.postValue() and read by getCurrentState() for thread-safe, immediate access in tests.
  • TcpSocketManager 3-arg constructor made public — Needed by the integration harness to inject dependencies.

5. Server Integration mode

Files: Program.cs (modified), IntegrationSeedService.cs (new), IntegrationResetController.cs (new), appsettings.Integration.json (new), launchSettings.json (modified)

Implemented the full Integration environment per Integration Test Contract §12:

  • Ephemeral database (§12.3): Creates a temp-file SQLite DB per run, ensuring clean state.
  • Auto-start network services (§12.1): UDP broadcast and TCP pairing hosted services start automatically (in production they're started on-demand via UI).
  • Test data seeding (§12.2): IntegrationSeedService seeds the required device config, materials, questions, attachments, and feedback on startup.
  • State reset endpoint: POST /api/v1/integration/reset clears all data and re-seeds, called by the test harness between test runs.
  • Skips orphan cleanup: The Integration environment bypasses the startup orphan cleanup logic intended for production.
  • Integration launch profile: Added a dedicated Integration profile to launchSettings.json to simplify running the server with the correct environment and port configuration.

6. TCP connection cleanup (flaky test fix)

Files: ITcpPairingService.cs, TcpPairingService.cs, IntegrationResetController.cs

The handRaised_receivesHandAck test was intermittently flaky (~1 in 4 full-suite runs) because the server retained TCP connection state from previous tests. Added DisconnectAllClients() to ITcpPairingService and its implementation in TcpPairingService, which:

  • Closes all TcpClient connections
  • Clears 6 tracking dictionaries: _connectedClients, _deviceConnections, _lastHeartbeat, _pendingMaterials, _pendingFeedbacks, _pendingLockUnlock

Called as step 0 of the reset controller before clearing database state.

7. GUID validation — return 404 instead of 400/403

Files: AttachmentController.cs, ConfigController.cs, DistributionController.cs, FeedbackController.cs

All 4 controllers previously returned 400 BadRequest for invalid GUID format, and ConfigController returned 403 Forbidden for non-Android devices. Changed all to return 404 NotFound with generic messages (e.g., "No materials available for this device"). This avoids leaking information about ID validity to unauthenticated callers and aligns with RESTful practice for resource-oriented endpoints.

8. Windows unit test alignment

Files: AttachmentControllerTests.cs, ConfigControllerTests.cs, DistributionControllerTests.cs, FeedbackControllerTests.cs

Updated 7 test methods across 4 files to expect NotFoundObjectResult instead of BadRequestObjectResult / 403 Forbidden, matching the controller changes above. Test method names were updated accordingly (e.g., Returns400BadRequest -> Returns404NotFound).

9. Comprehensive Integration Tests

Files: ResponseLifecycleIntegrationTest.java, AttachmentDownloadIntegrationTest.java, ConfigFieldsIntegrationTest.java, DistributionDataIntegrationTest.java, FeedbackDataIntegrationTest.java

Added five new integration test suites to ensure robust end-to-end functionality and strict adherence to the API Contract:

  • Response Lifecycle E2E: Verified the full sequence of device registration, distribution fetching, response submission, and feedback retrieval in a single session.
  • Attachment Download: Validated raw binary download of attachments (e.g., PNGs), verifying correct MIME types and file signature (magic bytes).
  • Config Validation: Verified all configuration fields meet range constraints (e.g., TextSize between 5-50) and comply with defined enums.
  • Distribution Data: Confirmed that distribution bundles are fully populated and that server-assigned material/question IDs are preserved.
  • Feedback Data: Validated that the feedback endpoint returns correctly populated items matching the seeded test data.

How to verify

Run the Windows server in Integration mode

Use the new launch profile for one-step startup:

cd windows/ManuscriptaTeacherApp/Main
dotnet run --launch-profile Integration

This starts the server with:

  • HTTP on port 5911, SignalR on port 5910
  • TCP pairing on port 5912, UDP broadcast on port 5913
  • Ephemeral SQLite database, auto-seeded with test data

Run Android integration tests against the server

With the server running in Integration mode on the same machine or network:

cd android
JAVA_HOME=$(/usr/libexec/java_home -v 17) ./gradlew test -Pintegration

To point at a remote server, set environment variables before running:

export MANUSCRIPTA_SERVER_HOST=<server-ip>
export MANUSCRIPTA_HTTP_PORT=5911
export MANUSCRIPTA_TCP_PORT=5912
export MANUSCRIPTA_UDP_PORT=5913

WillStephenn and others added 21 commits March 1, 2026 22:54
- Fix missing closing brace in RepositoryModule.provideConfigRepository
  that caused checkstyle's ANTLR parser to crash
- Exclude @category(IntegrationTest.class) tests from the unit test run
  in build.gradle.kts so e2e tests (which require a live server)
  do not fail CI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… to avoid leaking information about ID validity
…ices from 400/403 to 404 to avoid leaking information
@WillStephenn
Copy link
Copy Markdown
Collaborator Author

Hey @nemoshu, I'm still polishing this up (getting it passing CI/CD and resolving merge conflicts) - but most of the bones are in place now in terms of integration bug fixes if you want to start taking a look

@WillStephenn
Copy link
Copy Markdown
Collaborator Author

I've added more test cases:

  • Response Lifecycle E2E: Verified device registration, distribution fetching, response submission, and feedback retrieval in a single session.

  • Attachment Download: Validated raw binary download of PNG attachments with correct MIME types and magic bytes.

  • Config Validation: Verified range constraints (e.g., TextSize 5-50) and enum compliance for tablet settings.

  • Distribution Data: Validated field-level correctness of materials and questions, ensuring IDs match seeded values.

  • Feedback Data: Confirmed correctly populated feedback items (marks/text) for seeded response IDs.

@WillStephenn WillStephenn marked this pull request as ready for review March 4, 2026 12:30
Per PR #286 discussion: it is unreasonable to return 404 for malformed
GUIDs (incorrect format) — the original 400 semantics should be retained.
404 is kept for the config endpoint when the device is valid but unknown
or non-Android.

Controllers (4 files):
- AttachmentController, ConfigController, DistributionController,
  FeedbackController: Guid.TryParse failure now returns 400 BadRequest
  with descriptive messages (e.g. 'Invalid device ID format') instead
  of 404 NotFound.
- ConfigController: non-Android device catch block remains 404.

Windows unit tests (4 files):
- Updated assertions from NotFoundObjectResult to BadRequestObjectResult
  and renamed test methods accordingly.

Android integration tests (4 files):
- Renamed existing malformed-GUID tests to *_malformedId_returns400 /
  *_malformedDeviceId_returns400 and changed assertions to expect 400.
- Added new *_nonexistentId_returns404 / *_nonexistentDevice_returns404
  tests using a valid but nonexistent UUID (ffffffff-...) to properly
  cover 404 behaviour.

Documentation (2 files):
- API Contract: added Path Parameter Validation rule; added 400 Bad
  Request error responses to attachments, config, distribution, feedback.
- Integration Test Contract: added malformed-ID 400 rows to all endpoint
  tables; changed config non-client device from 403 Forbidden to 404.
@WillStephenn WillStephenn requested a review from nemoshu March 5, 2026 23:02
@nemoshu nemoshu merged commit 90e1a0a into integration/network-tests Mar 6, 2026
3 checks passed
@nemoshu nemoshu deleted the integration/test-suit-bug-fix-ralphing branch March 6, 2026 04:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants