From bd8e18b2c45e69b965adfbc0f18e58640c026570 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Mon, 20 Mar 2017 17:22:09 +0100 Subject: [PATCH] FluentMockServerSettings (#21) --- .../Program.cs | 7 +- src/WireMock.Net.StandAlone/Program.cs | 13 +- .../Server/FluentMockServer.Admin.cs | 13 +- src/WireMock.Net/Server/FluentMockServer.cs | 131 +++++++++++++----- .../Server/FluentMockServerSettings.cs | 48 +++++++ .../FluentMockServerTests.cs | 45 ++++++ .../00000002-ee28-4f29-ae63-1ac9b0802d86.json | 50 +++++++ .../__admin/mappings/documentdb_root.json | 42 ++++++ 8 files changed, 305 insertions(+), 44 deletions(-) create mode 100644 src/WireMock.Net/Server/FluentMockServerSettings.cs create mode 100644 test/WireMock.Net.Tests/__admin/mappings/00000002-ee28-4f29-ae63-1ac9b0802d86.json create mode 100644 test/WireMock.Net.Tests/__admin/mappings/documentdb_root.json diff --git a/examples/WireMock.Net.ConsoleApplication/Program.cs b/examples/WireMock.Net.ConsoleApplication/Program.cs index 28e2ca06..add20e33 100644 --- a/examples/WireMock.Net.ConsoleApplication/Program.cs +++ b/examples/WireMock.Net.ConsoleApplication/Program.cs @@ -16,7 +16,12 @@ namespace WireMock.Net.ConsoleApplication string url2 = "http://localhost:9091/"; string url3 = "https://localhost:9443/"; - var server = FluentMockServer.StartWithAdminInterface(url1, url2, url3); + var server = FluentMockServer.Start(new FluentMockServerSettings + { + Urls = new [] { url1, url2, url3 }, + StartAdminInterface = true, + ReadStaticMappings = true + }); Console.WriteLine("FluentMockServer listening at {0}", string.Join(" and ", server.Urls)); server.SetBasicAuthentication("a", "b"); diff --git a/src/WireMock.Net.StandAlone/Program.cs b/src/WireMock.Net.StandAlone/Program.cs index 37db89bf..f82109c2 100644 --- a/src/WireMock.Net.StandAlone/Program.cs +++ b/src/WireMock.Net.StandAlone/Program.cs @@ -16,6 +16,12 @@ namespace WireMock.Net.StandAlone [SwitchArgument('p', "AllowPartialMapping", true, Description = "Allow Partial Mapping (default set to true).", Optional = true)] public bool AllowPartialMapping { get; set; } + + [SwitchArgument('s', "StartAdminInterface", true, Description = "Start the AdminInterface (default set to true).", Optional = true)] + public bool StartAdminInterface { get; set; } + + [SwitchArgument('r', "ReadStaticMappings", true, Description = "Read StaticMappings from ./__admin/mappings (default set to true).", Optional = true)] + public bool ReadStaticMappings { get; set; } } static void Main(params string[] args) @@ -31,7 +37,12 @@ namespace WireMock.Net.StandAlone if (!options.Urls.Any()) options.Urls.Add("http://localhost:9090/"); - var server = FluentMockServer.StartWithAdminInterface(options.Urls.ToArray()); + var server = FluentMockServer.Start(new FluentMockServerSettings + { + Urls = options.Urls.ToArray(), + StartAdminInterface = options.StartAdminInterface, + ReadStaticMappings = options.ReadStaticMappings + }); if (options.AllowPartialMapping) server.AllowPartialMapping(); diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index 2fc4dbbb..36f50572 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -66,11 +66,16 @@ namespace WireMock.Server Check.NotNull(filename, nameof(filename)); string filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); - Guid guid; - if (!Guid.TryParse(filenameWithoutExtension, out guid)) - guid = Guid.NewGuid(); + Guid guidFromFilename; - DeserializeAndAddMapping(File.ReadAllText(filename), guid); + if (Guid.TryParse(filenameWithoutExtension, out guidFromFilename)) + { + DeserializeAndAddMapping(File.ReadAllText(filename), guidFromFilename); + } + else + { + DeserializeAndAddMapping(File.ReadAllText(filename)); + } } private void InitAdmin() diff --git a/src/WireMock.Net/Server/FluentMockServer.cs b/src/WireMock.Net/Server/FluentMockServer.cs index d5c553a0..9cdc0885 100644 --- a/src/WireMock.Net/Server/FluentMockServer.cs +++ b/src/WireMock.Net/Server/FluentMockServer.cs @@ -19,7 +19,7 @@ namespace WireMock.Server /// /// The fluent mock server. /// - public partial class FluentMockServer + public partial class FluentMockServer : IDisposable { private readonly TinyHttpServer _httpServer; @@ -112,6 +112,19 @@ namespace WireMock.Server } } + /// + /// Starts the specified settings. + /// + /// The FluentMockServerSettings. + /// The . + [PublicAPI] + public static FluentMockServer Start(FluentMockServerSettings settings) + { + Check.NotNull(settings, nameof(settings)); + + return new FluentMockServer(settings); + } + /// /// Start this FluentMockServer. /// @@ -119,14 +132,13 @@ namespace WireMock.Server /// The SSL support. /// The . [PublicAPI] - public static FluentMockServer Start(int port = 0, bool ssl = false) + public static FluentMockServer Start([CanBeNull] int? port = 0, bool ssl = false) { - Check.Condition(port, p => p >= 0, nameof(port)); - - if (port == 0) - port = PortUtil.FindFreeTcpPort(); - - return new FluentMockServer(false, port, ssl); + return new FluentMockServer(new FluentMockServerSettings + { + Port = port, + UseSSL = ssl + }); } /// @@ -139,7 +151,10 @@ namespace WireMock.Server { Check.NotEmpty(urls, nameof(urls)); - return new FluentMockServer(false, urls); + return new FluentMockServer(new FluentMockServerSettings + { + Urls = urls + }); } /// @@ -149,14 +164,14 @@ namespace WireMock.Server /// The SSL support. /// The . [PublicAPI] - public static FluentMockServer StartWithAdminInterface(int port = 0, bool ssl = false) + public static FluentMockServer StartWithAdminInterface(int? port = 0, bool ssl = false) { - Check.Condition(port, p => p >= 0, nameof(port)); - - if (port == 0) - port = PortUtil.FindFreeTcpPort(); - - return new FluentMockServer(true, port, ssl); + return new FluentMockServer(new FluentMockServerSettings + { + Port = port, + UseSSL = ssl, + StartAdminInterface = true + }); } /// @@ -169,7 +184,57 @@ namespace WireMock.Server { Check.NotEmpty(urls, nameof(urls)); - return new FluentMockServer(true, urls); + return new FluentMockServer(new FluentMockServerSettings + { + Urls = urls, + StartAdminInterface = true + }); + } + + /// + /// Start this FluentMockServer with the admin interface and read static mappings. + /// + /// The urls. + /// The . + [PublicAPI] + public static FluentMockServer StartWithAdminInterfaceAndReadStaticMappings(params string[] urls) + { + Check.NotEmpty(urls, nameof(urls)); + + return new FluentMockServer(new FluentMockServerSettings + { + Urls = urls, + StartAdminInterface = true, + ReadStaticMappings = true + }); + } + + private FluentMockServer(FluentMockServerSettings settings) + { + if (settings.Urls != null) + { + Urls = settings.Urls; + } + else + { + int port = settings.Port > 0 ? settings.Port.Value : PortUtil.FindFreeTcpPort(); + Urls = new[] { (settings.UseSSL == true ? "https" : "http") + "://localhost:" + port + "/" }; + } + + _httpServer = new TinyHttpServer(HandleRequestAsync, Urls); + Ports = _httpServer.Ports; + + _httpServer.Start(); + + if (settings.StartAdminInterface == true) + { + InitAdmin(); + } + + if (settings.ReadStaticMappings == true) + { + ReadStaticMappings(); + } } /// @@ -184,27 +249,6 @@ namespace WireMock.Server .RespondWith(new DynamicResponseProvider(request => new ResponseMessage { StatusCode = 404, Body = "No matching mapping found" })); } - private FluentMockServer(bool startAdminInterface, int port, bool ssl) : this(startAdminInterface, (ssl ? "https" : "http") + "://localhost:" + port + "/") - { - } - - private FluentMockServer(bool startAdminInterface, params string[] urls) - { - Urls = urls; - - _httpServer = new TinyHttpServer(HandleRequestAsync, urls); - Ports = _httpServer.Ports; - - _httpServer.Start(); - - if (startAdminInterface) - { - InitAdmin(); - } - - ReadStaticMappings(); - } - /// /// Stop this server. /// @@ -214,6 +258,17 @@ namespace WireMock.Server _httpServer.Stop(); } + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + if (_httpServer != null && _httpServer.IsStarted) + { + _httpServer.Stop(); + } + } + /// /// Resets LogEntries and Mappings. /// diff --git a/src/WireMock.Net/Server/FluentMockServerSettings.cs b/src/WireMock.Net/Server/FluentMockServerSettings.cs new file mode 100644 index 00000000..d4eecf5a --- /dev/null +++ b/src/WireMock.Net/Server/FluentMockServerSettings.cs @@ -0,0 +1,48 @@ +namespace WireMock.Server +{ + /// + /// FluentMockServerSettings + /// + public class FluentMockServerSettings + { + /// + /// Gets or sets the port. + /// + /// + /// The port. + /// + public int? Port { get; set; } + + /// + /// Gets or sets the use SSL. + /// + /// + /// The use SSL. + /// + public bool? UseSSL { get; set; } + + /// + /// Gets or sets the start admin interface. + /// + /// + /// The start admin interface. + /// + public bool? StartAdminInterface { get; set; } + + /// + /// Gets or sets the read static mappings. + /// + /// + /// The read static mappings. + /// + public bool? ReadStaticMappings { get; set; } + + /// + /// Gets or sets the urls. + /// + /// + /// The urls. + /// + public string[] Urls { get; set; } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs index 6c6c1a90..a20ca18b 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs @@ -19,6 +19,51 @@ namespace WireMock.Net.Tests { private FluentMockServer _server; + [Test] + public void FluentMockServer_ReadStaticMapping_WithNonGuidFilename() + { + var guid = Guid.Parse("04ee4872-9efd-4770-90d3-88d445265d0d"); + string title = "documentdb_root_title"; + + _server = FluentMockServer.Start(); + + _server.ReadStaticMapping("./__admin/mappings/documentdb_root.json"); + + var mappings = _server.Mappings.ToArray(); + Check.That(mappings).HasSize(1); + + Check.That(mappings.First().RequestMatcher).IsNotNull(); + Check.That(mappings.First().Provider).IsNotNull(); + Check.That(mappings.First().Guid).Equals(guid); + Check.That(mappings.First().Title).Equals(title); + } + + [Test] + public void FluentMockServer_ReadStaticMapping_WithGuidFilename() + { + string guid = "00000002-ee28-4f29-ae63-1ac9b0802d86"; + + _server = FluentMockServer.Start(); + _server.ReadStaticMapping("./__admin/mappings/" + guid + ".json"); + + var mappings = _server.Mappings.ToArray(); + Check.That(mappings).HasSize(1); + + Check.That(mappings.First().RequestMatcher).IsNotNull(); + Check.That(mappings.First().Provider).IsNotNull(); + Check.That(mappings.First().Guid).Equals(Guid.Parse(guid)); + Check.That(mappings.First().Title).IsNullOrEmpty(); + } + + [Test] + public void FluentMockServer_ReadStaticMappings() + { + _server = FluentMockServer.Start(new FluentMockServerSettings { ReadStaticMappings = true }); + + var mappings = _server.Mappings.ToArray(); + Check.That(mappings).HasSize(2); + } + [Test] public void FluentMockServer_Admin_Mappings_Get() { diff --git a/test/WireMock.Net.Tests/__admin/mappings/00000002-ee28-4f29-ae63-1ac9b0802d86.json b/test/WireMock.Net.Tests/__admin/mappings/00000002-ee28-4f29-ae63-1ac9b0802d86.json new file mode 100644 index 00000000..9f0cb7e3 --- /dev/null +++ b/test/WireMock.Net.Tests/__admin/mappings/00000002-ee28-4f29-ae63-1ac9b0802d86.json @@ -0,0 +1,50 @@ +{ + "Guid": "00000002-ee28-4f29-ae63-1ac9b0802d86", + "Priority": 0, + "Request": { + "Path": { + "Matchers": [ + { + "Name": "ExactMatcher", + "Pattern": "/dbs" + } + ] + }, + "Methods": [ + "post" + ], + "Body": { + "Matcher": { + "Name": "WildcardMatcher", + "Pattern": "*db-abc*" + } + } + }, + "Response": { + "StatusCode": 200, + "Body": "{\"_rid\":\"\",\"Databases\":[{\"id\":\"db-abc\",\"_rid\":\"hBYWAA==\",\"_self\":\"dbs/hBYWAA==/\",\"_etag\":\"\\\"00008e00-0000-0000-0000-58b94f910000\\\"\",\"_colls\":\"colls/\",\"_users\":\"users/\",\"_ts\":1488539514}],\"_count\":1}", + "BodyEncoding": { + "CodePage": 65001, + "EncodingName": "Unicode (UTF-8)", + "WebName": "utf-8" + }, + "UseTransformer": false, + "Headers": { + "x-ms-schemaversion": "1.3", + "Date": "Mon, 06 Mar 2017 10:56:43 GMT", + "x-ms-activity-id": "5e39429d-7fcc-4b75-93d6-519b7c582772", + "x-ms-item-count": "1", + "x-ms-resource-usage": "databases=1;", + "x-ms-gatewayversion": "version=1.11.164.3", + "x-ms-xp-role": "2", + "x-ms-session-token": "0:25908", + "x-ms-serviceversion": "version=1.11.150.2", + "Strict-Transport-Security": "max-age=31536000", + "Server": "Microsoft-HTTPAPI/2.0", + "x-ms-last-state-change-utc": "Fri, 24 Feb 2017 11:35:16.053 GMT", + "Content-Type": "application/json", + "x-ms-request-charge": "4.68", + "x-ms-resource-quota": "databases=100;" + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/__admin/mappings/documentdb_root.json b/test/WireMock.Net.Tests/__admin/mappings/documentdb_root.json new file mode 100644 index 00000000..b9e84681 --- /dev/null +++ b/test/WireMock.Net.Tests/__admin/mappings/documentdb_root.json @@ -0,0 +1,42 @@ +{ + "Guid": "04ee4872-9efd-4770-90d3-88d445265d0d", + "Title": "documentdb_root_title", + "Priority": 0, + "Request": { + "Path": { + "Matchers": [ + { + "Name": "ExactMatcher", + "Pattern": "/" + } + ] + }, + "Methods": [ + "get" + ], + "Body": {} + }, + "Response": { + "StatusCode": 200, + "Body": "{\"_self\":\"\",\"id\":\"abc\",\"_rid\":\"abc.documents.azure.com\",\"media\":\"//media/\",\"addresses\":\"//addresses/\",\"_dbs\":\"//dbs/\",\"writableLocations\":[{\"name\":\"West Europe\",\"databaseAccountEndpoint\":\"http://localhost:9090/\"}],\"readableLocations\":[{\"name\":\"West Europe\",\"databaseAccountEndpoint\":\"http://localhost:9090/\"}],\"userReplicationPolicy\":{\"asyncReplication\":false,\"minReplicaSetSize\":3,\"maxReplicasetSize\":4},\"userConsistencyPolicy\":{\"defaultConsistencyLevel\":\"Session\"},\"systemReplicationPolicy\":{\"minReplicaSetSize\":3,\"maxReplicasetSize\":4},\"readPolicy\":{\"primaryReadCoefficient\":1,\"secondaryReadCoefficient\":1},\"queryEngineConfiguration\":\"{\\\"maxSqlQueryInputLength\\\":30720,\\\"maxJoinsPerSqlQuery\\\":5,\\\"maxLogicalAndPerSqlQuery\\\":500,\\\"maxLogicalOrPerSqlQuery\\\":500,\\\"maxUdfRefPerSqlQuery\\\":2,\\\"maxInExpressionItemsCount\\\":8000,\\\"queryMaxInMemorySortDocumentCount\\\":500,\\\"maxQueryRequestTimeoutFraction\\\":0.9,\\\"sqlAllowNonFiniteNumbers\\\":false,\\\"sqlAllowAggregateFunctions\\\":true,\\\"sqlAllowSubQuery\\\":false,\\\"allowNewKeywords\\\":true,\\\"sqlAllowLike\\\":false,\\\"maxSpatialQueryCells\\\":12,\\\"spatialMaxGeometryPointCount\\\":256,\\\"sqlAllowTop\\\":true,\\\"enableSpatialIndexing\\\":true}\"}", + "BodyEncoding": { + "CodePage": 65001, + "EncodingName": "Unicode (UTF-8)", + "WebName": "utf-8" + }, + "UseTransformer": false, + "Headers": { + "x-ms-databaseaccount-reserved-mb": "0", + "x-ms-databaseaccount-consumed-mb": "0", + "Strict-Transport-Security": "max-age=31536000", + "x-ms-max-media-storage-usage-mb": "2048", + "x-ms-gatewayversion": "version=1.11.164.3", + "x-ms-media-storage-usage-mb": "0", + "x-ms-databaseaccount-provisioned-mb": "0", + "Content-Location": "http://localhost:9090/", + "Date": "Mon, 06 Mar 2017 10:56:40 GMT", + "Content-Type": "application/json", + "Server": "Microsoft-HTTPAPI/2.0" + } + } +} \ No newline at end of file