This commit is contained in:
Stef Heyenrath
2026-01-11 11:53:55 +01:00
parent 960399127e
commit 95d3978c7c
39 changed files with 216 additions and 178 deletions

View File

@@ -47,5 +47,5 @@ public class LogRequestMatchModel
/// <value> /// <value>
/// The match details. /// The match details.
/// </value> /// </value>
public IList<object> MatchDetails { get; set; } public IList<object> MatchDetails { get; set; } = [];
} }

View File

@@ -12,7 +12,7 @@ public class MatchDetail
/// <summary> /// <summary>
/// Gets or sets the type of the matcher. /// Gets or sets the type of the matcher.
/// </summary> /// </summary>
public Type MatcherType { get; set; } = null!; public required Type MatcherType { get; set; }
/// <summary> /// <summary>
/// Gets or sets the score between 0.0 and 1.0 /// Gets or sets the score between 0.0 and 1.0

View File

@@ -140,7 +140,7 @@ public class GraphQLMatcher : IGraphQLMatcher
} }
} }
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -97,7 +97,7 @@ public class CSharpCodeMatcher : ICSharpCodeMatcher
} }
} }
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
} }
private bool IsMatch(dynamic input, string pattern) private bool IsMatch(dynamic input, string pattern)

View File

@@ -1,6 +1,7 @@
// Copyright © WireMock.Net // Copyright © WireMock.Net
using System; using System;
using System.Collections.Generic;
using WireMock.Matchers.Helpers; using WireMock.Matchers.Helpers;
using WireMock.Models.Mime; using WireMock.Models.Mime;
using WireMock.Util; using WireMock.Util;
@@ -12,7 +13,7 @@ namespace WireMock.Matchers;
/// </summary> /// </summary>
public class MimePartMatcher : IMimePartMatcher public class MimePartMatcher : IMimePartMatcher
{ {
private readonly Func<IMimePartData, MatchResult>[] _funcs; private readonly IList<(string Name, Func<IMimePartData, MatchResult> func)> _matcherFunctions;
/// <inheritdoc /> /// <inheritdoc />
public string Name => nameof(MimePartMatcher); public string Name => nameof(MimePartMatcher);
@@ -49,34 +50,47 @@ public class MimePartMatcher : IMimePartMatcher
ContentTransferEncodingMatcher = contentTransferEncodingMatcher; ContentTransferEncodingMatcher = contentTransferEncodingMatcher;
ContentMatcher = contentMatcher; ContentMatcher = contentMatcher;
_funcs = _matcherFunctions = new List<(string Name, Func<IMimePartData, MatchResult> func)>();
[ if (ContentTypeMatcher != null)
mp => ContentTypeMatcher?.IsMatch(GetContentTypeAsString(mp.ContentType)) ?? MatchScores.Perfect, {
mp => ContentDispositionMatcher?.IsMatch(mp.ContentDisposition?.ToString()?.Replace("Content-Disposition: ", string.Empty)) ?? MatchScores.Perfect, _matcherFunctions.Add((nameof(ContentTypeMatcher), mp => ContentTypeMatcher.IsMatch(GetContentTypeAsString(mp.ContentType))));
mp => ContentTransferEncodingMatcher?.IsMatch(mp.ContentTransferEncoding.ToLowerInvariant()) ?? MatchScores.Perfect, }
MatchOnContent
]; if (ContentDispositionMatcher != null)
{
_matcherFunctions.Add((nameof(ContentDispositionMatcher), mp => ContentDispositionMatcher.IsMatch(mp.ContentDisposition?.ToString()?.Replace("Content-Disposition: ", string.Empty))));
}
if (ContentTransferEncodingMatcher != null)
{
_matcherFunctions.Add((nameof(ContentTransferEncodingMatcher), mp => ContentTransferEncodingMatcher.IsMatch(mp.ContentTransferEncoding.ToLowerInvariant())));
}
if (ContentMatcher != null)
{
_matcherFunctions.Add((ContentMatcher.Name, MatchOnContent));
}
} }
/// <inheritdoc /> /// <inheritdoc />
public MatchResult IsMatch(IMimePartData value) public MatchResult IsMatch(IMimePartData value)
{ {
var score = MatchScores.Mismatch; var results = new List<MatchResult>();
Exception? exception = null;
try foreach (var matcherFunction in _matcherFunctions)
{ {
if (Array.TrueForAll(_funcs, func => func(value).IsPerfect())) try
{ {
score = MatchScores.Perfect; var matchResult = matcherFunction.func(value);
results.Add(MatchResult.From(matcherFunction.Name, matchResult.Score));
}
catch (Exception ex)
{
results.Add(MatchResult.From(matcherFunction.Name, MatchScores.Mismatch, ex));
} }
} }
catch (Exception ex)
{
exception = ex;
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); return MatchResult.From(nameof(MimePartMatcher), results, MatchOperator.And);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -87,11 +101,6 @@ public class MimePartMatcher : IMimePartMatcher
private MatchResult MatchOnContent(IMimePartData mimePart) private MatchResult MatchOnContent(IMimePartData mimePart)
{ {
if (ContentMatcher == null)
{
return MatchScores.Perfect;
}
var bodyParserSettings = new BodyParserSettings var bodyParserSettings = new BodyParserSettings
{ {
Stream = mimePart.Open(), Stream = mimePart.Open(),
@@ -102,7 +111,7 @@ public class MimePartMatcher : IMimePartMatcher
}; };
var bodyData = BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false).GetAwaiter().GetResult(); var bodyData = BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false).GetAwaiter().GetResult();
return BodyDataMatchScoreCalculator.CalculateMatchScore(bodyData, ContentMatcher); return BodyDataMatchScoreCalculator.CalculateMatchScore(bodyData, ContentMatcher!);
} }
private static string? GetContentTypeAsString(IContentTypeData? contentType) private static string? GetContentTypeAsString(IContentTypeData? contentType)

View File

