Compare commits

..

10 Commits

Author SHA1 Message Date
Stef Heyenrath
6c65dfcff6 1.4.24 2021-10-20 20:40:02 +02:00
Stef Heyenrath
affe388e30 Add support for AzureAD authentication for REST admin interface (#637) 2021-10-20 16:39:51 +02:00
Stef Heyenrath
48b3e7a305 Add more tests for WithBody (Json and String) and WildcardMatcher 2021-10-19 09:28:52 +00:00
Stef Heyenrath
6194f4e460 Update NotNullOrEmptyMatcher to also implement IStringMatcher (#654)
* Update NotNullOrEmptyMatcher to also implement IStringMatcher

* NotNullOrEmptyMatcher_GetPatterns_Should_Return_EmptyArray

* 24
2021-10-15 12:59:03 +02:00
Stef Heyenrath
57cc616aa3 Implement PatternAsFile for StringMatcher (#651) 2021-10-15 08:54:12 +02:00
Daniel L. Romero
a2a581c84b Refactor method name MapHeaders and httpStatusCode (#649)
* Support edge case: first object, next an array.

* Add mapping to header parameters.

* Refactor the method MapHeadersParameters to MapHeaders

* Refactor method name 'cause is duplicate, only pass httpStatusCode when fail
2021-10-10 19:22:28 +02:00
Stef Heyenrath
e64ed45fcf Fix build from .NET452 and .NET461 example projects 2021-10-09 18:25:18 +02:00
Daniel L. Romero
267f0b7b6d Mapping headers in OpenAPI (#644)
* Support edge case: first object, next an array.

* Add mapping to header parameters.

* Refactor the method MapHeadersParameters to MapHeaders
2021-10-07 19:15:26 +02:00
Daniel L. Romero
34083d826e Support edge case: first object, next an array. (#643) 2021-10-06 17:18:46 +02:00
Stef Heyenrath
72eec7140b WireMock.FluentAssertions 2021-09-29 15:33:06 +00:00
68 changed files with 1254 additions and 555 deletions

View File

@@ -1,3 +1,11 @@
# 1.4.24 (20 October 2021)
- [#637](https://github.com/WireMock-Net/WireMock.Net/pull/637) - Add support for AzureAD authentication for REST admin interface [feature] contributed by [StefH](https://github.com/StefH)
- [#643](https://github.com/WireMock-Net/WireMock.Net/pull/643) - Support edge case: first object, next an array. [feature] contributed by [leolplex](https://github.com/leolplex)
- [#644](https://github.com/WireMock-Net/WireMock.Net/pull/644) - Mapping headers in OpenAPI [feature] contributed by [leolplex](https://github.com/leolplex)
- [#649](https://github.com/WireMock-Net/WireMock.Net/pull/649) - Refactor method name MapHeaders and httpStatusCode contributed by [leolplex](https://github.com/leolplex)
- [#651](https://github.com/WireMock-Net/WireMock.Net/pull/651) - Implement PatternAsFile for StringMatcher [feature] contributed by [StefH](https://github.com/StefH)
- [#654](https://github.com/WireMock-Net/WireMock.Net/pull/654) - Update NotNullOrEmptyMatcher to also implement IStringMatcher [feature] contributed by [StefH](https://github.com/StefH)
# 1.4.23 (27 September 2021)
- [#635](https://github.com/WireMock-Net/WireMock.Net/pull/635) - WireMock.Net.FluentAssertions : upgrade to latest FluentAssertions [feature] contributed by [StefH](https://github.com/StefH)
- [#634](https://github.com/WireMock-Net/WireMock.Net/issues/634) - Upgrade to latest FluentAssertions [bug]

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.4.23</VersionPrefix>
<VersionPrefix>1.4.24</VersionPrefix>
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>

View File

@@ -1,6 +1,6 @@
rem https://github.com/StefH/GitHubReleaseNotes
SET version=1.4.23
SET version=1.4.24
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%

View File

@@ -1,5 +1,9 @@
# 1.4.23 (27 September 2021)
- #635 WireMock.Net.FluentAssertions : upgrade to latest FluentAssertions [feature]
- #634 Upgrade to latest FluentAssertions [bug]
# 1.4.24 (20 October 2021)
- #637 Add support for AzureAD authentication for REST admin interface [feature]
- #643 Support edge case: first object, next an array. [feature]
- #644 Mapping headers in OpenAPI [feature]
- #649 Refactor method name MapHeaders and httpStatusCode
- #651 Implement PatternAsFile for StringMatcher [feature]
- #654 Update NotNullOrEmptyMatcher to also implement IStringMatcher [feature]
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md

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

@@ -1,4 +1,4 @@
using Newtonsoft.Json;
using Newtonsoft.Json;
using HandlebarsDotNet;
using System;
using System.Collections.Generic;
@@ -59,7 +59,10 @@ namespace WireMock.Net.ConsoleApplication
//},
PreWireMockMiddlewareInit = app => { System.Console.WriteLine($"PreWireMockMiddlewareInit : {app.GetType()}"); },
PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); },
#if USE_ASPNETCORE
AdditionalServiceRegistration = services => { System.Console.WriteLine($"AdditionalServiceRegistration : {services.GetType()}"); },
#endif
Logger = new WireMockConsoleLogger(),
HandlebarsRegistrationCallback = (handlebarsContext, fileSystemHandler) =>
@@ -74,9 +77,17 @@ namespace WireMock.Net.ConsoleApplication
System.Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
server.SetBasicAuthentication("a", "b");
//server.SetAzureADAuthentication("6c2a4722-f3b9-4970-b8fc-fac41e29stef", "8587fde1-7824-42c7-8592-faf92b04stef");
// server.AllowPartialMapping();
server.Given(Request.Create().WithPath("/mypath").UsingPost())
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson("{{JsonPath.SelectToken request.body \"..name\"}}")
.WithTransformer()
);
server
.Given(Request.Create().WithPath(p => p.Contains("x")).UsingGet())
.AtPriority(4)

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>
@@ -47,6 +50,9 @@
<Reference Include="log4net, Version=2.0.12.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\..\packages\log4net.2.0.12\lib\net45\log4net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>

View File

@@ -1,9 +1,11 @@
<?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" />
<package id="log4net" version="2.0.12" targetFramework="net461" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="2.2.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />
<package id="System.ValueTuple" version="4.3.0" 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,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using JetBrains.Annotations;
@@ -104,9 +104,9 @@ namespace WireMock.Server
void ReadStaticMappings([CanBeNull] string folder = null);
/// <summary>
/// Removes the basic authentication.
/// Removes the authentication.
/// </summary>
void RemoveBasicAuthentication();
void RemoveAuthentication();
/// <summary>
/// Resets LogEntries and Mappings.
@@ -134,6 +134,13 @@ namespace WireMock.Server
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
void SaveStaticMappings([CanBeNull] string folder = null);
/// <summary>
/// Sets the basic authentication.
/// </summary>
/// <param name="tenant">The Tenant.</param>
/// <param name="audience">The Audience or Resource.</param>
void SetAzureADAuthentication([NotNull] string tenant, [NotNull] string audience);
/// <summary>
/// Sets the basic authentication.
/// </summary>

View File

@@ -30,13 +30,13 @@ namespace WireMock.FluentAssertions
/// Asserts if <see cref="IWireMockServer"/> has received n-calls.
/// </summary>
/// <param name="callsCount"></param>
/// <returns><see cref="WireMockAssertions"/></returns>
/// <returns><see cref="WireMockANumberOfCallsAssertions"/></returns>
public WireMockANumberOfCallsAssertions HaveReceived(int callsCount)
{
return new WireMockANumberOfCallsAssertions(Subject, callsCount);
}
/// <inheritdoc/>
/// <inheritdoc cref="ReferenceTypeAssertions{IWireMockServer, WireMockReceivedAssertions}.Identifier"/>
protected override string Identifier => "wiremockserver";
}
}

View File

@@ -3,8 +3,16 @@ using WireMock.Server;
// ReSharper disable once CheckNamespace
namespace WireMock.FluentAssertions
{
/// <summary>
/// Contains extension methods for custom assertions in unit tests.
/// </summary>
public static class WireMockExtensions
{
/// <summary>
/// Returns a <see cref="WireMockReceivedAssertions"/> object that can be used to assert the current <see cref="IWireMockServer"/>.
/// </summary>
/// <param name="instance">The WireMockServer</param>
/// <returns><see cref="WireMockReceivedAssertions"/></returns>
public static WireMockReceivedAssertions Should(this IWireMockServer instance)
{
return new WireMockReceivedAssertions(instance);

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

@@ -45,6 +45,8 @@ namespace WireMock.Net.OpenApiParser.Mappers
{
var queryParameters = operation.Parameters.Where(p => p.In == ParameterLocation.Query);
var pathParameters = operation.Parameters.Where(p => p.In == ParameterLocation.Path);
var headers = operation.Parameters.Where(p => p.In == ParameterLocation.Header);
var response = operation.Responses.FirstOrDefault();
TryGetContent(response.Value?.Content, out OpenApiMediaType responseContent, out string responseContentType);
@@ -53,7 +55,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
var body = responseExample != null ? MapOpenApiAnyToJToken(responseExample) : MapSchemaToObject(responseSchema);
if (int.TryParse(response.Key, out var httpStatusCode))
if (!int.TryParse(response.Key, out var httpStatusCode))
{
httpStatusCode = 200;
}
@@ -65,7 +67,8 @@ namespace WireMock.Net.OpenApiParser.Mappers
{
Methods = new[] { httpMethod },
Path = MapPathWithParameters(path, pathParameters),
Params = MapQueryParameters(queryParameters)
Params = MapQueryParameters(queryParameters),
Headers = MapRequestHeaders(headers)
},
Response = new ResponseModel
{
@@ -152,13 +155,17 @@ namespace WireMock.Net.OpenApiParser.Mappers
{
string propertyName = schemaProperty.Key;
var openApiSchema = schemaProperty.Value;
if (openApiSchema.GetSchemaType() == SchemaType.Object)
if (openApiSchema.GetSchemaType() == SchemaType.Object || openApiSchema.GetSchemaType() == SchemaType.Array)
{
var mapped = MapSchemaToObject(schemaProperty.Value, schemaProperty.Key);
if (mapped is JProperty jp)
{
propertyAsJObject.Add(jp);
}
else
{
propertyAsJObject.Add(new JProperty(schemaProperty.Key, mapped));
}
}
else
{
@@ -247,6 +254,26 @@ namespace WireMock.Net.OpenApiParser.Mappers
return list.Any() ? list : null;
}
private IList<HeaderModel> MapRequestHeaders(IEnumerable<OpenApiParameter> headers)
{
var list = headers
.Select(qp => new HeaderModel
{
Name = qp.Name,
Matchers = new[]
{
new MatcherModel
{
Name = "ExactMatcher",
Pattern = GetDefaultValueAsStringForSchemaType(qp.Schema)
}
}
})
.ToList();
return list.Any() ? list : null;
}
private string GetDefaultValueAsStringForSchemaType(OpenApiSchema schema)
{
var value = _exampleValueGenerator.GetExampleValue(schema);

View File

@@ -0,0 +1,71 @@
#if !NETSTANDARD1_3
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Text.RegularExpressions;
using AnyOfTypes;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using WireMock.Matchers;
using WireMock.Models;
namespace WireMock.Authentication
{
/// <summary>
/// https://www.c-sharpcorner.com/article/how-to-validate-azure-ad-token-using-console-application/
/// https://stackoverflow.com/questions/38684865/validation-of-an-azure-ad-bearer-token-in-a-console-application
/// </summary>
internal class AzureADAuthenticationMatcher : IStringMatcher
{
private const string BearerPrefix = "Bearer ";
private readonly string _audience;
private readonly string _stsDiscoveryEndpoint;
public AzureADAuthenticationMatcher(string tenant, string audience)
{
_audience = audience;
_stsDiscoveryEndpoint = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/.well-known/openid-configuration", tenant);
}
public string Name => nameof(AzureADAuthenticationMatcher);
public MatchBehaviour MatchBehaviour => MatchBehaviour.AcceptOnMatch;
public bool ThrowException => false;
public AnyOf<string, StringPattern>[] GetPatterns()
{
return new AnyOf<string, StringPattern>[0];
}
public double IsMatch(string input)
{
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase);
try
{
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(_stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
var config = configManager.GetConfigurationAsync().GetAwaiter().GetResult();
var validationParameters = new TokenValidationParameters
{
ValidAudience = _audience,
ValidIssuer = config.Issuer,
IssuerSigningKeys = config.SigningKeys,
ValidateLifetime = true
};
// Throws an Exception as the token is invalid (expired, invalid-formatted, etc.)
new JwtSecurityTokenHandler().ValidateToken(token, validationParameters, out var _);
return MatchScores.Perfect;
}
catch
{
return MatchScores.Mismatch;
}
}
}
}
#endif

View File

@@ -0,0 +1,20 @@
using System;
using System.Text;
using WireMock.Matchers;
namespace WireMock.Authentication
{
internal class BasicAuthenticationMatcher : RegexMatcher
{
public BasicAuthenticationMatcher(string username, string password) : base(BuildPattern(username, password))
{
}
public override string Name => nameof(BasicAuthenticationMatcher);
private static string BuildPattern(string username, string password)
{
return "^(?i)BASIC " + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password)) + "$";
}
}
}

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,4 +1,6 @@
using System.Linq;
using AnyOfTypes;
using WireMock.Models;
namespace WireMock.Matchers
{
@@ -6,7 +8,7 @@ namespace WireMock.Matchers
/// NotNullOrEmptyMatcher
/// </summary>
/// <seealso cref="IObjectMatcher" />
public class NotNullOrEmptyMatcher : IObjectMatcher
public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher
{
/// <inheritdoc cref="IMatcher.Name"/>
public string Name => "NotNullOrEmptyMatcher";
@@ -48,5 +50,19 @@ namespace WireMock.Matchers
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match));
}
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
public double IsMatch(string input)
{
var match = !string.IsNullOrEmpty(input);
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match));
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public AnyOf<string, StringPattern>[] GetPatterns()
{
return new AnyOf<string, StringPattern>[0];
}
}
}

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,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using WireMock.Handlers;
using WireMock.Logging;
@@ -19,7 +19,7 @@ namespace WireMock.Owin
TimeSpan? RequestProcessingDelay { get; set; }
IStringMatcher AuthorizationMatcher { get; set; }
IStringMatcher AuthenticationMatcher { get; set; }
bool? AllowPartialMapping { get; set; }

View File

@@ -113,10 +113,10 @@ namespace WireMock.Owin
logRequest = targetMapping.LogMapping;
if (targetMapping.IsAdminInterface && _options.AuthorizationMatcher != null)
if (targetMapping.IsAdminInterface && _options.AuthenticationMatcher != null)
{
bool present = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out WireMockList<string> authorization);
if (!present || _options.AuthorizationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect)
if (!present || _options.AuthenticationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect)
{
_options.Logger.Error("HttpStatusCode set to 401");
response = ResponseMessageBuilder.Create(null, 401);

View File

@@ -19,7 +19,7 @@ namespace WireMock.Owin
public TimeSpan? RequestProcessingDelay { get; set; }
public IStringMatcher AuthorizationMatcher { get; set; }
public IStringMatcher AuthenticationMatcher { get; set; }
public bool? AllowPartialMapping { 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

@@ -9,6 +9,7 @@ using System.Threading;
using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.Admin.Mappings;
using WireMock.Authentication;
using WireMock.Exceptions;
using WireMock.Handlers;
using WireMock.Logging;
@@ -302,6 +303,11 @@ namespace WireMock.Server
SetBasicAuthentication(settings.AdminUsername, settings.AdminPassword);
}
if (!string.IsNullOrEmpty(settings.AdminAzureADTenant) && !string.IsNullOrEmpty(settings.AdminAzureADAudience))
{
SetAzureADAuthentication(settings.AdminAzureADTenant, settings.AdminAzureADAudience);
}
InitAdmin();
}
@@ -404,22 +410,35 @@ namespace WireMock.Server
_options.AllowPartialMapping = allow;
}
/// <inheritdoc cref="IWireMockServer.SetBasicAuthentication" />
/// <inheritdoc cref="IWireMockServer.SetAzureADAuthentication(string, string)" />
[PublicAPI]
public void SetAzureADAuthentication([NotNull] string tenant, [NotNull] string audience)
{
Check.NotNull(tenant, nameof(tenant));
Check.NotNull(audience, nameof(audience));
#if NETSTANDARD1_3
throw new NotSupportedException("AzureADAuthentication is not supported for NETStandard 1.3");
#else
_options.AuthenticationMatcher = new AzureADAuthenticationMatcher(tenant, audience);
#endif
}
/// <inheritdoc cref="IWireMockServer.SetBasicAuthentication(string, string)" />
[PublicAPI]
public void SetBasicAuthentication([NotNull] string username, [NotNull] string password)
{
Check.NotNull(username, nameof(username));
Check.NotNull(password, nameof(password));
string authorization = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
_options.AuthorizationMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, "^(?i)BASIC " + authorization + "$");
_options.AuthenticationMatcher = new BasicAuthenticationMatcher(username, password);
}
/// <inheritdoc cref="IWireMockServer.RemoveBasicAuthentication" />
/// <inheritdoc cref="IWireMockServer.RemoveAuthentication" />
[PublicAPI]
public void RemoveBasicAuthentication()
public void RemoveAuthentication()
{
_options.AuthorizationMatcher = null;
_options.AuthenticationMatcher = null;
}
/// <inheritdoc cref="IWireMockServer.SetMaxRequestLogCount" />

View File

@@ -1,4 +1,4 @@
using System;
using System;
using HandlebarsDotNet;
using JetBrains.Annotations;
using WireMock.Handlers;
@@ -88,6 +88,18 @@ namespace WireMock.Settings
[PublicAPI]
string AdminPassword { get; set; }
/// <summary>
/// The AzureAD Tenant needed for __admin access.
/// </summary>
[PublicAPI]
string AdminAzureADTenant { get; set; }
/// <summary>
/// The AzureAD Audience / Resource for __admin access.
/// </summary>
[PublicAPI]
string AdminAzureADAudience { get; set; }
/// <summary>
/// The RequestLog expiration in hours (optional).
/// </summary>

View File

@@ -1,4 +1,4 @@
using System;
using System;
using HandlebarsDotNet;
using JetBrains.Annotations;
using Newtonsoft.Json;
@@ -64,6 +64,14 @@ namespace WireMock.Settings
[PublicAPI]
public string AdminPassword { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AdminAzureADTenant"/>
[PublicAPI]
public string AdminAzureADTenant { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AdminAzureADAudience"/>
[PublicAPI]
public string AdminAzureADAudience { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.RequestLogExpirationDuration"/>
[PublicAPI]
public int? RequestLogExpirationDuration { get; set; }

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
using WireMock.Logging;
using WireMock.Validation;
@@ -39,6 +39,8 @@ namespace WireMock.Settings
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
AdminUsername = parser.GetStringValue("AdminUsername"),
AdminPassword = parser.GetStringValue("AdminPassword"),
AdminAzureADTenant = parser.GetStringValue(nameof(IWireMockServerSettings.AdminAzureADTenant)),
AdminAzureADAudience = parser.GetStringValue(nameof(IWireMockServerSettings.AdminAzureADAudience)),
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
AllowCSharpCodeMatcher = parser.GetBoolValue("AllowCSharpCodeMatcher"),

View File

@@ -1,137 +1,140 @@
<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>
<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>
<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="Stef.Validation" Version="0.0.3" />-->
<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" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.12.2" />
</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

@@ -36,11 +36,25 @@ namespace WireMock.Net.Tests.Matchers
[InlineData(null, 0.0)]
[InlineData("", 0.0)]
[InlineData("x", 1.0)]
public void NotNullOrEmptyMatcher_IsMatch_String(string data, double expected)
public void NotNullOrEmptyMatcher_IsMatch_String(string @string, double expected)
{
// Act
var matcher = new NotNullOrEmptyMatcher();
double result = matcher.IsMatch(data);
double result = matcher.IsMatch(@string);
// Assert
result.Should().Be(expected);
}
[Theory]
[InlineData(null, 0.0)]
[InlineData("", 0.0)]
[InlineData("x", 1.0)]
public void NotNullOrEmptyMatcher_IsMatch_StringAsObject(string @string, double expected)
{
// Act
var matcher = new NotNullOrEmptyMatcher();
double result = matcher.IsMatch((object)@string);
// Assert
result.Should().Be(expected);
@@ -56,5 +70,15 @@ namespace WireMock.Net.Tests.Matchers
// Assert
result.Should().Be(1.0);
}
[Fact]
public void NotNullOrEmptyMatcher_GetPatterns_Should_Return_EmptyArray()
{
// Act
var patterns = new NotNullOrEmptyMatcher().GetPatterns();
// Assert
patterns.Should().BeEmpty();
}
}
}

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

@@ -96,7 +96,7 @@ namespace WireMock.Net.Tests.Owin
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1", null, new Dictionary<string, string[]>());
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
_optionsMock.SetupGet(o => o.AuthorizationMatcher).Returns(new ExactMatcher());
_optionsMock.SetupGet(o => o.AuthenticationMatcher).Returns(new ExactMatcher());
_mappingMock.SetupGet(m => m.IsAdminInterface).Returns(true);
var result = new MappingMatcherResult { Mapping = _mappingMock.Object };
@@ -119,7 +119,7 @@ namespace WireMock.Net.Tests.Owin
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1", null, new Dictionary<string, string[]> { { "h", new[] { "x" } } });
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
_optionsMock.SetupGet(o => o.AuthorizationMatcher).Returns(new ExactMatcher());
_optionsMock.SetupGet(o => o.AuthenticationMatcher).Returns(new ExactMatcher());
_mappingMock.SetupGet(m => m.IsAdminInterface).Returns(true);
var result = new MappingMatcherResult { Mapping = _mappingMock.Object };
@@ -152,7 +152,7 @@ namespace WireMock.Net.Tests.Owin
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1", null, new Dictionary<string, string[]>());
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
_optionsMock.SetupGet(o => o.AuthorizationMatcher).Returns(new ExactMatcher());
_optionsMock.SetupGet(o => o.AuthenticationMatcher).Returns(new ExactMatcher());
var fileSystemHandlerMock = new Mock<IFileSystemHandler>();
fileSystemHandlerMock.Setup(f => f.GetMappingFolder()).Returns("m");
@@ -201,7 +201,7 @@ namespace WireMock.Net.Tests.Owin
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1", null, new Dictionary<string, string[]>());
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
_optionsMock.SetupGet(o => o.AuthorizationMatcher).Returns(new ExactMatcher());
_optionsMock.SetupGet(o => o.AuthenticationMatcher).Returns(new ExactMatcher());
var fileSystemHandlerMock = new Mock<IFileSystemHandler>();
fileSystemHandlerMock.Setup(f => f.GetMappingFolder()).Returns("m");

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,8 +1,8 @@
using Newtonsoft.Json;
using NFluent;
using System;
using System.Text;
using FluentAssertions;
using Newtonsoft.Json;
using NFluent;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Models;
@@ -96,10 +96,10 @@ namespace WireMock.Net.Tests
[Fact]
public void Request_WithBodyExactMatcher()
{
// given
// Arrange
var requestBuilder = Request.Create().UsingAnyMethod().WithBody(new ExactMatcher("cat"));
// when
// Act
var body = new BodyData
{
BodyAsString = "cat",
@@ -107,18 +107,18 @@ namespace WireMock.Net.Tests
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
// then
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBodyWildcardMatcher()
public void Request_BodyAsString_Using_WildcardMatcher()
{
// given
// Arrange
var spec = Request.Create().WithPath("/foo").UsingAnyMethod().WithBody(new WildcardMatcher("H*o*"));
// when
// Act
var body = new BodyData
{
BodyAsString = "Hello world!",
@@ -126,18 +126,38 @@ namespace WireMock.Net.Tests
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
// then
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
spec.GetMatchingScore(request, requestMatchResult).Should().Be(1.0);
}
[Fact]
public void Request_BodyAsJson_Using_WildcardMatcher()
{
// Arrange
var spec = Request.Create().WithPath("/foo").UsingAnyMethod().WithBody(new WildcardMatcher("*Hello*"));
// Act
var body = new BodyData
{
BodyAsJson = new { Hi = "Hello world!" },
BodyAsString = "{ Hi = \"Hello world!\" }",
DetectedBodyType = BodyType.Json
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
// Assert
var requestMatchResult = new RequestMatchResult();
spec.GetMatchingScore(request, requestMatchResult).Should().Be(1.0);
}
[Fact]
public void Request_WithBodyXPathMatcher_true()
{
// given
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new XPathMatcher("/todo-list[count(todo-item) = 3]"));
// when
// Act
var body = new BodyData
{
BodyAsString = @"
@@ -150,7 +170,7 @@ namespace WireMock.Net.Tests
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
// then
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
@@ -158,10 +178,10 @@ namespace WireMock.Net.Tests
[Fact]
public void Request_WithBodyXPathMatcher_false()
{
// given
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new XPathMatcher("/todo-list[count(todo-item) = 99]"));
// when
// Act
var body = new BodyData
{
BodyAsString = @"
@@ -174,7 +194,7 @@ namespace WireMock.Net.Tests
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
// then
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsNotEqualTo(1.0);
}
@@ -182,10 +202,10 @@ namespace WireMock.Net.Tests
[Fact]
public void Request_WithBodyJsonPathMatcher_true()
{
// given
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..things[?(@.name == 'RequiredThing')]"));
// when
// Act
var body = new BodyData
{
BodyAsString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }",
@@ -193,7 +213,7 @@ namespace WireMock.Net.Tests
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
// then
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
@@ -201,10 +221,10 @@ namespace WireMock.Net.Tests
[Fact]
public void Request_WithBodyJsonPathMatcher_false()
{
// given
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]"));
// when
// Act
var body = new BodyData
{
BodyAsString = "{ \"things\": { \"name\": \"Wiremock\" } }",
@@ -212,7 +232,7 @@ namespace WireMock.Net.Tests
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
// then
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsNotEqualTo(1.0);
}
@@ -220,10 +240,10 @@ namespace WireMock.Net.Tests
[Fact]
public void Request_WithBodyAsJson_Object_JsonPathMatcher_true()
{
// given
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..things[?(@.name == 'RequiredThing')]"));
// when
// Act
string jsonString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }";
var bodyData = new BodyData
{
@@ -235,7 +255,7 @@ namespace WireMock.Net.Tests
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData);
// then
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
@@ -243,10 +263,10 @@ namespace WireMock.Net.Tests
[Fact]
public void Request_WithBodyAsJson_Array_JsonPathMatcher_1()
{
// given
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..books[?(@.price < 10)]"));
// when
// Act
string jsonString = "{ \"books\": [ { \"category\": \"test1\", \"price\": 8.95 }, { \"category\": \"test2\", \"price\": 20 } ] }";
var bodyData = new BodyData
{
@@ -258,7 +278,7 @@ namespace WireMock.Net.Tests
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData);
// then
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
@@ -266,10 +286,10 @@ namespace WireMock.Net.Tests
[Fact]
public void Request_WithBodyAsJson_Array_JsonPathMatcher_2()
{
// given
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..[?(@.Id == 1)]"));
// when
// Act
string jsonString = "{ \"Id\": 1, \"Name\": \"Test\" }";
var bodyData = new BodyData
{
@@ -281,7 +301,7 @@ namespace WireMock.Net.Tests
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData);
// then
// Assert
var requestMatchResult = new RequestMatchResult();
double result = spec.GetMatchingScore(request, requestMatchResult);
Check.That(result).IsEqualTo(1.0);

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'">
@@ -72,6 +73,10 @@
<PackageReference Include="FluentAssertions" Version="6.1.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net452'">
<PackageReference Include="System.Net.Http.Json" Version="3.2.1" />
</ItemGroup>
<ItemGroup>
<None Update="responsebody.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

View File

@@ -1,3 +1,4 @@
using FluentAssertions;
using NFluent;
using WireMock.Matchers;
using WireMock.Owin;
@@ -19,26 +20,43 @@ namespace WireMock.Net.Tests
// Assert
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
Check.That(options.AuthorizationMatcher.Name).IsEqualTo("RegexMatcher");
Check.That(options.AuthorizationMatcher.MatchBehaviour).IsEqualTo(MatchBehaviour.AcceptOnMatch);
Check.That(options.AuthorizationMatcher.GetPatterns()).ContainsExactly("^(?i)BASIC eDp5$");
Check.That(options.AuthenticationMatcher.Name).IsEqualTo("BasicAuthenticationMatcher");
Check.That(options.AuthenticationMatcher.MatchBehaviour).IsEqualTo(MatchBehaviour.AcceptOnMatch);
Check.That(options.AuthenticationMatcher.GetPatterns()).ContainsExactly("^(?i)BASIC eDp5$");
server.Stop();
}
[Fact]
public void WireMockServer_Authentication_RemoveBasicAuthentication()
public void WireMockServer_Authentication_SetSetAzureADAuthentication()
{
// Assign
var server = WireMockServer.Start();
// Act
server.SetAzureADAuthentication("x", "y");
// Assert
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
options.AuthenticationMatcher.Name.Should().Be("AzureADAuthenticationMatcher");
options.AuthenticationMatcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch);
server.Stop();
}
[Fact]
public void WireMockServer_Authentication_RemoveAuthentication()
{
// Assign
var server = WireMockServer.Start();
server.SetBasicAuthentication("x", "y");
// Act
server.RemoveBasicAuthentication();
server.RemoveAuthentication();
// Assert
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
Check.That(options.AuthorizationMatcher).IsNull();
Check.That(options.AuthenticationMatcher).IsNull();
server.Stop();
}

View File

@@ -1,6 +1,8 @@
using System.Linq;
using FluentAssertions;
using Moq;
using NFluent;
using System.Linq;
using WireMock.Authentication;
using WireMock.Logging;
using WireMock.Owin;
using WireMock.Server;
@@ -32,7 +34,23 @@ namespace WireMock.Net.Tests
// Assert
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
Check.That(options.AuthorizationMatcher).IsNotNull();
options.AuthenticationMatcher.Should().NotBeNull().And.BeOfType<BasicAuthenticationMatcher>();
}
[Fact]
public void WireMockServer_WireMockServerSettings_StartAdminInterfaceTrue_AzureADAuthenticationIsSet()
{
// Assign and Act
var server = WireMockServer.Start(new WireMockServerSettings
{
StartAdminInterface = true,
AdminAzureADTenant = "t",
AdminAzureADAudience = "a"
});
// Assert
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
options.AuthenticationMatcher.Should().NotBeNull().And.BeOfType<AzureADAuthenticationMatcher>();
}
[Fact]
@@ -48,7 +66,7 @@ namespace WireMock.Net.Tests
// Assert
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
Check.That(options.AuthorizationMatcher).IsNull();
Check.That(options.AuthenticationMatcher).IsNull();
}
[Fact]

View File

@@ -0,0 +1,70 @@
#if !NET452
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
using FluentAssertions;
using WireMock.Matchers;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using Xunit;
namespace WireMock.Net.Tests
{
public partial class WireMockServerTests
{
public class DummyClass
{
public string Hi { get; set; }
}
[Fact]
public async Task WireMockServer_WithBodyAsJson_Using_PostAsJsonAsync_And_WildcardMatcher_ShouldMatch()
{
// Arrange
var server = WireMockServer.Start();
server.Given(
Request.Create().UsingPost().WithPath("/foo").WithBody(new WildcardMatcher("*Hello*"))
)
.RespondWith(
Response.Create().WithStatusCode(200)
);
var jsonObject = new DummyClass
{
Hi = "Hello World!"
};
// Act
var response = await new HttpClient().PostAsJsonAsync("http://localhost:" + server.Ports[0] + "/foo", jsonObject);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
server.Stop();
}
[Fact]
public async Task WireMockServer_WithBodyAsJson_Using_PostAsync_And_WildcardMatcher_ShouldMatch()
{
// Arrange
var server = WireMockServer.Start();
server.Given(
Request.Create().UsingPost().WithPath("/foo").WithBody(new WildcardMatcher("*Hello*"))
)
.RespondWith(
Response.Create().WithStatusCode(200)
);
// Act
var response = await new HttpClient().PostAsync("http://localhost:" + server.Ports[0] + "/foo", new StringContent("{ Hi = \"Hello World\" }"));
// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
server.Stop();
}
}
}
#endif