Purpose: Ensure the same proto definitions produce semantically identical JSON across go-http, go-client, ts-client, and OpenAPI. The server must serialize what clients expect, and OpenAPI must document what both produce. This is the final validation for Phase 7.
Output: Cross-generator consistency tests that verify generated code matches between generators, TypeScript types match Go serialization behavior, and OpenAPI schemas accurately reflect the wire format for all oneof and flatten combinations.
<execution_context> @/Users/sebastienmelki/.claude/get-shit-done/workflows/execute-plan.md @/Users/sebastienmelki/.claude/get-shit-done/templates/summary.md </execution_context>
Existing consistency test patterns from Phase 4-6 to follow exactly
@internal/httpgen/encoding_consistency_test.go @internal/httpgen/nullable_consistency_test.go @internal/httpgen/timestamp_format_consistency_test.go @internal/httpgen/bytes_encoding_consistency_test.go
The test file should contain these test functions (following the split-test pattern from D-04-05-01):
-
TestGoGeneratorsProduceIdenticalOneofDiscriminator -- Compare golden files:
- Read httpgen golden file for oneof_discriminator
- Read clientgen golden file for oneof_discriminator
- Normalize generator comments using normalizeGeneratorComment
- Assert byte-level equality after normalization
-
TestOneofDiscriminatorTypeScriptTypes -- Verify TS type mapping:
- Read tsclientgen golden file for oneof_discriminator
- Verify FlattenedEvent generates a discriminated union type with "type" discriminator
- Verify discriminator values match: "text" and "img" (custom oneof_value)
- Verify NestedEvent generates a union with "kind" discriminator and nested variants
- Verify PlainEvent generates standard interface (no discriminated union)
-
TestOneofDiscriminatorOpenAPISchemas -- Verify OpenAPI schemas:
- Read openapiv3 golden file for oneof_discriminator
- Verify FlattenedEvent schema uses oneOf with discriminator keyword
- Verify discriminator propertyName matches annotation
- Verify mapping includes custom oneof_value ("img" maps to ImageContent)
- Verify NestedEvent has discriminator with nested variant references
- Verify PlainEvent has no discriminator (standard object schema)
-
TestOneofDiscriminatorCrossGeneratorAgreement -- Cross-check all generators agree:
- Table-driven test with test cases for each message:
testCases := []struct { message string hasDiscriminator bool discriminatorField string // "type", "kind", or "" flatten bool variants []struct { name string // field name value string // discriminator value } }{ { "FlattenedEvent", true, "type", true, []struct{name, value string}{{"text", "text"}, {"image", "img"}}, }, { "NestedEvent", true, "kind", false, []struct{name, value string}{{"text", "text"}, {"image", "image"}, {"video", "vid"}}, }, {"PlainEvent", false, "", false, nil}, } - For each test case, verify:
- Go golden file contains MarshalJSON for discriminated messages, not for PlainEvent
- TypeScript golden has discriminated union types for discriminated messages
- OpenAPI golden has discriminator keyword for discriminated messages
- All agree on discriminator field name and variant values
- Table-driven test with test cases for each message:
Implementation approach: Read golden files from disk (same as existing consistency tests). Parse Go golden for type-switch patterns and discriminator strings, TS golden for union types, OpenAPI golden for discriminator keyword and mapping. Use string matching and regex patterns.
go test -v -run TestOneofDiscriminator ./internal/httpgen/...
make lint-fix-
TestGoGeneratorsProduceIdenticalFlatten -- Compare golden files:
- Read httpgen golden file for flatten
- Read clientgen golden file for flatten
- Normalize generator comments
- Assert byte-level equality after normalization
-
TestFlattenTypeScriptTypes -- Verify TS type mapping:
- Read tsclientgen golden file for flatten
- Verify SimpleFlatten interface contains street, city, zip at top level (no nested address)
- Verify DualFlatten interface contains billing_street, billing_city, shipping_street, shipping_city
- Verify MixedFlatten has flattened fields AND a nested contact property
- Verify PlainNested has standard nested address property
-
TestFlattenOpenAPISchemas -- Verify OpenAPI schemas:
- Read openapiv3 golden file for flatten
- Verify SimpleFlatten schema has street, city, zip as direct properties
- Verify DualFlatten schema has billing_street, billing_city, etc. as direct properties
- Verify MixedFlatten has both flattened and nested properties
- Verify PlainNested has $ref to Address schema
-
TestFlattenCrossGeneratorAgreement -- Cross-check all generators agree:
- Table-driven test with test cases:
testCases := []struct { message string hasFlatten bool flattenedFields []string // Expected top-level JSON field names from flattening nestedFields []string // Expected nested (non-flattened) fields }{ { "SimpleFlatten", true, []string{"street", "city", "zip"}, nil, }, { "DualFlatten", true, []string{"billing_street", "billing_city", "billing_zip", "shipping_street", "shipping_city", "shipping_zip"}, nil, }, { "MixedFlatten", true, []string{"street", "city", "zip"}, []string{"contact"}, }, {"PlainNested", false, nil, []string{"address"}}, } - For each test case, verify:
- Go golden contains MarshalJSON for flatten messages, not for PlainNested
- Go golden references the expected flattened field names (with prefixes)
- TypeScript golden has flattened fields at interface level
- OpenAPI golden has flattened fields as direct properties
- Table-driven test with test cases:
Implementation approach: Same as oneof_discriminator -- read golden files, parse patterns, compare.
go test -v -run TestFlatten ./internal/httpgen/...
make lint-fix- All existing tests still pass (zero regression)
- All new consistency tests pass
- All golden files are up to date
- Lint is clean
# Full test suite
go test ./...
# Specific generator tests
go test -v ./internal/httpgen/... ./internal/clientgen/... ./internal/tsclientgen/... ./internal/openapiv3/...
# Golden file tests
go test -v -run TestExhaustiveGoldenFiles ./internal/...
# All consistency tests (Phase 4, 5, 6, and 7)
go test -v -run "Consistency|Identical" ./internal/httpgen/...
# Lint check
make lint-fixVerify that:
- oneof_discriminator and flatten golden files exist for all 4 generators
- Generated code matches expected golden output
- Cross-generator consistency verified for all structural transform combinations
- No regressions in any Phase 4, 5, or 6 tests
- Phase 7 success criteria 6 is met: cross-generator consistency test confirms agreement
If any test fails, debug and fix. The consistency tests are the final gate ensuring Phase 7 success.
go test ./...
make lint-fixAll tests pass, lint clean, no regressions.
- All 4 generators produce consistent output for oneof discriminator annotations
- All 4 generators produce consistent output for flatten annotations
- go-http and go-client produce byte-identical encoding code for both features
- TypeScript types match Go serialization for all structural transform combinations
- OpenAPI schemas match Go serialization for all structural transform combinations
- All Phase 4, 5, and 6 consistency tests still pass (zero regression)
- Full test suite passes
- Lint clean
<success_criteria>
- go-http and go-client produce byte-identical code for oneof_discriminator and flatten
- All oneof discriminator combinations (flattened/non-flattened, custom values, unset) produce correct types in all 4 generators
- All flatten combinations (simple, prefix, dual, mixed) produce correct field names in all 4 generators
- OpenAPI discriminator and flatten schemas accurately reflect the wire format
- Zero regressions in existing tests (Phase 1-6)
- Phase 7 success criterion 6 met: cross-generator consistency test confirms agreement </success_criteria>