@@ -54,7 +54,7 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
{ {
if (string.IsNullOrEmpty(input)) if (string.IsNullOrEmpty(input))
{ {
return MatchScores.Mismatch; return MatchResult.From(Name);
} }
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase, RegexConstants.DefaultTimeout); var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase, RegexConstants.DefaultTimeout);
@@ -83,11 +83,11 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
// Throws an Exception as the token is invalid (expired, invalid-formatted, tenant mismatch, etc.) // Throws an Exception as the token is invalid (expired, invalid-formatted, tenant mismatch, etc.)
_jwtSecurityTokenHandler.ValidateToken(token, validationParameters, out _); _jwtSecurityTokenHandler.ValidateToken(token, validationParameters, out _);
return MatchScores.Perfect; return MatchResult.From(Name, MatchScores.Perfect);
} }
catch (Exception ex) catch (Exception ex)
{ {
return new MatchResult(MatchScores.Mismatch, ex); return MatchResult.From(Name, ex);
} }
} }

View File

@@ -62,7 +62,7 @@ public class ContentTypeMatcher : WildcardMatcher
{ {
if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out var contentType)) if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out var contentType))
{ {
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
} }
return base.IsMatch(contentType.MediaType); return base.IsMatch(contentType.MediaType);

View File

@@ -75,7 +75,7 @@ public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher
: pattern => pattern == input; : pattern => pattern == input;
var score = MatchScores.ToScore(_values.Select(v => equals(v)).ToArray(), MatchOperator); var score = MatchScores.ToScore(_values.Select(v => equals(v)).ToArray(), MatchOperator);
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score)); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score));
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -106,18 +106,18 @@ public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
// Input is null or empty and if no patterns defined, return Perfect match. // Input is null or empty and if no patterns defined, return Perfect match.
if (string.IsNullOrEmpty(input) && _patterns.Length == 0) if (string.IsNullOrEmpty(input) && _patterns.Length == 0)
{ {
return new MatchResult(MatchScores.Perfect); return MatchResult.From(Name, MatchScores.Perfect);
} }
if (!QueryStringParser.TryParse(input, IgnoreCase, out var inputNameValueCollection)) if (!QueryStringParser.TryParse(input, IgnoreCase, out var inputNameValueCollection))
{ {
return new MatchResult(MatchScores.Mismatch); return MatchResult.From(Name, MatchScores.Mismatch);
} }
var matches = GetMatches(inputNameValueCollection); var matches = GetMatches(inputNameValueCollection);
var score = MatchScores.ToScore(matches, MatchOperator); var score = MatchScores.ToScore(matches, MatchOperator);
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score)); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score));
} }
private bool[] GetMatches(IDictionary<string, string> inputNameValueCollection) private bool[] GetMatches(IDictionary<string, string> inputNameValueCollection)

View File

@@ -80,7 +80,7 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher
} }
} }
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -104,7 +104,7 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher
} }
} }
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -87,7 +87,7 @@ public class JmesPathMatcher : IStringMatcher, IObjectMatcher
} }
} }
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -102,7 +102,7 @@ public class JmesPathMatcher : IStringMatcher, IObjectMatcher
return IsMatch(inputAsString); return IsMatch(inputAsString);
} }
return MatchBehaviourHelper.Convert(MatchBehaviour, score); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score));
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -96,7 +96,7 @@ public class JsonMatcher : IJsonMatcher
} }
} }
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -24,12 +24,17 @@ public class RequestMatchResult : IRequestMatchResult
public double AverageTotalScore => TotalNumber == 0 ? MatchScores.Mismatch : TotalScore / TotalNumber; public double AverageTotalScore => TotalNumber == 0 ? MatchScores.Mismatch : TotalScore / TotalNumber;
/// <inheritdoc /> /// <inheritdoc />
public IList<MatchDetail> MatchDetails { get; } = new List<MatchDetail>(); public IList<MatchDetail> MatchDetails { get; } = [];
/// <inheritdoc /> /// <inheritdoc />
public double AddScore(Type matcherType, double score, Exception? exception) public double AddScore(Type matcherType, double score, Exception? exception)
{ {
MatchDetails.Add(new MatchDetail { MatcherType = matcherType, Score = score, Exception = exception }); MatchDetails.Add(new MatchDetail
{
MatcherType = matcherType,
Score = score,
Exception = exception
});
return score; return score;
} }

View File

