Implement PatternAsFile for StringMatcher (#651)

This commit is contained in:
Stef Heyenrath
2021-10-15 08:54:12 +02:00
committed by GitHub
parent a2a581c84b
commit 57cc616aa3
43 changed files with 817 additions and 491 deletions

View File

@@ -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));
}
/// <inheritdoc cref="IFileSystemHandler.ReadFileAsString"/>
public string ReadFileAsString(string path)
{
return File.ReadAllText(path);
}
/// <summary>
/// Adjusts the path to the MappingFolder.
/// </summary>

View File

@@ -36,6 +36,9 @@
<ApplicationIcon>..\..\resources\WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="AnyOf, Version=0.2.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
<HintPath>..\..\packages\AnyOf.0.2.0\lib\net45\AnyOf.dll</HintPath>
</Reference>
<Reference Include="Handlebars, Version=2.0.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.2.0.4\lib\net452\Handlebars.dll</HintPath>
</Reference>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AnyOf" version="0.2.0" targetFramework="net452" />
<package id="Handlebars.Net" version="2.0.4" targetFramework="net452" />
<package id="Handlebars.Net.Helpers" version="2.1.1-preview-01" targetFramework="net452" />
<package id="Handlebars.Net.Helpers.Core" version="2.1.1-preview-01" targetFramework="net452" />

View File

@@ -35,6 +35,9 @@
<StartupObject>WireMock.Net.ConsoleApplication.Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="AnyOf, Version=0.2.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
<HintPath>..\..\packages\AnyOf.0.2.0\lib\net45\AnyOf.dll</HintPath>
</Reference>
<Reference Include="Handlebars, Version=2.0.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.2.0.4\lib\net46\Handlebars.dll</HintPath>
</Reference>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AnyOf" version="0.2.0" targetFramework="net461" />
<package id="Handlebars.Net" version="2.0.4" targetFramework="net461" />
<package id="Handlebars.Net.Helpers" version="2.1.1-preview-01" targetFramework="net461" />
<package id="Handlebars.Net.Helpers.Core" version="2.1.1-preview-01" targetFramework="net461" />

View File

@@ -39,6 +39,9 @@
<StartupObject>WireMock.Net.ConsoleApplication.Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="AnyOf, Version=0.2.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
<HintPath>..\..\packages\AnyOf.0.2.0\lib\net45\AnyOf.dll</HintPath>
</Reference>
<Reference Include="Fare, Version=2.1.0.0, Culture=neutral, PublicKeyToken=ea68d375bf33a7c8, processorArchitecture=MSIL">
<HintPath>..\..\packages\Fare.2.1.1\lib\net35\Fare.dll</HintPath>
</Reference>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AnyOf" version="0.2.0" targetFramework="net472" />
<package id="Fare" version="2.1.1" targetFramework="net472" />
<package id="Handlebars.Net" version="2.0.4" targetFramework="net472" />
<package id="Handlebars.Net.Helpers" version="2.1.1-preview-01" targetFramework="net472" />

View File

@@ -1,4 +1,4 @@
namespace WireMock.Admin.Mappings
namespace WireMock.Admin.Mappings
{
/// <summary>
/// MatcherModel
@@ -12,15 +12,20 @@
public string Name { get; set; }
/// <summary>
/// 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.
/// </summary>
public object Pattern { get; set; }
/// <summary>
/// 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.
/// </summary>
public object[] Patterns { get; set; }
/// <summary>
/// Gets or sets the pattern as a file.
/// </summary>
public string PatternAsFile { get; set; }
/// <summary>
/// Gets or sets the ignore case.
/// </summary>

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
using System.Collections.Generic;
namespace WireMock.Handlers
@@ -89,5 +89,12 @@ namespace WireMock.Handlers
/// <param name="filename">The filename.</param>
/// <returns>The file content as bytes.</returns>
byte[] ReadFile([NotNull] string filename);
/// <summary>
/// Read a file as string.
/// </summary>
/// <param name="filename">The filename.</param>
/// <returns>The file content as a string.</returns>
string ReadFileAsString([NotNull] string filename);
}
}

