diff --git a/examples/WireMock.Net.Console.Net452.Classic/CustomFileSystemFileHandler.cs b/examples/WireMock.Net.Console.Net452.Classic/CustomFileSystemFileHandler.cs index 012b3350..45e06730 100644 --- a/examples/WireMock.Net.Console.Net452.Classic/CustomFileSystemFileHandler.cs +++ b/examples/WireMock.Net.Console.Net452.Classic/CustomFileSystemFileHandler.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using WireMock.Handlers; @@ -80,6 +80,12 @@ namespace WireMock.Net.ConsoleApplication return File.ReadAllBytes(AdjustPath(path)); } + /// + public string ReadFileAsString(string path) + { + return File.ReadAllText(path); + } + /// /// Adjusts the path to the MappingFolder. /// diff --git a/examples/WireMock.Net.Console.Net452.Classic/WireMock.Net.Console.Net452.Classic.csproj b/examples/WireMock.Net.Console.Net452.Classic/WireMock.Net.Console.Net452.Classic.csproj index 3a39c4e7..70d40b5b 100644 --- a/examples/WireMock.Net.Console.Net452.Classic/WireMock.Net.Console.Net452.Classic.csproj +++ b/examples/WireMock.Net.Console.Net452.Classic/WireMock.Net.Console.Net452.Classic.csproj @@ -36,6 +36,9 @@ ..\..\resources\WireMock.Net-Logo.ico + + ..\..\packages\AnyOf.0.2.0\lib\net45\AnyOf.dll + ..\..\packages\Handlebars.Net.2.0.4\lib\net452\Handlebars.dll diff --git a/examples/WireMock.Net.Console.Net452.Classic/packages.config b/examples/WireMock.Net.Console.Net452.Classic/packages.config index 8d57f57b..5aef79f8 100644 --- a/examples/WireMock.Net.Console.Net452.Classic/packages.config +++ b/examples/WireMock.Net.Console.Net452.Classic/packages.config @@ -1,5 +1,6 @@  + diff --git a/examples/WireMock.Net.Console.Net461.Classic/WireMock.Net.Console.Net461.Classic.csproj b/examples/WireMock.Net.Console.Net461.Classic/WireMock.Net.Console.Net461.Classic.csproj index c166cc39..312a39e7 100644 --- a/examples/WireMock.Net.Console.Net461.Classic/WireMock.Net.Console.Net461.Classic.csproj +++ b/examples/WireMock.Net.Console.Net461.Classic/WireMock.Net.Console.Net461.Classic.csproj @@ -35,6 +35,9 @@ WireMock.Net.ConsoleApplication.Program + + ..\..\packages\AnyOf.0.2.0\lib\net45\AnyOf.dll + ..\..\packages\Handlebars.Net.2.0.4\lib\net46\Handlebars.dll diff --git a/examples/WireMock.Net.Console.Net461.Classic/packages.config b/examples/WireMock.Net.Console.Net461.Classic/packages.config index ff8582dd..eeff0304 100644 --- a/examples/WireMock.Net.Console.Net461.Classic/packages.config +++ b/examples/WireMock.Net.Console.Net461.Classic/packages.config @@ -1,5 +1,6 @@  + diff --git a/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj b/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj index eba05faf..b6aa7714 100644 --- a/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj +++ b/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj @@ -39,6 +39,9 @@ WireMock.Net.ConsoleApplication.Program + + ..\..\packages\AnyOf.0.2.0\lib\net45\AnyOf.dll + ..\..\packages\Fare.2.1.1\lib\net35\Fare.dll diff --git a/examples/WireMock.Net.Console.Net472.Classic/packages.config b/examples/WireMock.Net.Console.Net472.Classic/packages.config index 04812545..955115a7 100644 --- a/examples/WireMock.Net.Console.Net472.Classic/packages.config +++ b/examples/WireMock.Net.Console.Net472.Classic/packages.config @@ -1,5 +1,6 @@  + diff --git a/src/WireMock.Net.Abstractions/Admin/Mappings/MatcherModel.cs b/src/WireMock.Net.Abstractions/Admin/Mappings/MatcherModel.cs index be5fdc51..38bf9948 100644 --- a/src/WireMock.Net.Abstractions/Admin/Mappings/MatcherModel.cs +++ b/src/WireMock.Net.Abstractions/Admin/Mappings/MatcherModel.cs @@ -1,4 +1,4 @@ -namespace WireMock.Admin.Mappings +namespace WireMock.Admin.Mappings { /// /// MatcherModel @@ -12,15 +12,20 @@ public string Name { get; set; } /// - /// Gets or sets the pattern. Can be a string (default) or an object; + /// 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; + /// 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 ignore case. /// diff --git a/src/WireMock.Net.Abstractions/Handlers/IFileSystemHandler.cs b/src/WireMock.Net.Abstractions/Handlers/IFileSystemHandler.cs index 498c5826..ffeb06ec 100644 --- a/src/WireMock.Net.Abstractions/Handlers/IFileSystemHandler.cs +++ b/src/WireMock.Net.Abstractions/Handlers/IFileSystemHandler.cs @@ -1,4 +1,4 @@ -using JetBrains.Annotations; +using JetBrains.Annotations; using System.Collections.Generic; namespace WireMock.Handlers @@ -89,5 +89,12 @@ namespace WireMock.Handlers /// The filename. /// The file content as bytes. byte[] ReadFile([NotNull] string filename); + + /// + /// Read a file as string. + /// + /// The filename. + /// The file content as a string. + string ReadFileAsString([NotNull] string filename); } } \ No newline at end of file diff --git a/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs b/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs index 70926936..a92f3771 100644 --- a/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs +++ b/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs @@ -1,225 +1,228 @@ -using System; -using System.Linq; +using System; +using System.Linq; using System.Reflection; using System.Text; -using JetBrains.Annotations; -using Newtonsoft.Json.Linq; -using WireMock.Exceptions; -using WireMock.Validation; - -namespace WireMock.Matchers -{ - /// - /// CSharpCode / CS-Script Matcher - /// - /// - internal class CSharpCodeMatcher : ICSharpCodeMatcher - { - private const string TemplateForIsMatchWithString = "public class CodeHelper {{ public bool IsMatch(string it) {{ {0} }} }}"; - - private const string TemplateForIsMatchWithDynamic = "public class CodeHelper {{ public bool IsMatch(dynamic it) {{ {0} }} }}"; - - private readonly string[] _usings = - { - "System", - "System.Linq", - "System.Collections.Generic", - "Microsoft.CSharp", - "Newtonsoft.Json.Linq" - }; - - public MatchBehaviour MatchBehaviour { get; } - - /// - public bool ThrowException { get; } - - private readonly string[] _patterns; - - /// - /// Initializes a new instance of the class. - /// - /// The patterns. - public CSharpCodeMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, patterns) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The match behaviour. - /// The patterns. - public CSharpCodeMatcher(MatchBehaviour matchBehaviour, [NotNull] params string[] patterns) - { - Check.NotNull(patterns, nameof(patterns)); - - MatchBehaviour = matchBehaviour; - ThrowException = false; - _patterns = patterns; - } - - public double IsMatch(string input) - { - return IsMatchInternal(input); - } - - public double IsMatch(object input) - { - return IsMatchInternal(input); - } - - public double IsMatchInternal(object input) - { - double match = MatchScores.Mismatch; - - if (input != null) - { - match = MatchScores.ToScore(_patterns.Select(pattern => IsMatch(input, pattern))); - } - - return MatchBehaviourHelper.Convert(MatchBehaviour, match); - } - - private bool IsMatch(dynamic input, string pattern) - { - bool isMatchWithString = input is string; - var inputValue = isMatchWithString ? input : JObject.FromObject(input); - string source = GetSourceForIsMatchWithString(pattern, isMatchWithString); - - object result = null; - -#if (NET451 || NET452) - var compilerParams = new System.CodeDom.Compiler.CompilerParameters - { - GenerateInMemory = true, - GenerateExecutable = false, - ReferencedAssemblies = - { - "System.dll", - "System.Core.dll", - "Microsoft.CSharp.dll", - "Newtonsoft.Json.dll" - } - }; - - using (var codeProvider = new Microsoft.CSharp.CSharpCodeProvider()) - { - var compilerResults = codeProvider.CompileAssemblyFromSource(compilerParams, source); - - if (compilerResults.Errors.Count != 0) - { - var errors = from System.CodeDom.Compiler.CompilerError er in compilerResults.Errors select er.ToString(); - throw new WireMockException(string.Join(", ", errors)); - } - - object helper = compilerResults.CompiledAssembly.CreateInstance("CodeHelper"); - if (helper == null) - { - throw new WireMockException("CSharpCodeMatcher: Unable to create instance from WireMock.CodeHelper"); - } - - var methodInfo = helper.GetType().GetMethod("IsMatch"); - if (methodInfo == null) - { - throw new WireMockException("CSharpCodeMatcher: Unable to find method 'IsMatch' in WireMock.CodeHelper"); - } - - try - { - result = methodInfo.Invoke(helper, new[] { inputValue }); - } - catch (Exception ex) - { - throw new WireMockException("CSharpCodeMatcher: Unable to call method 'IsMatch' in WireMock.CodeHelper", ex); - } - } -#elif (NET46 || NET461) - dynamic script; - try - { - script = CSScriptLibrary.CSScript.Evaluator.CompileCode(source).CreateObject("*"); - } - catch (Exception ex) - { - throw new WireMockException("CSharpCodeMatcher: Unable to create compiler for WireMock.CodeHelper", ex); - } - - try - { - result = script.IsMatch(inputValue); - } - catch (Exception ex) - { - throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex); - } - -#elif (NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1 || NET5_0) - Assembly assembly; - try +using AnyOfTypes; +using JetBrains.Annotations; +using Newtonsoft.Json.Linq; +using WireMock.Exceptions; +using WireMock.Extensions; +using WireMock.Models; +using WireMock.Validation; + +namespace WireMock.Matchers +{ + /// + /// CSharpCode / CS-Script Matcher + /// + /// + internal class CSharpCodeMatcher : ICSharpCodeMatcher + { + private const string TemplateForIsMatchWithString = "public class CodeHelper {{ public bool IsMatch(string it) {{ {0} }} }}"; + + private const string TemplateForIsMatchWithDynamic = "public class CodeHelper {{ public bool IsMatch(dynamic it) {{ {0} }} }}"; + + private readonly string[] _usings = + { + "System", + "System.Linq", + "System.Collections.Generic", + "Microsoft.CSharp", + "Newtonsoft.Json.Linq" + }; + + public MatchBehaviour MatchBehaviour { get; } + + /// + public bool ThrowException { get; } + + private readonly AnyOf[] _patterns; + + /// + /// Initializes a new instance of the class. + /// + /// The patterns. + public CSharpCodeMatcher([NotNull] params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, patterns) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The patterns. + public CSharpCodeMatcher(MatchBehaviour matchBehaviour, [NotNull] params AnyOf[] patterns) + { + Check.NotNull(patterns, nameof(patterns)); + + MatchBehaviour = matchBehaviour; + ThrowException = false; + _patterns = patterns; + } + + public double IsMatch(string input) + { + return IsMatchInternal(input); + } + + public double IsMatch(object input) + { + return IsMatchInternal(input); + } + + public double IsMatchInternal(object input) + { + double match = MatchScores.Mismatch; + + if (input != null) { - assembly = CSScriptLib.CSScript.Evaluator.CompileCode(source); - } - catch (Exception ex) - { - throw new WireMockException($"CSharpCodeMatcher: Unable to compile code `{source}` for WireMock.CodeHelper", ex); - } - - dynamic script; + match = MatchScores.ToScore(_patterns.Select(pattern => IsMatch(input, pattern.GetPattern()))); + } + + return MatchBehaviourHelper.Convert(MatchBehaviour, match); + } + + private bool IsMatch(dynamic input, string pattern) + { + bool isMatchWithString = input is string; + var inputValue = isMatchWithString ? input : JObject.FromObject(input); + string source = GetSourceForIsMatchWithString(pattern, isMatchWithString); + + object result = null; + +#if (NET451 || NET452) + var compilerParams = new System.CodeDom.Compiler.CompilerParameters + { + GenerateInMemory = true, + GenerateExecutable = false, + ReferencedAssemblies = + { + "System.dll", + "System.Core.dll", + "Microsoft.CSharp.dll", + "Newtonsoft.Json.dll" + } + }; + + using (var codeProvider = new Microsoft.CSharp.CSharpCodeProvider()) + { + var compilerResults = codeProvider.CompileAssemblyFromSource(compilerParams, source); + + if (compilerResults.Errors.Count != 0) + { + var errors = from System.CodeDom.Compiler.CompilerError er in compilerResults.Errors select er.ToString(); + throw new WireMockException(string.Join(", ", errors)); + } + + object helper = compilerResults.CompiledAssembly.CreateInstance("CodeHelper"); + if (helper == null) + { + throw new WireMockException("CSharpCodeMatcher: Unable to create instance from WireMock.CodeHelper"); + } + + var methodInfo = helper.GetType().GetMethod("IsMatch"); + if (methodInfo == null) + { + throw new WireMockException("CSharpCodeMatcher: Unable to find method 'IsMatch' in WireMock.CodeHelper"); + } + + try + { + result = methodInfo.Invoke(helper, new[] { inputValue }); + } + catch (Exception ex) + { + throw new WireMockException("CSharpCodeMatcher: Unable to call method 'IsMatch' in WireMock.CodeHelper", ex); + } + } +#elif (NET46 || NET461) + dynamic script; try { -#if NETSTANDARD2_0 - script = csscript.GenericExtensions.CreateObject(assembly, "*"); -#else - script = CSScriptLib.ReflectionExtensions.CreateObject(assembly, "*"); + script = CSScriptLibrary.CSScript.Evaluator.CompileCode(source).CreateObject("*"); + } + catch (Exception ex) + { + throw new WireMockException("CSharpCodeMatcher: Unable to create compiler for WireMock.CodeHelper", ex); + } + + try + { + result = script.IsMatch(inputValue); + } + catch (Exception ex) + { + throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex); + } + +#elif (NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1 || NET5_0) + Assembly assembly; + try + { + assembly = CSScriptLib.CSScript.Evaluator.CompileCode(source); + } + catch (Exception ex) + { + throw new WireMockException($"CSharpCodeMatcher: Unable to compile code `{source}` for WireMock.CodeHelper", ex); + } + + dynamic script; + try + { +#if NETSTANDARD2_0 + script = csscript.GenericExtensions.CreateObject(assembly, "*"); +#else + script = CSScriptLib.ReflectionExtensions.CreateObject(assembly, "*"); #endif - } - catch (Exception ex) + } + catch (Exception ex) { throw new WireMockException("CSharpCodeMatcher: Unable to create object from assembly", ex); - } - - try - { - result = script.IsMatch(inputValue); - } - catch (Exception ex) - { - throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex); } -#else - throw new NotSupportedException("The 'CSharpCodeMatcher' cannot be used in netstandard 1.3"); -#endif - try - { - return (bool)result; - } - catch - { - throw new WireMockException($"Unable to cast result '{result}' to bool"); - } - } - - private string GetSourceForIsMatchWithString(string pattern, bool isMatchWithString) - { - string template = isMatchWithString ? TemplateForIsMatchWithString : TemplateForIsMatchWithDynamic; - - var stringBuilder = new StringBuilder(); + + try + { + result = script.IsMatch(inputValue); + } + catch (Exception ex) + { + throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex); + } +#else + throw new NotSupportedException("The 'CSharpCodeMatcher' cannot be used in netstandard 1.3"); +#endif + try + { + return (bool)result; + } + catch + { + throw new WireMockException($"Unable to cast result '{result}' to bool"); + } + } + + private string GetSourceForIsMatchWithString(string pattern, bool isMatchWithString) + { + string template = isMatchWithString ? TemplateForIsMatchWithString : TemplateForIsMatchWithDynamic; + + var stringBuilder = new StringBuilder(); foreach (string @using in _usings) { stringBuilder.AppendLine($"using {@using};"); - } - stringBuilder.AppendLine(); - stringBuilder.AppendFormat(template, pattern); - - return stringBuilder.ToString(); - } - - /// - public string[] GetPatterns() - { - return _patterns; - } - - /// - public string Name => "CSharpCodeMatcher"; - } + } + stringBuilder.AppendLine(); + stringBuilder.AppendFormat(template, pattern); + + return stringBuilder.ToString(); + } + + /// + public AnyOf[] GetPatterns() + { + return _patterns; + } + + /// + public string Name => "CSharpCodeMatcher"; + } } \ No newline at end of file diff --git a/src/WireMock.Net/Extensions/AnyOfExtensions.cs b/src/WireMock.Net/Extensions/AnyOfExtensions.cs new file mode 100644 index 00000000..015690e2 --- /dev/null +++ b/src/WireMock.Net/Extensions/AnyOfExtensions.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Linq; +using AnyOfTypes; +using WireMock.Models; + +namespace WireMock.Extensions +{ + internal static class AnyOfExtensions + { + public static string GetPattern(this AnyOf value) + { + return value.IsFirst ? value.First : value.Second.Pattern; + } + + public static AnyOf[] ToAnyOfPatterns(this IEnumerable patterns) + { + return patterns.Select(p => p.ToAnyOfPattern()).ToArray(); + } + + public static AnyOf ToAnyOfPattern(this string pattern) + { + return new AnyOf(pattern); + } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Handlers/LocalFileSystemHandler.cs b/src/WireMock.Net/Handlers/LocalFileSystemHandler.cs index 2dd7e5e0..467701d3 100644 --- a/src/WireMock.Net/Handlers/LocalFileSystemHandler.cs +++ b/src/WireMock.Net/Handlers/LocalFileSystemHandler.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using WireMock.Util; using WireMock.Validation; @@ -130,6 +130,12 @@ namespace WireMock.Handlers return File.ReadAllBytes(AdjustPath(filename)); } + /// + public string ReadFileAsString(string filename) + { + return File.ReadAllText(AdjustPath(Check.NotNullOrEmpty(filename, nameof(filename)))); + } + /// /// Adjusts the path to the MappingFolder. /// @@ -140,4 +146,4 @@ namespace WireMock.Handlers return Path.Combine(GetMappingFolder(), filename); } } -} +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/ContentTypeMatcher.cs b/src/WireMock.Net/Matchers/ContentTypeMatcher.cs index 7c9ba1a1..d4ac069e 100644 --- a/src/WireMock.Net/Matchers/ContentTypeMatcher.cs +++ b/src/WireMock.Net/Matchers/ContentTypeMatcher.cs @@ -1,5 +1,7 @@ -using System.Net.Http.Headers; +using System.Net.Http.Headers; +using AnyOfTypes; using JetBrains.Annotations; +using WireMock.Models; namespace WireMock.Matchers { @@ -9,14 +11,14 @@ namespace WireMock.Matchers /// public class ContentTypeMatcher : WildcardMatcher { - private readonly string[] _patterns; + private readonly AnyOf[] _patterns; /// /// Initializes a new instance of the class. /// /// The pattern. /// IgnoreCase (default false) - public ContentTypeMatcher([NotNull] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) + public ContentTypeMatcher([NotNull] AnyOf pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) { } @@ -26,7 +28,7 @@ namespace WireMock.Matchers /// The match behaviour. /// The pattern. /// IgnoreCase (default false) - public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) + public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) { } @@ -35,7 +37,7 @@ namespace WireMock.Matchers /// /// The patterns. /// IgnoreCase (default false) - public ContentTypeMatcher([NotNull] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) + public ContentTypeMatcher([NotNull] AnyOf[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) { } @@ -46,7 +48,7 @@ namespace WireMock.Matchers /// The patterns. /// IgnoreCase (default false) /// Throw an exception when the internal matching fails because of invalid input. - public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] string[] patterns, bool ignoreCase = false, bool throwException = false) : + public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf[] patterns, bool ignoreCase = false, bool throwException = false) : base(matchBehaviour, patterns, ignoreCase, throwException) { _patterns = patterns; @@ -64,7 +66,7 @@ namespace WireMock.Matchers } /// - public override string[] GetPatterns() + public override AnyOf[] GetPatterns() { return _patterns; } diff --git a/src/WireMock.Net/Matchers/ExactMatcher.cs b/src/WireMock.Net/Matchers/ExactMatcher.cs index 4ceee72f..4568544e 100644 --- a/src/WireMock.Net/Matchers/ExactMatcher.cs +++ b/src/WireMock.Net/Matchers/ExactMatcher.cs @@ -1,5 +1,8 @@ -using System.Linq; +using System.Linq; +using AnyOfTypes; using JetBrains.Annotations; +using WireMock.Extensions; +using WireMock.Models; using WireMock.Validation; namespace WireMock.Matchers @@ -10,7 +13,7 @@ namespace WireMock.Matchers /// public class ExactMatcher : IStringMatcher { - private readonly string[] _values; + private readonly AnyOf[] _values; /// public MatchBehaviour MatchBehaviour { get; } @@ -22,7 +25,7 @@ namespace WireMock.Matchers /// Initializes a new instance of the class. /// /// The values. - public ExactMatcher([NotNull] params string[] values) : this(MatchBehaviour.AcceptOnMatch, false, values) + public ExactMatcher([NotNull] params AnyOf[] values) : this(MatchBehaviour.AcceptOnMatch, false, values) { } @@ -32,9 +35,9 @@ namespace WireMock.Matchers /// The match behaviour. /// Throw an exception when the internal matching fails because of invalid input. /// The values. - public ExactMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] values) + public ExactMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf[] values) { - Check.HasNoNulls(values, nameof(values)); + Check.NotNull(values, nameof(values)); MatchBehaviour = matchBehaviour; ThrowException = throwException; @@ -46,14 +49,14 @@ namespace WireMock.Matchers { if (_values.Length == 1) { - return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values[0] == input)); + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values[0].GetPattern() == input)); } - return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values.Contains(input))); + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values.Select(v => v.GetPattern()).Contains(input))); } /// - public string[] GetPatterns() + public AnyOf[] GetPatterns() { return _values; } diff --git a/src/WireMock.Net/Matchers/IStringMatcher.cs b/src/WireMock.Net/Matchers/IStringMatcher.cs index c580a33e..126373fe 100644 --- a/src/WireMock.Net/Matchers/IStringMatcher.cs +++ b/src/WireMock.Net/Matchers/IStringMatcher.cs @@ -1,4 +1,7 @@ -namespace WireMock.Matchers +using AnyOfTypes; +using WireMock.Models; + +namespace WireMock.Matchers { /// /// IStringMatcher @@ -17,6 +20,6 @@ /// Gets the patterns. /// /// Patterns - string[] GetPatterns(); + AnyOf[] GetPatterns(); } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/JSONPathMatcher.cs b/src/WireMock.Net/Matchers/JSONPathMatcher.cs index 65937497..6d6de3f2 100644 --- a/src/WireMock.Net/Matchers/JSONPathMatcher.cs +++ b/src/WireMock.Net/Matchers/JSONPathMatcher.cs @@ -1,7 +1,10 @@ -using System.Linq; +using System.Linq; +using AnyOfTypes; using JetBrains.Annotations; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using WireMock.Extensions; +using WireMock.Models; using WireMock.Validation; namespace WireMock.Matchers @@ -13,7 +16,7 @@ namespace WireMock.Matchers /// public class JsonPathMatcher : IStringMatcher, IObjectMatcher { - private readonly string[] _patterns; + private readonly AnyOf[] _patterns; /// public MatchBehaviour MatchBehaviour { get; } @@ -25,7 +28,15 @@ namespace WireMock.Matchers /// Initializes a new instance of the class. /// /// The patterns. - public JsonPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) + public JsonPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns.ToAnyOfPatterns()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The patterns. + public JsonPathMatcher([NotNull] params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) { } @@ -35,7 +46,7 @@ namespace WireMock.Matchers /// The match behaviour. /// Throw an exception when the internal matching fails because of invalid input. /// The patterns. - public JsonPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns) + public JsonPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf[] patterns) { Check.NotNull(patterns, nameof(patterns)); @@ -94,7 +105,7 @@ namespace WireMock.Matchers } /// - public string[] GetPatterns() + public AnyOf[] GetPatterns() { return _patterns; } @@ -104,7 +115,7 @@ namespace WireMock.Matchers private double IsMatch(JToken jtoken) { - return MatchScores.ToScore(_patterns.Select(pattern => jtoken.SelectToken(pattern) != null)); + return MatchScores.ToScore(_patterns.Select(pattern => jtoken.SelectToken(pattern.GetPattern()) != null)); } } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/JmesPathMatcher.cs b/src/WireMock.Net/Matchers/JmesPathMatcher.cs index 7f916746..368d42b4 100644 --- a/src/WireMock.Net/Matchers/JmesPathMatcher.cs +++ b/src/WireMock.Net/Matchers/JmesPathMatcher.cs @@ -1,7 +1,10 @@ -using DevLab.JmesPath; +using AnyOfTypes; +using DevLab.JmesPath; using JetBrains.Annotations; using Newtonsoft.Json; using System.Linq; +using WireMock.Extensions; +using WireMock.Models; using WireMock.Validation; namespace WireMock.Matchers @@ -11,7 +14,7 @@ namespace WireMock.Matchers /// public class JmesPathMatcher : IStringMatcher, IObjectMatcher { - private readonly string[] _patterns; + private readonly AnyOf[] _patterns; /// public MatchBehaviour MatchBehaviour { get; } @@ -23,7 +26,15 @@ namespace WireMock.Matchers /// Initializes a new instance of the class. /// /// The patterns. - public JmesPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) + public JmesPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns.ToAnyOfPatterns()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The patterns. + public JmesPathMatcher([NotNull] params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) { } @@ -32,7 +43,7 @@ namespace WireMock.Matchers /// /// Throw an exception when the internal matching fails because of invalid input. /// The patterns. - public JmesPathMatcher(bool throwException = false, [NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, throwException, patterns) + public JmesPathMatcher(bool throwException = false, [NotNull] params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, throwException, patterns) { } @@ -42,7 +53,7 @@ namespace WireMock.Matchers /// The match behaviour. /// Throw an exception when the internal matching fails because of invalid input. /// The patterns. - public JmesPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns) + public JmesPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf[] patterns) { Check.NotNull(patterns, nameof(patterns)); @@ -59,7 +70,7 @@ namespace WireMock.Matchers { try { - match = MatchScores.ToScore(_patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern)))); + match = MatchScores.ToScore(_patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern.GetPattern())))); } catch (JsonException) { @@ -89,7 +100,7 @@ namespace WireMock.Matchers } /// - public string[] GetPatterns() + public AnyOf[] GetPatterns() { return _patterns; } diff --git a/src/WireMock.Net/Matchers/LinqMatcher.cs b/src/WireMock.Net/Matchers/LinqMatcher.cs index b3134a03..19efe9ae 100644 --- a/src/WireMock.Net/Matchers/LinqMatcher.cs +++ b/src/WireMock.Net/Matchers/LinqMatcher.cs @@ -1,8 +1,12 @@ -using System.Linq; +using System.Linq; using System.Linq.Dynamic.Core; +using AnyOfTypes; using JetBrains.Annotations; using Newtonsoft.Json.Linq; +using WireMock.Extensions; +using WireMock.Models; using WireMock.Util; +using WireMock.Validation; namespace WireMock.Matchers { @@ -13,7 +17,7 @@ namespace WireMock.Matchers /// public class LinqMatcher : IObjectMatcher, IStringMatcher { - private readonly string[] _patterns; + private readonly AnyOf[] _patterns; /// public MatchBehaviour MatchBehaviour { get; } @@ -24,7 +28,7 @@ namespace WireMock.Matchers /// Initializes a new instance of the class. /// /// The pattern. - public LinqMatcher([NotNull] string pattern) : this(new[] { pattern }) + public LinqMatcher([NotNull] AnyOf pattern) : this(new[] { pattern }) { } @@ -32,7 +36,7 @@ namespace WireMock.Matchers /// Initializes a new instance of the class. /// /// The patterns. - public LinqMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) + public LinqMatcher([NotNull] params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) { } @@ -41,7 +45,7 @@ namespace WireMock.Matchers /// /// The match behaviour. /// The pattern. - public LinqMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern) : this(matchBehaviour, false, pattern) + public LinqMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf pattern) : this(matchBehaviour, false, pattern) { } @@ -51,8 +55,10 @@ namespace WireMock.Matchers /// The match behaviour. /// The patterns. /// Throw an exception when the internal matching fails because of invalid input. - public LinqMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns) + public LinqMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf[] patterns) { + Check.NotNull(patterns, nameof(patterns)); + MatchBehaviour = matchBehaviour; ThrowException = throwException; _patterns = patterns; @@ -69,7 +75,7 @@ namespace WireMock.Matchers try { // Use the Any(...) method to check if the result matches - match = MatchScores.ToScore(_patterns.Select(pattern => queryable.Any(pattern))); + match = MatchScores.ToScore(_patterns.Select(pattern => queryable.Any(pattern.GetPattern()))); return MatchBehaviourHelper.Convert(MatchBehaviour, match); } @@ -129,7 +135,7 @@ namespace WireMock.Matchers } /// - public string[] GetPatterns() + public AnyOf[] GetPatterns() { return _patterns; } diff --git a/src/WireMock.Net/Matchers/RegexMatcher.cs b/src/WireMock.Net/Matchers/RegexMatcher.cs index f0c22bac..5f2d6e57 100644 --- a/src/WireMock.Net/Matchers/RegexMatcher.cs +++ b/src/WireMock.Net/Matchers/RegexMatcher.cs @@ -1,7 +1,10 @@ -using System; +using System; using System.Linq; using System.Text.RegularExpressions; +using AnyOfTypes; using JetBrains.Annotations; +using WireMock.Extensions; +using WireMock.Models; using WireMock.Validation; namespace WireMock.Matchers @@ -13,7 +16,7 @@ namespace WireMock.Matchers /// public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher { - private readonly string[] _patterns; + private readonly AnyOf[] _patterns; private readonly Regex[] _expressions; /// @@ -27,7 +30,7 @@ namespace WireMock.Matchers /// /// The pattern. /// Ignore the case from the pattern. - public RegexMatcher([NotNull, RegexPattern] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) + public RegexMatcher([NotNull, RegexPattern] AnyOf pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) { } @@ -37,7 +40,7 @@ namespace WireMock.Matchers /// The match behaviour. /// The pattern. /// Ignore the case from the pattern. - public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) + public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] AnyOf pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) { } @@ -46,7 +49,7 @@ namespace WireMock.Matchers /// /// The patterns. /// Ignore the case from the pattern. - public RegexMatcher([NotNull, RegexPattern] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) + public RegexMatcher([NotNull, RegexPattern] AnyOf[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) { } @@ -57,7 +60,7 @@ namespace WireMock.Matchers /// The patterns. /// Ignore the case from the pattern. /// Throw an exception when the internal matching fails because of invalid input. - public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] string[] patterns, bool ignoreCase = false, bool throwException = false) + public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] AnyOf[] patterns, bool ignoreCase = false, bool throwException = false) { Check.NotNull(patterns, nameof(patterns)); @@ -73,7 +76,7 @@ namespace WireMock.Matchers options |= RegexOptions.IgnoreCase; } - _expressions = patterns.Select(p => new Regex(p, options)).ToArray(); + _expressions = patterns.Select(p => new Regex(p.GetPattern(), options)).ToArray(); } /// @@ -99,7 +102,7 @@ namespace WireMock.Matchers } /// - public virtual string[] GetPatterns() + public virtual AnyOf[] GetPatterns() { return _patterns; } diff --git a/src/WireMock.Net/Matchers/SimMetricsMatcher.cs b/src/WireMock.Net/Matchers/SimMetricsMatcher.cs index 95125cda..c02754d5 100644 --- a/src/WireMock.Net/Matchers/SimMetricsMatcher.cs +++ b/src/WireMock.Net/Matchers/SimMetricsMatcher.cs @@ -1,8 +1,11 @@ -using System.Linq; +using System.Linq; +using AnyOfTypes; using JetBrains.Annotations; using SimMetrics.Net; using SimMetrics.Net.API; using SimMetrics.Net.Metric; +using WireMock.Extensions; +using WireMock.Models; using WireMock.Validation; namespace WireMock.Matchers @@ -13,7 +16,7 @@ namespace WireMock.Matchers /// public class SimMetricsMatcher : IStringMatcher { - private readonly string[] _patterns; + private readonly AnyOf[] _patterns; private readonly SimMetricType _simMetricType; /// @@ -27,7 +30,7 @@ namespace WireMock.Matchers /// /// The pattern. /// The SimMetric Type - public SimMetricsMatcher([NotNull] string pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(new[] { pattern }, simMetricType) + public SimMetricsMatcher([NotNull] AnyOf pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(new[] { pattern }, simMetricType) { } @@ -37,7 +40,7 @@ namespace WireMock.Matchers /// The match behaviour. /// The pattern. /// The SimMetric Type - public SimMetricsMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(matchBehaviour, new[] { pattern }, simMetricType) + public SimMetricsMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(matchBehaviour, new[] { pattern }, simMetricType) { } @@ -46,7 +49,16 @@ namespace WireMock.Matchers /// /// The patterns. /// The SimMetric Type - public SimMetricsMatcher([NotNull] string[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein) : this(MatchBehaviour.AcceptOnMatch, patterns, simMetricType) + public SimMetricsMatcher([NotNull] string[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein) : this(MatchBehaviour.AcceptOnMatch, patterns.ToAnyOfPatterns(), simMetricType) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The patterns. + /// The SimMetric Type + public SimMetricsMatcher([NotNull] AnyOf[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein) : this(MatchBehaviour.AcceptOnMatch, patterns, simMetricType) { } @@ -57,9 +69,9 @@ namespace WireMock.Matchers /// The patterns. /// The SimMetric Type /// Throw an exception when the internal matching fails because of invalid input. - public SimMetricsMatcher(MatchBehaviour matchBehaviour, [NotNull] string[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein, bool throwException = false) + public SimMetricsMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein, bool throwException = false) { - Check.NotNullOrEmpty(patterns, nameof(patterns)); + Check.NotNull(patterns, nameof(patterns)); MatchBehaviour = matchBehaviour; ThrowException = throwException; @@ -71,9 +83,9 @@ namespace WireMock.Matchers /// public double IsMatch(string input) { - IStringMetric m = GetStringMetricType(); + IStringMetric stringmetricType = GetStringMetricType(); - return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_patterns.Select(p => m.GetSimilarity(p, input)))); + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_patterns.Select(p => stringmetricType.GetSimilarity(p.GetPattern(), input)))); } private IStringMetric GetStringMetricType() @@ -120,7 +132,7 @@ namespace WireMock.Matchers } /// - public string[] GetPatterns() + public AnyOf[] GetPatterns() { return _patterns; } diff --git a/src/WireMock.Net/Matchers/WildcardMatcher.cs b/src/WireMock.Net/Matchers/WildcardMatcher.cs index 6e1b534b..99423d63 100644 --- a/src/WireMock.Net/Matchers/WildcardMatcher.cs +++ b/src/WireMock.Net/Matchers/WildcardMatcher.cs @@ -1,6 +1,9 @@ -using System.Linq; +using System.Linq; using System.Text.RegularExpressions; +using AnyOfTypes; using JetBrains.Annotations; +using WireMock.Extensions; +using WireMock.Models; namespace WireMock.Matchers { @@ -10,14 +13,14 @@ namespace WireMock.Matchers /// public class WildcardMatcher : RegexMatcher { - private readonly string[] _patterns; + private readonly AnyOf[] _patterns; /// /// Initializes a new instance of the class. /// /// The pattern. /// IgnoreCase - public WildcardMatcher([NotNull] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) + public WildcardMatcher([NotNull] AnyOf pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) { } @@ -27,7 +30,7 @@ namespace WireMock.Matchers /// The match behaviour. /// The pattern. /// IgnoreCase - public WildcardMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) + public WildcardMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) { } @@ -36,7 +39,7 @@ namespace WireMock.Matchers /// /// The patterns. /// IgnoreCase - public WildcardMatcher([NotNull] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) + public WildcardMatcher([NotNull] AnyOf[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) { } @@ -47,19 +50,30 @@ namespace WireMock.Matchers /// The patterns. /// IgnoreCase /// Throw an exception when the internal matching fails because of invalid input. - public WildcardMatcher(MatchBehaviour matchBehaviour, [NotNull] string[] patterns, bool ignoreCase = false, bool throwException = false) : - base(matchBehaviour, patterns.Select(pattern => "^" + Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$").ToArray(), ignoreCase, throwException) + public WildcardMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf[] patterns, bool ignoreCase = false, bool throwException = false) : + base(matchBehaviour, CreateArray(patterns), ignoreCase, throwException) { _patterns = patterns; } /// - public override string[] GetPatterns() + public override AnyOf[] GetPatterns() { return _patterns; } /// public override string Name => "WildcardMatcher"; + + private static AnyOf[] CreateArray(AnyOf[] patterns) + { + return patterns.Select(pattern => new AnyOf( + new StringPattern + { + Pattern = "^" + Regex.Escape(pattern.GetPattern()).Replace(@"\*", ".*").Replace(@"\?", ".") + "$", + PatternAsFile = pattern.IsSecond ? pattern.Second.PatternAsFile : null + })) + .ToArray(); + } } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/XPathMatcher.cs b/src/WireMock.Net/Matchers/XPathMatcher.cs index ae8df174..3bfa7352 100644 --- a/src/WireMock.Net/Matchers/XPathMatcher.cs +++ b/src/WireMock.Net/Matchers/XPathMatcher.cs @@ -1,7 +1,10 @@ -using System; +using System; using System.Linq; using System.Xml; +using AnyOfTypes; using JetBrains.Annotations; +using WireMock.Extensions; +using WireMock.Models; using WireMock.Validation; #if !NETSTANDARD1_3 using Wmhelp.XPath2; @@ -15,7 +18,7 @@ namespace WireMock.Matchers /// public class XPathMatcher : IStringMatcher { - private readonly string[] _patterns; + private readonly AnyOf[] _patterns; /// public MatchBehaviour MatchBehaviour { get; } @@ -27,7 +30,7 @@ namespace WireMock.Matchers /// Initializes a new instance of the class. /// /// The patterns. - public XPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) + public XPathMatcher([NotNull] params AnyOf[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) { } @@ -37,7 +40,7 @@ namespace WireMock.Matchers /// The match behaviour. /// Throw an exception when the internal matching fails because of invalid input. /// The patterns. - public XPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns) + public XPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf[] patterns) { Check.NotNull(patterns, nameof(patterns)); @@ -56,9 +59,9 @@ namespace WireMock.Matchers { var nav = new XmlDocument { InnerXml = input }.CreateNavigator(); #if NETSTANDARD1_3 - match = MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.Evaluate($"boolean({p})")))); + match = MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.Evaluate($"boolean({p.GetPattern()})")))); #else - match = MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.XPath2Evaluate($"boolean({p})")))); + match = MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.XPath2Evaluate($"boolean({p.GetPattern()})")))); #endif } catch (Exception) @@ -74,7 +77,7 @@ namespace WireMock.Matchers } /// - public string[] GetPatterns() + public AnyOf[] GetPatterns() { return _patterns; } diff --git a/src/WireMock.Net/Models/StringPattern.cs b/src/WireMock.Net/Models/StringPattern.cs new file mode 100644 index 00000000..5a8a7be5 --- /dev/null +++ b/src/WireMock.Net/Models/StringPattern.cs @@ -0,0 +1,18 @@ +namespace WireMock.Models +{ + /// + /// StringPattern which defines the Pattern as a string, and optionally the filepath pattern file. + /// + public struct StringPattern + { + /// + /// The pattern as string. + /// + public string Pattern { get; set; } + + /// + /// The filepath (optionally) + /// + public string PatternAsFile { get; set; } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index c53d3099..38b311c7 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -1,13 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; +using AnyOfTypes; using JetBrains.Annotations; using SimMetrics.Net; using WireMock.Admin.Mappings; +using WireMock.Extensions; using WireMock.Matchers; +using WireMock.Models; using WireMock.Plugin; using WireMock.Settings; -using WireMock.Validation; namespace WireMock.Serialization { @@ -17,8 +19,7 @@ namespace WireMock.Serialization public MatcherMapper(IWireMockServerSettings settings) { - Check.NotNull(settings, nameof(settings)); - _settings = settings; + _settings = settings ?? throw new ArgumentNullException(nameof(settings)); } public IMatcher[] Map([CanBeNull] IEnumerable matchers) @@ -36,9 +37,8 @@ namespace WireMock.Serialization string[] parts = matcher.Name.Split('.'); string matcherName = parts[0]; string matcherType = parts.Length > 1 ? parts[1] : null; - - string[] stringPatterns = (matcher.Patterns != null ? matcher.Patterns : new[] { matcher.Pattern }).OfType().ToArray(); - MatchBehaviour matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch; + var stringPatterns = ParseStringPatterns(matcher); + var matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch; bool ignoreCase = matcher.IgnoreCase == true; bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true; @@ -68,12 +68,12 @@ namespace WireMock.Serialization return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails); case "JsonMatcher": - object value = matcher.Pattern ?? matcher.Patterns; - return new JsonMatcher(matchBehaviour, value, ignoreCase, throwExceptionWhenMatcherFails); + object valueForJsonMatcher = matcher.Pattern ?? matcher.Patterns; + return new JsonMatcher(matchBehaviour, valueForJsonMatcher, ignoreCase, throwExceptionWhenMatcherFails); case "JsonPartialMatcher": - object matcherValue = matcher.Pattern ?? matcher.Patterns; - return new JsonPartialMatcher(matchBehaviour, matcherValue, ignoreCase, throwExceptionWhenMatcherFails); + object valueForJsonPartialMatcher = matcher.Pattern ?? matcher.Patterns; + return new JsonPartialMatcher(matchBehaviour, valueForJsonPartialMatcher, ignoreCase, throwExceptionWhenMatcherFails); case "JsonPathMatcher": return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns); @@ -116,45 +116,85 @@ namespace WireMock.Serialization return null; } - object[] patterns = new object[0]; // Default empty array + bool? ignoreCase = matcher is IIgnoreCaseMatcher ignoreCaseMatcher ? ignoreCaseMatcher.IgnoreCase : (bool?)null; + bool? rejectOnMatch = matcher.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : (bool?)null; + + var model = new MatcherModel + { + RejectOnMatch = rejectOnMatch, + IgnoreCase = ignoreCase, + Name = matcher.Name + }; + switch (matcher) { // If the matcher is a IStringMatcher, get the patterns. case IStringMatcher stringMatcher: - patterns = stringMatcher.GetPatterns().Cast().ToArray(); + var stringPatterns = stringMatcher.GetPatterns(); + if (stringPatterns.Length == 1) + { + if (stringPatterns[0].IsFirst) + { + model.Pattern = stringPatterns[0].First; + } + else + { + model.Pattern = stringPatterns[0].Second.Pattern; + model.PatternAsFile = stringPatterns[0].Second.PatternAsFile; + } + } + else + { + model.Patterns = stringPatterns.Select(p => p.GetPattern()).Cast().ToArray(); + } break; // If the matcher is a IValueMatcher, get the value (can be string or object). case IValueMatcher valueMatcher: - patterns = new[] { valueMatcher.Value }; + model.Patterns = new[] { valueMatcher.Value }; break; // If the matcher is a ExactObjectMatcher, get the ValueAsObject or ValueAsBytes. case ExactObjectMatcher exactObjectMatcher: - patterns = new[] { exactObjectMatcher.ValueAsObject ?? exactObjectMatcher.ValueAsBytes }; + model.Patterns = new[] { exactObjectMatcher.ValueAsObject ?? exactObjectMatcher.ValueAsBytes }; break; } - bool? ignoreCase = matcher is IIgnoreCaseMatcher ignoreCaseMatcher ? ignoreCaseMatcher.IgnoreCase : (bool?)null; - - bool? rejectOnMatch = matcher.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : (bool?)null; - - return new MatcherModel - { - RejectOnMatch = rejectOnMatch, - IgnoreCase = ignoreCase, - Name = matcher.Name, - Pattern = patterns.Length == 1 ? patterns.First() : null, - Patterns = patterns.Length > 1 ? patterns : null - }; + return model; } - private ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, string stringPattern, bool throwException) + private AnyOf[] ParseStringPatterns(MatcherModel matcher) + { + if (matcher.Pattern is string patternAsString) + { + return new[] { new AnyOf(patternAsString) }; + } + + if (matcher.Pattern is IEnumerable patternAsStringArray) + { + return patternAsStringArray.ToAnyOfPatterns(); + } + + if (matcher.Patterns?.OfType() is IEnumerable patternsAsStringArray) + { + return patternsAsStringArray.ToAnyOfPatterns(); + } + + if (!string.IsNullOrEmpty(matcher.PatternAsFile)) + { + var pattern = _settings.FileSystemHandler.ReadFileAsString(matcher.PatternAsFile); + return new[] { new AnyOf(new StringPattern { Pattern = pattern, PatternAsFile = matcher.PatternAsFile }) }; + } + + return new AnyOf[0]; + } + + private ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, AnyOf stringPattern, bool throwException) { byte[] bytePattern; try { - bytePattern = Convert.FromBase64String(stringPattern); + bytePattern = Convert.FromBase64String(stringPattern.GetPattern()); } catch { diff --git a/src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs b/src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs index d603f4b1..5262f349 100644 --- a/src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs +++ b/src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs @@ -260,11 +260,13 @@ namespace WireMock.Server private void ProcessWireMockOrgJObjectAndUseIMatcher(JObject items, Action action) { - IMatcher matcher = null; + if (!(items.First is JProperty firstItem)) + { + return; + } - var firstItem = items.First as JProperty; - - if (firstItem?.Name == "equalToJson") + IMatcher matcher; + if (firstItem.Name == "equalToJson") { matcher = new JsonMatcher(firstItem.Value); } diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index eda841fd..6b8bf25c 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -1,137 +1,138 @@  - - Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape. - WireMock.Net - Stef Heyenrath - net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0 - true - WireMock.Net - WireMock.Net - tdd;mock;http;wiremock;test;server;unittest - WireMock - {D3804228-91F4-4502-9595-39584E5A01AD} - true - $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - true - - true - WireMock.Net.snk - - true - + true + WireMock.Net.snk + + true + - - - - + + + - - - true - + + + true + - - WireMock.Net.ruleset - + + WireMock.Net.ruleset + - - NETSTANDARD;USE_ASPNETCORE - + + NETSTANDARD;USE_ASPNETCORE + - - USE_ASPNETCORE - + + USE_ASPNETCORE + - - USE_ASPNETCORE;NET46 - + + USE_ASPNETCORE;NET46 + - - - - - - - - - + + + + + + + + + + - - - all - runtime; build; native; contentfiles; analyzers - - + + + all + runtime; build; native; contentfiles; analyzers + + - - - + + + - - - + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - + + + - - - + + + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + \ No newline at end of file diff --git a/src/WireMock.Org.Abstractions/WireMock.Org.Abstractions.csproj b/src/WireMock.Org.Abstractions/WireMock.Org.Abstractions.csproj index 77b786a8..f2a56474 100644 --- a/src/WireMock.Org.Abstractions/WireMock.Org.Abstractions.csproj +++ b/src/WireMock.Org.Abstractions/WireMock.Org.Abstractions.csproj @@ -1,4 +1,4 @@ - + Commonly used interfaces, models, enumerations and types. @@ -33,7 +33,7 @@ - + diff --git a/test/WireMock.Net.Tests/Handlers/LocalFileSystemHandlerTests.cs b/test/WireMock.Net.Tests/Handlers/LocalFileSystemHandlerTests.cs index b8d06c95..3da66fe2 100644 --- a/test/WireMock.Net.Tests/Handlers/LocalFileSystemHandlerTests.cs +++ b/test/WireMock.Net.Tests/Handlers/LocalFileSystemHandlerTests.cs @@ -1,6 +1,6 @@ -using NFluent; using System; using System.IO; +using NFluent; using WireMock.Handlers; using Xunit; @@ -65,6 +65,13 @@ namespace WireMock.Net.Tests.Handlers Check.ThatCode(() => _sut.ReadFile(null)).Throws(); } + [Fact] + public void LocalFileSystemHandler_ReadFileAsString_ThrowsArgumentNullException() + { + // Act + Check.ThatCode(() => _sut.ReadFileAsString(null)).Throws(); + } + [Fact] public void LocalFileSystemHandler_WriteFile_ThrowsArgumentNullException() { diff --git a/test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs index fbc2c8fb..a63d0c0b 100644 --- a/test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/CSharpCodeMatcherTests.cs @@ -1,4 +1,4 @@ -using NFluent; +using NFluent; using WireMock.Matchers; using Xunit; @@ -83,7 +83,7 @@ namespace WireMock.Net.Tests.Matchers var matcher = new CSharpCodeMatcher("x"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert Check.That(patterns).ContainsExactly("x"); diff --git a/test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs index 890a05e7..24a75f05 100644 --- a/test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/ContentTypeMatcherTests.cs @@ -1,4 +1,5 @@ -using NFluent; +using AnyOfTypes; +using NFluent; using WireMock.Matchers; using Xunit; @@ -49,7 +50,7 @@ namespace WireMock.Net.Tests.Matchers var matcher = new ContentTypeMatcher("x"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert Check.That(patterns).ContainsExactly("x"); diff --git a/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs index 1f58d1c8..46608a1f 100644 --- a/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/ExactMatcherTests.cs @@ -1,4 +1,4 @@ -using NFluent; +using NFluent; using WireMock.Matchers; using Xunit; @@ -26,7 +26,7 @@ namespace WireMock.Net.Tests.Matchers var matcher = new ExactMatcher("X"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert Check.That(patterns).ContainsExactly("X"); diff --git a/test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs index 22f4d407..eab4af1d 100644 --- a/test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JmesPathMatcherTests.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Linq; using NFluent; using WireMock.Matchers; using Xunit; @@ -27,7 +27,7 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JmesPathMatcher("X"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert Check.That(patterns).ContainsExactly("X"); diff --git a/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs index 2eca285b..262c9a9f 100644 --- a/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Linq; using NFluent; using WireMock.Matchers; using Xunit; @@ -27,7 +27,7 @@ namespace WireMock.Net.Tests.Matchers var matcher = new JsonPathMatcher("X"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert Check.That(patterns).ContainsExactly("X"); diff --git a/test/WireMock.Net.Tests/Matchers/LinqMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/LinqMatcherTests.cs index 85549ae6..1f15de17 100644 --- a/test/WireMock.Net.Tests/Matchers/LinqMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/LinqMatcherTests.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Linq; using NFluent; using WireMock.Matchers; using Xunit; @@ -103,7 +103,7 @@ namespace WireMock.Net.Tests.Matchers var matcher = new LinqMatcher("x"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert Check.That(patterns).ContainsExactly("x"); diff --git a/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs index 6f2c7aee..5271ccd4 100644 --- a/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/RegexMatcherTests.cs @@ -1,4 +1,4 @@ -using NFluent; +using NFluent; using WireMock.Matchers; using Xunit; @@ -26,7 +26,7 @@ namespace WireMock.Net.Tests.Matchers var matcher = new RegexMatcher("X"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert Check.That(patterns).ContainsExactly("X"); diff --git a/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs index eaa8c819..e792578d 100644 --- a/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/SimMetricsMatcherTests.cs @@ -1,4 +1,4 @@ -using NFluent; +using NFluent; using WireMock.Matchers; using Xunit; @@ -26,7 +26,7 @@ namespace WireMock.Net.Tests.Matchers var matcher = new SimMetricsMatcher("X"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert Check.That(patterns).ContainsExactly("X"); diff --git a/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs b/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs index e2d5e636..7fdefc2d 100644 --- a/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs +++ b/test/WireMock.Net.Tests/Matchers/WildcardMatcherTest.cs @@ -1,35 +1,55 @@ -using NFluent; +using AnyOfTypes; +using FluentAssertions; +using NFluent; using WireMock.Matchers; +using WireMock.Models; using Xunit; namespace WireMock.Net.Tests.Matchers { public class WildcardMatcherTest { + [Fact] + public void WildcardMatcher_IsMatch_With_StringMatcher_And_StringPattern() + { + // Arrange + var pattern = new StringPattern + { + Pattern = "*", + PatternAsFile = "pf" + }; + + // Act + var matcher = new WildcardMatcher(pattern); + + // Assert + matcher.IsMatch("a").Should().Be(1.0d); + } + [Fact] public void WildcardMatcher_IsMatch_Positive() { var tests = new[] { - new {p = "*", i = ""}, - new {p = "?", i = " "}, - new {p = "*", i = "a"}, - new {p = "*", i = "ab"}, - new {p = "?", i = "a"}, - new {p = "*?", i = "abc"}, - new {p = "?*", i = "abc"}, - new {p = "abc", i = "abc"}, - new {p = "abc*", i = "abc"}, - new {p = "abc*", i = "abcd"}, - new {p = "*abc*", i = "abc"}, - new {p = "*a*bc*", i = "abc"}, - new {p = "*a*b?", i = "aXXXbc"} + new { p = "*", i = "" }, + new { p = "?", i = " "}, + new { p = "*", i = "a "}, + new { p = "*", i = "ab" }, + new { p = "?", i = "a" }, + new { p = "*?", i = "abc" }, + new { p = "?*", i = "abc" }, + new { p = "abc", i = "abc" }, + new { p = "abc*", i = "abc" }, + new { p = "abc*", i = "abcd" }, + new { p = "*abc*", i = "abc" }, + new { p = "*a*bc*", i = "abc" }, + new { p = "*a*b?", i = "aXXXbc" } }; foreach (var test in tests) { var matcher = new WildcardMatcher(test.p); - Check.That(matcher.IsMatch(test.i)).IsEqualTo(1.0d); + matcher.IsMatch(test.i).Should().Be(1.0d, $"Pattern '{test.p}' with value '{test.i}' should be 1.0"); } } @@ -38,17 +58,17 @@ namespace WireMock.Net.Tests.Matchers { var tests = new[] { - new {p = "*a", i = ""}, - new {p = "a*", i = ""}, - new {p = "?", i = ""}, - new {p = "*b*", i = "a"}, - new {p = "b*a", i = "ab"}, - new {p = "??", i = "a"}, - new {p = "*?", i = ""}, - new {p = "??*", i = "a"}, - new {p = "*abc", i = "abX"}, - new {p = "*abc*", i = "Xbc"}, - new {p = "*a*bc*", i = "ac"} + new { p = "*a", i = "" }, + new { p = "a*", i = "" }, + new { p = "?", i = "" }, + new { p = "*b*", i = "a" }, + new { p = "b*a", i = "ab" }, + new { p = "??", i = "a" }, + new { p = "*?", i = "" }, + new { p = "??*", i = "a" }, + new { p = "*abc", i = "abX" }, + new { p = "*abc*", i = "Xbc" }, + new { p = "*a*bc*", i = "ac" } }; foreach (var test in tests) @@ -78,10 +98,10 @@ namespace WireMock.Net.Tests.Matchers var matcher = new WildcardMatcher("x"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert - Check.That(patterns).ContainsExactly("x"); + Check.That(patterns).ContainsExactly(new AnyOf("x")); } [Fact] diff --git a/test/WireMock.Net.Tests/Matchers/XPathMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/XPathMatcherTests.cs index ee4d6a03..d67806f8 100644 --- a/test/WireMock.Net.Tests/Matchers/XPathMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/XPathMatcherTests.cs @@ -1,4 +1,4 @@ -using NFluent; +using NFluent; using WireMock.Matchers; using Xunit; @@ -26,7 +26,7 @@ namespace WireMock.Net.Tests.Matchers var matcher = new XPathMatcher("X"); // Act - string[] patterns = matcher.GetPatterns(); + var patterns = matcher.GetPatterns(); // Assert Check.That(patterns).ContainsExactly("X"); diff --git a/test/WireMock.Net.Tests/Plugin/PluginLoaderTests.cs b/test/WireMock.Net.Tests/Plugin/PluginLoaderTests.cs index fe0f1262..69843a47 100644 --- a/test/WireMock.Net.Tests/Plugin/PluginLoaderTests.cs +++ b/test/WireMock.Net.Tests/Plugin/PluginLoaderTests.cs @@ -1,6 +1,8 @@ -using System; +using System; +using AnyOfTypes; using FluentAssertions; using WireMock.Matchers; +using WireMock.Models; using WireMock.Plugin; using Xunit; @@ -16,7 +18,8 @@ namespace WireMock.Net.Tests.Plugin public void Load_Valid() { // Act - var result = PluginLoader.Load(MatchBehaviour.AcceptOnMatch, "x"); + AnyOf pattern = "x"; + var result = PluginLoader.Load(MatchBehaviour.AcceptOnMatch, pattern); // Assert result.Should().NotBeNull(); diff --git a/test/WireMock.Net.Tests/RequestWithPathTests.cs b/test/WireMock.Net.Tests/RequestWithPathTests.cs index 163f8174..8d3122e9 100644 --- a/test/WireMock.Net.Tests/RequestWithPathTests.cs +++ b/test/WireMock.Net.Tests/RequestWithPathTests.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using NFluent; using WireMock.Matchers; using Xunit; @@ -88,7 +88,7 @@ namespace WireMock.Net.Tests } [Fact] - public void Request_WithPathRegexMatcher() + public void Request_WithPathRegexMatcher_HasMatch() { // given var spec = Request.Create().WithPath(new RegexMatcher("^/foo")); @@ -102,7 +102,7 @@ namespace WireMock.Net.Tests } [Fact] - public void Request_WithPathRegex_false() + public void Request_WithPathRegexMatcher_HasNoMatch() { // given var spec = Request.Create().WithPath("/foo"); @@ -115,6 +115,25 @@ namespace WireMock.Net.Tests Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsNotEqualTo(1.0); } + [Fact] + public void Request_WithPathRegexMatcher_WithPatternAsFile_HasMatch() + { + // Arrange + var pattern = new StringPattern + { + Pattern = "^/foo", + PatternAsFile = "c:\\x.txt" + }; + var spec = Request.Create().WithPath(new RegexMatcher(pattern)); + + // when + var request = new RequestMessage(new UrlDetails("http://localhost/foo/bar"), "blabla", ClientIp); + + // then + var requestMatchResult = new RequestMatchResult(); + Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); + } + [Fact] public void Should_specify_requests_matching_given_path_and_method_delete() { diff --git a/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs index d1d9f049..18254ea1 100644 --- a/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs +++ b/test/WireMock.Net.Tests/Serialization/MatcherMapperTests.cs @@ -1,9 +1,11 @@ -using System; +using System; +using AnyOfTypes; using FluentAssertions; using Moq; using NFluent; using WireMock.Admin.Mappings; using WireMock.Matchers; +using WireMock.Models; using WireMock.Serialization; using WireMock.Settings; using Xunit; @@ -60,7 +62,7 @@ namespace WireMock.Net.Tests.Serialization // Assign var matcherMock = new Mock(); matcherMock.Setup(m => m.Name).Returns("test"); - matcherMock.Setup(m => m.GetPatterns()).Returns(new[] { "p1", "p2" }); + matcherMock.Setup(m => m.GetPatterns()).Returns(new AnyOf[] { "p1", "p2" }); // Act var model = _sut.Map(matcherMock.Object); @@ -69,7 +71,30 @@ namespace WireMock.Net.Tests.Serialization model.IgnoreCase.Should().BeNull(); model.Name.Should().Be("test"); model.Pattern.Should().BeNull(); - model.Patterns.Should().Contain("p1", "p2"); + 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] @@ -301,5 +326,24 @@ namespace WireMock.Net.Tests.Serialization 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); + } } } diff --git a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs index a87b554f..cef96704 100644 --- a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs +++ b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs @@ -1,8 +1,12 @@ using System; +using AnyOfTypes; using FluentAssertions; +using Moq; using NFluent; using WireMock.Admin.Mappings; +using WireMock.Handlers; using WireMock.Matchers; +using WireMock.Models; using WireMock.Serialization; using WireMock.Settings; using Xunit; @@ -193,7 +197,7 @@ namespace WireMock.Net.Tests.Serialization } [Fact] - public void MatcherModelMapper_Map_WildcardMatcher() + public void MatcherModelMapper_Map_WildcardMatcher_IgnoreCase() { // Assign var model = new MatcherModel @@ -211,6 +215,40 @@ namespace WireMock.Net.Tests.Serialization Check.That(matcher.IsMatch("X")).IsEqualTo(0.5d); } + [Fact] + public void MatcherModelMapper_Map_WildcardMatcher_With_PatternAsFile() + { + // 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); + + var model = new MatcherModel + { + Name = "WildcardMatcher", + PatternAsFile = file + }; + + var settings = new WireMockServerSettings + { + FileSystemHandler = fileSystemHandleMock.Object + }; + var sut = new MatcherMapper(settings); + + // 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() { diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj index 2b50f371..0ed852d7 100644 --- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj +++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj @@ -60,6 +60,7 @@ +