@@ -17,27 +17,27 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// <summary> /// <summary>
/// The body function /// The body function
/// </summary> /// </summary>
public Func<string?, bool>? Func { get; } public Func<string?, bool>? MatchOnBodyAsStringFunc { get; }
/// <summary> /// <summary>
/// The body data function for byte[] /// The body data function for byte[]
/// </summary> /// </summary>
public Func<byte[]?, bool>? DataFunc { get; } public Func<byte[]?, bool>? MatchOnBodyAsBytesFunc { get; }
/// <summary> /// <summary>
/// The body data function for json /// The body data function for json
/// </summary> /// </summary>
public Func<object?, bool>? JsonFunc { get; } public Func<object?, bool>? MatchOnBodyAsJsonFunc { get; }
/// <summary> /// <summary>
/// The body data function for BodyData /// The body data function for BodyData
/// </summary> /// </summary>
public Func<IBodyData?, bool>? BodyDataFunc { get; } public Func<IBodyData?, bool>? MatchOnBodyAsBodyDataFunc { get; }
/// <summary> /// <summary>
/// The body data function for FormUrlEncoded /// The body data function for FormUrlEncoded
/// </summary> /// </summary>
public Func<IDictionary<string, string>?, bool>? FormUrlEncodedFunc { get; } public Func<IDictionary<string, string>?, bool>? MatchOnBodyAsFormUrlEncodedFunc { get; }
/// <summary> /// <summary>
/// The matchers. /// The matchers.
@@ -85,7 +85,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// <param name="func">The function.</param> /// <param name="func">The function.</param>
public RequestMessageBodyMatcher(Func<string?, bool> func) public RequestMessageBodyMatcher(Func<string?, bool> func)
{ {
Func = Guard.NotNull(func); MatchOnBodyAsStringFunc = Guard.NotNull(func);
} }
/// <summary> /// <summary>
@@ -94,7 +94,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// <param name="func">The function.</param> /// <param name="func">The function.</param>
public RequestMessageBodyMatcher(Func<byte[]?, bool> func) public RequestMessageBodyMatcher(Func<byte[]?, bool> func)
{ {
DataFunc = Guard.NotNull(func); MatchOnBodyAsBytesFunc = Guard.NotNull(func);
} }
/// <summary> /// <summary>
@@ -103,7 +103,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// <param name="func">The function.</param> /// <param name="func">The function.</param>
public RequestMessageBodyMatcher(Func<object?, bool> func) public RequestMessageBodyMatcher(Func<object?, bool> func)
{ {
JsonFunc = Guard.NotNull(func); MatchOnBodyAsJsonFunc = Guard.NotNull(func);
} }
/// <summary> /// <summary>
@@ -112,7 +112,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// <param name="func">The function.</param> /// <param name="func">The function.</param>
public RequestMessageBodyMatcher(Func<IBodyData?, bool> func) public RequestMessageBodyMatcher(Func<IBodyData?, bool> func)
{ {
BodyDataFunc = Guard.NotNull(func); MatchOnBodyAsBodyDataFunc = Guard.NotNull(func);
} }
/// <summary> /// <summary>
@@ -121,7 +121,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// <param name="func">The function.</param> /// <param name="func">The function.</param>
public RequestMessageBodyMatcher(Func<IDictionary<string, string>?, bool> func) public RequestMessageBodyMatcher(Func<IDictionary<string, string>?, bool> func)
{ {
FormUrlEncodedFunc = Guard.NotNull(func); MatchOnBodyAsFormUrlEncodedFunc = Guard.NotNull(func);
} }
/// <summary> /// <summary>
@@ -147,43 +147,43 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// <inheritdoc /> /// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{ {
var (score, exception) = CalculateMatchScore(requestMessage).Expand(); var (score, exception) = CalculateMatchResult(requestMessage).Expand();
return requestMatchResult.AddScore(GetType(), score, exception); return requestMatchResult.AddScore(GetType(), score, exception);
} }
private MatchResult CalculateMatchScore(IRequestMessage requestMessage) private MatchResult CalculateMatchResult(IRequestMessage requestMessage)
{ {
if (Matchers != null && Matchers.Any()) if (Matchers != null && Matchers.Any())
{ {
var results = Matchers.Select(matcher => BodyDataMatchScoreCalculator.CalculateMatchScore(requestMessage.BodyData, matcher)).ToArray(); var results = Matchers.Select(matcher => BodyDataMatchScoreCalculator.CalculateMatchScore(requestMessage.BodyData, matcher)).ToArray();
return MatchResult.From(results, MatchOperator); return MatchResult.From(nameof(RequestMessageBodyMatcher), results, MatchOperator);
} }
if (Func != null) if (MatchOnBodyAsStringFunc != null)
{ {
return MatchScores.ToScore(Func(requestMessage.BodyData?.BodyAsString)); return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsStringFunc)}", MatchScores.ToScore(MatchOnBodyAsStringFunc(requestMessage.BodyData?.BodyAsString)));
} }
if (FormUrlEncodedFunc != null) if (MatchOnBodyAsFormUrlEncodedFunc != null)
{ {
return MatchScores.ToScore(FormUrlEncodedFunc(requestMessage.BodyData?.BodyAsFormUrlEncoded)); return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsFormUrlEncodedFunc)}", MatchScores.ToScore(MatchOnBodyAsFormUrlEncodedFunc(requestMessage.BodyData?.BodyAsFormUrlEncoded)));
} }
if (JsonFunc != null) if (MatchOnBodyAsJsonFunc != null)
{ {
return MatchScores.ToScore(JsonFunc(requestMessage.BodyData?.BodyAsJson)); return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsJsonFunc)}", MatchScores.ToScore(MatchOnBodyAsJsonFunc(requestMessage.BodyData?.BodyAsJson)));
} }
if (DataFunc != null) if (MatchOnBodyAsBytesFunc != null)
{ {
return MatchScores.ToScore(DataFunc(requestMessage.BodyData?.BodyAsBytes)); return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsBytesFunc)}", MatchScores.ToScore(MatchOnBodyAsBytesFunc(requestMessage.BodyData?.BodyAsBytes)));
} }
if (BodyDataFunc != null) if (MatchOnBodyAsBodyDataFunc != null)
{ {
return MatchScores.ToScore(BodyDataFunc(requestMessage.BodyData)); return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsBodyDataFunc)}", MatchScores.ToScore(MatchOnBodyAsBodyDataFunc(requestMessage.BodyData)));
} }
return default; return MatchResult.From(nameof(RequestMessageBodyMatcher));
} }
} }

View File

@@ -11,6 +11,8 @@ namespace WireMock.Matchers.Request;
/// </summary> /// </summary>
public class RequestMessageBodyMatcher<T> : IRequestMatcher public class RequestMessageBodyMatcher<T> : IRequestMatcher
{ {
private const string _name = nameof(RequestMessageBodyMatcher<T>);
/// <summary> /// <summary>
/// The body data function for type T /// The body data function for type T
/// </summary> /// </summary>
@@ -46,15 +48,15 @@ public class RequestMessageBodyMatcher<T> : IRequestMatcher
try try
{ {
var bodyAsT = jsonObject.ToObject<T>(); var bodyAsT = jsonObject.ToObject<T>();
return MatchScores.ToScore(Func(bodyAsT)); return MatchResult.From(_name, MatchScores.ToScore(Func(bodyAsT)));
} }
catch (Exception ex) catch (Exception ex)
{ {
return new MatchResult(ex); return MatchResult.From(_name, ex);
} }
} }
} }
return default; return MatchResult.From(_name);
} }
} }

View File

@@ -14,6 +14,8 @@ namespace WireMock.Matchers.Request;
/// </summary> /// </summary>
public class RequestMessageClientIPMatcher : IRequestMatcher public class RequestMessageClientIPMatcher : IRequestMatcher
{ {
private const string _name = nameof(RequestMessageClientIPMatcher);
/// <summary> /// <summary>
/// The matchers /// The matchers
/// </summary> /// </summary>
@@ -86,15 +88,15 @@ public class RequestMessageClientIPMatcher : IRequestMatcher
if (Matchers != null) if (Matchers != null)
{ {
var results = Matchers.Select(m => m.IsMatch(requestMessage.ClientIP)).ToArray(); var results = Matchers.Select(m => m.IsMatch(requestMessage.ClientIP)).ToArray();
return MatchResult.From(results, MatchOperator); return MatchResult.From(_name, results, MatchOperator);
} }
if (Funcs != null) if (Funcs != null)
{ {
var results = Funcs.Select(func => func(requestMessage.ClientIP)).ToArray(); var results = Funcs.Select(func => func(requestMessage.ClientIP)).ToArray();
return MatchScores.ToScore(results, MatchOperator); return MatchResult.From(_name, MatchScores.ToScore(results, MatchOperator));
} }
return default; return MatchResult.From(_name);
} }
} }