View File

@@ -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
{
/// <summary>
/// CSharpCode / CS-Script Matcher
/// </summary>
/// <inheritdoc cref="ICSharpCodeMatcher"/>
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; }
/// <inheritdoc cref="IMatcher.ThrowException"/>
public bool ThrowException { get; }
private readonly string[] _patterns;
/// <summary>
/// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public CSharpCodeMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="patterns">The patterns.</param>
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
{
/// <summary>
/// CSharpCode / CS-Script Matcher
/// </summary>
/// <inheritdoc cref="ICSharpCodeMatcher"/>
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; }
/// <inheritdoc cref="IMatcher.ThrowException"/>
public bool ThrowException { get; }
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <summary>
/// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public CSharpCodeMatcher([NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="patterns">The patterns.</param>
public CSharpCodeMatcher(MatchBehaviour matchBehaviour, [NotNull] params AnyOf<string, StringPattern>[] 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();
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc cref="IMatcher.Name"/>
public string Name => "CSharpCodeMatcher";
}
}
stringBuilder.AppendLine();
stringBuilder.AppendFormat(template, pattern);
return stringBuilder.ToString();
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc cref="IMatcher.Name"/>
public string Name => "CSharpCodeMatcher";
}
}

View File

@@ -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<string, StringPattern> value)
{
return value.IsFirst ? value.First : value.Second.Pattern;
}
public static AnyOf<string, StringPattern>[] ToAnyOfPatterns(this IEnumerable<string> patterns)
{
return patterns.Select(p => p.ToAnyOfPattern()).ToArray();
}
public static AnyOf<string, StringPattern> ToAnyOfPattern(this string pattern)
{
return new AnyOf<string, StringPattern>(pattern);
}
}
}

View File

@@ -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));
}
/// <inheritdoc cref="IFileSystemHandler.ReadFileAsString"/>
public string ReadFileAsString(string filename)
{
return File.ReadAllText(AdjustPath(Check.NotNullOrEmpty(filename, nameof(filename))));
}
/// <summary>
/// Adjusts the path to the MappingFolder.
/// </summary>
@@ -140,4 +146,4 @@ namespace WireMock.Handlers
return Path.Combine(GetMappingFolder(), filename);
}
}
}
}

View File

@@ -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
/// <seealso cref="RegexMatcher" />
public class ContentTypeMatcher : WildcardMatcher
{
private readonly string[] _patterns;
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher([NotNull] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
public ContentTypeMatcher([NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
{
}
@@ -26,7 +28,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
{
}
@@ -35,7 +37,7 @@ namespace WireMock.Matchers
/// </summary>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher([NotNull] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
public ContentTypeMatcher([NotNull] AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
{
}
@@ -46,7 +48,7 @@ namespace WireMock.Matchers
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] string[] patterns, bool ignoreCase = false, bool throwException = false) :
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false, bool throwException = false) :
base(matchBehaviour, patterns, ignoreCase, throwException)
{
_patterns = patterns;
@@ -64,7 +66,7 @@ namespace WireMock.Matchers
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public override string[] GetPatterns()
public override AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}

View File

@@ -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
/// <seealso cref="IStringMatcher" />
public class ExactMatcher : IStringMatcher
{
private readonly string[] _values;
private readonly AnyOf<string, StringPattern>[] _values;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
public MatchBehaviour MatchBehaviour { get; }
@@ -22,7 +25,7 @@ namespace WireMock.Matchers
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="values">The values.</param>
public ExactMatcher([NotNull] params string[] values) : this(MatchBehaviour.AcceptOnMatch, false, values)
public ExactMatcher([NotNull] params AnyOf<string, StringPattern>[] values) : this(MatchBehaviour.AcceptOnMatch, false, values)
{
}
@@ -32,9 +35,9 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="values">The values.</param>
public ExactMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] values)
public ExactMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] 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)));
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _values;
}

View File

