diff --git a/test/Extensions/Orleans.Azure.Tests/Streaming/AzureQueueJsonDataAdapterTests.cs b/test/Extensions/Orleans.Azure.Tests/Streaming/AzureQueueJsonDataAdapterTests.cs index b89471e8a95..e0a428cbf89 100644 --- a/test/Extensions/Orleans.Azure.Tests/Streaming/AzureQueueJsonDataAdapterTests.cs +++ b/test/Extensions/Orleans.Azure.Tests/Streaming/AzureQueueJsonDataAdapterTests.cs @@ -1,6 +1,7 @@ #pragma warning disable StreamingJsonSerializationExperimental // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System.Buffers.Text; +using JsonValueKind = System.Text.Json.JsonValueKind; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; @@ -20,6 +21,9 @@ namespace Tester.AzureUtils.Streaming { [Collection(TestEnvironmentFixture.DefaultCollection)] [TestCategory("AzureStorage"), TestCategory("Streaming")] + [TestSuite("BVT")] + [TestProvider("AzureStorage")] + [TestArea("Streaming")] public class AzureQueueJsonDataAdapterTests { private const string CompactOrleans3JsonMessage = @@ -49,7 +53,10 @@ private AzureQueueJsonDataAdapter InitializeQueueJsonDataAdapter(AzureQueueJsonD { var serializer = this.fixture.Services.GetRequiredService(); var azureQueueDataAdapterV2 = new AzureQueueDataAdapterV2(serializer); - var jsonOptions = this.fixture.Services.GetRequiredService>(); + var jsonOptions = Options.Create(new OrleansJsonSerializerOptions + { + JsonSerializerSettings = OrleansJsonSerializerSettings.GetDefaultSerializerSettings(this.fixture.Services) + }); var jsonOrleansSerializer = new OrleansJsonSerializer(jsonOptions); return new AzureQueueJsonDataAdapter( @@ -196,6 +203,46 @@ public void JsonAdapter_DeserializesCompactOrleans3JsonMessage() batchContainer.StreamId); } + [Theory, TestCategory("BVT")] + [InlineData("\"1\"")] + [InlineData("2147483648")] + [InlineData("2")] + public void JsonAdapter_RejectsUnsupportedCompactEnvelopeVersion(string version) + { + var jsonAdapter = InitializeQueueJsonDataAdapter(new AzureQueueJsonDataAdapterOptions { EnableFallback = false }); + + var exception = Assert.Throws( + () => jsonAdapter.FromQueueMessage($"{{\"version\":{version}}}", sequenceId: 0)); + + Assert.Contains("Unsupported Azure Queue JSON envelope version", exception.Message); + Assert.Contains(version, exception.Message); + } + + [Theory, TestCategory("BVT")] + [MemberData(nameof(MalformedCompactEnvelopeCases))] + public void JsonAdapter_RejectsMalformedCompactEnvelope( + string message, + string expectedProperty, + string expectedKind) + { + var jsonAdapter = InitializeQueueJsonDataAdapter(new AzureQueueJsonDataAdapterOptions { EnableFallback = false }); + + var exception = Assert.Throws( + () => jsonAdapter.FromQueueMessage(message, sequenceId: 0)); + + Assert.Contains($"property '{expectedProperty}'", exception.Message); + Assert.Contains(expectedKind, exception.Message); + } + + [Fact, TestCategory("BVT")] + public void JsonAdapter_RejectsInvalidJson() + { + var jsonAdapter = InitializeQueueJsonDataAdapter(new AzureQueueJsonDataAdapterOptions { EnableFallback = false }); + + Assert.ThrowsAny( + () => jsonAdapter.FromQueueMessage("{\"version\":1", sequenceId: 0)); + } + [Fact, TestCategory("BVT")] public void JsonAdapter_ProducesCompactVersion1Message() { @@ -376,6 +423,60 @@ public void Configurators_UseProviderSpecificAdapterOptions() Assert.True(IsValidJson(jsonMessage)); } + public static TheoryData MalformedCompactEnvelopeCases => new() + { + { + """{"version":1,"events":[],"requestContext":{}}""", + "stream", + nameof(JsonValueKind.Object) + }, + { + """{"version":1,"stream":[],"events":[],"requestContext":{}}""", + "stream", + nameof(JsonValueKind.Object) + }, + { + """{"version":1,"stream":{"key":"key"},"events":[],"requestContext":{}}""", + "namespace", + $"{nameof(JsonValueKind.String)} or {nameof(JsonValueKind.Null)}" + }, + { + """{"version":1,"stream":{"namespace":1,"key":"key"},"events":[],"requestContext":{}}""", + "namespace", + $"{nameof(JsonValueKind.String)} or {nameof(JsonValueKind.Null)}" + }, + { + """{"version":1,"stream":{"namespace":"namespace"},"events":[],"requestContext":{}}""", + "key", + nameof(JsonValueKind.String) + }, + { + """{"version":1,"stream":{"namespace":"namespace","key":null},"events":[],"requestContext":{}}""", + "key", + nameof(JsonValueKind.String) + }, + { + """{"version":1,"stream":{"namespace":"namespace","key":"key"},"requestContext":{}}""", + "events", + nameof(JsonValueKind.Array) + }, + { + """{"version":1,"stream":{"namespace":"namespace","key":"key"},"events":{},"requestContext":{}}""", + "events", + nameof(JsonValueKind.Array) + }, + { + """{"version":1,"stream":{"namespace":"namespace","key":"key"},"events":[]}""", + "requestContext", + nameof(JsonValueKind.Object) + }, + { + """{"version":1,"stream":{"namespace":"namespace","key":"key"},"events":[],"requestContext":[]}""", + "requestContext", + nameof(JsonValueKind.Object) + } + }; + [GenerateSerializer] public sealed class EventData : IEquatable {