mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-03-27 19:41:08 +01:00
Add MatchOperator "Or", "And" and "Average" for patterns (#755)
* wip * ... * . * ... * ... * path * url * b * t * client * . * RequestMessageMethodMatcherTests * . * h * . * fix tests * .
This commit is contained in:
@@ -4,234 +4,254 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using Stef.Validation;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Serialization
|
||||
{
|
||||
internal class MappingConverter
|
||||
{
|
||||
private readonly MatcherMapper _mapper;
|
||||
namespace WireMock.Serialization;
|
||||
|
||||
public MappingConverter(MatcherMapper mapper)
|
||||
internal class MappingConverter
|
||||
{
|
||||
private readonly MatcherMapper _mapper;
|
||||
|
||||
public MappingConverter(MatcherMapper mapper)
|
||||
{
|
||||
_mapper = Guard.NotNull(mapper, nameof(mapper));
|
||||
}
|
||||
|
||||
public MappingModel ToMappingModel(IMapping mapping)
|
||||
{
|
||||
var request = (Request)mapping.RequestMatcher;
|
||||
var response = (Response)mapping.Provider;
|
||||
|
||||
var clientIPMatcher = request.GetRequestMessageMatcher<RequestMessageClientIPMatcher>();
|
||||
var pathMatcher = request.GetRequestMessageMatcher<RequestMessagePathMatcher>();
|
||||
var urlMatcher = request.GetRequestMessageMatcher<RequestMessageUrlMatcher>();
|
||||
var headerMatchers = request.GetRequestMessageMatchers<RequestMessageHeaderMatcher>();
|
||||
var cookieMatchers = request.GetRequestMessageMatchers<RequestMessageCookieMatcher>();
|
||||
var paramsMatchers = request.GetRequestMessageMatchers<RequestMessageParamMatcher>();
|
||||
var methodMatcher = request.GetRequestMessageMatcher<RequestMessageMethodMatcher>();
|
||||
var bodyMatcher = request.GetRequestMessageMatcher<RequestMessageBodyMatcher>();
|
||||
|
||||
var mappingModel = new MappingModel
|
||||
{
|
||||
_mapper = Guard.NotNull(mapper, nameof(mapper));
|
||||
Guid = mapping.Guid,
|
||||
TimeSettings = TimeSettingsMapper.Map(mapping.TimeSettings),
|
||||
Title = mapping.Title,
|
||||
Description = mapping.Description,
|
||||
Priority = mapping.Priority != 0 ? mapping.Priority : null,
|
||||
Scenario = mapping.Scenario,
|
||||
WhenStateIs = mapping.ExecutionConditionState,
|
||||
SetStateTo = mapping.NextState,
|
||||
Request = new RequestModel
|
||||
{
|
||||
Headers = headerMatchers.Any() ? headerMatchers.Select(hm => new HeaderModel
|
||||
{
|
||||
Name = hm.Name,
|
||||
Matchers = _mapper.Map(hm.Matchers)
|
||||
}).ToList() : null,
|
||||
|
||||
Cookies = cookieMatchers.Any() ? cookieMatchers.Select(cm => new CookieModel
|
||||
{
|
||||
Name = cm.Name,
|
||||
Matchers = _mapper.Map(cm.Matchers)
|
||||
}).ToList() : null,
|
||||
|
||||
Params = paramsMatchers.Any() ? paramsMatchers.Select(pm => new ParamModel
|
||||
{
|
||||
Name = pm.Key,
|
||||
IgnoreCase = pm.IgnoreCase == true ? true : null,
|
||||
Matchers = _mapper.Map(pm.Matchers)
|
||||
}).ToList() : null
|
||||
},
|
||||
Response = new ResponseModel()
|
||||
};
|
||||
|
||||
if (methodMatcher is { Methods: { } })
|
||||
{
|
||||
mappingModel.Request.Methods = methodMatcher.Methods;
|
||||
mappingModel.Request.MethodsRejectOnMatch = methodMatcher.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : null;
|
||||
mappingModel.Request.MethodsMatchOperator = methodMatcher.Methods.Length > 1 ? methodMatcher.MatchOperator.ToString() : null;
|
||||
}
|
||||
|
||||
public MappingModel ToMappingModel(IMapping mapping)
|
||||
if (clientIPMatcher is { Matchers: { } })
|
||||
{
|
||||
var request = (Request)mapping.RequestMatcher;
|
||||
var response = (Response)mapping.Provider;
|
||||
|
||||
var clientIPMatchers = request.GetRequestMessageMatchers<RequestMessageClientIPMatcher>().Where(m => m.Matchers != null).SelectMany(m => m.Matchers).ToList();
|
||||
var pathMatchers = request.GetRequestMessageMatchers<RequestMessagePathMatcher>().Where(m => m.Matchers != null).SelectMany(m => m.Matchers).ToList();
|
||||
var urlMatchers = request.GetRequestMessageMatchers<RequestMessageUrlMatcher>().Where(m => m.Matchers != null).SelectMany(m => m.Matchers).ToList();
|
||||
var headerMatchers = request.GetRequestMessageMatchers<RequestMessageHeaderMatcher>();
|
||||
var cookieMatchers = request.GetRequestMessageMatchers<RequestMessageCookieMatcher>();
|
||||
var paramsMatchers = request.GetRequestMessageMatchers<RequestMessageParamMatcher>();
|
||||
var methodMatcher = request.GetRequestMessageMatcher<RequestMessageMethodMatcher>();
|
||||
var bodyMatcher = request.GetRequestMessageMatcher<RequestMessageBodyMatcher>();
|
||||
|
||||
var mappingModel = new MappingModel
|
||||
var clientIPMatchers = _mapper.Map(clientIPMatcher.Matchers);
|
||||
mappingModel.Request.Path = new ClientIPModel
|
||||
{
|
||||
Guid = mapping.Guid,
|
||||
TimeSettings = TimeSettingsMapper.Map(mapping.TimeSettings),
|
||||
Title = mapping.Title,
|
||||
Description = mapping.Description,
|
||||
Priority = mapping.Priority != 0 ? mapping.Priority : (int?)null,
|
||||
Scenario = mapping.Scenario,
|
||||
WhenStateIs = mapping.ExecutionConditionState,
|
||||
SetStateTo = mapping.NextState,
|
||||
Request = new RequestModel
|
||||
{
|
||||
ClientIP = clientIPMatchers.Any() ? new ClientIPModel
|
||||
{
|
||||
Matchers = _mapper.Map(clientIPMatchers)
|
||||
} : null,
|
||||
|
||||
Path = pathMatchers.Any() ? new PathModel
|
||||
{
|
||||
Matchers = _mapper.Map(pathMatchers)
|
||||
} : null,
|
||||
|
||||
Url = urlMatchers.Any() ? new UrlModel
|
||||
{
|
||||
Matchers = _mapper.Map(urlMatchers)
|
||||
} : null,
|
||||
|
||||
Methods = methodMatcher?.Methods,
|
||||
|
||||
Headers = headerMatchers.Any() ? headerMatchers.Select(hm => new HeaderModel
|
||||
{
|
||||
Name = hm.Name,
|
||||
Matchers = _mapper.Map(hm.Matchers)
|
||||
}).ToList() : null,
|
||||
|
||||
Cookies = cookieMatchers.Any() ? cookieMatchers.Select(cm => new CookieModel
|
||||
{
|
||||
Name = cm.Name,
|
||||
Matchers = _mapper.Map(cm.Matchers)
|
||||
}).ToList() : null,
|
||||
|
||||
Params = paramsMatchers.Any() ? paramsMatchers.Select(pm => new ParamModel
|
||||
{
|
||||
Name = pm.Key,
|
||||
IgnoreCase = pm.IgnoreCase == true ? true : (bool?)null,
|
||||
Matchers = _mapper.Map(pm.Matchers)
|
||||
}).ToList() : null
|
||||
},
|
||||
Response = new ResponseModel()
|
||||
Matchers = clientIPMatchers,
|
||||
MatchOperator = clientIPMatchers?.Length > 1 ? clientIPMatcher.MatchOperator.ToString() : null
|
||||
};
|
||||
}
|
||||
|
||||
if (response.MinimumDelayMilliseconds >= 0 || response.MaximumDelayMilliseconds > 0)
|
||||
if (pathMatcher is { Matchers: { } })
|
||||
{
|
||||
var pathMatchers = _mapper.Map(pathMatcher.Matchers);
|
||||
mappingModel.Request.Path = new PathModel
|
||||
{
|
||||
mappingModel.Response.MinimumRandomDelay = response.MinimumDelayMilliseconds;
|
||||
mappingModel.Response.MaximumRandomDelay = response.MaximumDelayMilliseconds;
|
||||
Matchers = pathMatchers,
|
||||
MatchOperator = pathMatchers?.Length > 1 ? pathMatcher.MatchOperator.ToString() : null
|
||||
};
|
||||
}
|
||||
else if (urlMatcher is { Matchers: { } })
|
||||
{
|
||||
var urlMatchers = _mapper.Map(urlMatcher.Matchers);
|
||||
mappingModel.Request.Url = new UrlModel
|
||||
{
|
||||
Matchers = urlMatchers,
|
||||
MatchOperator = urlMatchers?.Length > 1 ? urlMatcher.MatchOperator.ToString() : null
|
||||
};
|
||||
}
|
||||
|
||||
if (response.MinimumDelayMilliseconds >= 0 || response.MaximumDelayMilliseconds > 0)
|
||||
{
|
||||
mappingModel.Response.MinimumRandomDelay = response.MinimumDelayMilliseconds;
|
||||
mappingModel.Response.MaximumRandomDelay = response.MaximumDelayMilliseconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
mappingModel.Response.Delay = (int?)(response.Delay == Timeout.InfiniteTimeSpan ? TimeSpan.MaxValue.TotalMilliseconds : response.Delay?.TotalMilliseconds);
|
||||
}
|
||||
|
||||
if (mapping.Webhooks?.Length == 1)
|
||||
{
|
||||
mappingModel.Webhook = WebhookMapper.Map(mapping.Webhooks[0]);
|
||||
}
|
||||
else if (mapping.Webhooks?.Length > 1)
|
||||
{
|
||||
mappingModel.Webhooks = mapping.Webhooks.Select(WebhookMapper.Map).ToArray();
|
||||
}
|
||||
|
||||
if (bodyMatcher?.Matchers != null)
|
||||
{
|
||||
mappingModel.Request.Body = new BodyModel();
|
||||
|
||||
if (bodyMatcher.Matchers.Length == 1)
|
||||
{
|
||||
mappingModel.Request.Body.Matcher = _mapper.Map(bodyMatcher.Matchers[0]);
|
||||
}
|
||||
else
|
||||
else if (bodyMatcher.Matchers.Length > 1)
|
||||
{
|
||||
mappingModel.Response.Delay = (int?)(response.Delay == Timeout.InfiniteTimeSpan ? TimeSpan.MaxValue.TotalMilliseconds : response.Delay?.TotalMilliseconds);
|
||||
mappingModel.Request.Body.Matchers = _mapper.Map(bodyMatcher.Matchers);
|
||||
mappingModel.Request.Body.MatchOperator = bodyMatcher.MatchOperator.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
if (response.ProxyAndRecordSettings != null)
|
||||
{
|
||||
mappingModel.Response.StatusCode = null;
|
||||
mappingModel.Response.Headers = null;
|
||||
mappingModel.Response.BodyDestination = null;
|
||||
mappingModel.Response.BodyAsJson = null;
|
||||
mappingModel.Response.BodyAsJsonIndented = null;
|
||||
mappingModel.Response.Body = null;
|
||||
mappingModel.Response.BodyAsBytes = null;
|
||||
mappingModel.Response.BodyAsFile = null;
|
||||
mappingModel.Response.BodyAsFileIsCached = null;
|
||||
mappingModel.Response.UseTransformer = null;
|
||||
mappingModel.Response.TransformerType = null;
|
||||
mappingModel.Response.UseTransformerForBodyAsFile = null;
|
||||
mappingModel.Response.TransformerReplaceNodeOptions = null;
|
||||
mappingModel.Response.BodyEncoding = null;
|
||||
mappingModel.Response.ProxyUrl = response.ProxyAndRecordSettings.Url;
|
||||
mappingModel.Response.Fault = null;
|
||||
mappingModel.Response.WebProxy = MapWebProxy(response.ProxyAndRecordSettings.WebProxySettings);
|
||||
}
|
||||
else
|
||||
{
|
||||
mappingModel.Response.WebProxy = null;
|
||||
mappingModel.Response.BodyDestination = response.ResponseMessage.BodyDestination;
|
||||
mappingModel.Response.StatusCode = response.ResponseMessage.StatusCode;
|
||||
|
||||
if (response.ResponseMessage.Headers != null && response.ResponseMessage.Headers.Count > 0)
|
||||
{
|
||||
mappingModel.Response.Headers = MapHeaders(response.ResponseMessage.Headers);
|
||||
}
|
||||
|
||||
if (mapping.Webhooks?.Length == 1)
|
||||
if (response.UseTransformer)
|
||||
{
|
||||
mappingModel.Webhook = WebhookMapper.Map(mapping.Webhooks[0]);
|
||||
}
|
||||
else if (mapping.Webhooks?.Length > 1)
|
||||
{
|
||||
mappingModel.Webhooks = mapping.Webhooks.Select(WebhookMapper.Map).ToArray();
|
||||
mappingModel.Response.UseTransformer = response.UseTransformer;
|
||||
mappingModel.Response.TransformerType = response.TransformerType.ToString();
|
||||
mappingModel.Response.TransformerReplaceNodeOptions = response.TransformerReplaceNodeOptions.ToString();
|
||||
}
|
||||
|
||||
if (bodyMatcher?.Matchers != null)
|
||||
if (response.UseTransformerForBodyAsFile)
|
||||
{
|
||||
mappingModel.Request.Body = new BodyModel();
|
||||
|
||||
if (bodyMatcher.Matchers.Length == 1)
|
||||
{
|
||||
mappingModel.Request.Body.Matcher = _mapper.Map(bodyMatcher.Matchers[0]);
|
||||
}
|
||||
else if (bodyMatcher.Matchers.Length > 1)
|
||||
{
|
||||
mappingModel.Request.Body.Matchers = _mapper.Map(bodyMatcher.Matchers);
|
||||
}
|
||||
mappingModel.Response.UseTransformerForBodyAsFile = response.UseTransformerForBodyAsFile;
|
||||
}
|
||||
|
||||
if (response.ProxyAndRecordSettings != null)
|
||||
if (response.ResponseMessage.BodyData != null)
|
||||
{
|
||||
mappingModel.Response.StatusCode = null;
|
||||
mappingModel.Response.Headers = null;
|
||||
mappingModel.Response.BodyDestination = null;
|
||||
mappingModel.Response.BodyAsJson = null;
|
||||
mappingModel.Response.BodyAsJsonIndented = null;
|
||||
mappingModel.Response.Body = null;
|
||||
mappingModel.Response.BodyAsBytes = null;
|
||||
mappingModel.Response.BodyAsFile = null;
|
||||
mappingModel.Response.BodyAsFileIsCached = null;
|
||||
mappingModel.Response.UseTransformer = null;
|
||||
mappingModel.Response.TransformerType = null;
|
||||
mappingModel.Response.UseTransformerForBodyAsFile = null;
|
||||
mappingModel.Response.TransformerReplaceNodeOptions = null;
|
||||
mappingModel.Response.BodyEncoding = null;
|
||||
mappingModel.Response.ProxyUrl = response.ProxyAndRecordSettings.Url;
|
||||
mappingModel.Response.Fault = null;
|
||||
mappingModel.Response.WebProxy = MapWebProxy(response.ProxyAndRecordSettings.WebProxySettings);
|
||||
}
|
||||
else
|
||||
{
|
||||
mappingModel.Response.WebProxy = null;
|
||||
mappingModel.Response.BodyDestination = response.ResponseMessage.BodyDestination;
|
||||
mappingModel.Response.StatusCode = response.ResponseMessage.StatusCode;
|
||||
|
||||
if (response.ResponseMessage.Headers != null && response.ResponseMessage.Headers.Count > 0)
|
||||
switch (response.ResponseMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
mappingModel.Response.Headers = MapHeaders(response.ResponseMessage.Headers);
|
||||
}
|
||||
case BodyType.String:
|
||||
mappingModel.Response.Body = response.ResponseMessage.BodyData.BodyAsString;
|
||||
break;
|
||||
|
||||
if (response.UseTransformer)
|
||||
{
|
||||
mappingModel.Response.UseTransformer = response.UseTransformer;
|
||||
mappingModel.Response.TransformerType = response.TransformerType.ToString();
|
||||
mappingModel.Response.TransformerReplaceNodeOptions = response.TransformerReplaceNodeOptions.ToString();
|
||||
}
|
||||
|
||||
if (response.UseTransformerForBodyAsFile)
|
||||
{
|
||||
mappingModel.Response.UseTransformerForBodyAsFile = response.UseTransformerForBodyAsFile;
|
||||
}
|
||||
|
||||
if (response.ResponseMessage.BodyData != null)
|
||||
{
|
||||
switch (response.ResponseMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
mappingModel.Response.Body = response.ResponseMessage.BodyData.BodyAsString;
|
||||
break;
|
||||
|
||||
case BodyType.Json:
|
||||
mappingModel.Response.BodyAsJson = response.ResponseMessage.BodyData.BodyAsJson;
|
||||
if (response.ResponseMessage.BodyData.BodyAsJsonIndented == true)
|
||||
{
|
||||
mappingModel.Response.BodyAsJsonIndented = response.ResponseMessage.BodyData.BodyAsJsonIndented;
|
||||
}
|
||||
break;
|
||||
|
||||
case BodyType.Bytes:
|
||||
mappingModel.Response.BodyAsBytes = response.ResponseMessage.BodyData.BodyAsBytes;
|
||||
break;
|
||||
|
||||
case BodyType.File:
|
||||
mappingModel.Response.BodyAsFile = response.ResponseMessage.BodyData.BodyAsFile;
|
||||
mappingModel.Response.BodyAsFileIsCached = response.ResponseMessage.BodyData.BodyAsFileIsCached;
|
||||
break;
|
||||
}
|
||||
|
||||
if (response.ResponseMessage.BodyData.Encoding != null && response.ResponseMessage.BodyData.Encoding.WebName != "utf-8")
|
||||
{
|
||||
mappingModel.Response.BodyEncoding = new EncodingModel
|
||||
case BodyType.Json:
|
||||
mappingModel.Response.BodyAsJson = response.ResponseMessage.BodyData.BodyAsJson;
|
||||
if (response.ResponseMessage.BodyData.BodyAsJsonIndented == true)
|
||||
{
|
||||
EncodingName = response.ResponseMessage.BodyData.Encoding.EncodingName,
|
||||
CodePage = response.ResponseMessage.BodyData.Encoding.CodePage,
|
||||
WebName = response.ResponseMessage.BodyData.Encoding.WebName
|
||||
};
|
||||
}
|
||||
mappingModel.Response.BodyAsJsonIndented = response.ResponseMessage.BodyData.BodyAsJsonIndented;
|
||||
}
|
||||
break;
|
||||
|
||||
case BodyType.Bytes:
|
||||
mappingModel.Response.BodyAsBytes = response.ResponseMessage.BodyData.BodyAsBytes;
|
||||
break;
|
||||
|
||||
case BodyType.File:
|
||||
mappingModel.Response.BodyAsFile = response.ResponseMessage.BodyData.BodyAsFile;
|
||||
mappingModel.Response.BodyAsFileIsCached = response.ResponseMessage.BodyData.BodyAsFileIsCached;
|
||||
break;
|
||||
}
|
||||
|
||||
if (response.ResponseMessage.FaultType != FaultType.NONE)
|
||||
if (response.ResponseMessage.BodyData.Encoding != null && response.ResponseMessage.BodyData.Encoding.WebName != "utf-8")
|
||||
{
|
||||
mappingModel.Response.Fault = new FaultModel
|
||||
mappingModel.Response.BodyEncoding = new EncodingModel
|
||||
{
|
||||
Type = response.ResponseMessage.FaultType.ToString(),
|
||||
Percentage = response.ResponseMessage.FaultPercentage
|
||||
EncodingName = response.ResponseMessage.BodyData.Encoding.EncodingName,
|
||||
CodePage = response.ResponseMessage.BodyData.Encoding.CodePage,
|
||||
WebName = response.ResponseMessage.BodyData.Encoding.WebName
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return mappingModel;
|
||||
}
|
||||
|
||||
private static WebProxyModel MapWebProxy(WebProxySettings settings)
|
||||
{
|
||||
return settings != null ? new WebProxyModel
|
||||
if (response.ResponseMessage.FaultType != FaultType.NONE)
|
||||
{
|
||||
Address = settings.Address,
|
||||
UserName = settings.UserName,
|
||||
Password = settings.Password
|
||||
} : null;
|
||||
}
|
||||
|
||||
private static IDictionary<string, object> MapHeaders(IDictionary<string, WireMockList<string>> dictionary)
|
||||
{
|
||||
var newDictionary = new Dictionary<string, object>();
|
||||
foreach (var entry in dictionary)
|
||||
{
|
||||
object value = entry.Value.Count == 1 ? (object)entry.Value.ToString() : entry.Value;
|
||||
newDictionary.Add(entry.Key, value);
|
||||
mappingModel.Response.Fault = new FaultModel
|
||||
{
|
||||
Type = response.ResponseMessage.FaultType.ToString(),
|
||||
Percentage = response.ResponseMessage.FaultPercentage
|
||||
};
|
||||
}
|
||||
|
||||
return newDictionary;
|
||||
}
|
||||
|
||||
return mappingModel;
|
||||
}
|
||||
|
||||
private static WebProxyModel? MapWebProxy(WebProxySettings? settings)
|
||||
{
|
||||
return settings != null ? new WebProxyModel
|
||||
{
|
||||
Address = settings.Address,
|
||||
UserName = settings.UserName,
|
||||
Password = settings.Password
|
||||
} : null;
|
||||
}
|
||||
|
||||
private static IDictionary<string, object> MapHeaders(IDictionary<string, WireMockList<string>> dictionary)
|
||||
{
|
||||
var newDictionary = new Dictionary<string, object>();
|
||||
foreach (var entry in dictionary)
|
||||
{
|
||||
object value = entry.Value.Count == 1 ? entry.Value.ToString() : entry.Value;
|
||||
newDictionary.Add(entry.Key, value);
|
||||
}
|
||||
|
||||
return newDictionary;
|
||||
}
|
||||
}
|
||||
@@ -9,208 +9,220 @@ using WireMock.Matchers;
|
||||
using WireMock.Models;
|
||||
using WireMock.Plugin;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Serialization
|
||||
namespace WireMock.Serialization;
|
||||
|
||||
internal class MatcherMapper
|
||||
{
|
||||
internal class MatcherMapper
|
||||
private readonly WireMockServerSettings _settings;
|
||||
|
||||
public MatcherMapper(WireMockServerSettings settings)
|
||||
{
|
||||
private readonly WireMockServerSettings _settings;
|
||||
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||
}
|
||||
|
||||
public MatcherMapper(WireMockServerSettings settings)
|
||||
public IMatcher[]? Map(IEnumerable<MatcherModel>? matchers)
|
||||
{
|
||||
if (matchers == null)
|
||||
{
|
||||
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||
return null;
|
||||
}
|
||||
return matchers.Select(Map).Where(m => m != null).ToArray()!;
|
||||
}
|
||||
|
||||
public IMatcher? Map(MatcherModel? matcher)
|
||||
{
|
||||
if (matcher == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IMatcher[] Map(IEnumerable<MatcherModel>? matchers)
|
||||
string[] parts = matcher.Name.Split('.');
|
||||
string matcherName = parts[0];
|
||||
string? matcherType = parts.Length > 1 ? parts[1] : null;
|
||||
var stringPatterns = ParseStringPatterns(matcher);
|
||||
var matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch;
|
||||
var matchOperator = StringUtils.ParseMatchOperator(matcher.MatchOperator);
|
||||
bool ignoreCase = matcher.IgnoreCase == true;
|
||||
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
||||
bool useRegexExtended = _settings.UseRegexExtended == true;
|
||||
|
||||
switch (matcherName)
|
||||
{
|
||||
return matchers?.Select(Map).Where(m => m != null).ToArray();
|
||||
case nameof(NotNullOrEmptyMatcher):
|
||||
return new NotNullOrEmptyMatcher(matchBehaviour);
|
||||
|
||||
case "CSharpCodeMatcher":
|
||||
if (_settings.AllowCSharpCodeMatcher == true)
|
||||
{
|
||||
return PluginLoader.Load<ICSharpCodeMatcher>(matchBehaviour, matchOperator, stringPatterns);
|
||||
}
|
||||
|
||||
throw new NotSupportedException("It's not allowed to use the 'CSharpCodeMatcher' because WireMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'.");
|
||||
|
||||
case nameof(LinqMatcher):
|
||||
return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns);
|
||||
|
||||
case nameof(ExactMatcher):
|
||||
return new ExactMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns);
|
||||
|
||||
case nameof(ExactObjectMatcher):
|
||||
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(RegexMatcher):
|
||||
return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails, useRegexExtended, matchOperator);
|
||||
|
||||
case nameof(JsonMatcher):
|
||||
var valueForJsonMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonMatcher(matchBehaviour, valueForJsonMatcher!, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(JsonPartialMatcher):
|
||||
var valueForJsonPartialMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonPartialMatcher(matchBehaviour, valueForJsonPartialMatcher!, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(JsonPartialWildcardMatcher):
|
||||
var valueForJsonPartialWildcardMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonPartialWildcardMatcher(matchBehaviour, valueForJsonPartialWildcardMatcher!, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(JsonPathMatcher):
|
||||
return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns);
|
||||
|
||||
case nameof(JmesPathMatcher):
|
||||
return new JmesPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns);
|
||||
|
||||
case nameof(XPathMatcher):
|
||||
return new XPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns);
|
||||
|
||||
case nameof(WildcardMatcher):
|
||||
return new WildcardMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails, matchOperator);
|
||||
|
||||
case nameof(ContentTypeMatcher):
|
||||
return new ContentTypeMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(SimMetricsMatcher):
|
||||
SimMetricType type = SimMetricType.Levenstein;
|
||||
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
|
||||
{
|
||||
throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported.");
|
||||
}
|
||||
|
||||
return new SimMetricsMatcher(matchBehaviour, stringPatterns, type, throwExceptionWhenMatcherFails);
|
||||
|
||||
default:
|
||||
if (_settings.CustomMatcherMappings != null && _settings.CustomMatcherMappings.ContainsKey(matcherName))
|
||||
{
|
||||
return _settings.CustomMatcherMappings[matcherName](matcher);
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Matcher '{matcherName}' is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public MatcherModel[]? Map(IEnumerable<IMatcher>? matchers)
|
||||
{
|
||||
if (matchers == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IMatcher? Map(MatcherModel? matcher)
|
||||
return matchers.Where(m => m != null).Select(Map).ToArray()!;
|
||||
}
|
||||
|
||||
public MatcherModel? Map(IMatcher? matcher)
|
||||
{
|
||||
if (matcher == null)
|
||||
{
|
||||
if (matcher == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string[] parts = matcher.Name.Split('.');
|
||||
string matcherName = parts[0];
|
||||
string? matcherType = parts.Length > 1 ? parts[1] : null;
|
||||
var stringPatterns = ParseStringPatterns(matcher);
|
||||
var matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch;
|
||||
bool ignoreCase = matcher.IgnoreCase == true;
|
||||
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
||||
bool useRegexExtended = _settings.UseRegexExtended == true;
|
||||
|
||||
switch (matcherName)
|
||||
{
|
||||
case nameof(NotNullOrEmptyMatcher):
|
||||
return new NotNullOrEmptyMatcher(matchBehaviour);
|
||||
|
||||
case "CSharpCodeMatcher":
|
||||
if (_settings.AllowCSharpCodeMatcher == true)
|
||||
{
|
||||
return PluginLoader.Load<ICSharpCodeMatcher>(matchBehaviour, stringPatterns);
|
||||
}
|
||||
|
||||
throw new NotSupportedException("It's not allowed to use the 'CSharpCodeMatcher' because WireMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'.");
|
||||
|
||||
case nameof(LinqMatcher):
|
||||
return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case nameof(ExactMatcher):
|
||||
return new ExactMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case nameof(ExactObjectMatcher):
|
||||
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(RegexMatcher):
|
||||
return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails, useRegexExtended);
|
||||
|
||||
case nameof(JsonMatcher):
|
||||
var valueForJsonMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonMatcher(matchBehaviour, valueForJsonMatcher!, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(JsonPartialMatcher):
|
||||
var valueForJsonPartialMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonPartialMatcher(matchBehaviour, valueForJsonPartialMatcher!, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(JsonPartialWildcardMatcher):
|
||||
var valueForJsonPartialWildcardMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonPartialWildcardMatcher(matchBehaviour, valueForJsonPartialWildcardMatcher!, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(JsonPathMatcher):
|
||||
return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case nameof(JmesPathMatcher):
|
||||
return new JmesPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case nameof(XPathMatcher):
|
||||
return new XPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case nameof(WildcardMatcher):
|
||||
return new WildcardMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(ContentTypeMatcher):
|
||||
return new ContentTypeMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(SimMetricsMatcher):
|
||||
SimMetricType type = SimMetricType.Levenstein;
|
||||
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
|
||||
{
|
||||
throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported.");
|
||||
}
|
||||
|
||||
return new SimMetricsMatcher(matchBehaviour, stringPatterns, type, throwExceptionWhenMatcherFails);
|
||||
|
||||
default:
|
||||
if (_settings.CustomMatcherMappings != null && _settings.CustomMatcherMappings.ContainsKey(matcherName))
|
||||
{
|
||||
return _settings.CustomMatcherMappings[matcherName](matcher);
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Matcher '{matcherName}' is not supported.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public MatcherModel[] Map(IEnumerable<IMatcher>? matchers)
|
||||
bool? ignoreCase = matcher is IIgnoreCaseMatcher ignoreCaseMatcher ? ignoreCaseMatcher.IgnoreCase : null;
|
||||
bool? rejectOnMatch = matcher.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : null;
|
||||
|
||||
var model = new MatcherModel
|
||||
{
|
||||
return matchers?.Select(Map).Where(m => m != null).ToArray();
|
||||
}
|
||||
RejectOnMatch = rejectOnMatch,
|
||||
IgnoreCase = ignoreCase,
|
||||
Name = matcher.Name
|
||||
};
|
||||
|
||||
public MatcherModel? Map(IMatcher? matcher)
|
||||
switch (matcher)
|
||||
{
|
||||
if (matcher == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
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:
|
||||
var stringPatterns = stringMatcher.GetPatterns();
|
||||
if (stringPatterns.Length == 1)
|
||||
// If the matcher is a IStringMatcher, get the operator & patterns.
|
||||
case IStringMatcher stringMatcher:
|
||||
var stringPatterns = stringMatcher.GetPatterns();
|
||||
if (stringPatterns.Length == 1)
|
||||
{
|
||||
if (stringPatterns[0].IsFirst)
|
||||
{
|
||||
if (stringPatterns[0].IsFirst)
|
||||
{
|
||||
model.Pattern = stringPatterns[0].First;
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Pattern = stringPatterns[0].Second.Pattern;
|
||||
model.PatternAsFile = stringPatterns[0].Second.PatternAsFile;
|
||||
}
|
||||
model.Pattern = stringPatterns[0].First;
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Patterns = stringPatterns.Select(p => p.GetPattern()).Cast<object>().ToArray();
|
||||
model.Pattern = stringPatterns[0].Second.Pattern;
|
||||
model.PatternAsFile = stringPatterns[0].Second.PatternAsFile;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Patterns = stringPatterns.Select(p => p.GetPattern()).Cast<object>().ToArray();
|
||||
model.MatchOperator = stringMatcher.MatchOperator.ToString();
|
||||
}
|
||||
break;
|
||||
|
||||
// If the matcher is a IValueMatcher, get the value (can be string or object).
|
||||
case IValueMatcher valueMatcher:
|
||||
model.Pattern = valueMatcher.Value;
|
||||
break;
|
||||
// If the matcher is a IValueMatcher, get the value (can be string or object).
|
||||
case IValueMatcher valueMatcher:
|
||||
model.Pattern = valueMatcher.Value;
|
||||
break;
|
||||
|
||||
// If the matcher is a ExactObjectMatcher, get the ValueAsObject or ValueAsBytes.
|
||||
case ExactObjectMatcher exactObjectMatcher:
|
||||
model.Pattern = exactObjectMatcher.ValueAsObject ?? exactObjectMatcher.ValueAsBytes;
|
||||
break;
|
||||
}
|
||||
|
||||
return model;
|
||||
// If the matcher is a ExactObjectMatcher, get the ValueAsObject or ValueAsBytes.
|
||||
case ExactObjectMatcher exactObjectMatcher:
|
||||
model.Pattern = exactObjectMatcher.ValueAsObject ?? exactObjectMatcher.ValueAsBytes;
|
||||
break;
|
||||
}
|
||||
|
||||
private AnyOf<string, StringPattern>[] ParseStringPatterns(MatcherModel matcher)
|
||||
return model;
|
||||
}
|
||||
|
||||
private AnyOf<string, StringPattern>[] ParseStringPatterns(MatcherModel matcher)
|
||||
{
|
||||
if (matcher.Pattern is string patternAsString)
|
||||
{
|
||||
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];
|
||||
return new[] { new AnyOf<string, StringPattern>(patternAsString) };
|
||||
}
|
||||
|
||||
private ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> stringPattern, bool throwException)
|
||||
if (matcher.Pattern is IEnumerable<string> patternAsStringArray)
|
||||
{
|
||||
byte[] bytePattern;
|
||||
try
|
||||
{
|
||||
bytePattern = Convert.FromBase64String(stringPattern.GetPattern());
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new ArgumentException($"Matcher 'ExactObjectMatcher' has invalid pattern. The pattern value '{stringPattern}' is not a Base64String.", nameof(stringPattern));
|
||||
}
|
||||
|
||||
return new ExactObjectMatcher(matchBehaviour, bytePattern, throwException);
|
||||
return patternAsStringArray.ToAnyOfPatterns();
|
||||
}
|
||||
|
||||
if (matcher.Patterns?.OfType<string>() is IEnumerable<string> patternsAsStringArray)
|
||||
{
|
||||
return patternsAsStringArray.ToAnyOfPatterns();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(matcher.PatternAsFile))
|
||||
{
|
||||
var patternAsFile = matcher.PatternAsFile!;
|
||||
var pattern = _settings.FileSystemHandler.ReadFileAsString(patternAsFile);
|
||||
return new[] { new AnyOf<string, StringPattern>(new StringPattern { Pattern = pattern, PatternAsFile = patternAsFile }) };
|
||||
}
|
||||
|
||||
return new AnyOf<string, StringPattern>[0];
|
||||
}
|
||||
|
||||
private static ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> stringPattern, bool throwException)
|
||||
{
|
||||
byte[] bytePattern;
|
||||
try
|
||||
{
|
||||
bytePattern = Convert.FromBase64String(stringPattern.GetPattern());
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new ArgumentException($"Matcher 'ExactObjectMatcher' has invalid pattern. The pattern value '{stringPattern}' is not a Base64String.", nameof(stringPattern));
|
||||
}
|
||||
|
||||
return new ExactObjectMatcher(matchBehaviour, bytePattern, throwException);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user