From a8315a437806f1e51d68abc13ae6948ec90b07b3 Mon Sep 17 00:00:00 2001 From: Stijn Moreels <9039753+stijnmoreels@users.noreply.github.com> Date: Sat, 27 Apr 2024 20:54:31 +0200 Subject: [PATCH] chore: support net8.0 version (#313) * chore: support net8.0 version * pr-ix: correct tests & extensions w/ new major versions --- .../Arcus.EventGrid.Core.csproj | 17 +- .../Arcus.EventGrid.Security.Core.csproj | 7 +- .../Arcus.EventGrid.Security.WebApi.csproj | 9 +- .../Arcus.EventGrid.Testing.csproj | 11 +- .../Infrastructure/Hosts/EventConsumerHost.cs | 248 +++--------------- .../Logging/NoOpLogger.cs | 46 ---- .../Events/EventSchema.cs | 14 + .../Arcus.EventGrid.Tests.Integration.csproj | 1 + .../Fixture/EventGridTopicEndpoint.cs | 2 +- .../Fixture/TestConfig.cs | 2 +- ...isherClientWithTrackingCloudEventsTests.cs | 2 +- ...erClientWithTrackingEventGridEventTests.cs | 2 +- ...entGridPublisherClientWithTrackingTests.cs | 2 +- ...ridSubscriptionValidationAttributeTests.cs | 60 +++-- .../Arcus.EventGrid.Tests.Unit.csproj | 1 + .../Artifacts/EventSamples.Designer.cs | 5 +- .../Artifacts/EventSamples.resx | 2 +- .../EventGridSubscriptionValidatorTests.cs | 45 ++-- .../Testing/EventConsumerHostTests.cs | 81 ++---- .../Fixture/InMemoryEventConsumerHost.cs | 10 + 20 files changed, 168 insertions(+), 399 deletions(-) delete mode 100644 src/Arcus.EventGrid.Testing/Logging/NoOpLogger.cs create mode 100644 src/Arcus.EventGrid.Tests.Core/Events/EventSchema.cs diff --git a/src/Arcus.EventGrid.Core/Arcus.EventGrid.Core.csproj b/src/Arcus.EventGrid.Core/Arcus.EventGrid.Core.csproj index 4f18829d..bd673f72 100644 --- a/src/Arcus.EventGrid.Core/Arcus.EventGrid.Core.csproj +++ b/src/Arcus.EventGrid.Core/Arcus.EventGrid.Core.csproj @@ -17,27 +17,22 @@ true - - - NU5104 - - - + - + - - - + + + - + diff --git a/src/Arcus.EventGrid.Security.Core/Arcus.EventGrid.Security.Core.csproj b/src/Arcus.EventGrid.Security.Core/Arcus.EventGrid.Security.Core.csproj index ae2deb58..f0838459 100644 --- a/src/Arcus.EventGrid.Security.Core/Arcus.EventGrid.Security.Core.csproj +++ b/src/Arcus.EventGrid.Security.Core/Arcus.EventGrid.Security.Core.csproj @@ -24,15 +24,12 @@ + + - - - - - \ No newline at end of file diff --git a/src/Arcus.EventGrid.Security.WebApi/Arcus.EventGrid.Security.WebApi.csproj b/src/Arcus.EventGrid.Security.WebApi/Arcus.EventGrid.Security.WebApi.csproj index 1f20912c..c7012e32 100644 --- a/src/Arcus.EventGrid.Security.WebApi/Arcus.EventGrid.Security.WebApi.csproj +++ b/src/Arcus.EventGrid.Security.WebApi/Arcus.EventGrid.Security.WebApi.csproj @@ -16,11 +16,6 @@ true - - - NU5104 - - @@ -28,8 +23,8 @@ - - + + diff --git a/src/Arcus.EventGrid.Testing/Arcus.EventGrid.Testing.csproj b/src/Arcus.EventGrid.Testing/Arcus.EventGrid.Testing.csproj index e8ffd935..ff383ee3 100644 --- a/src/Arcus.EventGrid.Testing/Arcus.EventGrid.Testing.csproj +++ b/src/Arcus.EventGrid.Testing/Arcus.EventGrid.Testing.csproj @@ -19,20 +19,15 @@ - + - - - - - - - + + diff --git a/src/Arcus.EventGrid.Testing/Infrastructure/Hosts/EventConsumerHost.cs b/src/Arcus.EventGrid.Testing/Infrastructure/Hosts/EventConsumerHost.cs index 7bdbcab4..b32d3a59 100644 --- a/src/Arcus.EventGrid.Testing/Infrastructure/Hosts/EventConsumerHost.cs +++ b/src/Arcus.EventGrid.Testing/Infrastructure/Hosts/EventConsumerHost.cs @@ -1,22 +1,15 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; -using Arcus.EventGrid.Contracts; -using Arcus.EventGrid.Parsers; -using CloudNative.CloudEvents; +using Azure.Messaging; +using Azure.Messaging.EventGrid; using GuardNet; -using Microsoft.Azure.EventGrid.Models; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Polly; using Polly.Timeout; -using NewCloudEvent = Azure.Messaging.CloudEvent; -using NewEventGridEvent = Azure.Messaging.EventGrid.EventGridEvent; -using OldCloudEvent = CloudNative.CloudEvents.CloudEvent; -using OldEventGridEvent = Microsoft.Azure.EventGrid.Models.EventGridEvent; namespace Arcus.EventGrid.Testing.Infrastructure.Hosts { @@ -25,8 +18,7 @@ namespace Arcus.EventGrid.Testing.Infrastructure.Hosts /// public class EventConsumerHost { - private readonly ConcurrentDictionary _oldEvents = new ConcurrentDictionary(); - private readonly ConcurrentDictionary _newEvents = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _events = new ConcurrentDictionary(); /// /// Initializes a new instance of the class. @@ -50,36 +42,25 @@ public EventConsumerHost(ILogger logger) /// /// The raw payload containing all received events. /// Thrown when the is blank. - /// Thrown when the failed to be read as valid JSON. protected void EventsReceived(string rawReceivedEvents) { Guard.NotNullOrWhitespace(rawReceivedEvents, nameof(rawReceivedEvents), "Requires a non-blank raw event payload containing the serialized received events"); -#pragma warning disable CS0618 - EventsReceived(rawReceivedEvents, Logger); -#pragma warning restore CS0618 - } - - /// - /// Handles new received events into the event consumer that can later be retrieved. - /// - /// The raw payload containing all received events. - /// The logger to use for writing event information of the received events. - /// Thrown when the is blank. - /// Thrown when the is null. - /// Thrown when the failed to be read as valid JSON. - [Obsolete("Use the overload without the logger instead")] - protected void EventsReceived(string rawReceivedEvents, ILogger logger) - { - Guard.NotNullOrWhitespace(rawReceivedEvents, nameof(rawReceivedEvents), "Requires a non-blank raw event payload containing the serialized received events"); - Guard.NotNull(logger, nameof(logger), "Requires an logger instance to write event information of the received events"); + JToken token = JToken.Parse(rawReceivedEvents); + JObject[] events = token.Type switch + { + JTokenType.Array => token.Children().ToArray(), + JTokenType.Object => new [] { (JObject) token }, + _ => throw new InvalidOperationException( + "Couldn't find a correct JSON structure (array or object) to parse the EventGridEvent/CloudEvents from") + }; - EventBatch eventBatch = EventParser.Parse(rawReceivedEvents); - foreach (Event receivedEvent in eventBatch.Events) + foreach (JObject ev in events) { - logger.LogTrace("Received event '{EventId}' on event consumer host", receivedEvent.Id); - _oldEvents.AddOrUpdate(receivedEvent.Id, (rawReceivedEvents, receivedEvent), (id, ev) => (rawReceivedEvents, receivedEvent)); - _newEvents.AddOrUpdate(receivedEvent.Id, rawReceivedEvents, (id, ev) => rawReceivedEvents); + var eventId = ev["id"]?.ToString() ?? Guid.NewGuid().ToString(); + + Logger.LogTrace("Received event '{EventId}' on event consumer host", eventId); + _events.AddOrUpdate(eventId, ev.ToString(), (id, raw) => ev.ToString()); } } @@ -158,29 +139,29 @@ public string GetReceivedEvent(string eventId, TimeSpan timeout) /// /// Gets the event envelope that includes a requested event (uses timeout). /// - /// The custom event filter to select a specific event. + /// The custom event filter to select a specific event. /// The time period in which the event should be consumed. /// - /// The deserialized event that matches the specified . + /// The deserialized event that matches the specified . /// /// Thrown when the is null. /// Thrown when the is a negative time range. /// /// Thrown when no event could be received within the specified time range that matches the given . /// - public NewCloudEvent GetReceivedEvent(Func cloudEventFilter, TimeSpan timeout) + public CloudEvent GetReceivedEvent(Func cloudEventFilter, TimeSpan timeout) { Guard.NotNull(cloudEventFilter, nameof(cloudEventFilter), "Requires a function to filter out received CloudEvent events"); Guard.NotLessThanOrEqualTo(timeout, TimeSpan.Zero, nameof(timeout), "Requires a timeout span representing a positive time range"); - Policy timeoutPolicy = - CreateTimeoutPolicy(ev => ev is null, timeout); + Policy timeoutPolicy = + CreateTimeoutPolicy(ev => ev is null, timeout); - PolicyResult result = + PolicyResult result = timeoutPolicy.ExecuteAndCapture(() => { return TryGetReceivedEvent( - received => NewCloudEvent.Parse(BinaryData.FromString(received)), + received => CloudEvent.Parse(BinaryData.FromString(received)), cloudEventFilter); }); @@ -195,76 +176,35 @@ public NewCloudEvent GetReceivedEvent(Func cloudEventFilter throw result.FinalException; } - return result.Result; - } - - /// - /// Gets the event envelope that includes a requested event (uses timeout). - /// - /// The custom event filter to select a specific event. - /// The time period in which the event should be consumed. - /// - /// The deserialized event that matches the specified . - /// - /// Thrown when the is null. - /// Thrown when the is a negative time range. - /// - /// Thrown when no event could be received within the specified time range that matches the given . - /// - [Obsolete("Use 'CloudEvent' overload from 'Azure.Messaging.EventGrid' package")] - public OldCloudEvent GetReceivedEvent(Func cloudEventFilter, TimeSpan timeout) - { - Guard.NotNull(cloudEventFilter, nameof(cloudEventFilter), "Requires a function to filter out received CloudEvent events"); - Guard.NotLessThanOrEqualTo(timeout, TimeSpan.Zero, nameof(timeout), "Requires a timeout span representing a positive time range"); - - Policy timeoutPolicy = - CreateTimeoutPolicy(ev => ev is null, timeout); - - PolicyResult result = - timeoutPolicy.ExecuteAndCapture(() => - TryGetReceivedEvent( - ev => cloudEventFilter(ev))); - - if (result.Outcome is OutcomeType.Failure) - { - if (result.FinalException is TimeoutRejectedException) - { - throw new TimeoutException( - $"Could not in the time available ({timeout:g}) receive an CloudEvent event from Azure Event Grid on the Service Bus topic that matches the given filter"); - } - - throw result.FinalException; - } - return result.Result; } /// /// Gets the event envelope that includes a requested event (uses timeout). /// - /// The custom event filter to select a specific event. + /// The custom event filter to select a specific event. /// The time period in which the event should be consumed. /// - /// The deserialized event that matches the specified . + /// The deserialized event that matches the specified . /// /// Thrown when the is null. /// Thrown when the is a negative time range. /// /// Thrown when no event could be received within the specified time range that matches the given . /// - public NewEventGridEvent GetReceivedEvent(Func eventGridEventFilter, TimeSpan timeout) + public EventGridEvent GetReceivedEvent(Func eventGridEventFilter, TimeSpan timeout) { Guard.NotNull(eventGridEventFilter, nameof(eventGridEventFilter), "Requires a function to filter out received CloudEvent events"); Guard.NotLessThanOrEqualTo(timeout, TimeSpan.Zero, nameof(timeout), "Requires a timeout span representing a positive time range"); - Policy timeoutPolicy = - CreateTimeoutPolicy(ev => ev is null, timeout); + Policy timeoutPolicy = + CreateTimeoutPolicy(ev => ev is null, timeout); - PolicyResult result = + PolicyResult result = timeoutPolicy.ExecuteAndCapture(() => { return TryGetReceivedEvent( - received => NewEventGridEvent.Parse(BinaryData.FromString(received)), + received => EventGridEvent.Parse(BinaryData.FromString(received)), eventGridEventFilter); }); @@ -282,92 +222,6 @@ public NewEventGridEvent GetReceivedEvent(Func eventGri return result.Result; } - /// - /// Gets the event envelope that includes a requested event (uses timeout). - /// - /// The custom event filter to select a specific event. - /// The time period in which the event should be consumed. - /// - /// The deserialized event that matches the specified . - /// - /// Thrown when the is null. - /// Thrown when the is a negative time range. - /// - /// Thrown when no event could be received within the specified time range that matches the given . - /// - [Obsolete("Use 'EventGridEvent' overload from 'Azure.Messaging.EventGrid' package")] - public OldEventGridEvent GetReceivedEvent(Func eventGridEventFilter, TimeSpan timeout) - { - Guard.NotNull(eventGridEventFilter, nameof(eventGridEventFilter), "Requires a function to filter out received CloudEvent events"); - Guard.NotLessThanOrEqualTo(timeout, TimeSpan.Zero, nameof(timeout), "Requires a timeout span representing a positive time range"); - - Policy timeoutPolicy = - CreateTimeoutPolicy(ev => ev is null, timeout); - - PolicyResult result = - timeoutPolicy.ExecuteAndCapture(() => - TryGetReceivedEvent(ev => eventGridEventFilter(ev))); - - if (result.Outcome is OutcomeType.Failure) - { - if (result.FinalException is TimeoutRejectedException) - { - throw new TimeoutException( - $"Could not in the time available ({timeout:g}) receive an CloudEvent event from Azure Event Grid on the Service Bus topic that matches the given filter"); - } - - throw result.FinalException; - } - - return result.Result; - } - - /// - /// Gets the event envelope that includes the requested event (uses timeout). - /// - /// The custom event payload of the requested consumed event. - /// The custom event filter to select an with a specific event payload. - /// The time period in which the event should be consumed. - /// - /// The deserialized abstract whose payload matches the specified . - /// - /// Thrown when the is null. - /// Thrown when the is a negative time range. - /// - /// Thrown when no event could be retrieved within the specified time range - /// whose event payload matches the given . - /// - [Obsolete("Use either 'CloudEvent' or 'EventGridEvent' overloads")] - public Event GetReceivedEvent(Func eventPayloadFilter, TimeSpan timeout) - { - Guard.NotNull(eventPayloadFilter, nameof(eventPayloadFilter), "Requires a function to filter out received CloudEvent events"); - Guard.NotLessThanOrEqualTo(timeout, TimeSpan.Zero, nameof(timeout), "Requires a timeout span representing a positive time range"); - - Policy timeoutPolicy = - CreateTimeoutPolicy(ev => ev is null, timeout); - - PolicyResult result = - timeoutPolicy.ExecuteAndCapture(() => - TryGetReceivedEvent(ev => - { - var payload = ev.GetPayload(); - return payload != null && eventPayloadFilter(payload); - })); - - if (result.Outcome is OutcomeType.Failure) - { - if (result.FinalException is TimeoutRejectedException) - { - throw new TimeoutException( - $"Could not in the time available ({timeout:g}) receive an CloudEvent event from Azure Event Grid on the Service Bus topic that matches the given filter"); - } - - throw result.FinalException; - } - - return result.Result; - } - /// /// Stop receiving traffic /// @@ -395,15 +249,15 @@ private TEvent TryGetReceivedEvent( Func eventFilter) where TEvent : class { - if (_newEvents.IsEmpty) + if (_events.IsEmpty) { Logger.LogTrace("No received events found"); } else { - Logger.LogTrace("Current received event batches are: {ReceivedEvents}", string.Join(", ", _newEvents.Keys)); + Logger.LogTrace("Current received event batches are: {ReceivedEvents}", string.Join(", ", _events.Keys)); - foreach (KeyValuePair received in _newEvents) + foreach (KeyValuePair received in _events) { try { @@ -420,33 +274,7 @@ private TEvent TryGetReceivedEvent( } } - Logger.LogInformation("None of the received events matches the event filter: {ReceivedEvents}", string.Join(Environment.NewLine, _newEvents.Keys)); - } - - return null; - } - - private Event TryGetReceivedEvent(Func eventFilter) - { - if (_oldEvents.IsEmpty) - { - Logger.LogTrace("No received events found"); - } - else - { - Logger.LogTrace("Current received event batches are: {ReceivedEvents}", String.Join(", ", _oldEvents.Keys)); - - (string eventId, (string originalEvent, Event parsedEvent)) = _oldEvents.FirstOrDefault(ev => eventFilter(ev.Value.parsedEvent)); - if (parsedEvent != null) - { - Logger.LogInformation("Found received event with ID: {EventId}", eventId); - } - else - { - Logger.LogInformation("None of the received events matches the event filter: {ReceivedEvents}", String.Join(Environment.NewLine, _oldEvents.Keys)); - } - - return parsedEvent; + Logger.LogInformation("None of the received events matches the event filter: {ReceivedEvents}", string.Join(Environment.NewLine, _events.Keys)); } return null; @@ -454,14 +282,14 @@ private Event TryGetReceivedEvent(Func eventFilter) private string TryGetReceivedEvent(string eventId) { - if (_newEvents.IsEmpty) + if (_events.IsEmpty) { Logger.LogTrace("No received events found with event ID: '{EventId}'", eventId); } else { - Logger.LogTrace("Current received events are: {ReceivedEvents}", string.Join(", ", _newEvents.Keys)); - if (_newEvents.TryGetValue(eventId, out string originalEvent)) + Logger.LogTrace("Current received events are: {ReceivedEvents}", string.Join(", ", _events.Keys)); + if (_events.TryGetValue(eventId, out string originalEvent)) { Logger.LogInformation("Found received event with ID: {EventId}", eventId); return originalEvent; diff --git a/src/Arcus.EventGrid.Testing/Logging/NoOpLogger.cs b/src/Arcus.EventGrid.Testing/Logging/NoOpLogger.cs deleted file mode 100644 index b0b11170..00000000 --- a/src/Arcus.EventGrid.Testing/Logging/NoOpLogger.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; - -namespace Arcus.EventGrid.Testing.Logging -{ - /// - /// Represents an model without any implementation. - /// - [Obsolete("Unused logger implementation with the same functionality as " + nameof(NullLogger) + " will be removed in future major")] - public class NoOpLogger : ILogger - { - /// - /// Writes a log entry. - /// - /// The entry will be written on this level. - /// The ID of the event. - /// The entry to be written. Can be also an object. - /// The exception related to this entry. - /// The function to create a string message of the and . - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - // Deliberately don't log anything - } - - /// - /// Checks if the given is enabled. - /// - /// level to be checked. - /// true if enabled. - public bool IsEnabled(LogLevel logLevel) - { - return false; - } - - /// - /// Begins a logical operation scope. - /// - /// The identifier for the scope. - /// An IDisposable that ends the logical operation scope on dispose. - public IDisposable BeginScope(TState state) - { - return null; - } - } -} diff --git a/src/Arcus.EventGrid.Tests.Core/Events/EventSchema.cs b/src/Arcus.EventGrid.Tests.Core/Events/EventSchema.cs new file mode 100644 index 00000000..5b620388 --- /dev/null +++ b/src/Arcus.EventGrid.Tests.Core/Events/EventSchema.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Arcus.EventGrid.Tests.Core.Events +{ + public enum EventSchema + { + CloudEvent, + EventGrid + } +} diff --git a/src/Arcus.EventGrid.Tests.Integration/Arcus.EventGrid.Tests.Integration.csproj b/src/Arcus.EventGrid.Tests.Integration/Arcus.EventGrid.Tests.Integration.csproj index a4639b9a..6cfc512a 100644 --- a/src/Arcus.EventGrid.Tests.Integration/Arcus.EventGrid.Tests.Integration.csproj +++ b/src/Arcus.EventGrid.Tests.Integration/Arcus.EventGrid.Tests.Integration.csproj @@ -7,6 +7,7 @@ + diff --git a/src/Arcus.EventGrid.Tests.Integration/Fixture/EventGridTopicEndpoint.cs b/src/Arcus.EventGrid.Tests.Integration/Fixture/EventGridTopicEndpoint.cs index f59f7a65..01389a41 100644 --- a/src/Arcus.EventGrid.Tests.Integration/Fixture/EventGridTopicEndpoint.cs +++ b/src/Arcus.EventGrid.Tests.Integration/Fixture/EventGridTopicEndpoint.cs @@ -1,8 +1,8 @@ using System; using System.Threading.Tasks; -using Arcus.EventGrid.Contracts; using Arcus.EventGrid.Testing.Infrastructure.Hosts; using Arcus.EventGrid.Testing.Infrastructure.Hosts.ServiceBus; +using Arcus.EventGrid.Tests.Core.Events; using Arcus.EventGrid.Tests.Integration.Publishing.Fixture; using Arcus.Testing.Logging; using GuardNet; diff --git a/src/Arcus.EventGrid.Tests.Integration/Fixture/TestConfig.cs b/src/Arcus.EventGrid.Tests.Integration/Fixture/TestConfig.cs index 2f71af2b..daf8f741 100644 --- a/src/Arcus.EventGrid.Tests.Integration/Fixture/TestConfig.cs +++ b/src/Arcus.EventGrid.Tests.Integration/Fixture/TestConfig.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Arcus.EventGrid.Contracts; +using Arcus.EventGrid.Tests.Core.Events; using GuardNet; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Primitives; diff --git a/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingCloudEventsTests.cs b/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingCloudEventsTests.cs index db52f0aa..65694283 100644 --- a/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingCloudEventsTests.cs +++ b/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingCloudEventsTests.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Arcus.EventGrid.Contracts; using Arcus.EventGrid.Core; using Arcus.EventGrid.Tests.Core.Events.Data; using Azure; @@ -9,6 +8,7 @@ using Azure.Messaging.EventGrid; using Xunit; using Arcus.EventGrid.Tests.Core; +using Arcus.EventGrid.Tests.Core.Events; using Xunit.Abstractions; using Arcus.EventGrid.Tests.Integration.Fixture; using SendCloudEventAsync = System.Func>; diff --git a/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingEventGridEventTests.cs b/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingEventGridEventTests.cs index 4d875ef9..c4e065bf 100644 --- a/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingEventGridEventTests.cs +++ b/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingEventGridEventTests.cs @@ -8,8 +8,8 @@ using Xunit.Abstractions; using Arcus.EventGrid.Tests.Integration.Fixture; using System.Collections.Generic; -using Arcus.EventGrid.Contracts; using Arcus.EventGrid.Core; +using Arcus.EventGrid.Tests.Core.Events; using SendEventGridEventAsync = System.Func>; namespace Arcus.EventGrid.Tests.Integration.Publishing diff --git a/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingTests.cs b/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingTests.cs index 3c23ebca..d4edcba0 100644 --- a/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingTests.cs +++ b/src/Arcus.EventGrid.Tests.Integration/Publishing/EventGridPublisherClientWithTrackingTests.cs @@ -2,8 +2,8 @@ using System.Diagnostics; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Arcus.EventGrid.Contracts; using Arcus.EventGrid.Core; +using Arcus.EventGrid.Tests.Core.Events; using Arcus.EventGrid.Tests.Integration.Fixture; using Arcus.EventGrid.Tests.Integration.Publishing.Fixture; using Arcus.Observability.Correlation; diff --git a/src/Arcus.EventGrid.Tests.Integration/WebApi/Security/EventGridSubscriptionValidationAttributeTests.cs b/src/Arcus.EventGrid.Tests.Integration/WebApi/Security/EventGridSubscriptionValidationAttributeTests.cs index 2fa57f2c..a3d697da 100644 --- a/src/Arcus.EventGrid.Tests.Integration/WebApi/Security/EventGridSubscriptionValidationAttributeTests.cs +++ b/src/Arcus.EventGrid.Tests.Integration/WebApi/Security/EventGridSubscriptionValidationAttributeTests.cs @@ -5,10 +5,12 @@ using Arcus.EventGrid.Tests.Integration.WebApi.Fixture; using Arcus.EventGrid.Tests.Integration.WebApi.Security.Controllers; using Arcus.Testing.Logging; +using Azure.Messaging.EventGrid; +using Azure.Messaging.EventGrid.SystemEvents; using Bogus; -using Microsoft.Azure.EventGrid.Models; using Microsoft.Extensions.Logging; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Xunit; using Xunit.Abstractions; @@ -99,15 +101,19 @@ public async Task CloudEventsValidationRequest_WithWrongWebHooRequestOriginHeade public async Task EventGridSubscriptionValidation_WithCorrectRequestValidationData_Succeeds() { // Arrange - var validationEventData = new SubscriptionValidationEventData(validationCode: Guid.NewGuid().ToString()); - var eventGridEvent = new EventGridEvent( - id: Guid.NewGuid().ToString(), - subject: "Sample.Subect", - data: validationEventData, - eventType: "Microsoft.EventGrid.SubscriptionValidationEvent", - eventTime: DateTime.Now, - dataVersion: "1.0"); - string json = JsonConvert.SerializeObject(eventGridEvent); + var validationCode = Guid.NewGuid().ToString(); + string json = $@"[ + {{ + ""id"": ""2d1781af-3a4c-4d7c-bd0c-e34b19da4e66"", + ""topic"": ""/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"", + ""subject"": ""Sample.Subject"", + ""data"": {{ + ""validationCode"": ""{validationCode}"" + }}, ""dataVersion"": """", + ""eventType"": ""Microsoft.EventGrid.SubscriptionValidationEvent"", + ""eventTime"": ""2017-08-06T22:09:30.740323Z"" + }} + ]"; await using (var server = await TestApiServer.StartNewAsync(_logger)) { @@ -123,7 +129,7 @@ public async Task EventGridSubscriptionValidation_WithCorrectRequestValidationDa Assert.Equal(HttpStatusCode.OK, response.StatusCode); string contents = await response.Content.ReadAsStringAsync(); var validationResponse = JsonConvert.DeserializeObject(contents); - Assert.Equal(validationEventData.ValidationCode, validationResponse.ValidationResponse); + Assert.Equal(validationCode, validationResponse.ValidationResponse); } } } @@ -132,21 +138,25 @@ public async Task EventGridSubscriptionValidation_WithCorrectRequestValidationDa public async Task EventGridSubscriptionValidation_WithMultipleEvents_Fails() { // Arrange - var validationEventData = new SubscriptionValidationEventData(validationCode: Guid.NewGuid().ToString()); + var validationCode = Guid.NewGuid().ToString(); var validationEvent = new EventGridEvent( - id: Guid.NewGuid().ToString(), subject: "Sample.Subect", - data: validationEventData, + data: JObject.Parse($"{{ \"validationCode\": \"{validationCode}\" }}"), eventType: "Microsoft.EventGrid.SubscriptionValidationEvent", - eventTime: DateTime.Now, - dataVersion: "1.0"); + dataVersion: "1.0") + { + Id = Guid.NewGuid().ToString(), + EventTime = DateTimeOffset.UtcNow + }; var blobCreatedEvent = new EventGridEvent( - id: Guid.NewGuid().ToString(), subject: "Sample.Subject", - data: new StorageBlobCreatedEventData(), + data: JObject.Parse($"{{ \"something\": \"else\" }}"), eventType: "Microsoft.Storage.BlobCreatedEvent", - eventTime: DateTime.Now, - dataVersion: "1.0"); + dataVersion: "1.0") + { + Id = Guid.NewGuid().ToString(), + EventTime = DateTimeOffset.UtcNow + }; EventGridEvent[] events = {validationEvent, blobCreatedEvent}; string json = JsonConvert.SerializeObject(events); @@ -171,12 +181,14 @@ public async Task EventGridSubscriptionValidation_WithWrongEventType_Fails() { // Arrange var blobCreatedEvent = new EventGridEvent( - id: Guid.NewGuid().ToString(), subject: "Sample.Subject", - data: new StorageBlobCreatedEventData(), + data: JObject.Parse($"{{ \"something\": \"else\" }}"), eventType: "Microsoft.Storage.BlobCreatedEvent", - eventTime: DateTime.Now, - dataVersion: "1.0"); + dataVersion: "1.0") + { + Id = Guid.NewGuid().ToString(), + EventTime = DateTimeOffset.UtcNow + }; string json = JsonConvert.SerializeObject(blobCreatedEvent); await using (var server = await TestApiServer.StartNewAsync(_logger)) diff --git a/src/Arcus.EventGrid.Tests.Unit/Arcus.EventGrid.Tests.Unit.csproj b/src/Arcus.EventGrid.Tests.Unit/Arcus.EventGrid.Tests.Unit.csproj index 36742f8f..183a4415 100644 --- a/src/Arcus.EventGrid.Tests.Unit/Arcus.EventGrid.Tests.Unit.csproj +++ b/src/Arcus.EventGrid.Tests.Unit/Arcus.EventGrid.Tests.Unit.csproj @@ -6,6 +6,7 @@ + diff --git a/src/Arcus.EventGrid.Tests.Unit/Artifacts/EventSamples.Designer.cs b/src/Arcus.EventGrid.Tests.Unit/Artifacts/EventSamples.Designer.cs index cd0555d5..e7123e88 100644 --- a/src/Arcus.EventGrid.Tests.Unit/Artifacts/EventSamples.Designer.cs +++ b/src/Arcus.EventGrid.Tests.Unit/Artifacts/EventSamples.Designer.cs @@ -150,10 +150,9 @@ internal static string IoTDeviceDeleteEvent { /// "subject": "Sample.Subject", /// "data": { /// "validationCode": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6" - /// }, + /// }, "dataVersion": "", /// "eventType": "Microsoft.EventGrid.SubscriptionValidationEvent", - /// "eventTime": "2017-08-06T22:09:30.740323Z" - /// [rest of string was truncated]";. + /// "eventTime": "2017-08-06T [rest of string was truncated]";. /// internal static string SubscriptionValidationEvent { get { diff --git a/src/Arcus.EventGrid.Tests.Unit/Artifacts/EventSamples.resx b/src/Arcus.EventGrid.Tests.Unit/Artifacts/EventSamples.resx index c4ee2985..b1dc2d91 100644 --- a/src/Arcus.EventGrid.Tests.Unit/Artifacts/EventSamples.resx +++ b/src/Arcus.EventGrid.Tests.Unit/Artifacts/EventSamples.resx @@ -268,7 +268,7 @@ "subject": "Sample.Subject", "data": { "validationCode": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6" - }, + }, "dataVersion": "", "eventType": "Microsoft.EventGrid.SubscriptionValidationEvent", "eventTime": "2017-08-06T22:09:30.740323Z" } diff --git a/src/Arcus.EventGrid.Tests.Unit/Security/EventGridSubscriptionValidatorTests.cs b/src/Arcus.EventGrid.Tests.Unit/Security/EventGridSubscriptionValidatorTests.cs index 2073ce85..baa70dbb 100644 --- a/src/Arcus.EventGrid.Tests.Unit/Security/EventGridSubscriptionValidatorTests.cs +++ b/src/Arcus.EventGrid.Tests.Unit/Security/EventGridSubscriptionValidatorTests.cs @@ -1,19 +1,18 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; -using Arcus.EventGrid.Contracts; -using Arcus.EventGrid.Parsers; using Arcus.EventGrid.Security.Core.Validation; +using Azure.Messaging.EventGrid; +using Azure.Messaging.EventGrid.SystemEvents; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Microsoft.Azure.EventGrid.Models; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Primitives; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Xunit; using SubscriptionValidationResponse = Azure.Messaging.EventGrid.SystemEvents.SubscriptionValidationResponse; @@ -61,16 +60,10 @@ public async Task ValidateEventGridSubscriptionRequest_WithSubscriptionValidatio { // Arrange var validator = new EventGridSubscriptionValidator(NullLogger); - var context = new DefaultHttpContext(); - var validationCode = "512d38b6-c7b8-40c8-89fe-f46f9e9622b6"; - var validationEvent = new EventGridEvent( - id: "2d1781af-3a4c-4d7c-bd0c-e34b19da4e66", - subject: "Sample.Event", - data: new SubscriptionValidationEventData(validationCode), - dataVersion: "1", - eventType: "Microsoft.EventGrid.SubscriptionValidationEvent"); - string json = JsonConvert.SerializeObject(validationEvent); - context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(json)); + var context = new DefaultHttpContext + { + Request = { Body = new MemoryStream(Encoding.UTF8.GetBytes(Artifacts.EventSamples.SubscriptionValidationEvent)) } + }; // Act IActionResult result = await validator.ValidateEventGridSubscriptionEventRequestAsync(context.Request); @@ -79,7 +72,7 @@ public async Task ValidateEventGridSubscriptionRequest_WithSubscriptionValidatio Assert.NotNull(result); var responseBody = Assert.IsType(result).Value; var subscriptionValidationResponse = Assert.IsType(responseBody); - Assert.Equal(validationCode, subscriptionValidationResponse.ValidationResponse); + Assert.Equal("512d38b6-c7b8-40c8-89fe-f46f9e9622b6", subscriptionValidationResponse.ValidationResponse); } [Fact] @@ -88,12 +81,14 @@ public async Task ValidateEventGridSubscriptionRequest_WithoutSubscriptionValida // Arrange var validator = new EventGridSubscriptionValidator(NullLogger); var context = new DefaultHttpContext(); - var validationEvent = new EventGridEvent( - id: "2d1781af-3a4c-4d7c-bd0c-e34b19da4e66", + var validationEvent = new EventGridEvent( subject: "Sample.Event", - data: new SubscriptionValidationEventData(validationCode: null), + data: JObject.Parse($"{{ \"validationCode\": null }}"), dataVersion: "1", - eventType: "Microsoft.EventGrid.SubscriptionValidationEvent"); + eventType: "Microsoft.EventGrid.SubscriptionValidationEvent") + { + Id = "2d1781af-3a4c-4d7c-bd0c-e34b19da4e66" + }; string json = JsonConvert.SerializeObject(validationEvent); context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(json)); @@ -145,13 +140,9 @@ public async Task ValidateEventGridSubscriptionRequest_WithMultipleEventsInHttpR // Arrange var validator = new EventGridSubscriptionValidator(NullLogger); var context = new DefaultHttpContext(); - EventBatch blobCreatedEvent = EventParser.Parse(Artifacts.EventSamples.BlobCreateEvent); - EventBatch iotDeviceDeletedEvent = EventParser.Parse(Artifacts.EventSamples.IoTDeviceDeleteEvent); - EventGridEvent[] events = - blobCreatedEvent.Events - .Concat(iotDeviceDeletedEvent.Events) - .Select(ev => ev.AsEventGridEvent()) - .ToArray(); + EventGridEvent[] blobCreatedEvent = EventGridEvent.ParseMany(BinaryData.FromString(Artifacts.EventSamples.BlobCreateEvent)); + EventGridEvent[] iotDeviceDeletedEvent = EventGridEvent.ParseMany(BinaryData.FromString(Artifacts.EventSamples.IoTDeviceDeleteEvent)); + EventGridEvent[] events = blobCreatedEvent.Concat(iotDeviceDeletedEvent).ToArray(); string requestBody = JsonConvert.SerializeObject(events); context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(requestBody)); diff --git a/src/Arcus.EventGrid.Tests.Unit/Testing/EventConsumerHostTests.cs b/src/Arcus.EventGrid.Tests.Unit/Testing/EventConsumerHostTests.cs index 3db69076..a4f594e1 100644 --- a/src/Arcus.EventGrid.Tests.Unit/Testing/EventConsumerHostTests.cs +++ b/src/Arcus.EventGrid.Tests.Unit/Testing/EventConsumerHostTests.cs @@ -1,16 +1,12 @@ using System; -using Arcus.EventGrid.Contracts; +using System.Collections.Generic; using Arcus.EventGrid.Testing.Infrastructure.Hosts; -using Arcus.EventGrid.Testing.Logging; using Arcus.EventGrid.Tests.Core.Events.Data; using Arcus.EventGrid.Tests.Unit.Testing.Fixture; using Arcus.Testing.Logging; using Azure.Messaging.EventGrid; -using Azure.Messaging.EventGrid.SystemEvents; using Bogus; -using CloudNative.CloudEvents; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; using Xunit; using Xunit.Abstractions; using CloudEvent = Azure.Messaging.CloudEvent; @@ -20,7 +16,7 @@ namespace Arcus.EventGrid.Tests.Unit.Testing public class EventConsumerHostTests { private readonly ILogger _logger; - private static readonly Faker BogusGenerator = new Faker(); + private static readonly Faker Bogus = new Faker(); /// /// Initializes a new instance of the class. @@ -30,6 +26,25 @@ public EventConsumerHostTests(ITestOutputHelper outputWriter) _logger = new XunitTestLogger(outputWriter); } + [Fact] + public void GetReceivedEventByEventId_WithAvailableEvents_Succeeds() + { + // Arrange + IEnumerable cloudEvents = Bogus.Make(Bogus.Random.Int(1, 10), () => GenerateCloudEvent()); + CloudEvent expected = Bogus.PickRandom(cloudEvents); + + var host = new InMemoryEventConsumerHost(_logger); + host.ReceiveEvents(cloudEvents); + + // Act + string receivedEvent = host.GetReceivedEvent(expected.Id); + + // Assert + CloudEvent actual = CloudEvent.Parse(BinaryData.FromString(receivedEvent)); + Assert.NotNull(actual); + Assert.Equal(expected.Id, actual.Id); + } + [Fact] public void GetReceivedEventByEventIdWithRetryCount_WithAvailableEvent_Succeeds() { @@ -206,9 +221,9 @@ public void GetReceivedEventByEventGridEventFilter_WithoutAvailableEvent_Fails() private static CloudEvent GenerateCloudEvent(string eventId = null) { return new CloudEvent( - source: BogusGenerator.Lorem.Word(), - type: BogusGenerator.Lorem.Word(), - jsonSerializableData: new CarEventData(BogusGenerator.Vehicle.Vin())) + source: Bogus.Lorem.Word(), + type: Bogus.Lorem.Word(), + jsonSerializableData: new CarEventData(Bogus.Vehicle.Vin())) { Id = eventId ?? Guid.NewGuid().ToString(), Time = DateTimeOffset.UtcNow @@ -218,10 +233,10 @@ private static CloudEvent GenerateCloudEvent(string eventId = null) private static EventGridEvent GenerateEventGridEvent(string eventId = null) { return new EventGridEvent( - subject: BogusGenerator.Lorem.Word(), - eventType: BogusGenerator.Lorem.Word(), - dataVersion: BogusGenerator.System.Version().ToString(), - data: new CarEventData(BogusGenerator.Vehicle.Vin())) + subject: Bogus.Lorem.Word(), + eventType: Bogus.Lorem.Word(), + dataVersion: Bogus.System.Version().ToString(), + data: new CarEventData(Bogus.Vehicle.Vin())) { Id = eventId ?? Guid.NewGuid().ToString(), EventTime = DateTimeOffset.UtcNow @@ -254,44 +269,6 @@ public void GetReceivedEvent_WithFailedEventFormat_Fails() () => host.GetReceivedEvent(Guid.NewGuid().ToString(), timeout: TimeSpan.FromMilliseconds(100))); } - [Fact] - public void GetReceivedEvent_WithCloudEvent_Succeeds() - { - // Arrange - var host = new InMemoryEventConsumerHost(_logger); - var eventId = Guid.NewGuid().ToString(); - CloudEvent expected = GenerateCloudEvent(eventId); - - // Act - host.ReceiveEvent(expected); - - // Assert - Event actualFromGeneric = host.GetReceivedEvent( - data => data.LicensePlate != null, - timeout: TimeSpan.FromMilliseconds(100)); - - Assert.NotNull(actualFromGeneric); - Assert.Equal(expected.Id, actualFromGeneric.Id); - Assert.Equal(expected.Subject, actualFromGeneric.Subject); - Assert.Equal(expected.Type, actualFromGeneric.EventType); - - var expectedData = expected.Data.ToObjectFromJson(); - var actualDataFromGeneric = actualFromGeneric.GetPayload(); - Assert.Equal(expectedData.LicensePlate, actualDataFromGeneric.LicensePlate); - - CloudNative.CloudEvents.CloudEvent actualFromFilter = host.GetReceivedEvent( - (CloudNative.CloudEvents.CloudEvent ev) => ev.Id == expected.Id, - timeout: TimeSpan.FromMilliseconds(100)); - - Assert.NotNull(actualFromFilter); - Assert.Equal(expected.Id, actualFromFilter.Id); - Assert.Equal(expected.Subject, actualFromFilter.Subject); - Assert.Equal(expected.Type, actualFromFilter.Type); - - var actualDataFromFilter = actualFromFilter.GetPayload(); - Assert.Equal(expectedData.LicensePlate, actualDataFromFilter.LicensePlate); - } - [Fact] public void GetReceivedEvent_WithoutEvents_Fails() { @@ -300,7 +277,7 @@ public void GetReceivedEvent_WithoutEvents_Fails() // Act / Assert Assert.Throws( - () => host.GetReceivedEvent(data => true, timeout: TimeSpan.FromMilliseconds(100))); + () => host.GetReceivedEvent((CloudEvent data) => true, timeout: TimeSpan.FromMilliseconds(100))); } } } diff --git a/src/Arcus.EventGrid.Tests.Unit/Testing/Fixture/InMemoryEventConsumerHost.cs b/src/Arcus.EventGrid.Tests.Unit/Testing/Fixture/InMemoryEventConsumerHost.cs index 3f7bed02..5772f99c 100644 --- a/src/Arcus.EventGrid.Tests.Unit/Testing/Fixture/InMemoryEventConsumerHost.cs +++ b/src/Arcus.EventGrid.Tests.Unit/Testing/Fixture/InMemoryEventConsumerHost.cs @@ -29,6 +29,16 @@ public void ReceiveEvent(EventGridEvent eventGridEvent) EventsReceived(rawReceivedEvents); } + public void ReceiveEvents(IEnumerable cloudEvents) + { + EventsReceived(JsonSerializer.Serialize(cloudEvents)); + } + + public void ReceiveEvents(IEnumerable eventGridEvents) + { + EventsReceived(JsonSerializer.Serialize(eventGridEvents)); + } + public void ReceiveEvent(string raw) { EventsReceived(raw);