diff --git a/src/Particular.LicensingComponent.Report.UnitTests/ApprovalFiles/ApiApprovals.Approve.approved.txt b/src/Particular.LicensingComponent.Report.UnitTests/ApprovalFiles/ApiApprovals.Approve.approved.txt index e4ea653..f8e31b4 100644 --- a/src/Particular.LicensingComponent.Report.UnitTests/ApprovalFiles/ApiApprovals.Approve.approved.txt +++ b/src/Particular.LicensingComponent.Report.UnitTests/ApprovalFiles/ApiApprovals.Approve.approved.txt @@ -27,6 +27,7 @@ namespace Particular.LicensingComponent.Report public QueueThroughput() { } public Particular.LicensingComponent.Report.DailyThroughput[] DailyThroughputFromAudit { get; init; } public Particular.LicensingComponent.Report.DailyThroughput[] DailyThroughputFromBroker { get; init; } + public Particular.LicensingComponent.Report.DailyThroughput[] DailyThroughputFromEndpoint { get; init; } public Particular.LicensingComponent.Report.DailyThroughput[] DailyThroughputFromMonitoring { get; init; } public string[] EndpointIndicators { get; init; } public string NameHash { get; set; } diff --git a/src/Particular.LicensingComponent.Report.UnitTests/LicensingComponent_Report_Signature_Tests.cs b/src/Particular.LicensingComponent.Report.UnitTests/LicensingComponent_Report_Signature_Tests.cs index 2119178..f9e37c7 100644 --- a/src/Particular.LicensingComponent.Report.UnitTests/LicensingComponent_Report_Signature_Tests.cs +++ b/src/Particular.LicensingComponent.Report.UnitTests/LicensingComponent_Report_Signature_Tests.cs @@ -135,6 +135,29 @@ public void Should_be_able_to_read_a_V2_report() Assert.That(Validate(validationResult)); } + [Test] + public void Should_be_able_to_read_a_V3_report() + { + //Arrange + using var stream = GetResourceStream("throughput-report-v3.0.json"); + + //Act + var report = ValidatingReportReader.ReadAndValidate(stream!, out var validationResult); + var data = report!.ReportData; + + //Assert + // Want to be explicit with asserts to ensure that a 3.0 report can be read correctly + // An approval test would be too easy to just accept changes on + Assert.That(data.Queues, Has.Length.EqualTo(5)); + Assert.That(data.Queues.All(q => !string.IsNullOrEmpty(q.QueueName))); + Assert.That(data.Queues.Any(q => q.QueueName == "EndpointWithSelfReportedUsage" && q.DailyThroughputFromEndpoint.Any(t => t.MessageCount == 65 && t.DateUTC.ToString("yyyy-MM-dd") == "2026-09-21"))); + Assert.That(data.Queues.Any(q => q.QueueName == "EndpointWithJustBrokerData" && q.DailyThroughputFromEndpoint.Length == 0)); + + Assert.That(report.Signature, Is.EqualTo("wveYaUgrMafyParJVSL8HppdywT5yeon3ZTEWIaagNGhLYaWDkkX3c7v+nvlkGIAQhLidjptsODcoTEipd+E/rQM6PrRnxw45sJlIrakANu8dbfuEDcIRq7WvUBynfeN/qGYhEsJZaQI93R8Twn7kgfaXPR86jo1IeJOB7ITYbfoVPmevAqzK17yZzfkHxPGoRJL3lf824S4Ak5vpoyckrRXs2wV4XqfiifWzcjBniwoHrYw6bY5Be0hd/qGxXF+AGmo6wdAVj6WpaVZx3rkLmMyVEGZoTtLtL8aJX0sabx3olWU1EdT+ouc00R0latZFNrMf8ZHgiT63urhkedAsQ==")); + + Assert.That(Validate(validationResult)); + } + #if !DEBUG [Ignore("This test is here to help with generating a signed report file from a file that only contains report data")] #endif diff --git a/src/Particular.LicensingComponent.Report.UnitTests/Particular.LicensingComponent.Report.UnitTests.csproj b/src/Particular.LicensingComponent.Report.UnitTests/Particular.LicensingComponent.Report.UnitTests.csproj index 785f73e..170ae34 100644 --- a/src/Particular.LicensingComponent.Report.UnitTests/Particular.LicensingComponent.Report.UnitTests.csproj +++ b/src/Particular.LicensingComponent.Report.UnitTests/Particular.LicensingComponent.Report.UnitTests.csproj @@ -24,6 +24,8 @@ + + diff --git a/src/Particular.LicensingComponent.Report.UnitTests/throughput-report-v3.0.json b/src/Particular.LicensingComponent.Report.UnitTests/throughput-report-v3.0.json new file mode 100644 index 0000000..c12584e --- /dev/null +++ b/src/Particular.LicensingComponent.Report.UnitTests/throughput-report-v3.0.json @@ -0,0 +1,174 @@ +{ + "ReportData": { + "CustomerName": "TestCustomer", + "MessageTransport": "AzureServiceBus", + "ReportMethod": "Broker", + "ToolType": "Platform Licensing Component", + "ToolVersion": "6.20", + "ScopeType": "testingScope", + "StartTime": "2026-09-20T00:00:00+00:00", + "EndTime": "2026-09-21T00:00:00+00:00", + "ReportDuration": "1.00:00:00", + "Queues": [ + { + "QueueName": "REDACTED1", + "Throughput": 65, + "EndpointIndicators": [ + "KnownEndpoint" + ], + "Scope": "", + "DailyThroughputFromBroker": [ + { + "DateUTC": "2026-09-20", + "MessageCount": 50 + }, + { + "DateUTC": "2026-09-21", + "MessageCount": 55 + } + ], + "DailyThroughputFromAudit": [], + "DailyThroughputFromMonitoring": [ + { + "DateUTC": "2026-09-20", + "MessageCount": 60 + }, + { + "DateUTC": "2026-09-21", + "MessageCount": 65 + } + ], + "DailyThroughputFromEndpoint": [] + }, + { + "QueueName": "EndpointWithSelfReportedUsage", + "Throughput": 65, + "EndpointIndicators": [ + "KnownEndpoint" + ], + "Scope": "", + "DailyThroughputFromBroker": [ + { + "DateUTC": "2026-09-20", + "MessageCount": 120 + }, + { + "DateUTC": "2026-09-21", + "MessageCount": 135 + } + ], + "DailyThroughputFromAudit": [], + "DailyThroughputFromMonitoring": [], + "DailyThroughputFromEndpoint": [ + { + "DateUTC": "2026-09-20", + "MessageCount": 60 + }, + { + "DateUTC": "2026-09-21", + "MessageCount": 65 + } + ] + }, + { + "QueueName": "EndpointWithAllSources", + "Throughput": 65, + "EndpointIndicators": [ + "KnownEndpoint" + ], + "Scope": "", + "DailyThroughputFromBroker": [ + { + "DateUTC": "2026-09-20", + "MessageCount": 120 + }, + { + "DateUTC": "2026-09-21", + "MessageCount": 135 + } + ], + "DailyThroughputFromAudit": [ + { + "DateUTC": "2026-09-20", + "MessageCount": 120 + }, + { + "DateUTC": "2026-09-21", + "MessageCount": 135 + } + ], + "DailyThroughputFromMonitoring": [ + { + "DateUTC": "2026-09-20", + "MessageCount": 95 + }, + { + "DateUTC": "2026-09-21", + "MessageCount": 105 + } + ], + "DailyThroughputFromEndpoint": [ + { + "DateUTC": "2026-09-20", + "MessageCount": 60 + }, + { + "DateUTC": "2026-09-21", + "MessageCount": 65 + } + ] + }, + { + "QueueName": "EndpointWithJustBrokerData", + "Throughput": 47, + "EndpointIndicators": [], + "UserIndicator": "PlannedToDecommission", + "Scope": "", + "DailyThroughputFromBroker": [ + { + "DateUTC": "2026-09-20", + "MessageCount": 42 + }, + { + "DateUTC": "2026-09-21", + "MessageCount": 47 + } + ], + "DailyThroughputFromAudit": [], + "DailyThroughputFromMonitoring": [], + "DailyThroughputFromEndpoint": [] + }, + { + "QueueName": "EndpointWithNoData", + "Throughput": 15, + "EndpointIndicators": [], + "UserIndicator": "NotNServiceBusEndpoint", + "Scope": "", + "DailyThroughputFromBroker": [], + "DailyThroughputFromAudit": [], + "DailyThroughputFromMonitoring": [], + "DailyThroughputFromEndpoint": [] + } + ], + "TotalQueues": 5, + "IgnoredQueues": [], + "EnvironmentInformation": { + "AuditServicesData": { + "Versions": { + "4.3.6": 2 + }, + "Transports": { + "AzureServiceBus": 2 + } + }, + "EnvironmentData": { + "BrokerVersion": "1.2", + "ServiceControlVersion": "6.20.0", + "ServicePulseVersion": "2.8.0", + "AuditEnabled": "True", + "MonitoringEnabled": "True" + } + } + }, + "Signature": "wveYaUgrMafyParJVSL8HppdywT5yeon3ZTEWIaagNGhLYaWDkkX3c7v+nvlkGIAQhLidjptsODcoTEipd+E/rQM6PrRnxw45sJlIrakANu8dbfuEDcIRq7WvUBynfeN/qGYhEsJZaQI93R8Twn7kgfaXPR86jo1IeJOB7ITYbfoVPmevAqzK17yZzfkHxPGoRJL3lf824S4Ak5vpoyckrRXs2wV4XqfiifWzcjBniwoHrYw6bY5Be0hd/qGxXF+AGmo6wdAVj6WpaVZx3rkLmMyVEGZoTtLtL8aJX0sabx3olWU1EdT+ouc00R0latZFNrMf8ZHgiT63urhkedAsQ==" +} \ No newline at end of file diff --git a/src/Particular.LicensingComponent.Report/Report.cs b/src/Particular.LicensingComponent.Report/Report.cs index c511174..f806bfd 100644 --- a/src/Particular.LicensingComponent.Report/Report.cs +++ b/src/Particular.LicensingComponent.Report/Report.cs @@ -165,6 +165,11 @@ public record QueueThroughput /// Breakdown of daily throughput for each queue obtained from monitoring /// public DailyThroughput[] DailyThroughputFromMonitoring { get; init; } + + /// + /// Breakdown of daily throughput as recorded by the endpoint + /// + public DailyThroughput[] DailyThroughputFromEndpoint { get; init; } } ///