View File

@@ -13,6 +13,8 @@ namespace WireMock.Matchers.Request;
/// <inheritdoc cref="IRequestMatcher"/> /// <inheritdoc cref="IRequestMatcher"/>
public class RequestMessageCookieMatcher : IRequestMatcher public class RequestMessageCookieMatcher : IRequestMatcher
{ {
private const string _name = nameof(RequestMessageCookieMatcher);
/// <summary> /// <summary>
/// MatchBehaviour /// MatchBehaviour
/// </summary> /// </summary>
@@ -104,7 +106,7 @@ public class RequestMessageCookieMatcher : IRequestMatcher
{ {
if (requestMessage.Cookies == null) if (requestMessage.Cookies == null)
{ {
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
} }
// Check if we want to use IgnoreCase to compare the Cookie-Name and Cookie-Value // Check if we want to use IgnoreCase to compare the Cookie-Name and Cookie-Value
@@ -112,19 +114,19 @@ public class RequestMessageCookieMatcher : IRequestMatcher
if (Funcs != null) if (Funcs != null)
{ {
return MatchScores.ToScore(Funcs.Any(f => f(cookies))); return MatchResult.From(_name, MatchScores.ToScore(Funcs.Any(f => f(cookies))));
} }
if (Matchers == null) if (Matchers == null)
{ {
return default; return MatchResult.From(_name);
} }
if (!cookies.ContainsKey(Name)) if (!cookies.ContainsKey(Name))
{ {
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
} }
return Matchers.Max(m => m.IsMatch(cookies[Name])); return MatchResult.From(_name, Matchers.Max(m => m.IsMatch(cookies[Name]))?.Score ?? MatchScores.Mismatch);
} }
} }

View File

@@ -14,6 +14,8 @@ namespace WireMock.Matchers.Request;
/// <inheritdoc cref="IRequestMatcher"/> /// <inheritdoc cref="IRequestMatcher"/>
public class RequestMessageHeaderMatcher : IRequestMatcher public class RequestMessageHeaderMatcher : IRequestMatcher
{ {
private const string _name = nameof(RequestMessageCookieMatcher);
/// <summary> /// <summary>
/// MatchBehaviour /// MatchBehaviour
/// </summary> /// </summary>
@@ -117,7 +119,7 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
{ {
if (requestMessage.Headers == null) if (requestMessage.Headers == null)
{ {
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
} }
// Check if we want to use IgnoreCase to compare the Header-Name and Header-Value(s) // Check if we want to use IgnoreCase to compare the Header-Name and Header-Value(s)
@@ -126,14 +128,14 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
if (Funcs != null) if (Funcs != null)
{ {
var funcResults = Funcs.Select(f => f(headers.ToDictionary(entry => entry.Key, entry => entry.Value.ToArray()))).ToArray(); var funcResults = Funcs.Select(f => f(headers.ToDictionary(entry => entry.Key, entry => entry.Value.ToArray()))).ToArray();
return MatchScores.ToScore(funcResults, MatchOperator); return MatchResult.From(_name, MatchScores.ToScore(funcResults, MatchOperator));
} }
if (Matchers != null) if (Matchers != null)
{ {
if (!headers.ContainsKey(Name)) if (!headers.ContainsKey(Name))
{ {
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
} }
var results = new List<MatchResult>(); var results = new List<MatchResult>();
@@ -141,12 +143,12 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
{ {
var resultsPerMatcher = headers[Name].Select(matcher.IsMatch).ToArray(); var resultsPerMatcher = headers[Name].Select(matcher.IsMatch).ToArray();
results.Add(MatchResult.From(resultsPerMatcher, MatchOperator.And)); results.Add(MatchResult.From(_name, resultsPerMatcher, MatchOperator.And));
} }
return MatchResult.From(results, MatchOperator); return MatchResult.From(_name, results, MatchOperator);
} }
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
} }
} }

View File

@@ -11,6 +11,8 @@ namespace WireMock.Matchers.Request;
/// </summary> /// </summary>
public class RequestMessageHttpVersionMatcher : IRequestMatcher public class RequestMessageHttpVersionMatcher : IRequestMatcher
{ {
private const string _name = nameof(RequestMessageHttpVersionMatcher);
/// <summary> /// <summary>
/// The matcher. /// The matcher.
/// </summary> /// </summary>
@@ -19,7 +21,7 @@ public class RequestMessageHttpVersionMatcher : IRequestMatcher
/// <summary> /// <summary>
/// The func. /// The func.
/// </summary> /// </summary>
public Func<string, bool>? Func { get; } public Func<string, bool>? MatcherOnStringFunc { get; }
/// <summary> /// <summary>
/// The <see cref="MatchBehaviour"/> /// The <see cref="MatchBehaviour"/>
@@ -61,7 +63,7 @@ public class RequestMessageHttpVersionMatcher : IRequestMatcher
/// <param name="func">The function.</param> /// <param name="func">The function.</param>
public RequestMessageHttpVersionMatcher(Func<string, bool> func) public RequestMessageHttpVersionMatcher(Func<string, bool> func)
{ {
Func = Guard.NotNull(func); MatcherOnStringFunc = Guard.NotNull(func);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -78,11 +80,11 @@ public class RequestMessageHttpVersionMatcher : IRequestMatcher
return Matcher.IsMatch(requestMessage.HttpVersion); return Matcher.IsMatch(requestMessage.HttpVersion);
} }
if (Func != null) if (MatcherOnStringFunc != null)
{ {
return MatchScores.ToScore(Func(requestMessage.HttpVersion)); return MatchResult.From($"{_name}:{nameof(MatcherOnStringFunc)}", MatchScores.ToScore(MatcherOnStringFunc(requestMessage.HttpVersion)));
} }
return default; return MatchResult.From(_name);
} }
} }

View File

@@ -62,7 +62,7 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher
var score = MatchScores.Mismatch; var score = MatchScores.Mismatch;
Exception? exception = null; Exception? exception = null;
if (Matchers?.Any() != true) if (Matchers == null)
{ {
return requestMatchResult.AddScore(GetType(), score, null); return requestMatchResult.AddScore(GetType(), score, null);
} }

