- Created 52 Gitea issues across milestones 1-7, one per completion criterion - Each criterion now links to its corresponding issue ([#N](url) format) - Milestone Tracking sections updated with Issue Updates subsection: when/how to comment, close issues via CLI or web UI - Phases 4-7 criteria converted from plain bullets to checkbox format
11 KiB
Phase 7: Porting Verification
Verify all ported code through targeted testing per module. This phase does NOT run the full test suite as a single pass -- it systematically verifies each module, marks items as verified, and confirms behavioral equivalence with the Go server.
Objective
Every ported module passes its targeted tests. Every item in the database reaches verified or n_a status. Cross-module integration tests pass. Key behavioral scenarios produce equivalent results between the Go and .NET servers.
Prerequisites
- Phase 6 complete: all non-N/A items at
completeor better - All tests ported and compilable
- Verify readiness:
dotnet run --project tools/NatsNet.PortTracker -- phase check 6 --db porting.db
Source and Target Locations
- Go source code is located in the
golang/folder (specificallygolang/nats-server/) - .NET ported version is located in the
dotnet/folder
Milestone Tracking
This phase corresponds to Milestone 7 in Gitea. When starting this phase, verify the milestone is open. Assign relevant issues to this milestone as work progresses.
Issue Updates
Each completion criterion has a corresponding Gitea issue. Update issues as you work:
- Starting a criterion: Add a comment noting work has begun
- Blocked: Add a comment describing the blocker
- Complete: Close the issue with a comment summarizing the result (e.g., counts, verification output)
Close issues via CLI:
curl -s -X PATCH "https://gitea.dohertylan.com/api/v1/repos/dohertj2/natsnet/issues/{N}" \
-H "Content-Type: application/json" \
-H "Authorization: token $GITEA_TOKEN" \
-d '{"state":"closed"}'
Or close via the Gitea web UI.
Verification Workflow
Work through modules one at a time. Do not move to the next module until the current one is fully verified.
Step 1: List modules to verify
# Show all modules — look for status 'complete' (not yet verified)
dotnet run --project tools/NatsNet.PortTracker -- module list --db porting.db
Start with leaf modules (those with the fewest dependencies) and work upward, same order as the porting phase.
Step 2: List tests for the module
For each module, identify all mapped tests:
dotnet run --project tools/NatsNet.PortTracker -- test list --module <module_id> --db porting.db
This shows every test associated with the module, its status, and its .NET method name.
Step 3: Run targeted tests
Run only the tests for this module using dotnet test --filter:
# Filter by namespace (matches all tests in the module's namespace)
dotnet test --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Protocol" \
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
# Filter by test class
dotnet test --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Protocol.NatsParserTests" \
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
# Filter by specific test method
dotnet test --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Protocol.NatsParserTests.TryParse_ValidInput_ReturnsTrue" \
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
The --filter flag uses partial matching on the fully qualified test name. Use the namespace pattern for module-wide runs, and the class or method pattern for debugging specific failures.
Step 4: Handle failures
When tests fail:
- Read the failure output. The test runner prints the assertion that failed, the expected vs actual values, and the stack trace.
- Locate the Go reference. Look up the test in the database to find the original Go test and source:
dotnet run --project tools/NatsNet.PortTracker -- test show <test_id> --db porting.db - Compare Go and .NET logic. Open the Go source at the stored line number. Check for translation errors: off-by-one, missing edge cases, different default values.
- Fix and re-run. After fixing, re-run only the failing test:
dotnet test --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Protocol.NatsParserTests.TryParse_EmptyInput_ReturnsFalse" \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ - Then re-run the full module. Confirm no regressions:
dotnet test --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Protocol" \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
Common failure causes:
| Symptom | Likely cause |
|---|---|
| Off-by-one in buffer parsing | Go slices are half-open [start:end), C# spans match but array indexing might differ |
| Timeout in async test | Missing CancellationToken, or Task not awaited |
| Wrong byte sequence | Go uses []byte("string") which is UTF-8; ensure C# uses Encoding.UTF8 |
| Nil vs null behavior | Go nil checks behave differently from C# null; check for default values |
| Map iteration order | Go maps iterate in random order; if the test depends on order, sort first |
Step 5: Mark module as verified
Once all tests pass for a module:
# Mark the module itself as verified
dotnet run --project tools/NatsNet.PortTracker -- module update <module_id> --status verified --db porting.db
# Mark all features in the module as verified
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status verified \
--all-in-module <module_id> --db porting.db
# Mark individual tests as verified
dotnet run --project tools/NatsNet.PortTracker -- test update <test_id> --status verified --db porting.db
Step 6: Move to next module
Repeat Steps 2-5 for each module. Track progress:
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
Integration Testing
After all modules are individually verified, run integration tests that exercise cross-module behavior.
Step 7: Run integration tests
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/
Integration tests cover scenarios like:
- Client connects, subscribes, receives published messages
- Multiple clients with wildcard subscriptions
- Connection lifecycle (connect, disconnect, reconnect)
- Protocol error handling (malformed commands, oversized payloads)
- Configuration loading and server startup
Fix any failures by tracing through the modules involved and checking the interaction boundaries.
Step 8: Behavioral comparison
Run both the Go server and the .NET server with the same workload and compare behavior. This catches semantic differences that unit tests might miss.
Setup:
- Start the Go server:
cd golang/nats-server && go run . -p 4222 - Start the .NET server:
dotnet run --project dotnet/src/ZB.MOM.NatsNet.Server.Host -- --port 4223
Comparison scenarios:
| Scenario | What to compare |
|---|---|
| Basic pub/sub | Publish a message, verify subscriber receives identical payload |
| Wildcard matching | Subscribe with foo.* and foo.>, publish to foo.bar, verify same match results |
| Queue groups | Multiple subscribers in a queue group, verify round-robin distribution |
| Protocol errors | Send malformed commands, verify same error responses |
| Connection info | Connect and check INFO response fields |
| Graceful shutdown | Send SIGTERM, verify clean disconnection |
Use the nats CLI tool to drive traffic:
# Subscribe on Go server
nats sub -s nats://localhost:4222 "test.>"
# Subscribe on .NET server
nats sub -s nats://localhost:4223 "test.>"
# Publish to both and compare
nats pub -s nats://localhost:4222 test.hello "payload"
nats pub -s nats://localhost:4223 test.hello "payload"
Document any behavioral differences. Some differences are expected (e.g., server name, version string) while others indicate bugs.
Step 9: Final verification
Run the complete check:
# Phase 7 check — all tests verified
dotnet run --project tools/NatsNet.PortTracker -- phase check 7 --db porting.db
# Final summary — all items should be verified or n_a
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
# Export final report
dotnet run --project tools/NatsNet.PortTracker -- report export \
--format md \
--output porting-final-report.md \
--db porting.db
Troubleshooting
Test passes individually but fails in module run
Likely a test ordering dependency or shared state. Check for:
- Static mutable state not reset between tests
- Port conflicts if tests start servers
- File system artifacts from previous test runs
Fix by adding proper test cleanup (IDisposable, IAsyncLifetime) and using unique ports/paths per test.
Module passes but integration test fails
The issue is at a module boundary. Check:
- Interface implementations match expectations
- Serialization/deserialization is consistent across modules
- Thread safety at module interaction points
- Async patterns are correct (no fire-and-forget
Taskwithout error handling)
Behavioral difference with Go server
- Identify the specific protocol message or state that differs
- Trace through both implementations step by step
- Check the NATS protocol specification for the correct behavior
- Fix the .NET implementation to match (the Go server is the reference)
Completion Criteria
- #45 All non-N/A modules have status
verified - #46 All non-N/A features have status
verified - #47 All non-N/A tests have status
verified - #48 All targeted tests pass:
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ - #49 All integration tests pass:
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/ - #50 Key behavioral scenarios produce equivalent results on Go and .NET servers
- #51
phase check 7passes with no errors - #52 Final report exported and reviewed
- Close the Phase 7 milestone in Gitea:
Or close it via the Gitea web UI at https://gitea.dohertylan.com/dohertj2/natsnet/milestone/7
curl -s -X PATCH "https://gitea.dohertylan.com/api/v1/repos/dohertj2/natsnet/milestones/7" \ -H "Content-Type: application/json" \ -H "Authorization: token $GITEA_TOKEN" \ -d '{"state":"closed"}' - Close the Final: Porting Complete milestone in Gitea:
Or close it via the Gitea web UI at https://gitea.dohertylan.com/dohertj2/natsnet/milestone/8
curl -s -X PATCH "https://gitea.dohertylan.com/api/v1/repos/dohertj2/natsnet/milestones/8" \ -H "Content-Type: application/json" \ -H "Authorization: token $GITEA_TOKEN" \ -d '{"state":"closed"}'
Related Documentation
- Phase 6: Porting -- the implementation phase this verifies
- Phase 4: .NET Solution Design -- the original design mappings