From bdd421e128171913882a14f142dfb905dada7bfd Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sun, 24 Jul 2022 15:54:53 +0200 Subject: [PATCH] JsonPartialMatcher - support Regex (#771) * JsonPartialMatcher - support Regex * . * . * more tests * . * . --- .../Admin/Mappings/MatcherModel.cs | 80 +- .../Matchers/Request/IRequestMatcher.cs | 27 +- .../Matchers/AbstractJsonPartialMatcher.cs | 29 +- src/WireMock.Net/Matchers/JsonMatcher.cs | 6 +- .../Matchers/JsonPartialMatcher.cs | 12 +- .../Matchers/JsonPartialWildCardMatcher.cs | 14 +- .../Request/RequestMessageHeaderMatcher.cs | 7 +- .../Request/RequestMessageParamMatcher.cs | 12 +- .../RegularExpressions/RegexExtended.cs | 147 ++-- src/WireMock.Net/RequestMessage.cs | 262 +++--- .../Serialization/MatcherMapper.cs | 16 +- .../Server/WireMockServer.Admin.cs | 2 +- .../Settings/WireMockServerSettings.cs | 2 +- src/WireMock.Net/Util/RegexUtils.cs | 57 +- .../Matchers/JsonPartialMatcherTests.cs | 77 +- .../JsonPartialWildcardMatcherTests.cs | 772 ++++++++--------- .../RequestMessageHeaderMatcherTests.cs | 259 +++--- .../WireMock.Net.Tests/RequestMessageTests.cs | 163 ++-- .../Serialization/MatcherMapperTests.cs | 789 +++++++++--------- .../Serialization/MatcherModelMapperTests.cs | 665 ++++++++------- 20 files changed, 1773 insertions(+), 1625 deletions(-) diff --git a/src/WireMock.Net.Abstractions/Admin/Mappings/MatcherModel.cs b/src/WireMock.Net.Abstractions/Admin/Mappings/MatcherModel.cs index 51e08357..9ef8604c 100644 --- a/src/WireMock.Net.Abstractions/Admin/Mappings/MatcherModel.cs +++ b/src/WireMock.Net.Abstractions/Admin/Mappings/MatcherModel.cs @@ -1,48 +1,52 @@ -namespace WireMock.Admin.Mappings +namespace WireMock.Admin.Mappings; + +/// +/// MatcherModel +/// +[FluentBuilder.AutoGenerateBuilder] +public class MatcherModel { /// - /// MatcherModel + /// Gets or sets the name. /// - [FluentBuilder.AutoGenerateBuilder] - public class MatcherModel - { - /// - /// Gets or sets the name. - /// - public string Name { get; set; } + public string Name { get; set; } = null!; - /// - /// Gets or sets the pattern. Can be a string (default) or an object. - /// - public object? Pattern { get; set; } + /// + /// Gets or sets the pattern. Can be a string (default) or an object. + /// + public object? Pattern { get; set; } - /// - /// Gets or sets the patterns. Can be array of strings (default) or an array of objects. - /// - public object[]? Patterns { get; set; } + /// + /// Gets or sets the patterns. Can be array of strings (default) or an array of objects. + /// + public object[]? Patterns { get; set; } - /// - /// Gets or sets the pattern as a file. - /// - public string? PatternAsFile { get; set; } + /// + /// Gets or sets the pattern as a file. + /// + public string? PatternAsFile { get; set; } - /// - /// Gets or sets the ignore case. - /// - public bool? IgnoreCase { get; set; } + /// + /// Gets or sets the ignore case. + /// + public bool? IgnoreCase { get; set; } - /// - /// Reject on match. - /// - public bool? RejectOnMatch { get; set; } + /// + /// Reject on match. + /// + public bool? RejectOnMatch { get; set; } - /// - /// The Operator to use when multiple patterns are defined. Optional. - /// - null = Same as "or". - /// - "or" = Only one pattern should match. - /// - "and" = All patterns should match. - /// - "average" = The average value from all patterns. - /// - public string? MatchOperator { get; set; } - } + /// + /// The Operator to use when multiple patterns are defined. Optional. + /// - null = Same as "or". + /// - "or" = Only one pattern should match. + /// - "and" = All patterns should match. + /// - "average" = The average value from all patterns. + /// + public string? MatchOperator { get; set; } + + /// + /// Support Regex, only used for JsonPartialMatcher. + /// + public bool? Regex { get; set; } } \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/Matchers/Request/IRequestMatcher.cs b/src/WireMock.Net.Abstractions/Matchers/Request/IRequestMatcher.cs index cc2e904b..476d3b24 100644 --- a/src/WireMock.Net.Abstractions/Matchers/Request/IRequestMatcher.cs +++ b/src/WireMock.Net.Abstractions/Matchers/Request/IRequestMatcher.cs @@ -1,20 +1,17 @@ -using JetBrains.Annotations; +namespace WireMock.Matchers.Request; -namespace WireMock.Matchers.Request +/// +/// The RequestMatcher interface. +/// +public interface IRequestMatcher { /// - /// The RequestMatcher interface. + /// Determines whether the specified RequestMessage is match. /// - public interface IRequestMatcher - { - /// - /// Determines whether the specified RequestMessage is match. - /// - /// The RequestMessage. - /// The RequestMatchResult. - /// - /// A value between 0.0 - 1.0 of the similarity. - /// - double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult); - } + /// The RequestMessage. + /// The RequestMatchResult. + /// + /// A value between 0.0 - 1.0 of the similarity. + /// + double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult); } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs b/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs index 2f3fb27a..f9c3c669 100644 --- a/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs +++ b/src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using Newtonsoft.Json.Linq; +using WireMock.Util; namespace WireMock.Matchers; @@ -9,15 +10,22 @@ namespace WireMock.Matchers; /// public abstract class AbstractJsonPartialMatcher : JsonMatcher { + /// + /// Support Regex + /// + public bool Regex { get; } + /// /// Initializes a new instance of the class. /// /// The string value to check for equality. /// Ignore the case from the PropertyName and PropertyValue (string only). /// Throw an exception when the internal matching fails because of invalid input. - protected AbstractJsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false) + /// Support Regex. + protected AbstractJsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false, bool regex = false) : base(value, ignoreCase, throwException) { + Regex = regex; } /// @@ -26,9 +34,11 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher /// The object value to check for equality. /// Ignore the case from the PropertyName and PropertyValue (string only). /// Throw an exception when the internal matching fails because of invalid input. - protected AbstractJsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false) + /// Support Regex. + protected AbstractJsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false, bool regex = false) : base(value, ignoreCase, throwException) { + Regex = regex; } /// @@ -38,9 +48,11 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher /// The value to check for equality. /// Ignore the case from the PropertyName and PropertyValue (string only). /// Throw an exception when the internal matching fails because of invalid input. - protected AbstractJsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false) + /// Support Regex. + protected AbstractJsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false, bool regex = false) : base(matchBehaviour, value, ignoreCase, throwException) { + Regex = regex; } /// @@ -51,6 +63,17 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher return true; } + if (Regex && value.Type == JTokenType.String && input != null) + { + var valueAsString = value.ToString(); + + var (valid, result) = RegexUtils.MatchRegex(valueAsString, input.ToString()); + if (valid) + { + return result; + } + } + if (input == null || value.Type != input.Type) { return false; diff --git a/src/WireMock.Net/Matchers/JsonMatcher.cs b/src/WireMock.Net/Matchers/JsonMatcher.cs index 12d5d43c..e445ad7f 100644 --- a/src/WireMock.Net/Matchers/JsonMatcher.cs +++ b/src/WireMock.Net/Matchers/JsonMatcher.cs @@ -13,12 +13,12 @@ namespace WireMock.Matchers; /// public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher { - /// - public object Value { get; } - /// public virtual string Name => "JsonMatcher"; + /// + public object Value { get; } + /// public MatchBehaviour MatchBehaviour { get; } diff --git a/src/WireMock.Net/Matchers/JsonPartialMatcher.cs b/src/WireMock.Net/Matchers/JsonPartialMatcher.cs index 9527e581..84fbbbf5 100644 --- a/src/WireMock.Net/Matchers/JsonPartialMatcher.cs +++ b/src/WireMock.Net/Matchers/JsonPartialMatcher.cs @@ -9,20 +9,20 @@ public class JsonPartialMatcher : AbstractJsonPartialMatcher public override string Name => nameof(JsonPartialMatcher); /// - public JsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false) - : base(value, ignoreCase, throwException) + public JsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false, bool regex = false) + : base(value, ignoreCase, throwException, regex) { } /// - public JsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false) - : base(value, ignoreCase, throwException) + public JsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false, bool regex = false) + : base(value, ignoreCase, throwException, regex) { } /// - public JsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false) - : base(matchBehaviour, value, ignoreCase, throwException) + public JsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false, bool regex = false) + : base(matchBehaviour, value, ignoreCase, throwException, regex) { } diff --git a/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs b/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs index bc0deb04..7ca88807 100644 --- a/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs +++ b/src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs @@ -1,5 +1,3 @@ -using JetBrains.Annotations; - namespace WireMock.Matchers; /// @@ -11,20 +9,20 @@ public class JsonPartialWildcardMatcher : AbstractJsonPartialMatcher public override string Name => nameof(JsonPartialWildcardMatcher); /// - public JsonPartialWildcardMatcher(string value, bool ignoreCase = false, bool throwException = false) - : base(value, ignoreCase, throwException) + public JsonPartialWildcardMatcher(string value, bool ignoreCase = false, bool throwException = false, bool regex = false) + : base(value, ignoreCase, throwException, regex) { } /// - public JsonPartialWildcardMatcher(object value, bool ignoreCase = false, bool throwException = false) - : base(value, ignoreCase, throwException) + public JsonPartialWildcardMatcher(object value, bool ignoreCase = false, bool throwException = false, bool regex = false) + : base(value, ignoreCase, throwException, regex) { } /// - public JsonPartialWildcardMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false) - : base(matchBehaviour, value, ignoreCase, throwException) + public JsonPartialWildcardMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false, bool regex = false) + : base(matchBehaviour, value, ignoreCase, throwException, regex) { } diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs index 67e4f3b8..f1f7095a 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs @@ -23,7 +23,7 @@ public class RequestMessageHeaderMatcher : IRequestMatcher /// /// The name /// - public string? Name { get; } + public string Name { get; } /// /// The matchers. @@ -94,6 +94,7 @@ public class RequestMessageHeaderMatcher : IRequestMatcher public RequestMessageHeaderMatcher(params Func, bool>[] funcs) { Funcs = Guard.NotNull(funcs); + Name = string.Empty; // Not used when Func, but set to a non-null valid value. } /// @@ -121,7 +122,7 @@ public class RequestMessageHeaderMatcher : IRequestMatcher if (Matchers != null) { - if (!headers.ContainsKey(Name!)) + if (!headers.ContainsKey(Name)) { return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch); } @@ -129,7 +130,7 @@ public class RequestMessageHeaderMatcher : IRequestMatcher var results = new List(); foreach (var matcher in Matchers) { - var resultsPerMatcher = headers[Name!].Select(v => matcher.IsMatch(v)).ToArray(); + var resultsPerMatcher = headers[Name].Select(v => matcher.IsMatch(v)).ToArray(); results.Add(MatchScores.ToScore(resultsPerMatcher, MatchOperator.And)); } diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs index e351995a..e15b4323 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs @@ -92,7 +92,7 @@ public class RequestMessageParamMatcher : IRequestMatcher return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query))); } - WireMockList valuesPresentInRequestMessage = ((RequestMessage)requestMessage).GetParameter(Key, IgnoreCase ?? false); + var valuesPresentInRequestMessage = ((RequestMessage)requestMessage).GetParameter(Key!, IgnoreCase ?? false); if (valuesPresentInRequestMessage == null) { // Key is not present at all, just return Mismatch @@ -102,7 +102,7 @@ public class RequestMessageParamMatcher : IRequestMatcher if (Matchers != null && Matchers.Any()) { // Return the score based on Matchers and valuesPresentInRequestMessage - return CalculateScore(valuesPresentInRequestMessage); + return CalculateScore(Matchers, valuesPresentInRequestMessage); } if (Matchers == null || !Matchers.Any()) @@ -114,14 +114,14 @@ public class RequestMessageParamMatcher : IRequestMatcher return MatchScores.Mismatch; } - private double CalculateScore(WireMockList valuesPresentInRequestMessage) + private double CalculateScore(IReadOnlyList matchers, WireMockList valuesPresentInRequestMessage) { var total = new List(); // If the total patterns in all matchers > values in message, use the matcher as base - if (Matchers.Sum(m => m.GetPatterns().Length) > valuesPresentInRequestMessage.Count) + if (matchers.Sum(m => m.GetPatterns().Length) > valuesPresentInRequestMessage.Count) { - foreach (var matcher in Matchers) + foreach (var matcher in matchers) { double score = 0d; foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage) @@ -136,7 +136,7 @@ public class RequestMessageParamMatcher : IRequestMatcher { foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage) { - double score = Matchers.Max(m => m.IsMatch(valuePresentInRequestMessage)); + double score = matchers.Max(m => m.IsMatch(valuePresentInRequestMessage)); total.Add(score); } } diff --git a/src/WireMock.Net/RegularExpressions/RegexExtended.cs b/src/WireMock.Net/RegularExpressions/RegexExtended.cs index 01d55054..e5971d56 100644 --- a/src/WireMock.Net/RegularExpressions/RegexExtended.cs +++ b/src/WireMock.Net/RegularExpressions/RegexExtended.cs @@ -3,88 +3,87 @@ using System.Collections.Generic; using System.Text.RegularExpressions; using Stef.Validation; -namespace WireMock.RegularExpressions +namespace WireMock.RegularExpressions; + +/// +/// Extension to the object, adding support for GUID tokens for matching on. +/// +#if !NETSTANDARD1_3 +[Serializable] +#endif +internal class RegexExtended : Regex { - /// - /// Extension to the object, adding support for GUID tokens for matching on. - /// -#if !NETSTANDARD1_3 - [Serializable] -#endif - internal class RegexExtended : Regex + /// + public RegexExtended(string pattern) : this(pattern, RegexOptions.None) { - /// - public RegexExtended(string pattern) : this(pattern, RegexOptions.None) - { - } + } - /// - public RegexExtended(string pattern, RegexOptions options) : - this(pattern, options, Regex.InfiniteMatchTimeout) - { - } + /// + public RegexExtended(string pattern, RegexOptions options) : + this(pattern, options, Regex.InfiniteMatchTimeout) + { + } - /// - public RegexExtended(string pattern, RegexOptions options, TimeSpan matchTimeout) : - base(ReplaceGuidPattern(pattern), options, matchTimeout) - { - } + /// + public RegexExtended(string pattern, RegexOptions options, TimeSpan matchTimeout) : + base(ReplaceGuidPattern(pattern), options, matchTimeout) + { + } #if !NETSTANDARD1_3 - /// - protected RegexExtended(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : - base(info, context) - { - } + /// + protected RegexExtended(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + base(info, context) + { + } #endif - // Dictionary of various Guid tokens with a corresponding regular expression pattern to use instead. - private static readonly Dictionary GuidTokenPatterns = new Dictionary + // Dictionary of various Guid tokens with a corresponding regular expression pattern to use instead. + private static readonly Dictionary GuidTokenPatterns = new() + { + // Lower case format `B` Guid pattern + { @"\guidb", @"(\{[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\})" }, + + // Upper case format `B` Guid pattern + { @"\GUIDB", @"(\{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\})" }, + + // Lower case format `D` Guid pattern + { @"\guidd", "([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12})" }, + + // Upper case format `D` Guid pattern + { @"\GUIDD", "([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12})" }, + + // Lower case format `N` Guid pattern + { @"\guidn", "([a-z0-9]{32})" }, + + // Upper case format `N` Guid pattern + { @"\GUIDN", "([A-Z0-9]{32})" }, + + // Lower case format `P` Guid pattern + { @"\guidp", @"(\([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\))" }, + + // Upper case format `P` Guid pattern + { @"\GUIDP", @"(\([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\))" }, + + // Lower case format `X` Guid pattern + { @"\guidx", @"(\{0x[a-f0-9]{8},0x[a-f0-9]{4},0x[a-f0-9]{4},\{(0x[a-f0-9]{2},){7}(0x[a-f0-9]{2})\}\})" }, + + // Upper case format `X` Guid pattern + { @"\GUIDX", @"(\{0x[A-F0-9]{8},0x[A-F0-9]{4},0x[A-F0-9]{4},\{(0x[A-F0-9]{2},){7}(0x[A-F0-9]{2})\}\})" }, + }; + + /// + /// Replaces all instances of valid GUID tokens with the correct regular expression to match. + /// + /// Pattern to replace token for. + private static string ReplaceGuidPattern(string pattern) + { + Guard.NotNull(pattern, nameof(pattern)); + + foreach (var tokenPattern in GuidTokenPatterns) { - // Lower case format `B` Guid pattern - { @"\guidb", @"(\{[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\})" }, - - // Upper case format `B` Guid pattern - { @"\GUIDB", @"(\{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\})" }, - - // Lower case format `D` Guid pattern - { @"\guidd", "([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12})" }, - - // Upper case format `D` Guid pattern - { @"\GUIDD", "([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12})" }, - - // Lower case format `N` Guid pattern - { @"\guidn", "([a-z0-9]{32})" }, - - // Upper case format `N` Guid pattern - { @"\GUIDN", "([A-Z0-9]{32})" }, - - // Lower case format `P` Guid pattern - { @"\guidp", @"(\([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\))" }, - - // Upper case format `P` Guid pattern - { @"\GUIDP", @"(\([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\))" }, - - // Lower case format `X` Guid pattern - { @"\guidx", @"(\{0x[a-f0-9]{8},0x[a-f0-9]{4},0x[a-f0-9]{4},\{(0x[a-f0-9]{2},){7}(0x[a-f0-9]{2})\}\})" }, - - // Upper case format `X` Guid pattern - { @"\GUIDX", @"(\{0x[A-F0-9]{8},0x[A-F0-9]{4},0x[A-F0-9]{4},\{(0x[A-F0-9]{2},){7}(0x[A-F0-9]{2})\}\})" }, - }; - - /// - /// Replaces all instances of valid GUID tokens with the correct regular expression to match. - /// - /// Pattern to replace token for. - private static string ReplaceGuidPattern(string pattern) - { - Guard.NotNull(pattern, nameof(pattern)); - - foreach (var tokenPattern in GuidTokenPatterns) - { - pattern = pattern.Replace(tokenPattern.Key, tokenPattern.Value); - } - - return pattern; + pattern = pattern.Replace(tokenPattern.Key, tokenPattern.Value); } + + return pattern; } } \ No newline at end of file diff --git a/src/WireMock.Net/RequestMessage.cs b/src/WireMock.Net/RequestMessage.cs index b2fba215..2470ee0f 100644 --- a/src/WireMock.Net/RequestMessage.cs +++ b/src/WireMock.Net/RequestMessage.cs @@ -1,159 +1,157 @@ // This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. // For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. -using JetBrains.Annotations; using System; using System.Collections.Generic; using System.Linq; using System.Net; +using Stef.Validation; using WireMock.Models; using WireMock.Types; using WireMock.Util; -using Stef.Validation; -namespace WireMock +namespace WireMock; + +/// +/// The RequestMessage. +/// +public class RequestMessage : IRequestMessage { + /// + public string ClientIP { get; } + + /// + public string Url { get; } + + /// + public string AbsoluteUrl { get; } + + /// + public string ProxyUrl { get; set; } + + /// + public DateTime DateTime { get; set; } + + /// + public string Path { get; } + + /// + public string AbsolutePath { get; } + + /// + public string[] PathSegments { get; } + + /// + public string[] AbsolutePathSegments { get; } + + /// + public string Method { get; } + + /// + public IDictionary>? Headers { get; } + + /// + public IDictionary? Cookies { get; } + + /// + public IDictionary>? Query { get; } + + /// + public string RawQuery { get; } + + /// + public IBodyData? BodyData { get; } + + /// + public string Body { get; } + + /// + public object BodyAsJson { get; } + + /// + public byte[] BodyAsBytes { get; } + + /// + public string DetectedBodyType { get; } + + /// + public string DetectedBodyTypeFromContentType { get; } + + /// + public string DetectedCompression { get; } + + /// + public string Host { get; } + + /// + public string Protocol { get; } + + /// + public int Port { get; } + + /// + public string Origin { get; } + /// - /// The RequestMessage. + /// Initializes a new instance of the class. /// - public class RequestMessage : IRequestMessage + /// The original url details. + /// The HTTP method. + /// The client IP Address. + /// The BodyData. + /// The headers. + /// The cookies. + public RequestMessage(UrlDetails urlDetails, string method, string clientIP, IBodyData? bodyData = null, IDictionary? headers = null, IDictionary? cookies = null) { - /// - public string ClientIP { get; } + Guard.NotNull(urlDetails, nameof(urlDetails)); + Guard.NotNull(method, nameof(method)); + Guard.NotNull(clientIP, nameof(clientIP)); - /// - public string Url { get; } + AbsoluteUrl = urlDetails.AbsoluteUrl.ToString(); + Url = urlDetails.Url.ToString(); + Protocol = urlDetails.Url.Scheme; + Host = urlDetails.Url.Host; + Port = urlDetails.Url.Port; + Origin = $"{Protocol}://{Host}:{Port}"; - /// - public string AbsoluteUrl { get; } + AbsolutePath = WebUtility.UrlDecode(urlDetails.AbsoluteUrl.AbsolutePath); + Path = WebUtility.UrlDecode(urlDetails.Url.AbsolutePath); + PathSegments = Path.Split('/').Skip(1).ToArray(); + AbsolutePathSegments = AbsolutePath.Split('/').Skip(1).ToArray(); - /// - public string ProxyUrl { get; set; } + Method = method; + ClientIP = clientIP; - /// - public DateTime DateTime { get; set; } + BodyData = bodyData; - /// - public string Path { get; } + // Convenience getters for e.g. Handlebars + Body = BodyData?.BodyAsString; + BodyAsJson = BodyData?.BodyAsJson; + BodyAsBytes = BodyData?.BodyAsBytes; + DetectedBodyType = BodyData?.DetectedBodyType.ToString(); + DetectedBodyTypeFromContentType = BodyData?.DetectedBodyTypeFromContentType.ToString(); + DetectedCompression = BodyData?.DetectedCompression; - /// - public string AbsolutePath { get; } + Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList(header.Value)); + Cookies = cookies; + RawQuery = urlDetails.Url.Query; + Query = QueryStringParser.Parse(RawQuery); + } - /// - public string[] PathSegments { get; } - - /// - public string[] AbsolutePathSegments { get; } - - /// - public string Method { get; } - - /// - public IDictionary>? Headers { get; } - - /// - public IDictionary? Cookies { get; } - - /// - public IDictionary>? Query { get; } - - /// - public string RawQuery { get; } - - /// - public IBodyData? BodyData { get; } - - /// - public string Body { get; } - - /// - public object BodyAsJson { get; } - - /// - public byte[] BodyAsBytes { get; } - - /// - public string DetectedBodyType { get; } - - /// - public string DetectedBodyTypeFromContentType { get; } - - /// - public string DetectedCompression { get; } - - /// - public string Host { get; } - - /// - public string Protocol { get; } - - /// - public int Port { get; } - - /// - public string Origin { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The original url details. - /// The HTTP method. - /// The client IP Address. - /// The BodyData. - /// The headers. - /// The cookies. - public RequestMessage(UrlDetails urlDetails, string method, string clientIP, IBodyData? bodyData = null, IDictionary? headers = null, IDictionary? cookies = null) + /// + /// Get a query parameter. + /// + /// The key. + /// Defines if the key should be matched using case-ignore. + /// The query parameter. + public WireMockList? GetParameter(string key, bool ignoreCase = false) + { + if (Query == null) { - Guard.NotNull(urlDetails, nameof(urlDetails)); - Guard.NotNull(method, nameof(method)); - Guard.NotNull(clientIP, nameof(clientIP)); - - AbsoluteUrl = urlDetails.AbsoluteUrl.ToString(); - Url = urlDetails.Url.ToString(); - Protocol = urlDetails.Url.Scheme; - Host = urlDetails.Url.Host; - Port = urlDetails.Url.Port; - Origin = $"{Protocol}://{Host}:{Port}"; - - AbsolutePath = WebUtility.UrlDecode(urlDetails.AbsoluteUrl.AbsolutePath); - Path = WebUtility.UrlDecode(urlDetails.Url.AbsolutePath); - PathSegments = Path.Split('/').Skip(1).ToArray(); - AbsolutePathSegments = AbsolutePath.Split('/').Skip(1).ToArray(); - - Method = method; - ClientIP = clientIP; - - BodyData = bodyData; - - // Convenience getters for e.g. Handlebars - Body = BodyData?.BodyAsString; - BodyAsJson = BodyData?.BodyAsJson; - BodyAsBytes = BodyData?.BodyAsBytes; - DetectedBodyType = BodyData?.DetectedBodyType.ToString(); - DetectedBodyTypeFromContentType = BodyData?.DetectedBodyTypeFromContentType.ToString(); - DetectedCompression = BodyData?.DetectedCompression; - - Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList(header.Value)); - Cookies = cookies; - RawQuery = urlDetails.Url.Query; - Query = QueryStringParser.Parse(RawQuery); + return null; } - /// - /// Get a query parameter. - /// - /// The key. - /// Defines if the key should be matched using case-ignore. - /// The query parameter. - public WireMockList? GetParameter(string? key, bool ignoreCase = false) - { - if (Query == null) - { - return null; - } + var query = !ignoreCase ? Query : new Dictionary>(Query, StringComparer.OrdinalIgnoreCase); - var query = !ignoreCase ? Query : new Dictionary>(Query, StringComparer.OrdinalIgnoreCase); - - return query.ContainsKey(key) ? query[key] : null; - } + return query.ContainsKey(key) ? query[key] : null; } } \ No newline at end of file diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index b4df5ea1..06ecbb77 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -47,6 +47,7 @@ internal class MatcherMapper bool ignoreCase = matcher.IgnoreCase == true; bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true; bool useRegexExtended = _settings.UseRegexExtended == true; + bool useRegex = matcher.Regex == true; switch (matcherName) { @@ -79,11 +80,11 @@ internal class MatcherMapper case nameof(JsonPartialMatcher): var valueForJsonPartialMatcher = matcher.Pattern ?? matcher.Patterns; - return new JsonPartialMatcher(matchBehaviour, valueForJsonPartialMatcher!, ignoreCase, throwExceptionWhenMatcherFails); + return new JsonPartialMatcher(matchBehaviour, valueForJsonPartialMatcher!, ignoreCase, throwExceptionWhenMatcherFails, useRegex); case nameof(JsonPartialWildcardMatcher): var valueForJsonPartialWildcardMatcher = matcher.Pattern ?? matcher.Patterns; - return new JsonPartialWildcardMatcher(matchBehaviour, valueForJsonPartialWildcardMatcher!, ignoreCase, throwExceptionWhenMatcherFails); + return new JsonPartialWildcardMatcher(matchBehaviour, valueForJsonPartialWildcardMatcher!, ignoreCase, throwExceptionWhenMatcherFails, useRegex); case nameof(JsonPathMatcher): return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns); @@ -146,6 +147,17 @@ internal class MatcherMapper Name = matcher.Name }; + switch (matcher) + { + case JsonPartialMatcher jsonPartialMatcher: + model.Regex = jsonPartialMatcher.Regex; + break; + + case JsonPartialWildcardMatcher jsonPartialWildcardMatcher: + model.Regex = jsonPartialWildcardMatcher.Regex; + break; + } + switch (matcher) { // If the matcher is a IStringMatcher, get the operator & patterns. diff --git a/src/WireMock.Net/Server/WireMockServer.Admin.cs b/src/WireMock.Net/Server/WireMockServer.Admin.cs index 3dc02fce..c98b3316 100644 --- a/src/WireMock.Net/Server/WireMockServer.Admin.cs +++ b/src/WireMock.Net/Server/WireMockServer.Admin.cs @@ -293,7 +293,7 @@ public partial class WireMockServer private IResponseMessage SettingsUpdate(IRequestMessage requestMessage) { - var settings = DeserializeObject(requestMessage); + var settings = DeserializeObject(requestMessage)!; // _settings _settings.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods; diff --git a/src/WireMock.Net/Settings/WireMockServerSettings.cs b/src/WireMock.Net/Settings/WireMockServerSettings.cs index 1c879870..1ad5bfea 100644 --- a/src/WireMock.Net/Settings/WireMockServerSettings.cs +++ b/src/WireMock.Net/Settings/WireMockServerSettings.cs @@ -9,9 +9,9 @@ using WireMock.Handlers; using WireMock.Logging; using WireMock.Matchers; using WireMock.RegularExpressions; -using WireMock.Types; #if USE_ASPNETCORE using Microsoft.Extensions.DependencyInjection; +using WireMock.Types; #endif namespace WireMock.Settings diff --git a/src/WireMock.Net/Util/RegexUtils.cs b/src/WireMock.Net/Util/RegexUtils.cs index bbd12fe8..ec819169 100644 --- a/src/WireMock.Net/Util/RegexUtils.cs +++ b/src/WireMock.Net/Util/RegexUtils.cs @@ -1,24 +1,53 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Text.RegularExpressions; +using WireMock.RegularExpressions; -namespace WireMock.Util +namespace WireMock.Util; + +internal static class RegexUtils { - internal static class RegexUtils + private static readonly TimeSpan RegexTimeOut = new(0, 0, 10); + + public static Dictionary GetNamedGroups(Regex regex, string input) { - public static Dictionary GetNamedGroups(Regex regex, string input) + var namedGroupsDictionary = new Dictionary(); + + GroupCollection groups = regex.Match(input).Groups; + foreach (string groupName in regex.GetGroupNames()) { - var namedGroupsDictionary = new Dictionary(); - - GroupCollection groups = regex.Match(input).Groups; - foreach (string groupName in regex.GetGroupNames()) + if (groups[groupName].Captures.Count > 0) { - if (groups[groupName].Captures.Count > 0) - { - namedGroupsDictionary.Add(groupName, groups[groupName].Value); - } + namedGroupsDictionary.Add(groupName, groups[groupName].Value); } + } - return namedGroupsDictionary; + return namedGroupsDictionary; + } + + public static (bool IsValid, bool Result) MatchRegex(string pattern, string input, bool useRegexExtended = true) + { + if (string.IsNullOrEmpty(pattern)) + { + return (false, false); + } + + try + { + if (useRegexExtended) + { + var r = new RegexExtended(pattern, RegexOptions.None, RegexTimeOut); + return (true, r.IsMatch(input)); + } + else + { + var r = new Regex(pattern, RegexOptions.None, RegexTimeOut); + return (true, r.IsMatch(input)); + } + } + catch + { + return (false, false); } } -} +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Matchers/JsonPartialMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JsonPartialMatcherTests.cs index 0e274035..02f20137 100644 --- a/test/WireMock.Net.Tests/Matchers/JsonPartialMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JsonPartialMatcherTests.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System; using System.IO; using FluentAssertions; using Newtonsoft.Json; @@ -42,6 +41,7 @@ namespace WireMock.Net.Tests.Matchers public void JsonPartialMatcher_WithInvalidStringValue_Should_ThrowException() { // Act + // ReSharper disable once ObjectCreationAsStatement Action action = () => new JsonPartialMatcher(MatchBehaviour.AcceptOnMatch, "{ \"Id\""); // Assert @@ -52,6 +52,7 @@ namespace WireMock.Net.Tests.Matchers public void JsonPartialMatcher_WithInvalidObjectValue_Should_ThrowException() { // Act + // ReSharper disable once ObjectCreationAsStatement Action action = () => new JsonPartialMatcher(MatchBehaviour.AcceptOnMatch, new MemoryStream()); // Assert @@ -102,7 +103,7 @@ namespace WireMock.Net.Tests.Matchers public void JsonPartialMatcher_IsMatch_NullString() { // Assign - string s = null; + string? s = null; var matcher = new JsonPartialMatcher(""); // Act @@ -116,7 +117,7 @@ namespace WireMock.Net.Tests.Matchers public void JsonPartialMatcher_IsMatch_NullObject() { // Assign - object o = null; + object? o = null; var matcher = new JsonPartialMatcher(""); // Act @@ -151,17 +152,53 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JsonPartialMatcher(new { Id = 1, Name = "Test" }); // Act - var jobject = new JObject + var jObject = new JObject { { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jobject); + double match = matcher.IsMatch(jObject); // Assert Assert.Equal(1.0, match); } + [Fact] + public void JsonPartialMatcher_IsMatch_WithRegexTrue() + { + // Assign + var matcher = new JsonPartialMatcher(new { Id = "^\\d+$", Name = "Test" }, false, false, true); + + // Act + var jObject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialMatcher_IsMatch_WithRegexFalse() + { + // Assign + var matcher = new JsonPartialMatcher(new { Id = "^\\d+$", Name = "Test" }); + + // Act + var jObject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(0.0, match); + } + [Fact] public void JsonPartialMatcher_IsMatch_WithIgnoreCaseTrue_JObject() { @@ -169,12 +206,12 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JsonPartialMatcher(new { id = 1, Name = "test" }, true); // Act - var jobject = new JObject + var jObject = new JObject { { "Id", new JValue(1) }, { "NaMe", new JValue("Test") } }; - double match = matcher.IsMatch(jobject); + double match = matcher.IsMatch(jObject); // Assert Assert.Equal(1.0, match); @@ -187,8 +224,8 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JsonPartialMatcher(new { Id = 1, Name = "Test" }); // Act - var jobject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jobject); + var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); + double match = matcher.IsMatch(jObject); // Assert Assert.Equal(1.0, match); @@ -201,8 +238,8 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JsonPartialMatcher(new { Id = 1, Name = "TESt" }, true); // Act - var jobject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jobject); + var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); + double match = matcher.IsMatch(jObject); // Assert Assert.Equal(1.0, match); @@ -233,12 +270,12 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JsonPartialMatcher("{ \"Id\" : 1, \"Name\" : \"Test\" }"); // Act - var jobject = new JObject + var jObject = new JObject { { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jobject); + double match = matcher.IsMatch(jObject); // Assert Assert.Equal(1.0, match); @@ -251,12 +288,12 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JsonPartialMatcher("{ \"Id\" : 1, \"Name\" : \"test\" }", true); // Act - var jobject = new JObject + var jObject = new JObject { { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jobject); + double match = matcher.IsMatch(jObject); // Assert Assert.Equal(1.0, match); @@ -269,12 +306,12 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JsonPartialMatcher(MatchBehaviour.RejectOnMatch, "{ \"Id\" : 1, \"Name\" : \"Test\" }"); // Act - var jobject = new JObject + var jObject = new JObject { { "Id", new JValue(1) }, { "Name", new JValue("Test") } }; - double match = matcher.IsMatch(jobject); + double match = matcher.IsMatch(jObject); // Assert Assert.Equal(0.0, match); @@ -287,11 +324,11 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JsonPartialMatcher("{ \"preferredAt\" : \"2019-11-21T10:32:53.2210009+00:00\" }"); // Act - var jobject = new JObject + var jObject = new JObject { { "preferredAt", new JValue("2019-11-21T10:32:53.2210009+00:00") } }; - double match = matcher.IsMatch(jobject); + double match = matcher.IsMatch(jObject); // Assert Assert.Equal(1.0, match); diff --git a/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs index 436b197e..e97a9013 100644 --- a/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JsonPartialWildcardMatcherTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using FluentAssertions; using Newtonsoft.Json; @@ -8,393 +7,394 @@ using NFluent; using WireMock.Matchers; using Xunit; -namespace WireMock.Net.Tests.Matchers +namespace WireMock.Net.Tests.Matchers; + +public class JsonPartialWildcardMatcherTests { - public class JsonPartialWildcardMatcherTests + [Fact] + public void JsonPartialWildcardMatcher_GetName() { - [Fact] - public void JsonPartialWildcardMatcher_GetName() - { - // Assign - var matcher = new JsonPartialWildcardMatcher("{}"); + // Assign + var matcher = new JsonPartialWildcardMatcher("{}"); - // Act - string name = matcher.Name; + // Act + string name = matcher.Name; - // Assert - Check.That(name).Equals("JsonPartialWildcardMatcher"); - } - - [Fact] - public void JsonPartialWildcardMatcher_GetValue() - { - // Assign - var matcher = new JsonPartialWildcardMatcher("{}"); - - // Act - object value = matcher.Value; - - // Assert - Check.That(value).Equals("{}"); - } - - [Fact] - public void JsonPartialWildcardMatcher_WithInvalidStringValue_Should_ThrowException() - { - // Act - Action action = () => new JsonPartialWildcardMatcher(MatchBehaviour.AcceptOnMatch, "{ \"Id\""); - - // Assert - action.Should().Throw(); - } - - [Fact] - public void JsonPartialWildcardMatcher_WithInvalidObjectValue_Should_ThrowException() - { - // Act - Action action = () => new JsonPartialWildcardMatcher(MatchBehaviour.AcceptOnMatch, new MemoryStream()); - - // Assert - action.Should().Throw(); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsFalse_Should_ReturnMismatch() - { - // Assign - var matcher = new JsonPartialWildcardMatcher(""); - - // Act - double match = matcher.IsMatch(new MemoryStream()); - - // Assert - Check.That(match).IsEqualTo(0); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsTrue_Should_ReturnMismatch() - { - // Assign - var matcher = new JsonPartialWildcardMatcher("", false, true); - - // Act - Action action = () => matcher.IsMatch(new MemoryStream()); - - // Assert - action.Should().Throw(); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_ByteArray() - { - // Assign - var bytes = new byte[0]; - var matcher = new JsonPartialWildcardMatcher(""); - - // Act - double match = matcher.IsMatch(bytes); - - // Assert - Check.That(match).IsEqualTo(0); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_NullString() - { - // Assign - string s = null; - var matcher = new JsonPartialWildcardMatcher(""); - - // Act - double match = matcher.IsMatch(s); - - // Assert - Check.That(match).IsEqualTo(0); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_NullObject() - { - // Assign - object o = null; - var matcher = new JsonPartialWildcardMatcher(""); - - // Act - double match = matcher.IsMatch(o); - - // Assert - Check.That(match).IsEqualTo(0); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_JArray() - { - // Assign - var matcher = new JsonPartialWildcardMatcher(new[] { "x", "y" }); - - // Act - var jArray = new JArray - { - "x", - "y" - }; - double match = matcher.IsMatch(jArray); - - // Assert - Assert.Equal(1.0, match); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_JObject() - { - // Assign - var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "Test" }); - - // Act - var jobject = new JObject - { - { "Id", new JValue(1) }, - { "Name", new JValue("Test") } - }; - double match = matcher.IsMatch(jobject); - - // Assert - Assert.Equal(1.0, match); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObject() - { - // Assign - var matcher = new JsonPartialWildcardMatcher(new { id = 1, Name = "test" }, true); - - // Act - var jobject = new JObject - { - { "Id", new JValue(1) }, - { "NaMe", new JValue("Test") } - }; - double match = matcher.IsMatch(jobject); - - // Assert - Assert.Equal(1.0, match); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_JObjectParsed() - { - // Assign - var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "Test" }); - - // Act - var jobject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jobject); - - // Assert - Assert.Equal(1.0, match); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObjectParsed() - { - // Assign - var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "TESt" }, true); - - // Act - var jobject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - double match = matcher.IsMatch(jobject); - - // Assert - Assert.Equal(1.0, match); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_JArrayAsString() - { - // Assign - var matcher = new JsonPartialWildcardMatcher("[ \"x\", \"y\" ]"); - - // Act - var jArray = new JArray - { - "x", - "y" - }; - double match = matcher.IsMatch(jArray); - - // Assert - Assert.Equal(1.0, match); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_JObjectAsString() - { - // Assign - var matcher = new JsonPartialWildcardMatcher("{ \"Id\" : 1, \"Name\" : \"Test\" }"); - - // Act - var jobject = new JObject - { - { "Id", new JValue(1) }, - { "Name", new JValue("Test") } - }; - double match = matcher.IsMatch(jobject); - - // Assert - Assert.Equal(1.0, match); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObjectAsString() - { - // Assign - var matcher = new JsonPartialWildcardMatcher("{ \"Id\" : 1, \"Name\" : \"test\" }", true); - - // Act - var jobject = new JObject - { - { "Id", new JValue(1) }, - { "Name", new JValue("Test") } - }; - double match = matcher.IsMatch(jobject); - - // Assert - Assert.Equal(1.0, match); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_JObjectAsString_RejectOnMatch() - { - // Assign - var matcher = new JsonPartialWildcardMatcher(MatchBehaviour.RejectOnMatch, "{ \"Id\" : 1, \"Name\" : \"Test\" }"); - - // Act - var jobject = new JObject - { - { "Id", new JValue(1) }, - { "Name", new JValue("Test") } - }; - double match = matcher.IsMatch(jobject); - - // Assert - Assert.Equal(0.0, match); - } - - [Fact] - public void JsonPartialWildcardMatcher_IsMatch_JObjectWithDateTimeOffsetAsString() - { - // Assign - var matcher = new JsonPartialWildcardMatcher("{ \"preferredAt\" : \"2019-11-21T10:32:53.2210009+00:00\" }"); - - // Act - var jobject = new JObject - { - { "preferredAt", new JValue("2019-11-21T10:32:53.2210009+00:00") } - }; - double match = matcher.IsMatch(jobject); - - // Assert - Assert.Equal(1.0, match); - } - - [Theory] - [InlineData("{\"test\":\"abc\"}", "{\"test\":\"abc\",\"other\":\"xyz\"}")] - [InlineData("\"test\"", "\"test\"")] - [InlineData("123", "123")] - [InlineData("[\"test\"]", "[\"test\"]")] - [InlineData("[\"test\"]", "[\"test\", \"other\"]")] - [InlineData("[123]", "[123]")] - [InlineData("[123]", "[123, 456]")] - [InlineData("{ \"test\":\"value\" }", "{\"test\":\"value\",\"other\":123}")] - [InlineData("{ \"test\":\"value\" }", "{\"test\":\"value\"}")] - [InlineData("{\"test\":{\"nested\":\"value\"}}", "{\"test\":{\"nested\":\"value\"}}")] - public void JsonPartialWildcardMatcher_IsMatch_StringInput_IsValidMatch(string value, string input) - { - // Assign - var matcher = new JsonPartialWildcardMatcher(value); - - // Act - double match = matcher.IsMatch(input); - - // Assert - Assert.Equal(1.0, match); - } - - [Theory] - [InlineData("{\"test\":\"*\"}", "{\"test\":\"xxx\",\"other\":\"xyz\"}")] - [InlineData("\"t*t\"", "\"test\"")] - public void JsonPartialWildcardMatcher_IsMatch_StringInputWithWildcard_IsValidMatch(string value, string input) - { - // Assign - var matcher = new JsonPartialWildcardMatcher(value); - - // Act - double match = matcher.IsMatch(input); - - // Assert - match.Should().Be(1.0); - } - - [Theory] - [InlineData("\"test\"", null)] - [InlineData("\"test1\"", "\"test2\"")] - [InlineData("123", "1234")] - [InlineData("[\"test\"]", "[\"test1\"]")] - [InlineData("[\"test\"]", "[\"test1\", \"test2\"]")] - [InlineData("[123]", "[1234]")] - [InlineData("{}", "\"test\"")] - [InlineData("{ \"test\":\"value\" }", "{\"test\":\"value2\"}")] - [InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value1\"}}")] - [InlineData("{\"test\":{\"test1\":\"value\"}}", "{\"test\":{\"test1\":\"value1\"}}")] - [InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value1\"}}]")] - public void JsonPartialWildcardMatcher_IsMatch_StringInputWithInvalidMatch(string value, string input) - { - // Assign - var matcher = new JsonPartialWildcardMatcher(value); - - // Act - double match = matcher.IsMatch(input); - - // Assert - Assert.Equal(0.0, match); - } - - [Theory] - [InlineData("{ \"test.nested\":123 }", "{\"test\":{\"nested\":123}}")] - [InlineData("{ \"test.nested\":[123, 456] }", "{\"test\":{\"nested\":[123, 456]}}")] - [InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value\"}}")] - [InlineData("{ \"['name.with.dot']\":\"value\" }", "{\"name.with.dot\":\"value\"}")] - [InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value\"}}]")] - [InlineData("[{ \"['name.with.dot']\":\"value\" }]", "[{\"name.with.dot\":\"value\"}]")] - public void JsonPartialWildcardMatcher_IsMatch_ValueAsJPathValidMatch(string value, string input) - { - // Assign - var matcher = new JsonPartialWildcardMatcher(value); - - // Act - double match = matcher.IsMatch(input); - - // Assert - Assert.Equal(1.0, match); - } - - [Theory] - [InlineData("{ \"test.nested\":123 }", "{\"test\":{\"nested\":456}}")] - [InlineData("{ \"test.nested\":[123, 456] }", "{\"test\":{\"nested\":[1, 2]}}")] - [InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value1\"}}")] - [InlineData("{ \"['name.with.dot']\":\"value\" }", "{\"name.with.dot\":\"value1\"}")] - [InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value1\"}}]")] - [InlineData("[{ \"['name.with.dot']\":\"value\" }]", "[{\"name.with.dot\":\"value1\"}]")] - public void JsonPartialWildcardMatcher_IsMatch_ValueAsJPathInvalidMatch(string value, string input) - { - // Assign - var matcher = new JsonPartialWildcardMatcher(value); - - // Act - double match = matcher.IsMatch(input); - - // Assert - Assert.Equal(0.0, match); - } + // Assert + Check.That(name).Equals("JsonPartialWildcardMatcher"); } -} + + [Fact] + public void JsonPartialWildcardMatcher_GetValue() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("{}"); + + // Act + object value = matcher.Value; + + // Assert + Check.That(value).Equals("{}"); + } + + [Fact] + public void JsonPartialWildcardMatcher_WithInvalidStringValue_Should_ThrowException() + { + // Act + // ReSharper disable once ObjectCreationAsStatement + Action action = () => new JsonPartialWildcardMatcher(MatchBehaviour.AcceptOnMatch, "{ \"Id\""); + + // Assert + action.Should().Throw(); + } + + [Fact] + public void JsonPartialWildcardMatcher_WithInvalidObjectValue_Should_ThrowException() + { + // Act + // ReSharper disable once ObjectCreationAsStatement + Action action = () => new JsonPartialWildcardMatcher(MatchBehaviour.AcceptOnMatch, new MemoryStream()); + + // Assert + action.Should().Throw(); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsFalse_Should_ReturnMismatch() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(""); + + // Act + double match = matcher.IsMatch(new MemoryStream()); + + // Assert + Check.That(match).IsEqualTo(0); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsTrue_Should_ReturnMismatch() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("", false, true); + + // Act + Action action = () => matcher.IsMatch(new MemoryStream()); + + // Assert + action.Should().Throw(); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_ByteArray() + { + // Assign + var bytes = new byte[0]; + var matcher = new JsonPartialWildcardMatcher(""); + + // Act + double match = matcher.IsMatch(bytes); + + // Assert + Check.That(match).IsEqualTo(0); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_NullString() + { + // Assign + string? s = null; + var matcher = new JsonPartialWildcardMatcher(""); + + // Act + double match = matcher.IsMatch(s); + + // Assert + Check.That(match).IsEqualTo(0); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_NullObject() + { + // Assign + object? o = null; + var matcher = new JsonPartialWildcardMatcher(""); + + // Act + double match = matcher.IsMatch(o); + + // Assert + Check.That(match).IsEqualTo(0); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JArray() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new[] { "x", "y" }); + + // Act + var jArray = new JArray + { + "x", + "y" + }; + double match = matcher.IsMatch(jArray); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObject() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "Test" }); + + // Act + var jObject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObject() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new { id = 1, Name = "test" }, true); + + // Act + var jObject = new JObject + { + { "Id", new JValue(1) }, + { "NaMe", new JValue("Test") } + }; + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObjectParsed() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "Test" }); + + // Act + var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObjectParsed() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "TESt" }, true); + + // Act + var jObject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }"); + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JArrayAsString() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("[ \"x\", \"y\" ]"); + + // Act + var jArray = new JArray + { + "x", + "y" + }; + double match = matcher.IsMatch(jArray); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObjectAsString() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("{ \"Id\" : 1, \"Name\" : \"Test\" }"); + + // Act + var jObject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObjectAsString() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("{ \"Id\" : 1, \"Name\" : \"test\" }", true); + + // Act + var jObject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(1.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObjectAsString_RejectOnMatch() + { + // Assign + var matcher = new JsonPartialWildcardMatcher(MatchBehaviour.RejectOnMatch, "{ \"Id\" : 1, \"Name\" : \"Test\" }"); + + // Act + var jObject = new JObject + { + { "Id", new JValue(1) }, + { "Name", new JValue("Test") } + }; + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(0.0, match); + } + + [Fact] + public void JsonPartialWildcardMatcher_IsMatch_JObjectWithDateTimeOffsetAsString() + { + // Assign + var matcher = new JsonPartialWildcardMatcher("{ \"preferredAt\" : \"2019-11-21T10:32:53.2210009+00:00\" }"); + + // Act + var jObject = new JObject + { + { "preferredAt", new JValue("2019-11-21T10:32:53.2210009+00:00") } + }; + double match = matcher.IsMatch(jObject); + + // Assert + Assert.Equal(1.0, match); + } + + [Theory] + [InlineData("{\"test\":\"abc\"}", "{\"test\":\"abc\",\"other\":\"xyz\"}")] + [InlineData("\"test\"", "\"test\"")] + [InlineData("123", "123")] + [InlineData("[\"test\"]", "[\"test\"]")] + [InlineData("[\"test\"]", "[\"test\", \"other\"]")] + [InlineData("[123]", "[123]")] + [InlineData("[123]", "[123, 456]")] + [InlineData("{ \"test\":\"value\" }", "{\"test\":\"value\",\"other\":123}")] + [InlineData("{ \"test\":\"value\" }", "{\"test\":\"value\"}")] + [InlineData("{\"test\":{\"nested\":\"value\"}}", "{\"test\":{\"nested\":\"value\"}}")] + public void JsonPartialWildcardMatcher_IsMatch_StringInput_IsValidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + Assert.Equal(1.0, match); + } + + [Theory] + [InlineData("{\"test\":\"*\"}", "{\"test\":\"xxx\",\"other\":\"xyz\"}")] + [InlineData("\"t*t\"", "\"test\"")] + public void JsonPartialWildcardMatcher_IsMatch_StringInputWithWildcard_IsValidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + match.Should().Be(1.0); + } + + [Theory] + [InlineData("\"test\"", null)] + [InlineData("\"test1\"", "\"test2\"")] + [InlineData("123", "1234")] + [InlineData("[\"test\"]", "[\"test1\"]")] + [InlineData("[\"test\"]", "[\"test1\", \"test2\"]")] + [InlineData("[123]", "[1234]")] + [InlineData("{}", "\"test\"")] + [InlineData("{ \"test\":\"value\" }", "{\"test\":\"value2\"}")] + [InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value1\"}}")] + [InlineData("{\"test\":{\"test1\":\"value\"}}", "{\"test\":{\"test1\":\"value1\"}}")] + [InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value1\"}}]")] + public void JsonPartialWildcardMatcher_IsMatch_StringInputWithInvalidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + Assert.Equal(0.0, match); + } + + [Theory] + [InlineData("{ \"test.nested\":123 }", "{\"test\":{\"nested\":123}}")] + [InlineData("{ \"test.nested\":[123, 456] }", "{\"test\":{\"nested\":[123, 456]}}")] + [InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value\"}}")] + [InlineData("{ \"['name.with.dot']\":\"value\" }", "{\"name.with.dot\":\"value\"}")] + [InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value\"}}]")] + [InlineData("[{ \"['name.with.dot']\":\"value\" }]", "[{\"name.with.dot\":\"value\"}]")] + public void JsonPartialWildcardMatcher_IsMatch_ValueAsJPathValidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + Assert.Equal(1.0, match); + } + + [Theory] + [InlineData("{ \"test.nested\":123 }", "{\"test\":{\"nested\":456}}")] + [InlineData("{ \"test.nested\":[123, 456] }", "{\"test\":{\"nested\":[1, 2]}}")] + [InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value1\"}}")] + [InlineData("{ \"['name.with.dot']\":\"value\" }", "{\"name.with.dot\":\"value1\"}")] + [InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value1\"}}]")] + [InlineData("[{ \"['name.with.dot']\":\"value\" }]", "[{\"name.with.dot\":\"value1\"}]")] + public void JsonPartialWildcardMatcher_IsMatch_ValueAsJPathInvalidMatch(string value, string input) + { + // Assign + var matcher = new JsonPartialWildcardMatcher(value); + + // Act + double match = matcher.IsMatch(input); + + // Assert + Assert.Equal(0.0, match); + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageHeaderMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageHeaderMatcherTests.cs index 01ea5717..988fd343 100644 --- a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageHeaderMatcherTests.cs +++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageHeaderMatcherTests.cs @@ -5,165 +5,164 @@ using WireMock.Matchers.Request; using WireMock.Models; using Xunit; -namespace WireMock.Net.Tests.RequestMatchers +namespace WireMock.Net.Tests.RequestMatchers; + +public class RequestMessageHeaderMatcherTests { - public class RequestMessageHeaderMatcherTests + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_AcceptOnMatch_HeaderDoesNotExists() { - [Fact] - public void RequestMessageHeaderMatcher_GetMatchingScore_AcceptOnMatch_HeaderDoesNotExists() - { - // Assign - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1"); - var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "h", "x", true); + // Assign + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1"); + var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "h", "x", true); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(0.0d); - } + // Assert + Check.That(score).IsEqualTo(0.0d); + } - [Fact] - public void RequestMessageHeaderMatcher_GetMatchingScore_RejectOnMatch_HeaderDoesNotExists() - { - // Assign - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1"); - var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.RejectOnMatch, "h", "x", true); + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_RejectOnMatch_HeaderDoesNotExists() + { + // Assign + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1"); + var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.RejectOnMatch, "h", "x", true); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(1.0d); - } + // Assert + Check.That(score).IsEqualTo(1.0d); + } - [Fact] - public void RequestMessageHeaderMatcher_GetMatchingScore_AcceptOnMatch_HeaderDoesNotMatchPattern() - { - // Assign - var headers = new Dictionary { { "h", new[] { "x" } } }; - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); - var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "no-match", "123", true); + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_AcceptOnMatch_HeaderDoesNotMatchPattern() + { + // Assign + var headers = new Dictionary { { "h", new[] { "x" } } }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "no-match", "123", true); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(0.0d); - } - [Fact] - public void RequestMessageHeaderMatcher_GetMatchingScore_RejectOnMatch_HeaderDoesNotMatchPattern() - { - // Assign - var headers = new Dictionary { { "h", new[] { "x" } } }; - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); - var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.RejectOnMatch, "no-match", "123", true); + // Assert + Check.That(score).IsEqualTo(0.0d); + } + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_RejectOnMatch_HeaderDoesNotMatchPattern() + { + // Assign + var headers = new Dictionary { { "h", new[] { "x" } } }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.RejectOnMatch, "no-match", "123", true); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(1.0d); - } + // Assert + Check.That(score).IsEqualTo(1.0d); + } - [Fact] - public void RequestMessageHeaderMatcher_GetMatchingScore_AcceptOnMatch() - { - // Assign - var headers = new Dictionary { { "h", new[] { "x" } } }; - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); - var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "h", "x", true); + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_AcceptOnMatch() + { + // Assign + var headers = new Dictionary { { "h", new[] { "x" } } }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "h", "x", true); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(1.0d); - } + // Assert + Check.That(score).IsEqualTo(1.0d); + } - [Fact(Skip = "does not work anymore since 'and'/'or'/'average'")] - public void RequestMessageHeaderMatcher_GetMatchingScore_RejectOnMatch() - { - // Assign - var headers = new Dictionary { { "h", new[] { "x" } } }; - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); - var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.RejectOnMatch, "h", "x", true); + [Fact(Skip = "does not work anymore since 'and'/'or'/'average'")] + public void RequestMessageHeaderMatcher_GetMatchingScore_RejectOnMatch() + { + // Assign + var headers = new Dictionary { { "h", new[] { "x" } } }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.RejectOnMatch, "h", "x", true); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(0.0d); - } + // Assert + Check.That(score).IsEqualTo(0.0d); + } - [Fact] - public void RequestMessageHeaderMatcher_GetMatchingScore_IStringMatcher_Match() - { - // Assign - var headers = new Dictionary { { "h", new[] { "x" } } }; - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); - var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, "h", false, new ExactMatcher("x")); + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_IStringMatcher_Match() + { + // Assign + var headers = new Dictionary { { "h", new[] { "x" } } }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, "h", false, new ExactMatcher("x")); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(1.0d); - } + // Assert + Check.That(score).IsEqualTo(1.0d); + } - [Fact] - public void RequestMessageHeaderMatcher_GetMatchingScore_Func_Match() - { - // Assign - var headers = new Dictionary { { "h", new[] { "x" } } }; - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); - var matcher = new RequestMessageHeaderMatcher(x => x.ContainsKey("h")); + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_Func_Match() + { + // Assign + var headers = new Dictionary { { "h", new[] { "x" } } }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher(x => x.ContainsKey("h")); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(1.0d); - } + // Assert + Check.That(score).IsEqualTo(1.0d); + } - [Fact] - public void RequestMessageHeaderMatcher_GetMatchingScore_CaseIgnoreForHeaderValue() - { - // Assign - var headers = new Dictionary { { "h", new[] { "teST" } } }; - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); - var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "h", "test", true); + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_CaseIgnoreForHeaderValue() + { + // Assign + var headers = new Dictionary { { "h", new[] { "teST" } } }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "h", "test", true); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(1.0d); - } + // Assert + Check.That(score).IsEqualTo(1.0d); + } - [Fact] - public void RequestMessageHeaderMatcher_GetMatchingScore_CaseIgnoreForHeaderName() - { - // Assign - var headers = new Dictionary { { "teST", new[] { "x" } } }; - var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); - var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "TEST", "x", true); + [Fact] + public void RequestMessageHeaderMatcher_GetMatchingScore_CaseIgnoreForHeaderName() + { + // Assign + var headers = new Dictionary { { "teST", new[] { "x" } } }; + var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); + var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "TEST", "x", true); - // Act - var result = new RequestMatchResult(); - double score = matcher.GetMatchingScore(requestMessage, result); + // Act + var result = new RequestMatchResult(); + double score = matcher.GetMatchingScore(requestMessage, result); - // Assert - Check.That(score).IsEqualTo(1.0d); - } + // Assert + Check.That(score).IsEqualTo(1.0d); } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestMessageTests.cs b/test/WireMock.Net.Tests/RequestMessageTests.cs index 69aee696..719454f8 100644 --- a/test/WireMock.Net.Tests/RequestMessageTests.cs +++ b/test/WireMock.Net.Tests/RequestMessageTests.cs @@ -1,107 +1,106 @@ -using NFluent; +using NFluent; using WireMock.Models; using WireMock.Util; using Xunit; -namespace WireMock.Net.Tests +namespace WireMock.Net.Tests; + +public class RequestMessageTests { - public class RequestMessageTests + private const string ClientIp = "::1"; + + [Fact] + public void RequestMessage_Method_Should_BeSame() { - private const string ClientIp = "::1"; + // given + var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "posT", ClientIp); - [Fact] - public void RequestMessage_Method_Should_BeSame() - { - // given - var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "posT", ClientIp); + // then + Check.That(request.Method).IsEqualTo("posT"); + } - // then - Check.That(request.Method).IsEqualTo("posT"); - } + [Fact] + public void RequestMessage_ParseQuery_NoKeys() + { + // given + var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp); - [Fact] - public void RequestMessage_ParseQuery_NoKeys() - { - // given - var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp); + // then + Check.That(request.GetParameter("not_there")).IsNull(); + } - // then - Check.That(request.GetParameter("not_there")).IsNull(); - } + [Fact] + public void RequestMessage_ParseQuery_SingleKey_SingleValue() + { + // Assign + var request = new RequestMessage(new UrlDetails("http://localhost?foo=bar"), "POST", ClientIp); - [Fact] - public void RequestMessage_ParseQuery_SingleKey_SingleValue() - { - // Assign - var request = new RequestMessage(new UrlDetails("http://localhost?foo=bar"), "POST", ClientIp); + // Assert + Check.That(request.GetParameter("foo")).ContainsExactly("bar"); + } - // Assert - Check.That(request.GetParameter("foo")).ContainsExactly("bar"); - } + [Fact] + public void RequestMessage_ParseQuery_SingleKey_SingleValue_WithIgnoreCase() + { + // Assign + var request = new RequestMessage(new UrlDetails("http://localhost?foo=bar"), "POST", ClientIp); - [Fact] - public void RequestMessage_ParseQuery_SingleKey_SingleValue_WithIgnoreCase() - { - // Assign - var request = new RequestMessage(new UrlDetails("http://localhost?foo=bar"), "POST", ClientIp); + // Assert + Check.That(request.GetParameter("FoO", true)).ContainsExactly("bar"); + } - // Assert - Check.That(request.GetParameter("FoO", true)).ContainsExactly("bar"); - } + [Fact] + public void RequestMessage_ParseQuery_MultipleKeys_MultipleValues() + { + // Assign + var request = new RequestMessage(new UrlDetails("http://localhost?key=1&key=2"), "POST", ClientIp); - [Fact] - public void RequestMessage_ParseQuery_MultipleKeys_MultipleValues() - { - // Assign - var request = new RequestMessage(new UrlDetails("http://localhost?key=1&key=2"), "POST", ClientIp); + // Assert + Check.That(request.GetParameter("key")).Contains("1"); + Check.That(request.GetParameter("key")).Contains("2"); + } - // Assert - Check.That(request.GetParameter("key")).Contains("1"); - Check.That(request.GetParameter("key")).Contains("2"); - } + [Fact] + public void RequestMessage_ParseQuery_SingleKey_MultipleValuesCommaSeparated() + { + // Assign + var request = new RequestMessage(new UrlDetails("http://localhost?key=1,2,3"), "POST", ClientIp); - [Fact] - public void RequestMessage_ParseQuery_SingleKey_MultipleValuesCommaSeparated() - { - // Assign - var request = new RequestMessage(new UrlDetails("http://localhost?key=1,2,3"), "POST", ClientIp); + // Assert + Check.That(request.GetParameter("key")).Contains("1"); + Check.That(request.GetParameter("key")).Contains("2"); + Check.That(request.GetParameter("key")).Contains("3"); + } - // Assert - Check.That(request.GetParameter("key")).Contains("1"); - Check.That(request.GetParameter("key")).Contains("2"); - Check.That(request.GetParameter("key")).Contains("3"); - } + [Fact] + public void RequestMessage_ParseQuery_SingleKey_MultipleValues() + { + // Assign + var request = new RequestMessage(new UrlDetails("http://localhost?key=1,2&foo=bar&key=3"), "POST", ClientIp); - [Fact] - public void RequestMessage_ParseQuery_SingleKey_MultipleValues() - { - // Assign - var request = new RequestMessage(new UrlDetails("http://localhost?key=1,2&foo=bar&key=3"), "POST", ClientIp); + // Assert + Check.That(request.GetParameter("key")).Contains("1"); + Check.That(request.GetParameter("key")).Contains("2"); + Check.That(request.GetParameter("key")).Contains("3"); + } - // Assert - Check.That(request.GetParameter("key")).Contains("1"); - Check.That(request.GetParameter("key")).Contains("2"); - Check.That(request.GetParameter("key")).Contains("3"); - } + [Fact] + public void RequestMessage_Constructor1_PathSegments() + { + // Assign + var request = new RequestMessage(new UrlDetails("http://localhost/a/b/c"), "POST", ClientIp); - [Fact] - public void RequestMessage_Constructor1_PathSegments() - { - // Assign - var request = new RequestMessage(new UrlDetails("http://localhost/a/b/c"), "POST", ClientIp); + // Assert + Check.That(request.PathSegments).ContainsExactly("a", "b", "c"); + } - // Assert - Check.That(request.PathSegments).ContainsExactly("a", "b", "c"); - } + [Fact] + public void RequestMessage_Constructor2_PathSegments() + { + // Assign + var request = new RequestMessage(new UrlDetails("http://localhost/a/b/c"), "POST", ClientIp, new BodyData()); - [Fact] - public void RequestMessage_Constructor2_PathSegments() - { - // Assign - var request = new RequestMessage(new UrlDetails("http://localhost/a/b/c"), "POST", ClientIp, new BodyData()); - - // Assert - Check.That(request.PathSegments).ContainsExactly("a", "b", "c"); - } + // Assert + Check.That(request.PathSegments).ContainsExactly("a", "b", "c"); } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs index 69f87a6e..d2853f23 100644 --- a/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs +++ b/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs @@ -10,399 +10,402 @@ using WireMock.Serialization; using WireMock.Settings; using Xunit; -namespace WireMock.Net.Tests.Serialization +namespace WireMock.Net.Tests.Serialization; + +public class MatcherMapperTests { - public class MatcherMapperTests + private readonly WireMockServerSettings _settings = new(); + private readonly MatcherMapper _sut; + + public MatcherMapperTests() { - private readonly WireMockServerSettings _settings = new WireMockServerSettings(); - private readonly MatcherMapper _sut; - - public MatcherMapperTests() - { - _sut = new MatcherMapper(_settings); - } - - [Fact] - public void MatcherMapper_Map_IMatcher_Null() - { - // Act - var model = _sut.Map((IMatcher)null); - - // Assert - model.Should().BeNull(); - } - - [Fact] - public void MatcherMapper_Map_IMatchers_Null() - { - // Act - var model = _sut.Map((IMatcher[])null); - - // Assert - model.Should().BeNull(); - } - - [Fact] - public void MatcherMapper_Map_IMatchers() - { - // Assign - var matcherMock1 = new Mock(); - var matcherMock2 = new Mock(); - - // Act - var models = _sut.Map(new[] { matcherMock1.Object, matcherMock2.Object }); - - // Assert - models.Should().HaveCount(2); - } - - [Fact] - public void MatcherMapper_Map_IStringMatcher() - { - // Assign - var matcherMock = new Mock(); - matcherMock.Setup(m => m.Name).Returns("test"); - matcherMock.Setup(m => m.GetPatterns()).Returns(new AnyOf[] { "p1", "p2" }); - - // Act - var model = _sut.Map(matcherMock.Object); - - // Assert - model.IgnoreCase.Should().BeNull(); - model.Name.Should().Be("test"); - model.Pattern.Should().BeNull(); - model.Patterns.Should().HaveCount(2) - .And.Contain("p1") - .And.Contain("p2"); - } - - [Fact] - public void MatcherMapper_Map_IStringMatcher_With_PatternAsFile() - { - // Arrange - var pattern = new StringPattern { Pattern = "p", PatternAsFile = "pf" }; - - var matcherMock = new Mock(); - matcherMock.Setup(m => m.Name).Returns("test"); - matcherMock.Setup(m => m.GetPatterns()).Returns(new AnyOf[] { pattern }); - - // Act - var model = _sut.Map(matcherMock.Object); - - // Assert - model.IgnoreCase.Should().BeNull(); - model.Name.Should().Be("test"); - model.Pattern.Should().Be("p"); - model.Patterns.Should().BeNull(); - model.PatternAsFile.Should().Be("pf"); - } - - [Fact] - public void MatcherMapper_Map_IIgnoreCaseMatcher() - { - // Assign - var matcherMock = new Mock(); - matcherMock.Setup(m => m.IgnoreCase).Returns(true); - - // Act - var model = _sut.Map(matcherMock.Object); - - // Assert - model.IgnoreCase.Should().BeTrue(); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_Null() - { - // Act - var result = _sut.Map((MatcherModel)null); - - // Assert - result.Should().BeNull(); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_Exception() - { - // Assign - var model = new MatcherModel { Name = "test" }; - - // Act and Assert - Check.ThatCode(() => _sut.Map(model)).Throws(); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_LinqMatcher_Pattern() - { - // Assign - var model = new MatcherModel - { - Name = "LinqMatcher", - Pattern = "p" - }; - - // Act - var matcher = (LinqMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.GetPatterns().Should().Contain("p"); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_LinqMatcher_Patterns() - { - // Assign - var model = new MatcherModel - { - Name = "LinqMatcher", - Patterns = new[] { "p1", "p2" } - }; - - // Act - var matcher = (LinqMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.GetPatterns().Should().Contain("p1", "p2"); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonMatcher_Pattern_As_String() - { - // Assign - var pattern = "{ \"AccountIds\": [ 1, 2, 3 ] }"; - var model = new MatcherModel - { - Name = "JsonMatcher", - Pattern = pattern - }; - - // Act - var matcher = (JsonMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(pattern); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonMatcher_Patterns_1_Value_As_String() - { - // Assign - var pattern = "{ \"post1\": \"value1\", \"post2\": \"value2\" }"; - var patterns = new[] { pattern }; - var model = new MatcherModel - { - Name = "JsonMatcher", - Patterns = patterns - }; - - // Act - var matcher = (JsonMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(patterns); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonMatcher_Patterns_2_Values_As_String() - { - // Assign - var pattern1 = "{ \"AccountIds\": [ 1, 2, 3 ] }"; - var pattern2 = "{ \"post1\": \"value1\", \"post2\": \"value2\" }"; - var patterns = new[] { pattern1, pattern2 }; - var model = new MatcherModel - { - Name = "JsonMatcher", - Patterns = patterns - }; - - // Act - var matcher = (JsonMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(patterns); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonMatcher_Pattern_As_Object() - { - // Assign - var pattern = new { AccountIds = new[] { 1, 2, 3 } }; - var model = new MatcherModel - { - Name = "JsonMatcher", - Pattern = pattern - }; - - // Act - var matcher = (JsonMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(pattern); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonMatcher_Patterns_1_Value_As_Object() - { - // Assign - object pattern = new { post1 = "value1", post2 = "value2" }; - var patterns = new[] { pattern }; - var model = new MatcherModel - { - Name = "JsonMatcher", - Patterns = patterns - }; - - // Act - var matcher = (JsonMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(patterns); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonMatcher_Patterns_2_Values_As_Object() - { - // Assign - object pattern1 = new { AccountIds = new[] { 1, 2, 3 } }; - object pattern2 = new { post1 = "value1", post2 = "value2" }; - var patterns = new[] { pattern1, pattern2 }; - var model = new MatcherModel - { - Name = "JsonMatcher", - Patterns = patterns - }; - - // Act - var matcher = (JsonMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(patterns); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_Pattern_As_String() - { - // Assign - var pattern = "{ \"AccountIds\": [ 1, 2, 3 ] }"; - var model = new MatcherModel - { - Name = "JsonPartialMatcher", - Pattern = pattern - }; - - // Act - var matcher = (JsonPartialMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(pattern); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_Patterns_As_String() - { - // Assign - var pattern1 = "{ \"AccountIds\": [ 1, 2, 3 ] }"; - var pattern2 = "{ \"X\": \"x\" }"; - var patterns = new[] { pattern1, pattern2 }; - var model = new MatcherModel - { - Name = "JsonPartialMatcher", - Pattern = patterns - }; - - // Act - var matcher = (JsonPartialMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(patterns); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_Pattern_As_Object() - { - // Assign - var pattern = new { AccountIds = new[] { 1, 2, 3 } }; - var model = new MatcherModel - { - Name = "JsonPartialMatcher", - Pattern = pattern - }; - - // Act - var matcher = (JsonPartialMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(pattern); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_Patterns_As_Object() - { - // Assign - object pattern1 = new { AccountIds = new[] { 1, 2, 3 } }; - object pattern2 = new { X = "x" }; - var patterns = new[] { pattern1, pattern2 }; - var model = new MatcherModel - { - Name = "JsonPartialMatcher", - Patterns = patterns - }; - - // Act - var matcher = (JsonMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(patterns); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_StringPattern_With_PatternAsFile() - { - // Assign - var pattern = new StringPattern { Pattern = "{ \"AccountIds\": [ 1, 2, 3 ] }", PatternAsFile = "pf" }; - var model = new MatcherModel - { - Name = "JsonPartialMatcher", - Pattern = pattern - }; - - // Act - var matcher = (JsonPartialMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(pattern); - } - - [Fact] - public void MatcherMapper_Map_MatcherModel_JsonPartialWilcardMatcher_Patterns_As_Object() - { - // Assign - object pattern = new { X = "*" }; - var model = new MatcherModel - { - Name = "JsonPartialWildcardMatcher", - Pattern = pattern - }; - - // Act - var matcher = (JsonPartialWildcardMatcher)_sut.Map(model); - - // Assert - matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); - matcher.Value.Should().BeEquivalentTo(pattern); - } + _sut = new MatcherMapper(_settings); } -} + + [Fact] + public void MatcherMapper_Map_IMatcher_Null() + { + // Act + var model = _sut.Map((IMatcher?)null); + + // Assert + model.Should().BeNull(); + } + + [Fact] + public void MatcherMapper_Map_IMatchers_Null() + { + // Act + var model = _sut.Map((IMatcher[]?)null); + + // Assert + model.Should().BeNull(); + } + + [Fact] + public void MatcherMapper_Map_IMatchers() + { + // Assign + var matcherMock1 = new Mock(); + var matcherMock2 = new Mock(); + + // Act + var models = _sut.Map(new[] { matcherMock1.Object, matcherMock2.Object }); + + // Assert + models.Should().HaveCount(2); + } + + [Fact] + public void MatcherMapper_Map_IStringMatcher() + { + // Assign + var matcherMock = new Mock(); + matcherMock.Setup(m => m.Name).Returns("test"); + matcherMock.Setup(m => m.GetPatterns()).Returns(new AnyOf[] { "p1", "p2" }); + + // Act + var model = _sut.Map(matcherMock.Object)!; + + // Assert + model.IgnoreCase.Should().BeNull(); + model.Name.Should().Be("test"); + model.Pattern.Should().BeNull(); + model.Patterns.Should().HaveCount(2) + .And.Contain("p1") + .And.Contain("p2"); + } + + [Fact] + public void MatcherMapper_Map_IStringMatcher_With_PatternAsFile() + { + // Arrange + var pattern = new StringPattern { Pattern = "p", PatternAsFile = "pf" }; + + var matcherMock = new Mock(); + matcherMock.Setup(m => m.Name).Returns("test"); + matcherMock.Setup(m => m.GetPatterns()).Returns(new AnyOf[] { pattern }); + + // Act + var model = _sut.Map(matcherMock.Object)!; + + // Assert + model.IgnoreCase.Should().BeNull(); + model.Name.Should().Be("test"); + model.Pattern.Should().Be("p"); + model.Patterns.Should().BeNull(); + model.PatternAsFile.Should().Be("pf"); + } + + [Fact] + public void MatcherMapper_Map_IIgnoreCaseMatcher() + { + // Assign + var matcherMock = new Mock(); + matcherMock.Setup(m => m.IgnoreCase).Returns(true); + + // Act + var model = _sut.Map(matcherMock.Object)!; + + // Assert + model.IgnoreCase.Should().BeTrue(); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_Null() + { + // Act + var result = _sut.Map((MatcherModel?)null); + + // Assert + result.Should().BeNull(); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_Exception() + { + // Assign + var model = new MatcherModel { Name = "test" }; + + // Act and Assert + Check.ThatCode(() => _sut.Map(model)).Throws(); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_LinqMatcher_Pattern() + { + // Assign + var model = new MatcherModel + { + Name = "LinqMatcher", + Pattern = "p" + }; + + // Act + var matcher = (LinqMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.GetPatterns().Should().Contain("p"); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_LinqMatcher_Patterns() + { + // Assign + var model = new MatcherModel + { + Name = "LinqMatcher", + Patterns = new[] { "p1", "p2" } + }; + + // Act + var matcher = (LinqMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.GetPatterns().Should().Contain("p1", "p2"); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonMatcher_Pattern_As_String() + { + // Assign + var pattern = "{ \"AccountIds\": [ 1, 2, 3 ] }"; + var model = new MatcherModel + { + Name = "JsonMatcher", + Pattern = pattern + }; + + // Act + var matcher = (JsonMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(pattern); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonMatcher_Patterns_1_Value_As_String() + { + // Assign + var pattern = "{ \"post1\": \"value1\", \"post2\": \"value2\" }"; + var patterns = new[] { pattern }; + var model = new MatcherModel + { + Name = "JsonMatcher", + Patterns = patterns + }; + + // Act + var matcher = (JsonMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(patterns); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonMatcher_Patterns_2_Values_As_String() + { + // Assign + var pattern1 = "{ \"AccountIds\": [ 1, 2, 3 ] }"; + var pattern2 = "{ \"post1\": \"value1\", \"post2\": \"value2\" }"; + var patterns = new[] { pattern1, pattern2 }; + var model = new MatcherModel + { + Name = "JsonMatcher", + Patterns = patterns + }; + + // Act + var matcher = (JsonMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(patterns); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonMatcher_Pattern_As_Object() + { + // Assign + var pattern = new { AccountIds = new[] { 1, 2, 3 } }; + var model = new MatcherModel + { + Name = "JsonMatcher", + Pattern = pattern + }; + + // Act + var matcher = (JsonMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(pattern); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonMatcher_Patterns_1_Value_As_Object() + { + // Assign + object pattern = new { post1 = "value1", post2 = "value2" }; + var patterns = new[] { pattern }; + var model = new MatcherModel + { + Name = "JsonMatcher", + Patterns = patterns + }; + + // Act + var matcher = (JsonMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(patterns); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonMatcher_Patterns_2_Values_As_Object() + { + // Assign + object pattern1 = new { AccountIds = new[] { 1, 2, 3 } }; + object pattern2 = new { post1 = "value1", post2 = "value2" }; + var patterns = new[] { pattern1, pattern2 }; + var model = new MatcherModel + { + Name = "JsonMatcher", + Patterns = patterns + }; + + // Act + var matcher = (JsonMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(patterns); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_Pattern_As_String() + { + // Assign + var pattern = "{ \"AccountIds\": [ 1, 2, 3 ] }"; + var model = new MatcherModel + { + Name = "JsonPartialMatcher", + Pattern = pattern + }; + + // Act + var matcher = (JsonPartialMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(pattern); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_Patterns_As_String() + { + // Assign + var pattern1 = "{ \"AccountIds\": [ 1, 2, 3 ] }"; + var pattern2 = "{ \"X\": \"x\" }"; + var patterns = new[] { pattern1, pattern2 }; + var model = new MatcherModel + { + Name = "JsonPartialMatcher", + Pattern = patterns + }; + + // Act + var matcher = (JsonPartialMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(patterns); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_Pattern_As_Object() + { + // Assign + var pattern = new { AccountIds = new[] { 1, 2, 3 } }; + var model = new MatcherModel + { + Name = "JsonPartialMatcher", + Pattern = pattern + }; + + // Act + var matcher = (JsonPartialMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(pattern); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_Patterns_As_Object() + { + // Assign + object pattern1 = new { AccountIds = new[] { 1, 2, 3 } }; + object pattern2 = new { X = "x" }; + var patterns = new[] { pattern1, pattern2 }; + var model = new MatcherModel + { + Name = "JsonPartialMatcher", + Patterns = patterns + }; + + // Act + var matcher = (JsonMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(patterns); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonPartialMatcher_StringPattern_With_PatternAsFile() + { + // Assign + var pattern = new StringPattern { Pattern = "{ \"AccountIds\": [ 1, 2, 3 ] }", PatternAsFile = "pf" }; + var model = new MatcherModel + { + Name = "JsonPartialMatcher", + Pattern = pattern, + Regex = true + }; + + // Act + var matcher = (JsonPartialMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(pattern); + matcher.Regex.Should().BeTrue(); + } + + [Fact] + public void MatcherMapper_Map_MatcherModel_JsonPartialWildcardMatcher_Patterns_As_Object() + { + // Assign + object pattern = new { X = "*" }; + var model = new MatcherModel + { + Name = "JsonPartialWildcardMatcher", + Pattern = pattern, + Regex = false + }; + + // Act + var matcher = (JsonPartialWildcardMatcher)_sut.Map(model)!; + + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.Value.Should().BeEquivalentTo(pattern); + matcher.Regex.Should().BeFalse(); + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs index 4ab9742e..a10de874 100644 --- a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs +++ b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs @@ -14,378 +14,427 @@ using WireMock.Serialization; using WireMock.Settings; using Xunit; -namespace WireMock.Net.Tests.Serialization +namespace WireMock.Net.Tests.Serialization; + +public class MatcherModelMapperTests { - public class MatcherModelMapperTests + private readonly WireMockServerSettings _settings = new(); + + private readonly MatcherMapper _sut; + + public MatcherModelMapperTests() { - private readonly WireMockServerSettings _settings = new WireMockServerSettings(); + _sut = new MatcherMapper(_settings); + } - private readonly MatcherMapper _sut; - - public MatcherModelMapperTests() + [Fact] + public void MatcherModelMapper_Map_CSharpCodeMatcher() + { + // Assign + var model = new MatcherModel { - _sut = new MatcherMapper(_settings); - } + Name = "CSharpCodeMatcher", + Patterns = new[] { "return it == \"x\";" } + }; + var sut = new MatcherMapper(new WireMockServerSettings { AllowCSharpCodeMatcher = true }); - [Fact] - public void MatcherModelMapper_Map_CSharpCodeMatcher() + // Act 1 + var matcher1 = (ICSharpCodeMatcher)sut.Map(model)!; + + // Assert 1 + matcher1.Should().NotBeNull(); + matcher1.IsMatch("x").Should().Be(1.0d); + + // Act 2 + var matcher2 = (ICSharpCodeMatcher)sut.Map(model)!; + + // Assert 2 + matcher2.Should().NotBeNull(); + matcher2.IsMatch("x").Should().Be(1.0d); + } + + [Fact] + public void MatcherModelMapper_Map_CSharpCodeMatcher_NotAllowed_ThrowsException() + { + // Assign + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "CSharpCodeMatcher", - Patterns = new[] { "return it == \"x\";" } - }; - var sut = new MatcherMapper(new WireMockServerSettings { AllowCSharpCodeMatcher = true }); + Name = "CSharpCodeMatcher", + Patterns = new[] { "x" } + }; + var sut = new MatcherMapper(new WireMockServerSettings { AllowCSharpCodeMatcher = false }); - // Act 1 - var matcher1 = (ICSharpCodeMatcher)sut.Map(model); + // Act + Action action = () => sut.Map(model); - // Assert 1 - matcher1.Should().NotBeNull(); - matcher1.IsMatch("x").Should().Be(1.0d); + // Assert + action.Should().Throw(); + } - // Act 2 - var matcher2 = (ICSharpCodeMatcher)sut.Map(model); + [Fact] + public void MatcherModelMapper_Map_Null() + { + // Act + IMatcher matcher = _sut.Map((MatcherModel?)null)!; - // Assert 2 - matcher2.Should().NotBeNull(); - matcher2.IsMatch("x").Should().Be(1.0d); - } + // Assert + Check.That(matcher).IsNull(); + } - [Fact] - public void MatcherModelMapper_Map_CSharpCodeMatcher_NotAllowed_ThrowsException() + [Fact] + public void MatcherModelMapper_Map_ExactMatcher_Pattern() + { + // Assign + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "CSharpCodeMatcher", - Patterns = new[] { "x" } - }; - var sut = new MatcherMapper(new WireMockServerSettings { AllowCSharpCodeMatcher = false }); + Name = "ExactMatcher", + Patterns = new[] { "x" } + }; - // Act - Action action = () => sut.Map(model); + // Act + var matcher = (ExactMatcher)_sut.Map(model)!; - // Assert - action.Should().Throw(); - } + // Assert + matcher.GetPatterns().Should().ContainSingle("x"); + matcher.ThrowException.Should().BeFalse(); + } - [Fact] - public void MatcherModelMapper_Map_Null() + [Fact] + public void MatcherModelMapper_Map_ExactMatcher_Patterns() + { + // Assign + var model = new MatcherModel { - // Act - IMatcher matcher = _sut.Map((MatcherModel)null); + Name = "ExactMatcher", + Patterns = new[] { "x", "y" } + }; - // Assert - Check.That(matcher).IsNull(); - } + // Act + var matcher = (ExactMatcher)_sut.Map(model)!; - [Fact] - public void MatcherModelMapper_Map_ExactMatcher_Pattern() + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); + } + + [Fact] + public void MatcherModelMapper_Map_JsonPartialMatcher_RegexFalse() + { + // Assign + var pattern = "{ \"x\": 1 }"; + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "ExactMatcher", - Patterns = new[] { "x" } - }; + Name = "JsonPartialMatcher", + Regex = false, + Pattern = pattern + }; - // Act - var matcher = (ExactMatcher)_sut.Map(model); + // Act + var matcher = (JsonPartialMatcher)_sut.Map(model)!; - // Assert - matcher.GetPatterns().Should().ContainSingle("x"); - matcher.ThrowException.Should().BeFalse(); - } + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.IgnoreCase.Should().BeFalse(); + matcher.Value.Should().Be(pattern); + matcher.Regex.Should().BeFalse(); + matcher.ThrowException.Should().BeFalse(); + } - [Fact] - public void MatcherModelMapper_Map_ExactMatcher_Patterns() + [Fact] + public void MatcherModelMapper_Map_JsonPartialMatcher_RegexTrue() + { + // Assign + var pattern = "{ \"x\": 1 }"; + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "ExactMatcher", - Patterns = new[] { "x", "y" } - }; + Name = "JsonPartialMatcher", + Regex = true, + Pattern = pattern + }; - // Act - var matcher = (ExactMatcher)_sut.Map(model); + // Act + var matcher = (JsonPartialMatcher)_sut.Map(model)!; - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); - } + // Assert + matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch); + matcher.IgnoreCase.Should().BeFalse(); + matcher.Value.Should().Be(pattern); + matcher.Regex.Should().BeTrue(); + matcher.ThrowException.Should().BeFalse(); + } - [Theory] - [InlineData(nameof(LinqMatcher))] - [InlineData(nameof(ExactMatcher))] - [InlineData(nameof(ExactObjectMatcher))] - [InlineData(nameof(RegexMatcher))] - [InlineData(nameof(JsonMatcher))] - [InlineData(nameof(JsonPathMatcher))] - [InlineData(nameof(JmesPathMatcher))] - [InlineData(nameof(XPathMatcher))] - [InlineData(nameof(WildcardMatcher))] - [InlineData(nameof(ContentTypeMatcher))] - [InlineData(nameof(SimMetricsMatcher))] - public void MatcherModelMapper_Map_ThrowExceptionWhenMatcherFails_True(string name) + [Theory] + [InlineData(nameof(LinqMatcher))] + [InlineData(nameof(ExactMatcher))] + [InlineData(nameof(ExactObjectMatcher))] + [InlineData(nameof(RegexMatcher))] + [InlineData(nameof(JsonMatcher))] + [InlineData(nameof(JsonPartialMatcher))] + [InlineData(nameof(JsonPartialWildcardMatcher))] + [InlineData(nameof(JsonPathMatcher))] + [InlineData(nameof(JmesPathMatcher))] + [InlineData(nameof(XPathMatcher))] + [InlineData(nameof(WildcardMatcher))] + [InlineData(nameof(ContentTypeMatcher))] + [InlineData(nameof(SimMetricsMatcher))] + public void MatcherModelMapper_Map_ThrowExceptionWhenMatcherFails_True(string name) + { + // Assign + var settings = new WireMockServerSettings { - // Assign - var settings = new WireMockServerSettings - { - ThrowExceptionWhenMatcherFails = true - }; - var sut = new MatcherMapper(settings); - var model = new MatcherModel - { - Name = name, - Patterns = new[] { "" } - }; - - // Act - var matcher = sut.Map(model); - - // Assert - matcher.ThrowException.Should().BeTrue(); - } - - [Fact] - public void MatcherModelMapper_Map_ExactObjectMatcher_ValidBase64StringPattern() + ThrowExceptionWhenMatcherFails = true + }; + var sut = new MatcherMapper(settings); + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "ExactObjectMatcher", - Patterns = new object[] { "c3RlZg==" } - }; + Name = name, + Patterns = new[] { "" } + }; - // Act - var matcher = (ExactObjectMatcher)_sut.Map(model); + // Act + var matcher = sut.Map(model)!; - // Assert - Check.That(matcher.ValueAsBytes).ContainsExactly(new byte[] { 115, 116, 101, 102 }); - } + // Assert + matcher.Should().NotBeNull(); + matcher.ThrowException.Should().BeTrue(); + } - [Fact] - public void MatcherModelMapper_Map_ExactObjectMatcher_InvalidBase64StringPattern() + [Fact] + public void MatcherModelMapper_Map_ExactObjectMatcher_ValidBase64StringPattern() + { + // Assign + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "ExactObjectMatcher", - Patterns = new object[] { "_" } - }; + Name = "ExactObjectMatcher", + Patterns = new object[] { "c3RlZg==" } + }; - // Act & Assert - Check.ThatCode(() => _sut.Map(model)).Throws(); - } + // Act + var matcher = (ExactObjectMatcher)_sut.Map(model)!; - [Theory] - [InlineData(MatchOperator.Or, 1.0d)] - [InlineData(MatchOperator.And, 0.0d)] - [InlineData(MatchOperator.Average, 0.5d)] - public void MatcherModelMapper_Map_RegexMatcher(MatchOperator matchOperator, double expected) + // Assert + Check.That(matcher.ValueAsBytes).ContainsExactly(new byte[] { 115, 116, 101, 102 }); + } + + [Fact] + public void MatcherModelMapper_Map_ExactObjectMatcher_InvalidBase64StringPattern() + { + // Assign + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "RegexMatcher", - Patterns = new[] { "x", "y" }, - IgnoreCase = true, - MatchOperator = matchOperator.ToString() - }; + Name = "ExactObjectMatcher", + Patterns = new object[] { "_" } + }; - // Act - var matcher = (RegexMatcher)_sut.Map(model)!; + // Act & Assert + Check.ThatCode(() => _sut.Map(model)).Throws(); + } - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); - Check.That(matcher.IsMatch("X")).IsEqualTo(expected); - } - - [Theory] - [InlineData(MatchOperator.Or, 1.0d)] - [InlineData(MatchOperator.And, 0.0d)] - [InlineData(MatchOperator.Average, 0.5d)] - public void MatcherModelMapper_Map_WildcardMatcher_IgnoreCase(MatchOperator matchOperator, double expected) + [Theory] + [InlineData(MatchOperator.Or, 1.0d)] + [InlineData(MatchOperator.And, 0.0d)] + [InlineData(MatchOperator.Average, 0.5d)] + public void MatcherModelMapper_Map_RegexMatcher(MatchOperator matchOperator, double expected) + { + // Assign + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "WildcardMatcher", - Patterns = new[] { "x", "y" }, - IgnoreCase = true, - MatchOperator = matchOperator.ToString() - }; + Name = "RegexMatcher", + Patterns = new[] { "x", "y" }, + IgnoreCase = true, + MatchOperator = matchOperator.ToString() + }; - // Act - var matcher = (WildcardMatcher)_sut.Map(model)!; + // Act + var matcher = (RegexMatcher)_sut.Map(model)!; - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); - Check.That(matcher.IsMatch("X")).IsEqualTo(expected); - } + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); + Check.That(matcher.IsMatch("X")).IsEqualTo(expected); + } - [Fact] - public void MatcherModelMapper_Map_WildcardMatcher_With_PatternAsFile() + [Theory] + [InlineData(MatchOperator.Or, 1.0d)] + [InlineData(MatchOperator.And, 0.0d)] + [InlineData(MatchOperator.Average, 0.5d)] + public void MatcherModelMapper_Map_WildcardMatcher_IgnoreCase(MatchOperator matchOperator, double expected) + { + // Assign + var model = new MatcherModel { - // Arrange - var file = "c:\\test.txt"; - var fileContent = "c"; - var stringPattern = new StringPattern - { - Pattern = fileContent, - PatternAsFile = file - }; - var fileSystemHandleMock = new Mock(); - fileSystemHandleMock.Setup(f => f.ReadFileAsString(file)).Returns(fileContent); + Name = "WildcardMatcher", + Patterns = new[] { "x", "y" }, + IgnoreCase = true, + MatchOperator = matchOperator.ToString() + }; - var model = new MatcherModel - { - Name = "WildcardMatcher", - PatternAsFile = file - }; + // Act + var matcher = (WildcardMatcher)_sut.Map(model)!; - var settings = new WireMockServerSettings - { - FileSystemHandler = fileSystemHandleMock.Object - }; - var sut = new MatcherMapper(settings); + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x", "y"); + Check.That(matcher.IsMatch("X")).IsEqualTo(expected); + } - // Act - var matcher = (WildcardMatcher)sut.Map(model); - - // Assert - matcher.GetPatterns().Should().HaveCount(1).And.Contain(new AnyOf(stringPattern)); - matcher.IsMatch("c").Should().Be(1.0d); - } - - [Fact] - public void MatcherModelMapper_Map_SimMetricsMatcher() + [Fact] + public void MatcherModelMapper_Map_WildcardMatcher_With_PatternAsFile() + { + // Arrange + var file = "c:\\test.txt"; + var fileContent = "c"; + var stringPattern = new StringPattern { - // Assign - var model = new MatcherModel - { - Name = "SimMetricsMatcher", - Pattern = "x" - }; + Pattern = fileContent, + PatternAsFile = file + }; + var fileSystemHandleMock = new Mock(); + fileSystemHandleMock.Setup(f => f.ReadFileAsString(file)).Returns(fileContent); - // Act - var matcher = (SimMetricsMatcher)_sut.Map(model); - - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x"); - } - - [Fact] - public void MatcherModelMapper_Map_SimMetricsMatcher_BlockDistance() + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "SimMetricsMatcher.BlockDistance", - Pattern = "x" - }; + Name = "WildcardMatcher", + PatternAsFile = file + }; - // Act - var matcher = (SimMetricsMatcher)_sut.Map(model); - - // Assert - Check.That(matcher.GetPatterns()).ContainsExactly("x"); - } - - [Fact] - public void MatcherModelMapper_Map_SimMetricsMatcher_Throws1() + var settings = new WireMockServerSettings { - // Assign - var model = new MatcherModel - { - Name = "error", - Pattern = "x" - }; + FileSystemHandler = fileSystemHandleMock.Object + }; + var sut = new MatcherMapper(settings); - // Act - Check.ThatCode(() => _sut.Map(model)).Throws(); - } + // Act + var matcher = (WildcardMatcher)sut.Map(model)!; - [Fact] - public void MatcherModelMapper_Map_SimMetricsMatcher_Throws2() + // Assert + matcher.GetPatterns().Should().HaveCount(1).And.Contain(new AnyOf(stringPattern)); + matcher.IsMatch("c").Should().Be(1.0d); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher() + { + // Assign + var model = new MatcherModel { - // Assign - var model = new MatcherModel - { - Name = "SimMetricsMatcher.error", - Pattern = "x" - }; + Name = "SimMetricsMatcher", + Pattern = "x" + }; - // Act - Check.ThatCode(() => _sut.Map(model)).Throws(); - } + // Act + var matcher = (SimMetricsMatcher)_sut.Map(model)!; - [Fact] - public void MatcherModelMapper_Map_MatcherModelToCustomMatcher() + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x"); + } + + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher_BlockDistance() + { + // Assign + var model = new MatcherModel { - // Arrange - var patternModel = new CustomPathParamMatcherModel("/customer/{customerId}/document/{documentId}", - new Dictionary(2) - { - { "customerId", @"^[0-9]+$" }, - { "documentId", @"^[0-9a-zA-Z\-\_]+\.[a-zA-Z]+$" } - }); - var model = new MatcherModel - { - Name = nameof(CustomPathParamMatcher), - Pattern = JsonConvert.SerializeObject(patternModel) - }; + Name = "SimMetricsMatcher.BlockDistance", + Pattern = "x" + }; - var settings = new WireMockServerSettings(); - settings.CustomMatcherMappings = settings.CustomMatcherMappings ?? new Dictionary>(); - settings.CustomMatcherMappings[nameof(CustomPathParamMatcher)] = matcherModel => - { - var matcherParams = JsonConvert.DeserializeObject((string)matcherModel.Pattern); - return new CustomPathParamMatcher( - matcherModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch, - matcherParams.Path, matcherParams.PathParams, - settings.ThrowExceptionWhenMatcherFails == true - ); - }; - var sut = new MatcherMapper(settings); + // Act + var matcher = (SimMetricsMatcher)_sut.Map(model)!; - // Act - var matcher = sut.Map(model) as CustomPathParamMatcher; + // Assert + Check.That(matcher.GetPatterns()).ContainsExactly("x"); + } - // Assert - matcher.Should().NotBeNull(); - } - - [Fact] - public void MatcherModelMapper_Map_CustomMatcherToMatcherModel() + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher_Throws1() + { + // Assign + var model = new MatcherModel { - // Arrange - var matcher = new CustomPathParamMatcher("/customer/{customerId}/document/{documentId}", - new Dictionary(2) - { - { "customerId", @"^[0-9]+$" }, - { "documentId", @"^[0-9a-zA-Z\-\_]+\.[a-zA-Z]+$" } - }); + Name = "error", + Pattern = "x" + }; - // Act - var model = _sut.Map(matcher); + // Act + Check.ThatCode(() => _sut.Map(model)).Throws(); + } - // Assert - using (new AssertionScope()) + [Fact] + public void MatcherModelMapper_Map_SimMetricsMatcher_Throws2() + { + // Assign + var model = new MatcherModel + { + Name = "SimMetricsMatcher.error", + Pattern = "x" + }; + + // Act + Check.ThatCode(() => _sut.Map(model)).Throws(); + } + + [Fact] + public void MatcherModelMapper_Map_MatcherModelToCustomMatcher() + { + // Arrange + var patternModel = new CustomPathParamMatcherModel("/customer/{customerId}/document/{documentId}", + new Dictionary(2) { - model.Should().NotBeNull(); - model.Name.Should().Be(nameof(CustomPathParamMatcher)); + { "customerId", @"^[0-9]+$" }, + { "documentId", @"^[0-9a-zA-Z\-\_]+\.[a-zA-Z]+$" } + }); + var model = new MatcherModel + { + Name = nameof(CustomPathParamMatcher), + Pattern = JsonConvert.SerializeObject(patternModel) + }; - var matcherParams = JsonConvert.DeserializeObject((string)model.Pattern); - matcherParams.Path.Should().Be("/customer/{customerId}/document/{documentId}"); - matcherParams.PathParams.Should().BeEquivalentTo(new Dictionary(2) - { - { "customerId", @"^[0-9]+$" }, - { "documentId", @"^[0-9a-zA-Z\-\_]+\.[a-zA-Z]+$" } - }); - } + var settings = new WireMockServerSettings(); + settings.CustomMatcherMappings = settings.CustomMatcherMappings ?? new Dictionary>(); + settings.CustomMatcherMappings[nameof(CustomPathParamMatcher)] = matcherModel => + { + var matcherParams = JsonConvert.DeserializeObject((string)matcherModel.Pattern!)!; + return new CustomPathParamMatcher( + matcherModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch, + matcherParams.Path, + matcherParams.PathParams, + settings.ThrowExceptionWhenMatcherFails == true + ); + }; + var sut = new MatcherMapper(settings); + + // Act + var matcher = sut.Map(model) as CustomPathParamMatcher; + + // Assert + matcher.Should().NotBeNull(); + } + + [Fact] + public void MatcherModelMapper_Map_CustomMatcherToMatcherModel() + { + // Arrange + var matcher = new CustomPathParamMatcher("/customer/{customerId}/document/{documentId}", + new Dictionary(2) + { + { "customerId", @"^[0-9]+$" }, + { "documentId", @"^[0-9a-zA-Z\-\_]+\.[a-zA-Z]+$" } + }); + + // Act + var model = _sut.Map(matcher)!; + + // Assert + using (new AssertionScope()) + { + model.Should().NotBeNull(); + model.Name.Should().Be(nameof(CustomPathParamMatcher)); + + var matcherParams = JsonConvert.DeserializeObject((string)model.Pattern!)!; + matcherParams.Path.Should().Be("/customer/{customerId}/document/{documentId}"); + matcherParams.PathParams.Should().BeEquivalentTo(new Dictionary(2) + { + { "customerId", @"^[0-9]+$" }, + { "documentId", @"^[0-9a-zA-Z\-\_]+\.[a-zA-Z]+$" } + }); } } } \ No newline at end of file