From d34ac34322b5abc3453b7b4f0961ff52764b290b Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 30 Jan 2025 08:20:50 +0100 Subject: [PATCH 1/9] AddProtoDefinitionAsync --- .../IWireMockAdminApi.cs | 9 +++++++++ src/WireMock.Net/Server/WireMockServer.Admin.cs | 17 +++++++++++------ .../Server/WireMockServer.AdminFiles.cs | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/WireMock.Net.RestClient/IWireMockAdminApi.cs b/src/WireMock.Net.RestClient/IWireMockAdminApi.cs index fc4e4d726..5cd335462 100644 --- a/src/WireMock.Net.RestClient/IWireMockAdminApi.cs +++ b/src/WireMock.Net.RestClient/IWireMockAdminApi.cs @@ -311,6 +311,15 @@ public interface IWireMockAdminApi [Delete("files/{filename}")] Task DeleteFileAsync([Path] string filename, CancellationToken cancellationToken = default); + /// + /// Add a Grpc ProtoDefinition at server-level. + /// + /// Unique identifier for the ProtoDefinition. + /// The ProtoDefinition as text. + /// The optional cancellationToken. + [Post("protodefinitions/{id}")] + Task AddProtoDefinitionAsync([Path] string id, [Body] string body, CancellationToken cancellationToken = default); + /// /// Check if a file exists /// diff --git a/src/WireMock.Net/Server/WireMockServer.Admin.cs b/src/WireMock.Net/Server/WireMockServer.Admin.cs index e79ff52d3..6b6bea8c8 100644 --- a/src/WireMock.Net/Server/WireMockServer.Admin.cs +++ b/src/WireMock.Net/Server/WireMockServer.Admin.cs @@ -68,6 +68,7 @@ public AdminPaths(WireMockServerSettings settings) public RegexMatcher ScenariosNameMatcher => new($"^{_prefixEscaped}\\/scenarios\\/.+$"); public RegexMatcher ScenariosNameWithResetMatcher => new($"^{_prefixEscaped}\\/scenarios\\/.+\\/reset$"); public RegexMatcher FilesFilenamePathMatcher => new($"^{_prefixEscaped}\\/files\\/.+$"); + public RegexMatcher ProtoDefinitionsIdPathMatcher => new($"^{_prefixEscaped}\\/protodefinitions\\/.+$"); } #region InitAdmin @@ -147,6 +148,9 @@ private void InitAdmin() // __admin/openapi Given(Request.Create().WithPath($"{_adminPaths.OpenApi}/convert").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(OpenApiConvertToMappings)); Given(Request.Create().WithPath($"{_adminPaths.OpenApi}/save").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(OpenApiSaveToMappings)); + + // __admin/protodefinitions/{id} + Given(Request.Create().WithPath(_adminPaths.ProtoDefinitionsIdPathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ProtoDefinitionAdd)); } #endregion @@ -369,7 +373,7 @@ private IResponseMessage MappingCodeGet(IRequestMessage requestMessage) { if (TryParseGuidFromRequestMessage(requestMessage, out var guid)) { - var code = _mappingBuilder.ToCSharpCode(guid, GetMappingConverterType(requestMessage)); + var code = _mappingBuilder.ToCSharpCode(guid, GetEnumFromQuery(requestMessage, MappingConverterType.Server)); if (code is null) { _settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found"); @@ -383,15 +387,16 @@ private IResponseMessage MappingCodeGet(IRequestMessage requestMessage) return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "GUID is missing"); } - private static MappingConverterType GetMappingConverterType(IRequestMessage requestMessage) + private static TEnum GetEnumFromQuery(IRequestMessage requestMessage, TEnum defaultValue) + where TEnum : struct { - if (requestMessage.QueryIgnoreCase?.TryGetValue(nameof(MappingConverterType), out var values) == true && - Enum.TryParse(values.FirstOrDefault(), true, out MappingConverterType parsed)) + if (requestMessage.QueryIgnoreCase?.TryGetValue(typeof(TEnum).Name, out var values) == true && + Enum.TryParse(values.FirstOrDefault(), true, out var parsed)) { return parsed; } - return MappingConverterType.Server; + return defaultValue; } private IMapping? FindMappingByGuid(IRequestMessage requestMessage) @@ -465,7 +470,7 @@ private IResponseMessage MappingsGet(IRequestMessage requestMessage) private IResponseMessage MappingsCodeGet(IRequestMessage requestMessage) { - var converterType = GetMappingConverterType(requestMessage); + var converterType = GetEnumFromQuery(requestMessage, MappingConverterType.Server); var code = _mappingBuilder.ToCSharpCode(converterType); diff --git a/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs b/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs index 7d2ccb3b8..37c722b74 100644 --- a/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs +++ b/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs @@ -13,6 +13,22 @@ public partial class WireMockServer { private static readonly Encoding[] FileBodyIsString = [Encoding.UTF8, Encoding.ASCII]; + #region ProtoDefinitions/{id} + private IResponseMessage ProtoDefinitionAdd(IRequestMessage requestMessage) + { + if (requestMessage.BodyAsString is null) + { + return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null"); + } + + var id = requestMessage.Path.Split('/').Last(); + + AddProtoDefinition(id, requestMessage.BodyAsString); + + return ResponseMessageBuilder.Create(HttpStatusCode.OK, "ProtoDefinition added"); + } + #endregion + #region Files/{filename} private IResponseMessage FilePost(IRequestMessage requestMessage) { From 550ab685d814ab533b89ef1f30f327fcdfcad223 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 30 Jan 2025 11:57:15 +0100 Subject: [PATCH 2/9] ... --- .../WireMockConfiguration.cs | 21 ++++++++++++++++++- .../WireMockContainer.cs | 20 +++++++++++++++--- src/WireMock.Net/Server/WireMockServer.cs | 3 ++- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs b/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs index 159e99019..23bbd81dc 100644 --- a/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs +++ b/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs @@ -28,6 +28,8 @@ public sealed class WireMockConfiguration : ContainerConfiguration public List AdditionalUrls { get; private set; } = []; + public Dictionary ProtoDefinitions { get; set; } = new (); + public WireMockConfiguration(string? username = null, string? password = null) { Username = username; @@ -75,6 +77,7 @@ public WireMockConfiguration(WireMockConfiguration oldValue, WireMockConfigurati WatchStaticMappings = BuildConfiguration.Combine(oldValue.WatchStaticMappings, newValue.WatchStaticMappings); WatchStaticMappingsInSubdirectories = BuildConfiguration.Combine(oldValue.WatchStaticMappingsInSubdirectories, newValue.WatchStaticMappingsInSubdirectories); AdditionalUrls = BuildConfiguration.Combine(oldValue.AdditionalUrls.AsEnumerable(), newValue.AdditionalUrls.AsEnumerable()).ToList(); + ProtoDefinitions = BuildConfiguration.Combine(oldValue.ProtoDefinitions, newValue.ProtoDefinitions); } /// @@ -107,7 +110,23 @@ public WireMockConfiguration WithWatchStaticMappings(bool includeSubDirectories) /// public WireMockConfiguration WithAdditionalUrl(string url) { - AdditionalUrls.Add(url); + AdditionalUrls.Add(Guard.NotNullOrWhiteSpace(url)); + return this; + } + + /// + /// Add a Grpc ProtoDefinition at server-level. + /// + /// Unique identifier for the ProtoDefinition. + /// The ProtoDefinition as text. + /// + public WireMockConfiguration AddProtoDefinition(string id, params string[] protoDefinition) + { + Guard.NotNullOrWhiteSpace(id); + Guard.NotNullOrEmpty(protoDefinition); + + ProtoDefinitions[id] = protoDefinition; + return this; } } \ No newline at end of file diff --git a/src/WireMock.Net.Testcontainers/WireMockContainer.cs b/src/WireMock.Net.Testcontainers/WireMockContainer.cs index b03a10bb2..73206c94e 100644 --- a/src/WireMock.Net.Testcontainers/WireMockContainer.cs +++ b/src/WireMock.Net.Testcontainers/WireMockContainer.cs @@ -29,6 +29,7 @@ public sealed class WireMockContainer : DockerContainer internal const int ContainerPort = 80; private readonly WireMockConfiguration _configuration; + private readonly EventHandler _startedHandler = async (sender, eventArgs) => await WireMockContainerStartedAsync(sender, eventArgs); private IWireMockAdminApi? _adminApi; private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher; @@ -42,7 +43,7 @@ public WireMockContainer(WireMockConfiguration configuration) : base(configurati { _configuration = Stef.Validation.Guard.NotNull(configuration); - Started += WireMockContainer_Started; + Started += _startedHandler; } /// @@ -175,7 +176,7 @@ protected override ValueTask DisposeAsyncCore() _enhancedFileSystemWatcher = null; } - Started -= WireMockContainer_Started; + Started -= _startedHandler; return base.DisposeAsyncCore(); } @@ -195,7 +196,7 @@ private void ValidateIfRunning() } } - private void WireMockContainer_Started(object sender, EventArgs e) + private async Task WireMockContainerStartedAsync(object sender, EventArgs e) { _adminApi = CreateWireMockAdminClient(); @@ -212,6 +213,19 @@ private void WireMockContainer_Started(object sender, EventArgs e) _enhancedFileSystemWatcher.Changed += FileCreatedChangedOrDeleted; _enhancedFileSystemWatcher.Deleted += FileCreatedChangedOrDeleted; _enhancedFileSystemWatcher.EnableRaisingEvents = true; + + await CallAdditionalActionsAfterStartedAsync(); + } + + private Task CallAdditionalActionsAfterStartedAsync() + { + foreach (var kvp in _configuration.ProtoDefinitions) + { + foreach (var protoDefinition in kvp.Value) + { + await _adminApi!.AddProtoDefinitionAsync(kvp.Key, protoDefinition); + } + } } private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args) diff --git a/src/WireMock.Net/Server/WireMockServer.cs b/src/WireMock.Net/Server/WireMockServer.cs index 1d91f490b..bcde468a2 100644 --- a/src/WireMock.Net/Server/WireMockServer.cs +++ b/src/WireMock.Net/Server/WireMockServer.cs @@ -602,7 +602,8 @@ public WireMockServer AddProtoDefinition(string id, params string[] protoDefinit _settings.ProtoDefinitions ??= new Dictionary(); - _settings.ProtoDefinitions[id] = protoDefinition; + // _settings.ProtoDefinitions[id] = protoDefinition; + _settings.ProtoDefinitions[id] = _settings.ProtoDefinitions[id].Union(protoDefinition).ToArray(); return this; } From f344098298bb2d425590e4b7898338653a1ca09d Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 30 Jan 2025 13:54:13 +0100 Subject: [PATCH 3/9] Body --- src/WireMock.Net.Testcontainers/WireMockContainer.cs | 1 + src/WireMock.Net/Server/WireMockServer.AdminFiles.cs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/WireMock.Net.Testcontainers/WireMockContainer.cs b/src/WireMock.Net.Testcontainers/WireMockContainer.cs index 73206c94e..7c6985122 100644 --- a/src/WireMock.Net.Testcontainers/WireMockContainer.cs +++ b/src/WireMock.Net.Testcontainers/WireMockContainer.cs @@ -221,6 +221,7 @@ private Task CallAdditionalActionsAfterStartedAsync() { foreach (var kvp in _configuration.ProtoDefinitions) { + Logger.LogInformation("Adding ProtoDefinition {Id}', kvp.Key); foreach (var protoDefinition in kvp.Value) { await _adminApi!.AddProtoDefinitionAsync(kvp.Key, protoDefinition); diff --git a/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs b/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs index 37c722b74..2629fbb1b 100644 --- a/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs +++ b/src/WireMock.Net/Server/WireMockServer.AdminFiles.cs @@ -16,14 +16,14 @@ public partial class WireMockServer #region ProtoDefinitions/{id} private IResponseMessage ProtoDefinitionAdd(IRequestMessage requestMessage) { - if (requestMessage.BodyAsString is null) + if (requestMessage.Body is null) { return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null"); } var id = requestMessage.Path.Split('/').Last(); - AddProtoDefinition(id, requestMessage.BodyAsString); + AddProtoDefinition(id, requestMessage.Body); return ResponseMessageBuilder.Create(HttpStatusCode.OK, "ProtoDefinition added"); } From fb28796f1c59abcc7d15da5869834d21eace30bb Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 30 Jan 2025 15:07:39 +0100 Subject: [PATCH 4/9] " --- src/WireMock.Net.Testcontainers/WireMockContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WireMock.Net.Testcontainers/WireMockContainer.cs b/src/WireMock.Net.Testcontainers/WireMockContainer.cs index 7c6985122..dec99c4d3 100644 --- a/src/WireMock.Net.Testcontainers/WireMockContainer.cs +++ b/src/WireMock.Net.Testcontainers/WireMockContainer.cs @@ -221,7 +221,7 @@ private Task CallAdditionalActionsAfterStartedAsync() { foreach (var kvp in _configuration.ProtoDefinitions) { - Logger.LogInformation("Adding ProtoDefinition {Id}', kvp.Key); + Logger.LogInformation("Adding ProtoDefinition {Id}", kvp.Key); foreach (var protoDefinition in kvp.Value) { await _adminApi!.AddProtoDefinitionAsync(kvp.Key, protoDefinition); From f9d2e7e46401aec1d3ed343e19997cde2db16558 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 30 Jan 2025 17:17:46 +0100 Subject: [PATCH 5/9] . --- .../WireMockConfiguration.cs | 3 ++- src/WireMock.Net.Testcontainers/WireMockContainer.cs | 10 ++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs b/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs index 23bbd81dc..9017745b1 100644 --- a/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs +++ b/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs @@ -6,6 +6,7 @@ using DotNet.Testcontainers.Builders; using DotNet.Testcontainers.Configurations; using JetBrains.Annotations; +using Stef.Validation; namespace WireMock.Net.Testcontainers; @@ -28,7 +29,7 @@ public sealed class WireMockConfiguration : ContainerConfiguration public List AdditionalUrls { get; private set; } = []; - public Dictionary ProtoDefinitions { get; set; } = new (); + public Dictionary ProtoDefinitions { get; set; } = new(); public WireMockConfiguration(string? username = null, string? password = null) { diff --git a/src/WireMock.Net.Testcontainers/WireMockContainer.cs b/src/WireMock.Net.Testcontainers/WireMockContainer.cs index dec99c4d3..142f13f60 100644 --- a/src/WireMock.Net.Testcontainers/WireMockContainer.cs +++ b/src/WireMock.Net.Testcontainers/WireMockContainer.cs @@ -17,6 +17,7 @@ using WireMock.Http; using WireMock.Net.Testcontainers.Utils; using WireMock.Util; +using Stef.Validation; namespace WireMock.Net.Testcontainers; @@ -29,7 +30,6 @@ public sealed class WireMockContainer : DockerContainer internal const int ContainerPort = 80; private readonly WireMockConfiguration _configuration; - private readonly EventHandler _startedHandler = async (sender, eventArgs) => await WireMockContainerStartedAsync(sender, eventArgs); private IWireMockAdminApi? _adminApi; private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher; @@ -41,9 +41,9 @@ public sealed class WireMockContainer : DockerContainer /// The container configuration. public WireMockContainer(WireMockConfiguration configuration) : base(configuration) { - _configuration = Stef.Validation.Guard.NotNull(configuration); + _configuration = Guard.NotNull(configuration); - Started += _startedHandler; + Started += async (sender, eventArgs) => await WireMockContainerStartedAsync(sender, eventArgs); } /// @@ -176,8 +176,6 @@ protected override ValueTask DisposeAsyncCore() _enhancedFileSystemWatcher = null; } - Started -= _startedHandler; - return base.DisposeAsyncCore(); } @@ -217,7 +215,7 @@ private async Task WireMockContainerStartedAsync(object sender, EventArgs e) await CallAdditionalActionsAfterStartedAsync(); } - private Task CallAdditionalActionsAfterStartedAsync() + private async Task CallAdditionalActionsAfterStartedAsync() { foreach (var kvp in _configuration.ProtoDefinitions) { From 8c889395ce4b57d157e4ae8f8c06c1264fd0c2e9 Mon Sep 17 00:00:00 2001 From: Stef Date: Fri, 31 Jan 2025 06:40:53 +0100 Subject: [PATCH 6/9] . --- Directory.Build.props | 2 +- .../WireMockContainer.cs | 11 ++++- .../WireMockContainerBuilder.cs | 17 ++++++++ src/WireMock.Net/Server/WireMockServer.cs | 10 ++++- test/WireMock.Net.Tests/Constants.cs | 10 +++++ .../TestcontainersTests.Grpc.cs | 40 ++++++++++++++++--- .../WireMock.Net.Tests.csproj | 3 ++ .../WireMockServer.Admin.cs | 8 ++-- .../WireMockServer.Proxy.cs | 2 +- .../WireMockServer.Settings.cs | 10 ++--- .../__admin/mappings/greet.proto | 21 ++++++++++ 11 files changed, 110 insertions(+), 24 deletions(-) create mode 100644 test/WireMock.Net.Tests/Constants.cs create mode 100644 test/WireMock.Net.Tests/__admin/mappings/greet.proto diff --git a/Directory.Build.props b/Directory.Build.props index f69ba6156..7e51d15e3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ - 1.7.1 + 1.7.2-preview-01 WireMock.Net-Logo.png https://github.com/WireMock-Net/WireMock.Net Apache-2.0 diff --git a/src/WireMock.Net.Testcontainers/WireMockContainer.cs b/src/WireMock.Net.Testcontainers/WireMockContainer.cs index 142f13f60..35ce5677f 100644 --- a/src/WireMock.Net.Testcontainers/WireMockContainer.cs +++ b/src/WireMock.Net.Testcontainers/WireMockContainer.cs @@ -12,12 +12,12 @@ using JetBrains.Annotations; using Microsoft.Extensions.Logging; using RestEase; +using Stef.Validation; using WireMock.Client; using WireMock.Client.Extensions; using WireMock.Http; using WireMock.Net.Testcontainers.Utils; using WireMock.Util; -using Stef.Validation; namespace WireMock.Net.Testcontainers; @@ -222,7 +222,14 @@ private async Task CallAdditionalActionsAfterStartedAsync() Logger.LogInformation("Adding ProtoDefinition {Id}", kvp.Key); foreach (var protoDefinition in kvp.Value) { - await _adminApi!.AddProtoDefinitionAsync(kvp.Key, protoDefinition); + try + { + await _adminApi!.AddProtoDefinitionAsync(kvp.Key, protoDefinition); + } + catch (Exception ex) + { + Logger.LogWarning(ex, "Error adding ProtoDefinition '{Id}'.", kvp.Key); + } } } } diff --git a/src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs b/src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs index ea2e90741..ef634ff98 100644 --- a/src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs +++ b/src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs @@ -164,6 +164,23 @@ public WireMockContainerBuilder AddUrl(string url) return WithPortBinding(port, true); } + /// + /// Add a Grpc ProtoDefinition at server-level. + /// + /// Unique identifier for the ProtoDefinition. + /// The ProtoDefinition as text. + /// + [PublicAPI] + public WireMockContainerBuilder AddProtoDefinition(string id, params string[] protoDefinition) + { + Guard.NotNullOrWhiteSpace(id); + Guard.NotNullOrEmpty(protoDefinition); + + DockerResourceConfiguration.AddProtoDefinition(id, protoDefinition); + + return this; + } + private WireMockContainerBuilder WithCommand(string param, bool value) { return !value ? this : WithCommand($"{param} true"); diff --git a/src/WireMock.Net/Server/WireMockServer.cs b/src/WireMock.Net/Server/WireMockServer.cs index bcde468a2..c99d6ab58 100644 --- a/src/WireMock.Net/Server/WireMockServer.cs +++ b/src/WireMock.Net/Server/WireMockServer.cs @@ -602,8 +602,14 @@ public WireMockServer AddProtoDefinition(string id, params string[] protoDefinit _settings.ProtoDefinitions ??= new Dictionary(); - // _settings.ProtoDefinitions[id] = protoDefinition; - _settings.ProtoDefinitions[id] = _settings.ProtoDefinitions[id].Union(protoDefinition).ToArray(); + if (_settings.ProtoDefinitions.TryGetValue(id, out var existingProtoDefinitions)) + { + _settings.ProtoDefinitions[id] = existingProtoDefinitions.Union(protoDefinition).ToArray(); + } + else + { + _settings.ProtoDefinitions[id] = protoDefinition; + } return this; } diff --git a/test/WireMock.Net.Tests/Constants.cs b/test/WireMock.Net.Tests/Constants.cs new file mode 100644 index 000000000..a7b36152d --- /dev/null +++ b/test/WireMock.Net.Tests/Constants.cs @@ -0,0 +1,10 @@ +// Copyright © WireMock.Net + +namespace WireMock.Net.Tests; + +internal static class Constants +{ + internal const int NumStaticMappings = 10; + + internal const int NumAdminMappings = 36; +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs b/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs index 365ccc589..a9188807c 100644 --- a/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs +++ b/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs @@ -129,9 +129,9 @@ public async Task WireMockContainer_Build_Grpc_TestPortsAndUrls2() [Fact] public async Task WireMockContainer_Build_Grpc_ProtoDefinitionFromJson_UsingGrpcGeneratedClient() { - var wireMockContainer = await Given_WireMockContainerIsStartedForHttpAndGrpc(); + var wireMockContainer = await Given_WireMockContainerIsStartedForHttpAndGrpcAsync(); - await Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(wireMockContainer); + await Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(wireMockContainer, "protobuf-mapping-1.json"); var reply = await When_GrpcClient_Calls_SayHelloAsync(wireMockContainer); @@ -140,12 +140,40 @@ public async Task WireMockContainer_Build_Grpc_ProtoDefinitionFromJson_UsingGrpc await wireMockContainer.StopAsync(); } - private static async Task Given_WireMockContainerIsStartedForHttpAndGrpc() + [Fact] + public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient() + { + var wireMockContainer = await Given_WireMockContainerWithProtodefinitionAtServerLevelIsStartedForHttpAndGrpcAsync(); + + await Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(wireMockContainer, "protobuf-mapping-4.json"); + + var reply = await When_GrpcClient_Calls_SayHelloAsync(wireMockContainer); + + Then_ReplyMessage_Should_BeCorrect(reply); + + await wireMockContainer.StopAsync(); + } + + private static async Task Given_WireMockContainerIsStartedForHttpAndGrpcAsync() + { + var wireMockContainer = new WireMockContainerBuilder() + .WithAutoRemove(true) + .WithCleanUp(true) + .AddUrl("grpc://*:9090") + .Build(); + + await wireMockContainer.StartAsync(); + + return wireMockContainer; + } + + private static async Task Given_WireMockContainerWithProtodefinitionAtServerLevelIsStartedForHttpAndGrpcAsync() { var wireMockContainer = new WireMockContainerBuilder() .WithAutoRemove(true) .WithCleanUp(true) .AddUrl("grpc://*:9090") + .AddProtoDefinition("my-greeter", ReadFile("greet.proto")) .Build(); await wireMockContainer.StartAsync(); @@ -153,9 +181,9 @@ private static async Task Given_WireMockContainerIsStartedFor return wireMockContainer; } - private static async Task Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(WireMockContainer wireMockContainer) + private static async Task Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(WireMockContainer wireMockContainer, string filename) { - var mappingsJson = ReadMappingFile("protobuf-mapping-1.json"); + var mappingsJson = ReadFile(filename); using var httpClient = wireMockContainer.CreateClient(); @@ -178,7 +206,7 @@ private static void Then_ReplyMessage_Should_BeCorrect(HelloReply reply) reply.Message.Should().Be("hello stef POST"); } - private static string ReadMappingFile(string filename) + private static string ReadFile(string filename) { return File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings", filename)); } diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj index 038dafafb..8aa2e2420 100644 --- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj +++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj @@ -154,6 +154,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/test/WireMock.Net.Tests/WireMockServer.Admin.cs b/test/WireMock.Net.Tests/WireMockServer.Admin.cs index 684633f96..4a26a7bf6 100644 --- a/test/WireMock.Net.Tests/WireMockServer.Admin.cs +++ b/test/WireMock.Net.Tests/WireMockServer.Admin.cs @@ -26,8 +26,6 @@ namespace WireMock.Net.Tests; public class WireMockServerAdminTests { - private const int NumStaticMappings = 10; - private static string GetCurrentFolder() { return Directory.GetCurrentDirectory(); @@ -40,8 +38,8 @@ public void WireMockServer_Admin_ResetMappings() string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings"); server.ReadStaticMappings(folder); - Check.That(server.Mappings).HasSize(NumStaticMappings); - Check.That(server.MappingModels).HasSize(NumStaticMappings); + Check.That(server.Mappings).HasSize(Constants.NumStaticMappings); + Check.That(server.MappingModels).HasSize(Constants.NumStaticMappings); // Act server.ResetMappings(); @@ -220,7 +218,7 @@ public void WireMockServer_Admin_ReadStaticMappings() server.ReadStaticMappings(folder); var mappings = server.Mappings.ToArray(); - Check.That(mappings).HasSize(NumStaticMappings); + Check.That(mappings).HasSize(Constants.NumStaticMappings); server.Stop(); } diff --git a/test/WireMock.Net.Tests/WireMockServer.Proxy.cs b/test/WireMock.Net.Tests/WireMockServer.Proxy.cs index 0513983a6..f2564c2e3 100644 --- a/test/WireMock.Net.Tests/WireMockServer.Proxy.cs +++ b/test/WireMock.Net.Tests/WireMockServer.Proxy.cs @@ -119,7 +119,7 @@ public async Task WireMockServer_Proxy_AdminTrue_With_SaveMapping_Is_True_And_Sa } // Assert - server.Mappings.Should().HaveCount(37); + server.Mappings.Should().HaveCount(Constants.NumAdminMappings + 2); } [Fact] diff --git a/test/WireMock.Net.Tests/WireMockServer.Settings.cs b/test/WireMock.Net.Tests/WireMockServer.Settings.cs index f6a8ab96a..91defc859 100644 --- a/test/WireMock.Net.Tests/WireMockServer.Settings.cs +++ b/test/WireMock.Net.Tests/WireMockServer.Settings.cs @@ -75,8 +75,6 @@ public void WireMockServer_WireMockServerSettings_StartAdminInterfaceFalse_Basic [Fact] public void WireMockServer_WireMockServerSettings_PriorityFromAllAdminMappingsIsLow_When_StartAdminInterface_IsTrue() { - const int count = 35; - // Assign and Act var server = WireMockServer.Start(new WireMockServerSettings { @@ -85,15 +83,13 @@ public void WireMockServer_WireMockServerSettings_PriorityFromAllAdminMappingsIs // Assert server.Mappings.Should().NotBeNull(); - server.Mappings.Should().HaveCount(count); + server.Mappings.Should().HaveCount(Constants.NumAdminMappings); server.Mappings.All(m => m.Priority == WireMockConstants.AdminPriority).Should().BeTrue(); } [Fact] public void WireMockServer_WireMockServerSettings_ProxyAndRecordSettings_ProxyPriority_IsMinus2000000_When_StartAdminInterface_IsTrue() { - const int count = 36; - // Assign and Act var server = WireMockServer.Start(new WireMockServerSettings { @@ -106,9 +102,9 @@ public void WireMockServer_WireMockServerSettings_ProxyAndRecordSettings_ProxyPr // Assert server.Mappings.Should().NotBeNull(); - server.Mappings.Should().HaveCount(count); + server.Mappings.Should().HaveCount(Constants.NumAdminMappings + 1); - server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(count - 1); + server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(Constants.NumAdminMappings); server.Mappings.Count(m => m.Priority == WireMockConstants.ProxyPriority).Should().Be(1); } diff --git a/test/WireMock.Net.Tests/__admin/mappings/greet.proto b/test/WireMock.Net.Tests/__admin/mappings/greet.proto new file mode 100644 index 000000000..f4e1ead02 --- /dev/null +++ b/test/WireMock.Net.Tests/__admin/mappings/greet.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +package greet; + +service Greeter { + rpc SayHello (HelloRequest) returns (HelloReply); +} + +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; + enum PhoneType { + none = 0; + mobile = 1; + home = 2; + } + PhoneType phoneType = 2; +} \ No newline at end of file From ce7627f4e7f8f01622eb45278e68873905a1825c Mon Sep 17 00:00:00 2001 From: Stef Date: Sat, 1 Feb 2025 23:21:14 +0100 Subject: [PATCH 7/9] . --- .../WireMockConfiguration.cs | 16 ++++++++++++++-- .../WireMockContainer.cs | 9 +++++++-- .../__admin/mappings/protobuf-mapping-2.json | 2 +- .../__admin/mappings/protobuf-mapping-4.json | 2 +- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs b/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs index 9017745b1..f72606703 100644 --- a/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs +++ b/src/WireMock.Net.Testcontainers/WireMockConfiguration.cs @@ -77,8 +77,8 @@ public WireMockConfiguration(WireMockConfiguration oldValue, WireMockConfigurati StaticMappingsPath = BuildConfiguration.Combine(oldValue.StaticMappingsPath, newValue.StaticMappingsPath); WatchStaticMappings = BuildConfiguration.Combine(oldValue.WatchStaticMappings, newValue.WatchStaticMappings); WatchStaticMappingsInSubdirectories = BuildConfiguration.Combine(oldValue.WatchStaticMappingsInSubdirectories, newValue.WatchStaticMappingsInSubdirectories); - AdditionalUrls = BuildConfiguration.Combine(oldValue.AdditionalUrls.AsEnumerable(), newValue.AdditionalUrls.AsEnumerable()).ToList(); - ProtoDefinitions = BuildConfiguration.Combine(oldValue.ProtoDefinitions, newValue.ProtoDefinitions); + AdditionalUrls = Combine(oldValue.AdditionalUrls, newValue.AdditionalUrls); + ProtoDefinitions = Combine(oldValue.ProtoDefinitions, newValue.ProtoDefinitions); } /// @@ -130,4 +130,16 @@ public WireMockConfiguration AddProtoDefinition(string id, params string[] proto return this; } + + private static List Combine(List oldValue, List newValue) + { + return oldValue.Concat(newValue).ToList(); + } + + private static Dictionary Combine(Dictionary oldValue, Dictionary newValue) + { + return newValue + .Concat(oldValue.Where(item => !newValue.Keys.Contains(item.Key))) + .ToDictionary(item => item.Key, item => item.Value); + } } \ No newline at end of file diff --git a/src/WireMock.Net.Testcontainers/WireMockContainer.cs b/src/WireMock.Net.Testcontainers/WireMockContainer.cs index 35ce5677f..f87c99bea 100644 --- a/src/WireMock.Net.Testcontainers/WireMockContainer.cs +++ b/src/WireMock.Net.Testcontainers/WireMockContainer.cs @@ -198,6 +198,13 @@ private async Task WireMockContainerStartedAsync(object sender, EventArgs e) { _adminApi = CreateWireMockAdminClient(); + RegisterEnhancedFileSystemWatcher(); + + await CallAdditionalActionsAfterStartedAsync(); + } + + private void RegisterEnhancedFileSystemWatcher() + { if (!_configuration.WatchStaticMappings || string.IsNullOrEmpty(_configuration.StaticMappingsPath)) { return; @@ -211,8 +218,6 @@ private async Task WireMockContainerStartedAsync(object sender, EventArgs e) _enhancedFileSystemWatcher.Changed += FileCreatedChangedOrDeleted; _enhancedFileSystemWatcher.Deleted += FileCreatedChangedOrDeleted; _enhancedFileSystemWatcher.EnableRaisingEvents = true; - - await CallAdditionalActionsAfterStartedAsync(); } private async Task CallAdditionalActionsAfterStartedAsync() diff --git a/test/WireMock.Net.Tests/__admin/mappings/protobuf-mapping-2.json b/test/WireMock.Net.Tests/__admin/mappings/protobuf-mapping-2.json index 41f1e95e8..68ec82ff7 100644 --- a/test/WireMock.Net.Tests/__admin/mappings/protobuf-mapping-2.json +++ b/test/WireMock.Net.Tests/__admin/mappings/protobuf-mapping-2.json @@ -31,7 +31,7 @@ }, "Response": { "BodyAsJson": { - "message": "hello {{request.BodyAsJson.name}}" + "message": "hello {{request.BodyAsJson.name}} {{request.method}}" }, "UseTransformer": true, "TransformerType": "Handlebars", diff --git a/test/WireMock.Net.Tests/__admin/mappings/protobuf-mapping-4.json b/test/WireMock.Net.Tests/__admin/mappings/protobuf-mapping-4.json index a56d43545..930dc941f 100644 --- a/test/WireMock.Net.Tests/__admin/mappings/protobuf-mapping-4.json +++ b/test/WireMock.Net.Tests/__admin/mappings/protobuf-mapping-4.json @@ -23,7 +23,7 @@ }, "Response": { "BodyAsJson": { - "message": "hello {{request.BodyAsJson.name}}" + "message": "hello {{request.BodyAsJson.name}} {{request.method}}" }, "UseTransformer": true, "TransformerType": "Handlebars", From 2ad143998e1d03baf79dbbf488e0000dc80017df Mon Sep 17 00:00:00 2001 From: Stef Date: Fri, 7 Feb 2025 15:51:56 +0100 Subject: [PATCH 8/9] [Fact(Skip = "new docker is needed")] --- .../Testcontainers/TestcontainersTests.Grpc.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs b/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs index a9188807c..8a5a973ae 100644 --- a/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs +++ b/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs @@ -140,7 +140,7 @@ public async Task WireMockContainer_Build_Grpc_ProtoDefinitionFromJson_UsingGrpc await wireMockContainer.StopAsync(); } - [Fact] + [Fact(Skip = "new docker is needed")] public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient() { var wireMockContainer = await Given_WireMockContainerWithProtodefinitionAtServerLevelIsStartedForHttpAndGrpcAsync(); From 973d2bc027d1e273a2609c52b85b0bcb73f34667 Mon Sep 17 00:00:00 2001 From: Stef Date: Sat, 8 Feb 2025 17:32:42 +0100 Subject: [PATCH 9/9] x --- .../Testcontainers/TestcontainersTests.Grpc.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs b/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs index 8a5a973ae..f1b7cc10c 100644 --- a/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs +++ b/test/WireMock.Net.Tests/Testcontainers/TestcontainersTests.Grpc.cs @@ -3,7 +3,6 @@ #if NET6_0_OR_GREATER using System; using System.IO; -using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; @@ -140,10 +139,10 @@ public async Task WireMockContainer_Build_Grpc_ProtoDefinitionFromJson_UsingGrpc await wireMockContainer.StopAsync(); } - [Fact(Skip = "new docker is needed")] + [Fact] public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient() { - var wireMockContainer = await Given_WireMockContainerWithProtodefinitionAtServerLevelIsStartedForHttpAndGrpcAsync(); + var wireMockContainer = await Given_WireMockContainerWithProtoDefinitionAtServerLevelIsStartedForHttpAndGrpcAsync(); await Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(wireMockContainer, "protobuf-mapping-4.json"); @@ -167,7 +166,7 @@ private static async Task Given_WireMockContainerIsStartedFor return wireMockContainer; } - private static async Task Given_WireMockContainerWithProtodefinitionAtServerLevelIsStartedForHttpAndGrpcAsync() + private static async Task Given_WireMockContainerWithProtoDefinitionAtServerLevelIsStartedForHttpAndGrpcAsync() { var wireMockContainer = new WireMockContainerBuilder() .WithAutoRemove(true)