View File

@@ -86,15 +86,16 @@ public class RequestMessagePathMatcher : IRequestMatcher
if (Matchers != null) if (Matchers != null)
{ {
var results = Matchers.Select(m => m.IsMatch(requestMessage.Path)).ToArray(); var results = Matchers.Select(m => m.IsMatch(requestMessage.Path)).ToArray();
return MatchResult.From(results, MatchOperator); return MatchResult.From(nameof(RequestMessagePathMatcher), results, MatchOperator);
} }
if (Funcs != null) if (Funcs != null)
{ {
var results = Funcs.Select(func => func(requestMessage.Path)).ToArray(); var results = Funcs.Select(func => func(requestMessage.Path)).ToArray();
return MatchScores.ToScore(results, MatchOperator); var score = MatchScores.ToScore(results, MatchOperator);
return MatchResult.From(nameof(RequestMessagePathMatcher), score);
} }
return default; return MatchResult.From(nameof(RequestMessagePathMatcher));
} }
} }

View File

@@ -86,15 +86,16 @@ public class RequestMessageUrlMatcher : IRequestMatcher
if (Matchers != null) if (Matchers != null)
{ {
var results = Matchers.Select(m => m.IsMatch(requestMessage.Url)).ToArray(); var results = Matchers.Select(m => m.IsMatch(requestMessage.Url)).ToArray();
return MatchResult.From(results, MatchOperator); return MatchResult.From(nameof(RequestMessageUrlMatcher), results, MatchOperator);
} }
if (Funcs != null) if (Funcs != null)
{ {
var results = Funcs.Select(func => func(requestMessage.Url)).ToArray(); var results = Funcs.Select(func => func(requestMessage.Url)).ToArray();
return MatchScores.ToScore(results, MatchOperator); var score = MatchScores.ToScore(results, MatchOperator);
return MatchResult.From(nameof(RequestMessageUrlMatcher), score);
} }
return default; return MatchResult.From(nameof(RequestMessageUrlMatcher));
} }
} }

View File

@@ -86,7 +86,7 @@ public class SimMetricsMatcher : IStringMatcher
IStringMetric stringMetricType = GetStringMetricType(); IStringMetric stringMetricType = GetStringMetricType();
var score = MatchScores.ToScore(_patterns.Select(p => stringMetricType.GetSimilarity(p.GetPattern(), input)).ToArray(), MatchOperator); var score = MatchScores.ToScore(_patterns.Select(p => stringMetricType.GetSimilarity(p.GetPattern(), input)).ToArray(), MatchOperator);
return MatchBehaviourHelper.Convert(MatchBehaviour, score); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score));
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -116,7 +116,7 @@ public class XPathMatcher : IStringMatcher
private MatchResult CreateMatchResult(double score, Exception? exception = null) private MatchResult CreateMatchResult(double score, Exception? exception = null)
{ {
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
} }
private sealed class XPathEvaluator private sealed class XPathEvaluator

View File

@@ -57,7 +57,7 @@ public class ProtoBufMatcher : IProtoBufMatcher
/// <inheritdoc /> /// <inheritdoc />
public async Task<MatchResult> IsMatchAsync(byte[]? input, CancellationToken cancellationToken = default) public async Task<MatchResult> IsMatchAsync(byte[]? input, CancellationToken cancellationToken = default)
{ {
var result = new MatchResult(); var result = MatchResult.From(Name);
if (input != null) if (input != null)
{ {
@@ -65,11 +65,11 @@ public class ProtoBufMatcher : IProtoBufMatcher
{ {
var instance = await DecodeAsync(input, true, cancellationToken).ConfigureAwait(false); var instance = await DecodeAsync(input, true, cancellationToken).ConfigureAwait(false);
result = Matcher?.IsMatch(instance) ?? new MatchResult(MatchScores.Perfect); result = Matcher?.IsMatch(instance) ?? MatchResult.From(Name, MatchScores.Perfect);
} }
catch (Exception e) catch (Exception ex)
{ {
result = new MatchResult(MatchScores.Mismatch, e); result = MatchResult.From(Name, ex);
} }
} }

View File

@@ -68,7 +68,7 @@ public class ExactObjectMatcher : IObjectMatcher
equals = Equals(Value, input); equals = Equals(Value, input);
} }
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(equals)); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(equals)));
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -8,13 +8,15 @@ namespace WireMock.Matchers.Helpers;
internal static class BodyDataMatchScoreCalculator internal static class BodyDataMatchScoreCalculator
{ {
private static string _name = nameof(BodyDataMatchScoreCalculator);
internal static MatchResult CalculateMatchScore(IBodyData? bodyData, IMatcher matcher) internal static MatchResult CalculateMatchScore(IBodyData? bodyData, IMatcher matcher)
{ {
Guard.NotNull(matcher); Guard.NotNull(matcher);
if (bodyData == null) if (bodyData == null)
{ {
return default; return MatchResult.From(_name);
} }
if (matcher is NotNullOrEmptyMatcher notNullOrEmptyMatcher) if (matcher is NotNullOrEmptyMatcher notNullOrEmptyMatcher)
@@ -30,7 +32,7 @@ internal static class BodyDataMatchScoreCalculator
return notNullOrEmptyMatcher.IsMatch(bodyData.BodyAsBytes); return notNullOrEmptyMatcher.IsMatch(bodyData.BodyAsBytes);
default: default:
return default; return MatchResult.From(_name);
} }
} }
@@ -68,6 +70,6 @@ internal static class BodyDataMatchScoreCalculator
return protoBufMatcher.IsMatchAsync(bodyData.BodyAsBytes).GetAwaiter().GetResult(); return protoBufMatcher.IsMatchAsync(bodyData.BodyAsBytes).GetAwaiter().GetResult();
} }
return default; return MatchResult.From(_name);
} }
} }

View File

@@ -36,6 +36,6 @@ internal static class MatchBehaviourHelper
/// <returns>match result</returns> /// <returns>match result</returns>
internal static MatchResult Convert(MatchBehaviour matchBehaviour, MatchResult result) internal static MatchResult Convert(MatchBehaviour matchBehaviour, MatchResult result)
{ {
return matchBehaviour == MatchBehaviour.AcceptOnMatch ? result : new MatchResult(Convert(matchBehaviour, result.Score), result.Exception); return matchBehaviour == MatchBehaviour.AcceptOnMatch ? result : MatchResult.From(result.Name, Convert(matchBehaviour, result.Score), result.Exception);
} }
} }

