Files
natsnet/docs/plans/phases/phase-7-porting-verification.md
2026-02-26 06:23:13 -05:00

8.6 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 complete or better
  • All tests ported and compilable
  • Verify readiness: dotnet run --project tools/NatsNet.PortTracker -- phase check 6 --db porting.db

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~NATS.Server.Tests.Protocol" \
  tests/NATS.Server.Tests/

# Filter by test class
dotnet test --filter "FullyQualifiedName~NATS.Server.Tests.Protocol.NatsParserTests" \
  tests/NATS.Server.Tests/

# Filter by specific test method
dotnet test --filter "FullyQualifiedName~NATS.Server.Tests.Protocol.NatsParserTests.TryParse_ValidInput_ReturnsTrue" \
  tests/NATS.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:

  1. Read the failure output. The test runner prints the assertion that failed, the expected vs actual values, and the stack trace.
  2. 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
    
  3. 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.
  4. Fix and re-run. After fixing, re-run only the failing test:
    dotnet test --filter "FullyQualifiedName~NATS.Server.Tests.Protocol.NatsParserTests.TryParse_EmptyInput_ReturnsFalse" \
      tests/NATS.Server.Tests/
    
  5. Then re-run the full module. Confirm no regressions:
    dotnet test --filter "FullyQualifiedName~NATS.Server.Tests.Protocol" \
      tests/NATS.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 tests/NATS.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:

  1. Start the Go server:
    cd golang/nats-server && go run . -p 4222
    
  2. Start the .NET server:
    dotnet run --project src/NATS.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 Task without error handling)

Behavioral difference with Go server

  1. Identify the specific protocol message or state that differs
  2. Trace through both implementations step by step
  3. Check the NATS protocol specification for the correct behavior
  4. Fix the .NET implementation to match (the Go server is the reference)

Completion Criteria

  • All non-N/A modules have status verified
  • All non-N/A features have status verified
  • All non-N/A tests have status verified
  • All targeted tests pass: dotnet test tests/NATS.Server.Tests/
  • All integration tests pass: dotnet test tests/NATS.Server.IntegrationTests/
  • Key behavioral scenarios produce equivalent results on Go and .NET servers
  • phase check 7 passes with no errors
  • Final report exported and reviewed