Closes #4
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
using System.Text.Json;
|
||||
using FinalFactory.Rendezvous.Contracts;
|
||||
|
||||
namespace FinalFactory.Rendezvous.Tests.Contracts;
|
||||
|
||||
public sealed class ContractSerializationTests
|
||||
{
|
||||
public static TheoryData<string, Type> GoldenJsonVectors => new()
|
||||
{
|
||||
{ "register-session.json", typeof(RegisterSessionRequest) },
|
||||
{ "browse-sessions.json", typeof(BrowseSessionsResponse) },
|
||||
{ "create-join-response.json", typeof(CreateJoinAttemptResponse) },
|
||||
{ "api-error.json", typeof(ApiError) },
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GoldenJsonVectors))]
|
||||
public void CanonicalJsonRoundtripsGoldenVectors(string fileName, Type contractType)
|
||||
{
|
||||
string expected = ContractTestFiles.Read(fileName);
|
||||
object? value = JsonSerializer.Deserialize(expected, contractType, ContractJson.Options);
|
||||
|
||||
Assert.NotNull(value);
|
||||
Assert.Equal(expected, JsonSerializer.Serialize(value, contractType, ContractJson.Options));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IdentifiersAreSerializedAsStrings()
|
||||
{
|
||||
SessionListingId id = new(new Guid("00112233-4455-6677-8899-aabbccddeeff"));
|
||||
|
||||
Assert.Equal(
|
||||
"\"00112233-4455-6677-8899-aabbccddeeff\"",
|
||||
JsonSerializer.Serialize(id, ContractJson.Options));
|
||||
Assert.Equal(id, JsonSerializer.Deserialize<SessionListingId>(
|
||||
"\"00112233-4455-6677-8899-aabbccddeeff\"",
|
||||
ContractJson.Options));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnknownObjectFieldsAreIgnoredForAdditiveV1Changes()
|
||||
{
|
||||
const string json = """
|
||||
{"contractVersion":1,"idempotencyKey":"join-001","gameId":"space-game","environmentId":"production","listingId":"00112233-4455-6677-8899-aabbccddeeff","protocolVersion":7,"futureField":{"nested":true}}
|
||||
""";
|
||||
|
||||
CreateJoinAttemptRequest? request = JsonSerializer.Deserialize<CreateJoinAttemptRequest>(
|
||||
json,
|
||||
ContractJson.Options);
|
||||
|
||||
Assert.NotNull(request);
|
||||
Assert.Equal(new GameId("space-game"), request.GameId);
|
||||
Assert.Equal(7u, request.ProtocolVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MissingNormativeFieldsAreRejectedInsteadOfDefaulted()
|
||||
{
|
||||
const string missingVersion = """
|
||||
{"idempotencyKey":"join-001","gameId":"space-game","environmentId":"production","listingId":"00112233-4455-6677-8899-aabbccddeeff","protocolVersion":7}
|
||||
""";
|
||||
|
||||
Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<CreateJoinAttemptRequest>(
|
||||
missingVersion,
|
||||
ContractJson.Options));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnknownEnumNamesAndNumericValuesAreRejected()
|
||||
{
|
||||
Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<ReportConnectionOutcomeRequest>(
|
||||
"{\"contractVersion\":1,\"outcome\":\"futureOutcome\",\"elapsedMilliseconds\":1}",
|
||||
ContractJson.Options));
|
||||
Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<ReportConnectionOutcomeRequest>(
|
||||
"{\"contractVersion\":1,\"outcome\":99,\"elapsedMilliseconds\":1}",
|
||||
ContractJson.Options));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(2)]
|
||||
[InlineData(int.MaxValue)]
|
||||
public void UnknownContractVersionsFailPredictably(int version)
|
||||
{
|
||||
Assert.Equal(
|
||||
RendezvousErrorCode.UnsupportedContractVersion,
|
||||
ContractValidation.ValidateContractVersion(version));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GameplayProtocolCompatibilityIsExactAndBuildIndependent()
|
||||
{
|
||||
Assert.True(ContractValidation.AreProtocolsCompatible(7, 7));
|
||||
Assert.False(ContractValidation.AreProtocolsCompatible(7, 8));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SharedCanonicalOptionsCannotBeMutatedByConsumers()
|
||||
{
|
||||
Assert.True(ContractJson.Options.IsReadOnly);
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
ContractJson.Options.WriteIndented = true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user