View File

@@ -11,7 +11,7 @@ namespace WireMock.Matchers;
/// <summary> /// <summary>
/// The MatchResult which contains the score (value between 0.0 - 1.0 of the similarity) and an optional error message. /// The MatchResult which contains the score (value between 0.0 - 1.0 of the similarity) and an optional error message.
/// </summary> /// </summary>
public struct MatchResult public class MatchResult
{ {
/// <summary> /// <summary>
/// A value between 0.0 - 1.0 of the similarity. /// A value between 0.0 - 1.0 of the similarity.
@@ -25,46 +25,55 @@ public struct MatchResult
public Exception? Exception { get; set; } public Exception? Exception { get; set; }
/// <summary> /// <summary>
/// Create a MatchResult /// The name or description of the matcher.
/// </summary> /// </summary>
/// <param name="score">A value between 0.0 - 1.0 of the similarity.</param> public required string Name { get; set; }
/// <param name="exception">The exception in case the matching fails. [Optional]</param>
public MatchResult(double score, Exception? exception = null)
{
Score = score;
Exception = exception;
}
/// <summary> /// <summary>
/// Create a MatchResult /// The sub MatchResults in case of multiple matchers.
/// </summary> /// </summary>
/// <param name="exception">The exception in case the matching fails.</param> public MatchResult[]? MatchResults { get; set; }
public MatchResult(Exception exception)
{
Exception = Guard.NotNull(exception);
}
/// <summary>
/// Implicitly converts a double to a MatchResult.
/// </summary>
/// <param name="score">The score</param>
public static implicit operator MatchResult(double score)
{
return new MatchResult(score);
}
/// <summary> /// <summary>
/// Is the value a perfect match? /// Is the value a perfect match?
/// </summary> /// </summary>
public bool IsPerfect() => MatchScores.IsPerfect(Score); public bool IsPerfect() => MatchScores.IsPerfect(Score);
/// <summary>
/// Create a MatchResult.
/// </summary>
/// <param name="name">The name or description of the matcher.</param>
/// <param name="score">A value between 0.0 - 1.0 of the similarity.</param>
/// <param name="exception">The exception in case the matching fails. [Optional]</param>
public static MatchResult From(string name, double score = 0, Exception? exception = null)
{
return new MatchResult
{
Name = name,
Score = score,
Exception = exception
};
}
/// <summary>
/// Create a MatchResult from exception.
/// </summary>
/// <param name="name">The name or description of the matcher.</param>
/// <param name="exception">The exception in case the matching fails.</param>
/// <returns>MatchResult</returns>
public static MatchResult From(string name, Exception exception)
{
return From(name, MatchScores.Mismatch, exception);
}
/// <summary> /// <summary>
/// Create a MatchResult from multiple MatchResults. /// Create a MatchResult from multiple MatchResults.
/// </summary> /// </summary>
/// <param name="name">The name or description of the matcher.</param>
/// <param name="matchResults">A list of MatchResults.</param> /// <param name="matchResults">A list of MatchResults.</param>
/// <param name="matchOperator">The MatchOperator</param> /// <param name="matchOperator">The MatchOperator</param>
/// <returns>MatchResult</returns> /// <returns>MatchResult</returns>
public static MatchResult From(IReadOnlyList<MatchResult> matchResults, MatchOperator matchOperator) public static MatchResult From(string name, IReadOnlyList<MatchResult> matchResults, MatchOperator matchOperator)
{ {
Guard.NotNullOrEmpty(matchResults); Guard.NotNullOrEmpty(matchResults);
@@ -75,6 +84,8 @@ public struct MatchResult
return new MatchResult return new MatchResult
{ {
Name = name,
MatchResults = matchResults.ToArray(),
Score = MatchScores.ToScore(matchResults.Select(r => r.Score).ToArray(), matchOperator), Score = MatchScores.ToScore(matchResults.Select(r => r.Score).ToArray(), matchOperator),
Exception = matchResults.Select(m => m.Exception).OfType<Exception>().ToArray().ToException() Exception = matchResults.Select(m => m.Exception).OfType<Exception>().ToArray().ToException()
}; };

View File

@@ -1,6 +1,5 @@
// Copyright © WireMock.Net // Copyright © WireMock.Net
using System;
using System.Linq; using System.Linq;
using AnyOfTypes; using AnyOfTypes;
using WireMock.Extensions; using WireMock.Extensions;
@@ -53,7 +52,7 @@ public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher
break; break;
} }
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)));
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -61,7 +60,7 @@ public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher
{ {
var match = !string.IsNullOrEmpty(input); var match = !string.IsNullOrEmpty(input);
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)));
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -111,7 +111,7 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
} }
} }
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -73,7 +73,7 @@ public class RequestMessageGraphQLMatcher : IRequestMatcher
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{ {
var results = CalculateMatchResults(requestMessage); var results = CalculateMatchResults(requestMessage);
var (score, exception) = MatchResult.From(results, MatchOperator).Expand(); var (score, exception) = MatchResult.From(nameof(RequestMessageGraphQLMatcher), results, MatchOperator).Expand();
return requestMatchResult.AddScore(GetType(), score, exception); return requestMatchResult.AddScore(GetType(), score, exception);
} }
@@ -86,12 +86,12 @@ public class RequestMessageGraphQLMatcher : IRequestMatcher
return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString); return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
} }
return default; return MatchResult.From(nameof(RequestMessageGraphQLMatcher));
} }
private IReadOnlyList<MatchResult> CalculateMatchResults(IRequestMessage requestMessage) private IReadOnlyList<MatchResult> CalculateMatchResults(IRequestMessage requestMessage)
{ {
return Matchers == null ? [new MatchResult()] : Matchers.Select(matcher => CalculateMatchResult(requestMessage, matcher)).ToArray(); return Matchers == null ? [MatchResult.From(nameof(RequestMessageGraphQLMatcher))] : Matchers.Select(matcher => CalculateMatchResult(requestMessage, matcher)).ToArray();
} }
private static IMatcher[] CreateMatcherArray( private static IMatcher[] CreateMatcherArray(

View File

@@ -20,7 +20,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="WireMock.Net" Version="1.8.11" /> <PackageReference Include="WireMock.Net" Version="1.23.0" />
<PackageReference Include="xunit" Version="2.9.3" /> <PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1"> <PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View File

@@ -27,7 +27,7 @@ public partial class WireMockServerTests
var textPlainMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textPlainContentTypeMatcher, null, null, textPlainContentMatcher); var textPlainMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textPlainContentTypeMatcher, null, null, textPlainContentMatcher);
var textJson = "{ \"Key\" : \"Value\" }"; var textJson = "{ \"Key\" : \"Value\" }";
var textJsonContentType = "text/json"; var textJsonContentType = "applicatiom/json";
var textJsonContentTypeMatcher = new ContentTypeMatcher(textJsonContentType); var textJsonContentTypeMatcher = new ContentTypeMatcher(textJsonContentType);
var textJsonContentMatcher = new JsonMatcher(new { Key = "Value" }, true); var textJsonContentMatcher = new JsonMatcher(new { Key = "Value" }, true);
var jsonMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textJsonContentTypeMatcher, null, null, textJsonContentMatcher); var jsonMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textJsonContentTypeMatcher, null, null, textJsonContentMatcher);