@@ -1,4 +1,7 @@
namespace WireMock.Matchers
using AnyOfTypes;
using WireMock.Models;
namespace WireMock.Matchers
{
/// <summary>
/// IStringMatcher
@@ -17,6 +20,6 @@
/// Gets the patterns.
/// </summary>
/// <returns>Patterns</returns>
string[] GetPatterns();
AnyOf<string, StringPattern>[] GetPatterns();
}
}

View File

@@ -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
/// <seealso cref="IObjectMatcher" />
public class JsonPathMatcher : IStringMatcher, IObjectMatcher
{
private readonly string[] _patterns;
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
public MatchBehaviour MatchBehaviour { get; }
@@ -25,7 +28,15 @@ namespace WireMock.Matchers
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
public JsonPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns.ToAnyOfPatterns())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher([NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
{
}
@@ -35,7 +46,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns)
public JsonPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] patterns)
{
Check.NotNull(patterns, nameof(patterns));
@@ -94,7 +105,7 @@ namespace WireMock.Matchers
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
public AnyOf<string, StringPattern>[] 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));
}
}
}

View File

@@ -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
/// </summary>
public class JmesPathMatcher : IStringMatcher, IObjectMatcher
{
private readonly string[] _patterns;
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
public MatchBehaviour MatchBehaviour { get; }
@@ -23,7 +26,15 @@ namespace WireMock.Matchers
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
public JmesPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns.ToAnyOfPatterns())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher([NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
{
}
@@ -32,7 +43,7 @@ namespace WireMock.Matchers
/// </summary>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(bool throwException = false, [NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, throwException, patterns)
public JmesPathMatcher(bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, throwException, patterns)
{
}
@@ -42,7 +53,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns)
public JmesPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] 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
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}

View File

@@ -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
/// <inheritdoc cref="IStringMatcher"/>
public class LinqMatcher : IObjectMatcher, IStringMatcher
{
private readonly string[] _patterns;
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
public MatchBehaviour MatchBehaviour { get; }
@@ -24,7 +28,7 @@ namespace WireMock.Matchers
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
public LinqMatcher([NotNull] string pattern) : this(new[] { pattern })
public LinqMatcher([NotNull] AnyOf<string, StringPattern> pattern) : this(new[] { pattern })
{
}
@@ -32,7 +36,7 @@ namespace WireMock.Matchers
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public LinqMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
public LinqMatcher([NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
{
}
@@ -41,7 +45,7 @@ namespace WireMock.Matchers
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
public LinqMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern) : this(matchBehaviour, false, pattern)
public LinqMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern> pattern) : this(matchBehaviour, false, pattern)
{
}
@@ -51,8 +55,10 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
public LinqMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns)
public LinqMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] 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
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}

View File

@@ -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
/// <inheritdoc cref="IIgnoreCaseMatcher"/>
public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
{
private readonly string[] _patterns;
private readonly AnyOf<string, StringPattern>[] _patterns;
private readonly Regex[] _expressions;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
@@ -27,7 +30,7 @@ namespace WireMock.Matchers
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
public RegexMatcher([NotNull, RegexPattern] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
public RegexMatcher([NotNull, RegexPattern] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
{
}
@@ -37,7 +40,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
{
}
@@ -46,7 +49,7 @@ namespace WireMock.Matchers
/// </summary>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
public RegexMatcher([NotNull, RegexPattern] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
public RegexMatcher([NotNull, RegexPattern] AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
{
}
@@ -57,7 +60,7 @@ namespace WireMock.Matchers
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] string[] patterns, bool ignoreCase = false, bool throwException = false)
public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] AnyOf<string, StringPattern>[] 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();
}
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
@@ -99,7 +102,7 @@ namespace WireMock.Matchers
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public virtual string[] GetPatterns()
public virtual AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}

View File

