diff --git a/tools/code/code.sln b/tools/code/code.sln index 99c97541..8dfdd6e5 100644 --- a/tools/code/code.sln +++ b/tools/code/code.sln @@ -11,11 +11,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "publisher", "publisher\publ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "common.tests", "common.tests\common.tests.csproj", "{D1ED4FC5-8C52-4380-8520-BC46F475A4F8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "integration.tests", "integration.tests\integration.tests.csproj", "{05923D65-3595-445A-8EB3-5ECC1F99A727}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "integration.tests", "integration.tests\integration.tests.csproj", "{05923D65-3595-445A-8EB3-5ECC1F99A727}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "aspire", "aspire\aspire.csproj", "{C0AD9089-77B8-4E2F-ADD3-1F0846B8D370}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "publisher.unit.tests", "publisher.unit.tests\publisher.unit.tests.csproj", "{C24D7BC6-5BFA-4D11-A903-63049623258D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "aspire", "aspire\aspire.csproj", "{C0AD9089-77B8-4E2F-ADD3-1F0846B8D370}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -47,10 +45,6 @@ Global {C0AD9089-77B8-4E2F-ADD3-1F0846B8D370}.Debug|Any CPU.Build.0 = Debug|Any CPU {C0AD9089-77B8-4E2F-ADD3-1F0846B8D370}.Release|Any CPU.ActiveCfg = Release|Any CPU {C0AD9089-77B8-4E2F-ADD3-1F0846B8D370}.Release|Any CPU.Build.0 = Release|Any CPU - {C24D7BC6-5BFA-4D11-A903-63049623258D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C24D7BC6-5BFA-4D11-A903-63049623258D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C24D7BC6-5BFA-4D11-A903-63049623258D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C24D7BC6-5BFA-4D11-A903-63049623258D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/tools/code/common/common.csproj b/tools/code/common/common.csproj index 190f0a47..e770010c 100644 --- a/tools/code/common/common.csproj +++ b/tools/code/common/common.csproj @@ -2,7 +2,7 @@ net8.0 - true + 8-all false CA1034,CA1062,CA1724,CA2007,CA1848 diff --git a/tools/code/extractor/extractor.csproj b/tools/code/extractor/extractor.csproj index da427dc9..99e201d7 100644 --- a/tools/code/extractor/extractor.csproj +++ b/tools/code/extractor/extractor.csproj @@ -2,13 +2,13 @@ net8.0 - true + 8-all CA1708,CA1724,CA1812,CA1848,CA2007,CA1034,CA1062 6ce9dc18-ea0d-4d82-8f1a-e63877f35b88 Exe enable - 6.0.1.1 + 6.0.1 diff --git a/tools/code/publisher.unit.tests/ApiDiagnostic.cs b/tools/code/publisher.unit.tests/ApiDiagnostic.cs deleted file mode 100644 index 252bd1b3..00000000 --- a/tools/code/publisher.unit.tests/ApiDiagnostic.cs +++ /dev/null @@ -1,159 +0,0 @@ -using common; -using common.tests; -using CsCheck; -using LanguageExt; -using LanguageExt.UnsafeValueAccess; -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Linq; -using System.Text.Json.Nodes; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace publisher.unit.tests; - -public class FindApiDiagnosticDtoTests -{ - [Fact] - public async Task Returns_none_if_the_dto_does_not_exist() - { - var generator = from fixture in Fixture.Generate() - where fixture.OriginalDto.IsNone - select fixture; - - await generator.SampleAsync(async fixture => - { - var dtoOption = await fixture.Run(CancellationToken.None); - - dtoOption.Should().BeNone(); - }); - } - - [Fact] - public async Task Returns_the_original_dto_if_there_is_no_override() - { - var generator = from fixture in Fixture.Generate() - where fixture.OriginalDto.IsSome - where fixture.DtoOverride.IsNone - select fixture; - - await generator.SampleAsync(async fixture => - { - var dtoOption = await fixture.Run(CancellationToken.None); - - var expectedDto = fixture.OriginalDto.ValueUnsafe() ?? throw new InvalidOperationException("Expected dto should not be null."); - dtoOption.Should().BeSome(expectedDto); - }); - } - - [Fact] - public async Task Returns_the_overridden_dto_if_there_is_an_override() - { - var generator = from fixture in Fixture.Generate() - where fixture.OriginalDto.IsSome - where fixture.DtoOverride.IsSome - select fixture; - - await generator.SampleAsync(async fixture => - { - var dtoOption = await fixture.Run(CancellationToken.None); - - // Assert - var originalDto = fixture.OriginalDto.ValueUnsafe() ?? throw new InvalidOperationException("Original dto should not be null."); - var dtoOverride = fixture.DtoOverride.ValueUnsafe() ?? throw new InvalidOperationException("Override should not be null."); - var expectedDto = OverrideDtoFactory.Override(originalDto, dtoOverride); - dtoOption.Should().BeSome(expectedDto); - }); - } - - private sealed record Fixture - { - public required ManagementServiceDirectory ServiceDirectory { get; init; } - public required ApiName ApiName { get; init; } - public required ApiDiagnosticName Name { get; init; } - public required Option OriginalDto { get; init; } - public required Option DtoOverride { get; init; } - - public async ValueTask> Run(CancellationToken cancellationToken) - { - var provider = GetServiceProvider(); - - var findDto = ApiDiagnosticModule.GetFindApiDiagnosticDto(provider); - - return await findDto(Name, ApiName, cancellationToken); - } - - private IServiceProvider GetServiceProvider() - { - var services = new ServiceCollection(); - - services.AddSingleton(ServiceDirectory); - - services.AddSingleton(async (file, cancellationToken) => - { - await ValueTask.CompletedTask; - - return OriginalDto.Map(dto => BinaryData.FromObjectAsJson(dto)); - }); - - services.AddSingleton(new ConfigurationJson - { - Value = DtoOverride.Map(@override => new JsonObject - { - ["apis"] = new JsonObject - { - [ApiName.Value] = new JsonObject - { - ["diagnostics"] = new JsonObject - { - [Name.Value] = @override - } - } - } - }).IfNone([]) - }); - - services.AddSingleton(ConfigurationJsonModule.GetFindConfigurationSection); - - return services.BuildServiceProvider(); - } - - public static Gen Generate() => - from serviceDirectory in from directoryInfo in Generator.DirectoryInfo - select ManagementServiceDirectory.From(directoryInfo) - from apiName in from apiType in ApiType.Generate() - from apiName in ApiModel.GenerateName(apiType) - select apiName - from name in ApiDiagnosticModel.GenerateName() - from originalDto in from modelOption in ApiDiagnosticModel.Generate().OptionOf() - select modelOption.Map(ModelToDto) - from dtoOverride in from modelOption in ApiDiagnosticModel.Generate().OptionOf() - select from model in modelOption - let dto = ModelToDto(model) - select JsonObjectExtensions.Parse(dto) - select new Fixture - { - ServiceDirectory = serviceDirectory, - ApiName = apiName, - Name = name, - OriginalDto = originalDto, - DtoOverride = dtoOverride - }; - - private static ApiDiagnosticDto ModelToDto(ApiDiagnosticModel model) => - new() - { - Properties = new ApiDiagnosticDto.DiagnosticContract - { - LoggerId = $"/loggers/{model.LoggerName}", - AlwaysLog = model.AlwaysLog.ValueUnsafe(), - Sampling = model.Sampling.Map(sampling => new ApiDiagnosticDto.SamplingSettings - { - SamplingType = sampling.Type, - Percentage = sampling.Percentage - }).ValueUnsafe() - } - }; - } -} diff --git a/tools/code/publisher.unit.tests/ConfigurationJson.cs b/tools/code/publisher.unit.tests/ConfigurationJson.cs deleted file mode 100644 index 4e1aac42..00000000 --- a/tools/code/publisher.unit.tests/ConfigurationJson.cs +++ /dev/null @@ -1,118 +0,0 @@ -using common; -using common.tests; -using CsCheck; -using FluentAssertions; -using LanguageExt; -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.Json.Nodes; -using Xunit; - -namespace publisher.unit.tests; - -public class FindConfigurationSectionTests -{ - [Fact] - public void No_argments_always_returns_none() - { - var generator = Fixture.Generate(); - - generator.Sample(fixture => - { - var result = fixture.FindConfigurationSection(); - - result.Should().BeNone(); - }); - } - - [Fact] - public void Return_none_when_section_does_not_exist() - { - var generator = from jsonObject in Generator.JsonObject - from missingSection in Generator.NonEmptyString - where jsonObject.ContainsKey(missingSection) is false - from fixture in Fixture.Generate() - let updatedFixture = fixture with { ConfigurationJson = fixture.ConfigurationJson with { Value = jsonObject } } - select (updatedFixture, missingSection); - - generator.Sample(x => - { - var (fixture, missingSection) = x; - - var result = fixture.FindConfigurationSection(missingSection); - - result.Should().BeNone(); - }); - } - - [Fact] - public void Returns_existing_section() - { - var generator = from sections in Generator.AlphaNumericStringBetween(5, 10).Array[1, 5] - from expectedValue in Generator.JsonObject - from jsonObject in sections.Select(sectionName => from jsonObject in Generator.JsonObject - select KeyValuePair.Create(sectionName, jsonObject)) - .Reverse() - .Aggregate(Gen.Const(expectedValue), - (jsonObjectGen, kvpGen) => from previousJsonObject in jsonObjectGen - from newJsonObject in Generator.JsonObject - from kvp in kvpGen - select newJsonObject.SetProperty(kvp.Key, previousJsonObject)) - from fixture in Fixture.Generate() - let updatedFixture = fixture with { ConfigurationJson = fixture.ConfigurationJson with { Value = jsonObject } } - select (updatedFixture, sections, expectedValue); - - generator.Sample(x => - { - // Arrange - var (fixture, sections, expectedValue) = x; - - // Act - var result = fixture.FindConfigurationSection(sections); - - // Assert - var expectedValueString = expectedValue.ToJsonString(); - var actualValueString = result.Map(json => json.ToJsonString()); - actualValueString.Should().BeSome(expected: expectedValueString); - }); - } - - private sealed record Fixture - { - public required ConfigurationJson ConfigurationJson { get; init; } - - public static Gen Generate() => - from configurationJson in GenerateConfigurationJson() - select new Fixture - { - ConfigurationJson = configurationJson - }; - - private static Gen GenerateConfigurationJson() => - from jsonObject in Generator.JsonObject - select new ConfigurationJson - { - Value = jsonObject - }; - - public Option FindConfigurationSection(params string[] sectionNames) - { - var serviceProvider = GetServiceProvider(); - - var findConfigurationSection = ConfigurationJsonModule.GetFindConfigurationSection(serviceProvider); - - return findConfigurationSection(sectionNames); - } - - private IServiceProvider GetServiceProvider() - { - var services = new ServiceCollection(); - - services.AddSingleton(ConfigurationJson); - - return services.BuildServiceProvider(); - } - } -} \ No newline at end of file diff --git a/tools/code/publisher.unit.tests/publisher.unit.tests.csproj b/tools/code/publisher.unit.tests/publisher.unit.tests.csproj deleted file mode 100644 index 59b5a642..00000000 --- a/tools/code/publisher.unit.tests/publisher.unit.tests.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - net8.0 - enable - latest-all - true - true - false - true - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - diff --git a/tools/code/publisher/ApiDiagnostic.cs b/tools/code/publisher/ApiDiagnostic.cs index 831441b1..44e900da 100644 --- a/tools/code/publisher/ApiDiagnostic.cs +++ b/tools/code/publisher/ApiDiagnostic.cs @@ -127,7 +127,7 @@ private static void ConfigureFindApiDiagnosticDto(IHostApplicationBuilder builde { AzureModule.ConfigureManagementServiceDirectory(builder); CommonModule.ConfigureTryGetFileContents(builder); - ConfigurationJsonModule.ConfigureFindConfigurationSection(builder); + ConfigurationModule.ConfigureConfigurationJson(builder); builder.Services.TryAddSingleton(GetFindApiDiagnosticDto); } @@ -136,7 +136,7 @@ public static FindApiDiagnosticDto GetFindApiDiagnosticDto(IServiceProvider prov { var serviceDirectory = provider.GetRequiredService(); var tryGetFileContents = provider.GetRequiredService(); - var findConfigurationSection = provider.GetRequiredService(); + var configurationJson = provider.GetRequiredService(); return async (name, apiName, cancellationToken) => { @@ -148,10 +148,33 @@ public static FindApiDiagnosticDto GetFindApiDiagnosticDto(IServiceProvider prov select overrideDto(dto, name, apiName); }; - ApiDiagnosticDto overrideDto(ApiDiagnosticDto dto, ApiDiagnosticName name, ApiName apiName) => - findConfigurationSection(["apis", apiName.Value, "diagnostics", name.Value]) - .Map(configurationJson => OverrideDtoFactory.Override(dto, configurationJson)) - .IfNone(dto); + ApiDiagnosticDto overrideDto(ApiDiagnosticDto dto, ApiDiagnosticName name, ApiName apiName) + { + var diagnosticSectionOption = + // Get the apis section from the configuration json + from apis in configurationJson.Value + .TryGetJsonArrayProperty("apis") + .ToOption() + // Get the API with the specified name + from api in apis.PickJsonObjects() + .Where(api => api.TryGetStringProperty("name") + .Where(name => name.Equals(apiName.ToString(), StringComparison.OrdinalIgnoreCase)) + .Any()) + .HeadOrNone() + // Get the diagnostics section from the API + from diagnostics in api.TryGetJsonArrayProperty("diagnostics") + .ToOption() + // Get the diagnostic with the specified name + from diagnostic in diagnostics.PickJsonObjects() + .Where(diagnostic => diagnostic.TryGetStringProperty("name") + .Where(name => name.Equals(name.ToString(), StringComparison.OrdinalIgnoreCase)) + .Any()) + .HeadOrNone() + select diagnostic; + + return diagnosticSectionOption.Map(json => OverrideDtoFactory.Override(dto, json)) + .IfNone(dto); + } } private static void ConfigurePutApiDiagnosticInApim(IHostApplicationBuilder builder) diff --git a/tools/code/publisher/ConfigurationJson.cs b/tools/code/publisher/ConfigurationJson.cs deleted file mode 100644 index 7f2eeb2a..00000000 --- a/tools/code/publisher/ConfigurationJson.cs +++ /dev/null @@ -1,37 +0,0 @@ -using common; -using LanguageExt; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Hosting; -using System; -using System.Linq; -using System.Text.Json.Nodes; - -namespace publisher; - -public delegate Option FindConfigurationSection(params string[] sectionNames); - -public static class ConfigurationJsonModule -{ - public static void ConfigureFindConfigurationSection(IHostApplicationBuilder builder) - { - ConfigurationModule.ConfigureConfigurationJson(builder); - - builder.Services.TryAddSingleton(GetFindConfigurationSection); - } - - public static FindConfigurationSection GetFindConfigurationSection(IServiceProvider provider) - { - var configurationJson = provider.GetRequiredService(); - - return sectionNames => - sectionNames.Select((sectionName, index) => (sectionName, index)) - .Aggregate(Option.None, - (option, section) => section.index == 0 - ? configurationJson.Value - .TryGetJsonObjectProperty(section.sectionName) - .ToOption() - : option.Bind(jsonObject => jsonObject.TryGetJsonObjectProperty(section.sectionName) - .ToOption())); - } -} \ No newline at end of file diff --git a/tools/code/publisher/publisher.csproj b/tools/code/publisher/publisher.csproj index 2be99fdc..56ed1fe0 100644 --- a/tools/code/publisher/publisher.csproj +++ b/tools/code/publisher/publisher.csproj @@ -2,13 +2,13 @@ net8.0 - true + 8-all CA1708,CA1724,CA1812,CA1848,CA2007,CA1034,CA1062 Exe enable 6ce9dc18-ea0d-4d82-8f1a-e63877f35b88 - 6.0.1.1 + 6.0.1