View File

@@ -15,12 +15,12 @@ public class RequestMatchResultTests
{ {
// Arrange // Arrange
var result1 = new RequestMatchResult(); var result1 = new RequestMatchResult();
result1.AddScore(typeof(WildcardMatcher), 1, null); result1.AddMatchResult(typeof(WildcardMatcher), 1, null);
result1.AddScore(typeof(WildcardMatcher), 0.9, null); result1.AddMatchResult(typeof(WildcardMatcher), 0.9, null);
var result2 = new RequestMatchResult(); var result2 = new RequestMatchResult();
result2.AddScore(typeof(JsonMatcher), 1, null); result2.AddMatchResult(typeof(JsonMatcher), 1, null);
result2.AddScore(typeof(JsonMatcher), 1, null); result2.AddMatchResult(typeof(JsonMatcher), 1, null);
var results = new[] { result1, result2 }; var results = new[] { result1, result2 };
@@ -36,13 +36,13 @@ public class RequestMatchResultTests
{ {
// Arrange // Arrange
var result1 = new RequestMatchResult(); var result1 = new RequestMatchResult();
result1.AddScore(typeof(WildcardMatcher), 1, null); result1.AddMatchResult(typeof(WildcardMatcher), 1, null);
result1.AddScore(typeof(WildcardMatcher), 1, null); result1.AddMatchResult(typeof(WildcardMatcher), 1, null);
var result2 = new RequestMatchResult(); var result2 = new RequestMatchResult();
result2.AddScore(typeof(JsonMatcher), 1, null); result2.AddMatchResult(typeof(JsonMatcher), 1, null);
result2.AddScore(typeof(JsonMatcher), 1, null); result2.AddMatchResult(typeof(JsonMatcher), 1, null);
result2.AddScore(typeof(JsonMatcher), 1, null); result2.AddMatchResult(typeof(JsonMatcher), 1, null);
var results = new[] { result1, result2 }; var results = new[] { result1, result2 };

View File

@@ -243,7 +243,7 @@ public class MappingMatcherTests
var requestMatchResult = new RequestMatchResult(); var requestMatchResult = new RequestMatchResult();
foreach (var score in match.scores) foreach (var score in match.scores)
{ {
requestMatchResult.AddScore(typeof(object), score, null); requestMatchResult.AddMatchResult(typeof(object), score, null);
} }
mappingMock.SetupGet(m => m.Probability).Returns(match.probability); mappingMock.SetupGet(m => m.Probability).Returns(match.probability);

View File

@@ -29,7 +29,7 @@ public class RequestMessageBodyMatcherTests
DetectedBodyType = BodyType.String DetectedBodyType = BodyType.String
}; };
var stringMatcherMock = new Mock<IStringMatcher>(); var stringMatcherMock = new Mock<IStringMatcher>();
stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(1d); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), 1d));
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);
@@ -61,10 +61,10 @@ public class RequestMessageBodyMatcherTests
DetectedBodyType = BodyType.String DetectedBodyType = BodyType.String
}; };
var stringMatcherMock1 = new Mock<IStringMatcher>(); var stringMatcherMock1 = new Mock<IStringMatcher>();
stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(one); stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), one));
var stringMatcherMock2 = new Mock<IStringMatcher>(); var stringMatcherMock2 = new Mock<IStringMatcher>();
stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(two); stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), two));
var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object }; var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object };
@@ -102,10 +102,10 @@ public class RequestMessageBodyMatcherTests
DetectedBodyType = BodyType.String DetectedBodyType = BodyType.String
}; };
var stringMatcherMock1 = new Mock<IStringMatcher>(); var stringMatcherMock1 = new Mock<IStringMatcher>();
stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(one); stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), one));
var stringMatcherMock2 = new Mock<IStringMatcher>(); var stringMatcherMock2 = new Mock<IStringMatcher>();
stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(two); stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), two));
var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object }; var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object };
@@ -143,10 +143,10 @@ public class RequestMessageBodyMatcherTests
DetectedBodyType = BodyType.String DetectedBodyType = BodyType.String
}; };
var stringMatcherMock1 = new Mock<IStringMatcher>(); var stringMatcherMock1 = new Mock<IStringMatcher>();
stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(one); stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), one));
var stringMatcherMock2 = new Mock<IStringMatcher>(); var stringMatcherMock2 = new Mock<IStringMatcher>();
stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(two); stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), two));
var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object }; var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object };
@@ -175,11 +175,11 @@ public class RequestMessageBodyMatcherTests
// Assign // Assign
var body = new BodyData var body = new BodyData
{ {
BodyAsBytes = new byte[] { 1 }, BodyAsBytes = [1],
DetectedBodyType = BodyType.Bytes DetectedBodyType = BodyType.Bytes
}; };
var stringMatcherMock = new Mock<IStringMatcher>(); var stringMatcherMock = new Mock<IStringMatcher>();
stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(0.5d); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), 0.5d));
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);
@@ -207,7 +207,7 @@ public class RequestMessageBodyMatcherTests
DetectedBodyType = BodyType.Json DetectedBodyType = BodyType.Json
}; };
var stringMatcherMock = new Mock<IStringMatcher>(); var stringMatcherMock = new Mock<IStringMatcher>();
stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(1.0d); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), 1.0d));
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);
@@ -235,7 +235,7 @@ public class RequestMessageBodyMatcherTests
DetectedBodyType = BodyType.Json DetectedBodyType = BodyType.Json
}; };
var stringMatcherMock = new Mock<IStringMatcher>(); var stringMatcherMock = new Mock<IStringMatcher>();
stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(1d); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), 1d));
stringMatcherMock.SetupGet(m => m.MatchOperator).Returns(MatchOperator.Or); stringMatcherMock.SetupGet(m => m.MatchOperator).Returns(MatchOperator.Or);
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);
@@ -263,7 +263,7 @@ public class RequestMessageBodyMatcherTests
DetectedBodyType = BodyType.Json DetectedBodyType = BodyType.Json
}; };
var objectMatcherMock = new Mock<IObjectMatcher>(); var objectMatcherMock = new Mock<IObjectMatcher>();
objectMatcherMock.Setup(m => m.IsMatch(It.IsAny<object>())).Returns(1d); objectMatcherMock.Setup(m => m.IsMatch(It.IsAny<object>())).Returns(MatchResult.From(nameof(IStringMatcher), 1d));
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);
@@ -387,7 +387,7 @@ public class RequestMessageBodyMatcherTests
DetectedBodyType = BodyType.Bytes DetectedBodyType = BodyType.Bytes
}; };
var objectMatcherMock = new Mock<IObjectMatcher>(); var objectMatcherMock = new Mock<IObjectMatcher>();
objectMatcherMock.Setup(m => m.IsMatch(It.IsAny<object>())).Returns(1.0d); objectMatcherMock.Setup(m => m.IsMatch(It.IsAny<object>())).Returns(MatchResult.From(nameof(IStringMatcher), 1.0d));
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);