@@ -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
/// <seealso cref="IStringMatcher" />
public class SimMetricsMatcher : IStringMatcher
{
private readonly string[] _patterns;
private readonly AnyOf<string, StringPattern>[] _patterns;
private readonly SimMetricType _simMetricType;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
@@ -27,7 +30,7 @@ namespace WireMock.Matchers
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="simMetricType">The SimMetric Type</param>
public SimMetricsMatcher([NotNull] string pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(new[] { pattern }, simMetricType)
public SimMetricsMatcher([NotNull] AnyOf<string, StringPattern> pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(new[] { pattern }, simMetricType)
{
}
@@ -37,7 +40,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="simMetricType">The SimMetric Type</param>
public SimMetricsMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(matchBehaviour, new[] { pattern }, simMetricType)
public SimMetricsMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern> pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(matchBehaviour, new[] { pattern }, simMetricType)
{
}
@@ -46,7 +49,16 @@ namespace WireMock.Matchers
/// </summary>
/// <param name="patterns">The patterns.</param>
/// <param name="simMetricType">The SimMetric Type</param>
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)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SimMetricsMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
/// <param name="simMetricType">The SimMetric Type</param>
public SimMetricsMatcher([NotNull] AnyOf<string, StringPattern>[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein) : this(MatchBehaviour.AcceptOnMatch, patterns, simMetricType)
{
}
@@ -57,9 +69,9 @@ namespace WireMock.Matchers
/// <param name="patterns">The patterns.</param>
/// <param name="simMetricType">The SimMetric Type</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
public SimMetricsMatcher(MatchBehaviour matchBehaviour, [NotNull] string[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein, bool throwException = false)
public SimMetricsMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern>[] 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
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
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
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}

View File

@@ -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
/// <seealso cref="RegexMatcher" />
public class WildcardMatcher : RegexMatcher
{
private readonly string[] _patterns;
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <summary>
/// Initializes a new instance of the <see cref="WildcardMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase</param>
public WildcardMatcher([NotNull] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
public WildcardMatcher([NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
{
}
@@ -27,7 +30,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase</param>
public WildcardMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
public WildcardMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
{
}
@@ -36,7 +39,7 @@ namespace WireMock.Matchers
/// </summary>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase</param>
public WildcardMatcher([NotNull] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
public WildcardMatcher([NotNull] AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
{
}
@@ -47,19 +50,30 @@ namespace WireMock.Matchers
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
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<string, StringPattern>[] patterns, bool ignoreCase = false, bool throwException = false) :
base(matchBehaviour, CreateArray(patterns), ignoreCase, throwException)
{
_patterns = patterns;
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public override string[] GetPatterns()
public override AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc cref="IMatcher.Name"/>
public override string Name => "WildcardMatcher";
private static AnyOf<string, StringPattern>[] CreateArray(AnyOf<string, StringPattern>[] patterns)
{
return patterns.Select(pattern => new AnyOf<string, StringPattern>(
new StringPattern
{
Pattern = "^" + Regex.Escape(pattern.GetPattern()).Replace(@"\*", ".*").Replace(@"\?", ".") + "$",
PatternAsFile = pattern.IsSecond ? pattern.Second.PatternAsFile : null
}))
.ToArray();
}
}
}

View File

@@ -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
/// <seealso cref="IStringMatcher" />
public class XPathMatcher : IStringMatcher
{
private readonly string[] _patterns;
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
public MatchBehaviour MatchBehaviour { get; }
@@ -27,7 +30,7 @@ namespace WireMock.Matchers
/// Initializes a new instance of the <see cref="XPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public XPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
public XPathMatcher([NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
{
}
@@ -37,7 +40,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="patterns">The patterns.</param>
public XPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns)
public XPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] 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
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}

View File

@@ -0,0 +1,18 @@
namespace WireMock.Models
{
/// <summary>
/// StringPattern which defines the Pattern as a string, and optionally the filepath pattern file.
/// </summary>
public struct StringPattern
{
/// <summary>
/// The pattern as string.
/// </summary>
public string Pattern { get; set; }
/// <summary>
/// The filepath (optionally)
/// </summary>
public string PatternAsFile { get; set; }
}
}

View File

@@ -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<MatcherModel> 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<string>().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<object>().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<object>().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<string, StringPattern>[] ParseStringPatterns(MatcherModel matcher)
{
if (matcher.Pattern is string patternAsString)
{
return new[] { new AnyOf<string, StringPattern>(patternAsString) };
}
if (matcher.Pattern is IEnumerable<string> patternAsStringArray)
{
return patternAsStringArray.ToAnyOfPatterns();
}
if (matcher.Patterns?.OfType<string>() is IEnumerable<string> patternsAsStringArray)
{
return patternsAsStringArray.ToAnyOfPatterns();
}
if (!string.IsNullOrEmpty(matcher.PatternAsFile))
{
var pattern = _settings.FileSystemHandler.ReadFileAsString(matcher.PatternAsFile);
return new[] { new AnyOf<string, StringPattern>(new StringPattern { Pattern = pattern, PatternAsFile = matcher.PatternAsFile }) };
}
return new AnyOf<string, StringPattern>[0];
}
private ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> stringPattern, bool throwException)
{
byte[] bytePattern;
try
{
bytePattern = Convert.FromBase64String(stringPattern);
bytePattern = Convert.FromBase64String(stringPattern.GetPattern());
}
catch
{

View File

@@ -260,11 +260,13 @@ namespace WireMock.Server
private void ProcessWireMockOrgJObjectAndUseIMatcher(JObject items, Action<IMatcher> 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);
}

View File

@@ -1,137 +1,138 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description>
<AssemblyTitle>WireMock.Net</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net</AssemblyName>
<PackageId>WireMock.Net</PackageId>
<PackageTags>tdd;mock;http;wiremock;test;server;unittest</PackageTags>
<RootNamespace>WireMock</RootNamespace>
<ProjectGuid>{D3804228-91F4-4502-9595-39584E5A01AD}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<!--<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<PropertyGroup>
<Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description>
<AssemblyTitle>WireMock.Net</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net</AssemblyName>
<PackageId>WireMock.Net</PackageId>
<PackageTags>tdd;mock;http;wiremock;test;server;unittest</PackageTags>
<RootNamespace>WireMock</RootNamespace>
<ProjectGuid>{D3804228-91F4-4502-9595-39584E5A01AD}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<!--<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>-->
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<!--<ItemGroup>
<!--<ItemGroup>
<None Include="WireMock.Net-Logo.png" Pack="true" PackagePath="../../"/>
</ItemGroup>-->
<!-- https://github.com/aspnet/RoslynCodeDomProvider/issues/51 -->
<!-- This is needed else we cannot build net452 in Azure DevOps Pipeline -->
<!--<Target Name="CheckIfShouldKillVBCSCompiler" />-->
<!-- https://github.com/aspnet/RoslynCodeDomProvider/issues/51 -->
<!-- This is needed else we cannot build net452 in Azure DevOps Pipeline -->
<!--<Target Name="CheckIfShouldKillVBCSCompiler" />-->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.3' or '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1'">
<DefineConstants>NETSTANDARD;USE_ASPNETCORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.3' or '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1'">
<DefineConstants>NETSTANDARD;USE_ASPNETCORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1' or '$(TargetFramework)' == 'netcoreapp2.2' or '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0'">
<DefineConstants>USE_ASPNETCORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1' or '$(TargetFramework)' == 'netcoreapp2.2' or '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0'">
<DefineConstants>USE_ASPNETCORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net461'">
<DefineConstants>USE_ASPNETCORE;NET46</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net461'">
<DefineConstants>USE_ASPNETCORE;NET46</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.12" />
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.12" />
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
<PackageReference Include="AnyOf" Version="0.2.0" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<PackageReference Include="SonarAnalyzer.CSharp" Version="7.8.0.7320">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<PackageReference Include="SonarAnalyzer.CSharp" Version="7.8.0.7320">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard1.3' ">
<PackageReference Include="XPath2.Extensions" Version="1.1.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard1.3' ">
<PackageReference Include="XPath2.Extensions" Version="1.1.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net452' ">
<!-- Required for WebRequestHandler -->
<Reference Include="System.Net.Http.WebRequest" />
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net452' ">
<!-- Required for WebRequestHandler -->
<Reference Include="System.Net.Http.WebRequest" />
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
</ItemGroup>
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
<PackageReference Include="Microsoft.Owin" Version="4.0.0" />
<PackageReference Include="Microsoft.Owin.Host.HttpListener" Version="4.0.0" />
<PackageReference Include="Microsoft.Owin.Hosting" Version="4.0.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
<PackageReference Include="Microsoft.Owin" Version="4.0.0" />
<PackageReference Include="Microsoft.Owin.Host.HttpListener" Version="4.0.0" />
<PackageReference Include="Microsoft.Owin.Hosting" Version="4.0.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<!-- https://github.com/WireMock-Net/WireMock.Net/issues/507 -->
<PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
</ItemGroup>
<!-- https://github.com/WireMock-Net/WireMock.Net/issues/507 -->
<PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.7" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="1.1.3" />
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
<PackageReference Include="System.Xml.XPath.XmlDocument" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.7" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="1.1.3" />
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
<PackageReference Include="System.Xml.XPath.XmlDocument" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' ">
<PackageReference Include="Scriban.Signed" Version="3.3.2" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' ">
<PackageReference Include="Scriban.Signed" Version="3.3.2" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<!-- https://github.com/WireMock-Net/WireMock.Net/issues/507 -->
<PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
</ItemGroup>
<!-- https://github.com/WireMock-Net/WireMock.Net/issues/507 -->
<PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Scriban.Signed" Version="3.3.2" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Scriban.Signed" Version="3.3.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Handlebars.Net.Helpers" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.2.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Handlebars.Net.Helpers" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.2.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
<ProjectReference Include="..\WireMock.Org.Abstractions\WireMock.Org.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
<ProjectReference Include="..\WireMock.Org.Abstractions\WireMock.Org.Abstractions.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Commonly used interfaces, models, enumerations and types.</Description>
@@ -33,7 +33,7 @@
</PropertyGroup>
<ItemGroup>
<!--<PackageReference Include="AnyOf" Version="0.0.23" />-->
<!--<PackageReference Include="AnyOf" Version="0.1.0" />-->
<PackageReference Include="JetBrains.Annotations" Version="2021.2.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>

View File

@@ -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<ArgumentNullException>();
}
[Fact]
public void LocalFileSystemHandler_ReadFileAsString_ThrowsArgumentNullException()
{
// Act
Check.ThatCode(() => _sut.ReadFileAsString(null)).Throws<ArgumentNullException>();
}
[Fact]
public void LocalFileSystemHandler_WriteFile_ThrowsArgumentNullException()
{

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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<string, StringPattern>("x"));
}
[Fact]

View File

@@ -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");

View File

@@ -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<ICSharpCodeMatcher>(MatchBehaviour.AcceptOnMatch, "x");
AnyOf<string, StringPattern> pattern = "x";
var result = PluginLoader.Load<ICSharpCodeMatcher>(MatchBehaviour.AcceptOnMatch, pattern);
// Assert
result.Should().NotBeNull();

View File

@@ -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()
{

View File

@@ -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<IStringMatcher>();
matcherMock.Setup(m => m.Name).Returns("test");
matcherMock.Setup(m => m.GetPatterns()).Returns(new[] { "p1", "p2" });
matcherMock.Setup(m => m.GetPatterns()).Returns(new AnyOf<string, StringPattern>[] { "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<IStringMatcher>();
matcherMock.Setup(m => m.Name).Returns("test");
matcherMock.Setup(m => m.GetPatterns()).Returns(new AnyOf<string, StringPattern>[] { 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);
}
}
}

View File

@@ -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<IFileSystemHandler>();
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<string, StringPattern>(stringPattern));
matcher.IsMatch("c").Should().Be(1.0d);
}
[Fact]
public void MatcherModelMapper_Map_SimMetricsMatcher()
{

View File

@@ -60,6 +60,7 @@
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
<!--<PackageReference Include="StrongNamer" Version="0.0.8" />-->
<PackageReference Include="AnyOf" Version="0.2.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net461'">