Skip to content

Fix dictionary key order sensitivity in Spector tests for languages with non-deterministic ordering #7866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jul 9, 2025

This PR resolves an issue where Spector tests would fail when client libraries sent JSON dictionaries with keys in different orders than expected, which was particularly problematic for languages like Rust where HashMap key order is not guaranteed.

Problem

When Rust clients (and other languages with non-deterministic object key ordering) sent dictionary data to Spector mock APIs, tests would fail even when the data was semantically identical:

// Rust client sends:
{"k2": 2, "k1": 1}

// Spector expects:
{"k1": 1, "k2": 2}

The raw body validation used strict string comparison, causing these semantically equivalent JSON objects to be treated as different.

Solution

Enhanced the validateRawBodyEquals function in @typespec/spec-api to perform semantic JSON comparison when both the actual and expected bodies are JSON content, while preserving exact string comparison for non-JSON content.

Key Changes

  1. Added JSON detection: isJsonContent() helper safely identifies JSON strings
  2. Semantic JSON comparison: Parse and compare JSON objects semantically for key order independence
  3. Graceful fallback: Falls back to string comparison if JSON parsing fails
  4. Preserved behavior: Non-JSON content (plain text, binary) still uses exact comparison

Example

// Before: This would fail ❌
validateRawBodyEquals(
  { rawBody: '{"k2":2,"k1":1}' },
  '{"k1":1,"k2":2}'
);

// After: This now passes ✅
validateRawBodyEquals(
  { rawBody: '{"k2":2,"k1":1}' },
  '{"k1":1,"k2":2}'
);

Testing

  • ✅ All existing tests continue to pass
  • ✅ Added comprehensive test suite covering dictionary ordering scenarios
  • ✅ Verified edge cases (invalid JSON, non-JSON content, semantic differences)
  • ✅ Manual testing confirms fix works for real-world TypeSpec dictionary patterns

Impact

  • Rust clients: Can now use HashMap without worrying about serialization key order
  • Other languages: Any language with non-deterministic object key order now works
  • Backward compatibility: Zero impact on existing functionality
  • Performance: Minimal overhead - only parses JSON when both sides are JSON-like

Fixes #7687.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

antkmsft and others added 2 commits July 9, 2025 14:06
Copy link
Contributor

github-actions bot commented Jul 9, 2025

No changes needing a change description found.

@Copilot Copilot AI changed the title [WIP] Update spector test to stop requiring dictionaries being sorted by key Fix dictionary key order sensitivity in Spector tests for languages with non-deterministic ordering Jul 9, 2025
@Copilot Copilot AI requested a review from antkmsft July 9, 2025 21:14
Copilot finished work on behalf of antkmsft July 9, 2025 21:14
@microsoft-github-policy-service microsoft-github-policy-service bot added compiler:core Issues for @typespec/compiler compiler:emitter-framework Issues for the emitter framework ide Issues for VS, VSCode, Monaco, etc. lib:http lib:openapi lib:rest lib:versioning lib:http-specs For issues/prs related to the @typespec/http-specs package meta:blog Blog updates meta:website TypeSpec.io updates tspd Issues for the tspd tool emitter:client:all General issue for client emitters emitter:client:js Issue for the JS client emitter: @typespec/http-client-js emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp emitter:client:java Issue for the Java client emitter: @typespec/http-client-java emitter:client:python Issue for the Python client emitter: @typespec/http-client-python emitter:graphql Issues for @typespec/graphql emitter emitter:json-schema emitter:protobuf The protobuf emitter emitter:openapi3 Issues for @typespec/openapi3 emitter labels Jul 9, 2025
@microsoft-github-policy-service microsoft-github-policy-service bot added openapi3:converter Issues for @typespec/openapi3 openapi to typespec converter emitter:service:csharp emitter:service:js emitter:service:java Issue for Java service emitter eng ui:playground ui:type-graph-viewer spector Issues related to spector and the spec sets labels Jul 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:core Issues for @typespec/compiler compiler:emitter-framework Issues for the emitter framework emitter:client:all General issue for client emitters emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp emitter:client:java Issue for the Java client emitter: @typespec/http-client-java emitter:client:js Issue for the JS client emitter: @typespec/http-client-js emitter:client:python Issue for the Python client emitter: @typespec/http-client-python emitter:graphql Issues for @typespec/graphql emitter emitter:json-schema emitter:openapi3 Issues for @typespec/openapi3 emitter emitter:protobuf The protobuf emitter emitter:service:csharp emitter:service:java Issue for Java service emitter emitter:service:js eng ide Issues for VS, VSCode, Monaco, etc. lib:http lib:http-specs For issues/prs related to the @typespec/http-specs package lib:openapi lib:rest lib:versioning meta:blog Blog updates meta:website TypeSpec.io updates openapi3:converter Issues for @typespec/openapi3 openapi to typespec converter spector Issues related to spector and the spec sets tspd Issues for the tspd tool ui:playground ui:type-graph-viewer
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update spector test to stop requiring dictionaries being sorted by key
2 participants