View File

@@ -25,7 +25,7 @@ public class RequestMessageGraphQLMatcherTests
DetectedBodyType = BodyType.String DetectedBodyType = BodyType.String
}; };
var stringMatcherMock = new Mock<IStringMatcher>(); var stringMatcherMock = new Mock<IStringMatcher>();
stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(1d); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), 1d));
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);
@@ -57,10 +57,10 @@ public class RequestMessageGraphQLMatcherTests
DetectedBodyType = BodyType.String DetectedBodyType = BodyType.String
}; };
var stringMatcherMock1 = new Mock<IStringMatcher>(); var stringMatcherMock1 = new Mock<IStringMatcher>();
stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(one); stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), one));
var stringMatcherMock2 = new Mock<IStringMatcher>(); var stringMatcherMock2 = new Mock<IStringMatcher>();
stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(two); stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), two));
var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object }; var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object };
@@ -98,10 +98,10 @@ public class RequestMessageGraphQLMatcherTests
DetectedBodyType = BodyType.String DetectedBodyType = BodyType.String
}; };
var stringMatcherMock1 = new Mock<IStringMatcher>(); var stringMatcherMock1 = new Mock<IStringMatcher>();
stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(one); stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), one));
var stringMatcherMock2 = new Mock<IStringMatcher>(); var stringMatcherMock2 = new Mock<IStringMatcher>();
stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(two); stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), two));
var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object }; var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object };
@@ -139,10 +139,10 @@ public class RequestMessageGraphQLMatcherTests
DetectedBodyType = BodyType.String DetectedBodyType = BodyType.String
}; };
var stringMatcherMock1 = new Mock<IStringMatcher>(); var stringMatcherMock1 = new Mock<IStringMatcher>();
stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(one); stringMatcherMock1.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), one));
var stringMatcherMock2 = new Mock<IStringMatcher>(); var stringMatcherMock2 = new Mock<IStringMatcher>();
stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(two); stringMatcherMock2.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), two));
var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object }; var matchers = new[] { stringMatcherMock1.Object, stringMatcherMock2.Object };
@@ -175,7 +175,7 @@ public class RequestMessageGraphQLMatcherTests
DetectedBodyType = BodyType.Bytes DetectedBodyType = BodyType.Bytes
}; };
var stringMatcherMock = new Mock<IStringMatcher>(); var stringMatcherMock = new Mock<IStringMatcher>();
stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(0.5d); stringMatcherMock.Setup(m => m.IsMatch(It.IsAny<string>())).Returns(MatchResult.From(nameof(IStringMatcher), 0.5d));
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body);

View File

@@ -46,7 +46,7 @@ public class CustomPathParamMatcher : IStringMatcher
var inputParts = GetPathParts(input); var inputParts = GetPathParts(input);
if (inputParts.Length != _pathParts.Length) if (inputParts.Length != _pathParts.Length)
{ {
return MatchScores.Mismatch; return MatchResult.From(Name);
} }
try try
@@ -60,29 +60,29 @@ public class CustomPathParamMatcher : IStringMatcher
var pathParamName = pathPart.Trim('{').Trim('}'); var pathParamName = pathPart.Trim('{').Trim('}');
if (!_pathParams.ContainsKey(pathParamName)) if (!_pathParams.ContainsKey(pathParamName))
{ {
return MatchScores.Mismatch; return MatchResult.From(Name);
} }
if (!Regex.IsMatch(inputPart, _pathParams[pathParamName], RegexOptions.IgnoreCase)) if (!Regex.IsMatch(inputPart, _pathParams[pathParamName], RegexOptions.IgnoreCase))
{ {
return MatchScores.Mismatch; return MatchResult.From(Name);
} }
} }
else else
{ {
if (!inputPart.Equals(pathPart, StringComparison.InvariantCultureIgnoreCase)) if (!inputPart.Equals(pathPart, StringComparison.InvariantCultureIgnoreCase))
{ {
return MatchScores.Mismatch; return MatchResult.From(Name);
} }
} }
} }
} }
catch catch
{ {
return MatchScores.Mismatch; return MatchResult.From(Name);
} }
return MatchScores.Perfect; return MatchResult.From(Name, MatchScores.Perfect);
} }
public AnyOf<string, StringPattern>[] GetPatterns() public AnyOf<string, StringPattern>[] GetPatterns()