ExactMatcher : IgnoreCase (#817)

* ...

* mm

* fix some null warnings

* fx
This commit is contained in:
Stef Heyenrath
2022-10-15 08:23:58 +02:00
committed by GitHub
parent b523ab9125
commit 55afc8041f
20 changed files with 849 additions and 735 deletions

View File

@@ -13,12 +13,12 @@ public interface IBodyData
/// <summary> /// <summary>
/// The body (as bytearray). /// The body (as bytearray).
/// </summary> /// </summary>
byte[] BodyAsBytes { get; set; } byte[]? BodyAsBytes { get; set; }
/// <summary> /// <summary>
/// Gets or sets the body as a file. /// Gets or sets the body as a file.
/// </summary> /// </summary>
string BodyAsFile { get; set; } string? BodyAsFile { get; set; }
/// <summary> /// <summary>
/// Is the body as file cached? /// Is the body as file cached?
@@ -38,7 +38,7 @@ public interface IBodyData
/// <summary> /// <summary>
/// The body as string, this is defined when BodyAsString or BodyAsJson are not null. /// The body as string, this is defined when BodyAsString or BodyAsJson are not null.
/// </summary> /// </summary>
string BodyAsString { get; set; } string? BodyAsString { get; set; }
/// <summary> /// <summary>
/// The detected body type (detection based on body content). /// The detected body type (detection based on body content).

View File

@@ -1,7 +1,7 @@
using System;
using System.Linq; using System.Linq;
using AnyOfTypes; using AnyOfTypes;
using Stef.Validation; using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models; using WireMock.Models;
namespace WireMock.Matchers; namespace WireMock.Matchers;
@@ -9,8 +9,8 @@ namespace WireMock.Matchers;
/// <summary> /// <summary>
/// ExactMatcher /// ExactMatcher
/// </summary> /// </summary>
/// <seealso cref="IStringMatcher" /> /// <seealso cref="IStringMatcher" /> and <seealso cref="IIgnoreCaseMatcher" />
public class ExactMatcher : IStringMatcher public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher
{ {
private readonly AnyOf<string, StringPattern>[] _values; private readonly AnyOf<string, StringPattern>[] _values;
@@ -24,7 +24,16 @@ public class ExactMatcher : IStringMatcher
/// Initializes a new instance of the <see cref="ExactMatcher"/> class. /// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary> /// </summary>
/// <param name="values">The values.</param> /// <param name="values">The values.</param>
public ExactMatcher(params AnyOf<string, StringPattern>[] values) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, values) public ExactMatcher(params AnyOf<string, StringPattern>[] values) : this(MatchBehaviour.AcceptOnMatch, false, false, MatchOperator.Or, values)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="ignoreCase">Ignore the case from the pattern(s).</param>
/// <param name="values">The values.</param>
public ExactMatcher(bool ignoreCase, params AnyOf<string, StringPattern>[] values) : this(MatchBehaviour.AcceptOnMatch, ignoreCase, false, MatchOperator.Or, values)
{ {
} }
@@ -32,11 +41,13 @@ public class ExactMatcher : IStringMatcher
/// Initializes a new instance of the <see cref="ExactMatcher"/> class. /// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary> /// </summary>
/// <param name="matchBehaviour">The match behaviour.</param> /// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="ignoreCase">Ignore the case from the pattern(s).</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param> /// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param> /// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
/// <param name="values">The values.</param> /// <param name="values">The values.</param>
public ExactMatcher( public ExactMatcher(
MatchBehaviour matchBehaviour, MatchBehaviour matchBehaviour,
bool ignoreCase = false,
bool throwException = false, bool throwException = false,
MatchOperator matchOperator = MatchOperator.Or, MatchOperator matchOperator = MatchOperator.Or,
params AnyOf<string, StringPattern>[] values) params AnyOf<string, StringPattern>[] values)
@@ -45,13 +56,18 @@ public class ExactMatcher : IStringMatcher
MatchBehaviour = matchBehaviour; MatchBehaviour = matchBehaviour;
ThrowException = throwException; ThrowException = throwException;
IgnoreCase = ignoreCase;
MatchOperator = matchOperator; MatchOperator = matchOperator;
} }
/// <inheritdoc cref="IStringMatcher.IsMatch"/> /// <inheritdoc cref="IStringMatcher.IsMatch"/>
public double IsMatch(string? input) public double IsMatch(string? input)
{ {
double score = MatchScores.ToScore(_values.Select(v => v.GetPattern() == input).ToArray(), MatchOperator); Func<string?, bool> equals = IgnoreCase
? pattern => string.Equals(pattern, input, StringComparison.OrdinalIgnoreCase)
: pattern => pattern == input;
double score = MatchScores.ToScore(_values.Select(v => equals(v)).ToArray(), MatchOperator);
return MatchBehaviourHelper.Convert(MatchBehaviour, score); return MatchBehaviourHelper.Convert(MatchBehaviour, score);
} }
@@ -66,4 +82,7 @@ public class ExactMatcher : IStringMatcher
/// <inheritdoc cref="IMatcher.Name"/> /// <inheritdoc cref="IMatcher.Name"/>
public string Name => "ExactMatcher"; public string Name => "ExactMatcher";
/// <inheritdoc />
public bool IgnoreCase { get; }
} }

View File

@@ -29,7 +29,7 @@ public class JsonPartialMatcher : AbstractJsonPartialMatcher
/// <inheritdoc /> /// <inheritdoc />
protected override bool IsMatch(string value, string input) protected override bool IsMatch(string value, string input)
{ {
var exactStringMatcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, ThrowException, MatchOperator.Or, value); var exactStringMatcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, IgnoreCase, ThrowException, MatchOperator.Or, value);
return MatchScores.IsPerfect(exactStringMatcher.IsMatch(input)); return MatchScores.IsPerfect(exactStringMatcher.IsMatch(input));
} }
} }

View File

@@ -18,5 +18,5 @@ public enum MatchOperator
/// <summary> /// <summary>
/// The average value from all patterns. /// The average value from all patterns.
/// </summary> /// </summary>
Average, Average
} }

View File

@@ -16,22 +16,22 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// <summary> /// <summary>
/// The body function /// The body function
/// </summary> /// </summary>
public Func<string, bool>? Func { get; } public Func<string?, bool>? Func { 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>? DataFunc { 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>? JsonFunc { 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>? BodyDataFunc { get; }
/// <summary> /// <summary>
/// The matchers. /// The matchers.
@@ -77,7 +77,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class. /// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary> /// </summary>
/// <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); Func = Guard.NotNull(func);
} }
@@ -86,7 +86,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class. /// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary> /// </summary>
/// <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); DataFunc = Guard.NotNull(func);
} }
@@ -95,7 +95,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class. /// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary> /// </summary>
/// <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); JsonFunc = Guard.NotNull(func);
} }
@@ -158,9 +158,9 @@ public class RequestMessageBodyMatcher : IRequestMatcher
{ {
// If the body is a byte array, try to match. // If the body is a byte array, try to match.
var detectedBodyType = requestMessage.BodyData?.DetectedBodyType; var detectedBodyType = requestMessage.BodyData?.DetectedBodyType;
if (detectedBodyType == BodyType.Bytes || detectedBodyType == BodyType.String) if (detectedBodyType is BodyType.Bytes or BodyType.String)
{ {
return exactObjectMatcher.IsMatch(requestMessage.BodyData.BodyAsBytes); return exactObjectMatcher.IsMatch(requestMessage.BodyData?.BodyAsBytes);
} }
} }

View File

@@ -53,7 +53,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
/// <param name="key">The key.</param> /// <param name="key">The key.</param>
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param> /// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
/// <param name="values">The values.</param> /// <param name="values">The values.</param>
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, string[]? values) : this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, false, MatchOperator.And, value)).Cast<IStringMatcher>().ToArray()) public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, string[]? values) : this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, ignoreCase, false, MatchOperator.And, value)).Cast<IStringMatcher>().ToArray())
{ {
} }

View File

@@ -11,7 +11,7 @@ namespace WireMock.Util
/// <inheritdoc cref="IBodyData.Encoding" /> /// <inheritdoc cref="IBodyData.Encoding" />
public Encoding? Encoding { get; set; } public Encoding? Encoding { get; set; }
/// <inheritdoc cref="IBodyData.BodyAsBytes" /> /// <inheritdoc />
public string? BodyAsString { get; set; } public string? BodyAsString { get; set; }
/// <inheritdoc cref="IBodyData.BodyAsJson" /> /// <inheritdoc cref="IBodyData.BodyAsJson" />

View File

@@ -107,7 +107,7 @@ namespace WireMock.Owin
{ {
try try
{ {
var appLifetime = (IApplicationLifetime)_host.Services.GetService(typeof(IApplicationLifetime)); var appLifetime = _host.Services.GetRequiredService<IApplicationLifetime>();
appLifetime.ApplicationStarted.Register(() => appLifetime.ApplicationStarted.Register(() =>
{ {
var addresses = _host.ServerFeatures var addresses = _host.ServerFeatures

View File

@@ -1,10 +1,17 @@
using Stef.Validation; using Stef.Validation;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using WireMock.Constants;
using WireMock.Http; using WireMock.Http;
using WireMock.Matchers;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Serialization; using WireMock.Serialization;
using WireMock.Settings; using WireMock.Settings;
using WireMock.Types;
using WireMock.Util; using WireMock.Util;
namespace WireMock.Proxy; namespace WireMock.Proxy;
@@ -55,4 +62,69 @@ internal class ProxyHelper
return (responseMessage, newMapping); return (responseMessage, newMapping);
} }
private IMapping ToMapping(ProxyAndRecordSettings proxyAndRecordSettings, IRequestMessage requestMessage, ResponseMessage responseMessage)
{
var excludedHeaders = proxyAndRecordSettings.ExcludedHeaders ?? new string[] { };
var excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? new string[] { };
var request = Request.Create();
request.WithPath(requestMessage.Path);
request.UsingMethod(requestMessage.Method);
requestMessage.Query?.Loop((key, value) => request.WithParam(key, false, value.ToArray()));
requestMessage.Cookies?.Loop((key, value) =>
{
if (!excludedCookies.Contains(key, StringComparer.OrdinalIgnoreCase))
{
request.WithCookie(key, value);
}
});
var allExcludedHeaders = new List<string>(excludedHeaders) { "Cookie" };
requestMessage.Headers?.Loop((key, value) =>
{
if (!allExcludedHeaders.Contains(key, StringComparer.OrdinalIgnoreCase))
{
request.WithHeader(key, value.ToArray());
}
});
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
switch (requestMessage.BodyData?.DetectedBodyType)
{
case BodyType.Json:
request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson!, true, throwExceptionWhenMatcherFails));
break;
case BodyType.String:
request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString));
break;
case BodyType.Bytes:
request.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes, throwExceptionWhenMatcherFails));
break;
}
var response = Response.Create(responseMessage);
return new Mapping
(
guid: Guid.NewGuid(),
title: $"Proxy Mapping for {requestMessage.Method} {requestMessage.Path}",
description: string.Empty,
path: null,
settings: _settings,
request,
response,
priority: WireMockConstants.ProxyPriority, // This was 0
scenario: null,
executionConditionState: null,
nextState: null,
stateTimes: null,
webhooks: null,
useWebhooksFireAndForget: null,
timeSettings: null
);
}
} }

View File

@@ -66,7 +66,7 @@ internal class MatcherMapper
return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns); return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns);
case nameof(ExactMatcher): case nameof(ExactMatcher):
return new ExactMatcher(matchBehaviour, throwExceptionWhenMatcherFails, matchOperator, stringPatterns); return new ExactMatcher(matchBehaviour, ignoreCase, throwExceptionWhenMatcherFails, matchOperator, stringPatterns);
case nameof(ExactObjectMatcher): case nameof(ExactObjectMatcher):
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails); return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails);

View File

@@ -140,11 +140,11 @@ internal class ProxyMappingConverter
break; break;
case BodyType.String: case BodyType.String:
newRequest.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString)); newRequest.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, true, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString!));
break; break;
case BodyType.Bytes: case BodyType.Bytes:
newRequest.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes, throwExceptionWhenMatcherFails)); newRequest.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes!, throwExceptionWhenMatcherFails));
break; break;
} }
} }

View File

@@ -1,12 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using JetBrains.Annotations;
using WireMock.Models; using WireMock.Models;
using WireMock.ResponseProviders; using WireMock.ResponseProviders;
using WireMock.Types; using WireMock.Types;
namespace WireMock.Server namespace WireMock.Server;
{
/// <summary> /// <summary>
/// IRespondWithAProvider /// IRespondWithAProvider
/// </summary> /// </summary>
@@ -141,10 +140,10 @@ namespace WireMock.Server
/// <param name="transformerType">The transformer type. [optional]</param> /// <param name="transformerType">The transformer type. [optional]</param>
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns> /// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
IRespondWithAProvider WithWebhook( IRespondWithAProvider WithWebhook(
[NotNull] string url, string url,
[CanBeNull] string method = "post", string? method = "post",
[CanBeNull] IDictionary<string, WireMockList<string>> headers = null, IDictionary<string, WireMockList<string>>? headers = null,
[CanBeNull] string body = null, string? body = null,
bool useTransformer = true, bool useTransformer = true,
TransformerType transformerType = TransformerType.Handlebars TransformerType transformerType = TransformerType.Handlebars
); );
@@ -160,12 +159,11 @@ namespace WireMock.Server
/// <param name="transformerType">The transformer type. [optional]</param> /// <param name="transformerType">The transformer type. [optional]</param>
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns> /// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
IRespondWithAProvider WithWebhook( IRespondWithAProvider WithWebhook(
[NotNull] string url, string url,
[CanBeNull] string method = "post", string? method = "post",
[CanBeNull] IDictionary<string, WireMockList<string>> headers = null, IDictionary<string, WireMockList<string>>? headers = null,
[CanBeNull] object body = null, object? body = null,
bool useTransformer = true, bool useTransformer = true,
TransformerType transformerType = TransformerType.Handlebars TransformerType transformerType = TransformerType.Handlebars
); );
} }
}

View File

@@ -17,6 +17,7 @@ public static class DictionaryExtensions
/// <param name="dictionary">The dictionary to loop (can be null).</param> /// <param name="dictionary">The dictionary to loop (can be null).</param>
/// <param name="action">The action.</param> /// <param name="action">The action.</param>
public static void Loop<TKey, TValue>(this IDictionary<TKey, TValue>? dictionary, Action<TKey, TValue> action) public static void Loop<TKey, TValue>(this IDictionary<TKey, TValue>? dictionary, Action<TKey, TValue> action)
where TKey : notnull
{ {
Guard.NotNull(action); Guard.NotNull(action);

View File

@@ -32,7 +32,7 @@ internal static class TypeBuilderUtils
CreateGetSetMethods(typeBuilder, property.Key, property.Value); CreateGetSetMethods(typeBuilder, property.Key, property.Value);
} }
var type = typeBuilder.CreateTypeInfo().AsType(); var type = typeBuilder.CreateTypeInfo()!.AsType();
Types.TryAdd(properties, type); Types.TryAdd(properties, type);
@@ -43,6 +43,7 @@ internal static class TypeBuilderUtils
/// https://stackoverflow.com/questions/3804367/testing-for-equality-between-dictionaries-in-c-sharp /// https://stackoverflow.com/questions/3804367/testing-for-equality-between-dictionaries-in-c-sharp
/// </summary> /// </summary>
private static bool Compare<TKey, TValue>(IDictionary<TKey, TValue> dict1, IDictionary<TKey, TValue> dict2) private static bool Compare<TKey, TValue>(IDictionary<TKey, TValue> dict1, IDictionary<TKey, TValue> dict2)
where TKey : notnull
{ {
if (dict1 == dict2) if (dict1 == dict2)
{ {

View File

@@ -2,8 +2,8 @@ using NFluent;
using WireMock.Matchers; using WireMock.Matchers;
using Xunit; using Xunit;
namespace WireMock.Net.Tests.Matchers namespace WireMock.Net.Tests.Matchers;
{
public class ExactMatcherTests public class ExactMatcherTests
{ {
[Fact] [Fact]
@@ -32,6 +32,19 @@ namespace WireMock.Net.Tests.Matchers
Check.That(patterns).ContainsExactly("X"); Check.That(patterns).ContainsExactly("X");
} }
[Fact]
public void ExactMatcher_IsMatch_IgnoreCase()
{
// Assign
var matcher = new ExactMatcher(true, "x");
// Act
double result = matcher.IsMatch("X");
// Assert
Check.That(result).IsEqualTo(1.0);
}
[Fact] [Fact]
public void ExactMatcher_IsMatch_WithSinglePattern_ReturnsMatch1_0() public void ExactMatcher_IsMatch_WithSinglePattern_ReturnsMatch1_0()
{ {
@@ -91,7 +104,7 @@ namespace WireMock.Net.Tests.Matchers
public void ExactMatcher_IsMatch_WithMultiplePatterns_Average_ReturnsMatch(MatchOperator matchOperator, double score) public void ExactMatcher_IsMatch_WithMultiplePatterns_Average_ReturnsMatch(MatchOperator matchOperator, double score)
{ {
// Assign // Assign
var matcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, matchOperator, "x", "y"); var matcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, false, matchOperator, "x", "y");
// Act // Act
double result = matcher.IsMatch("x"); double result = matcher.IsMatch("x");
@@ -117,7 +130,7 @@ namespace WireMock.Net.Tests.Matchers
public void ExactMatcher_IsMatch_SinglePattern_AcceptOnMatch() public void ExactMatcher_IsMatch_SinglePattern_AcceptOnMatch()
{ {
// Assign // Assign
var matcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, "cat"); var matcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, false, MatchOperator.Or, "cat");
// Act // Act
double result = matcher.IsMatch("cat"); double result = matcher.IsMatch("cat");
@@ -130,7 +143,7 @@ namespace WireMock.Net.Tests.Matchers
public void ExactMatcher_IsMatch_SinglePattern_RejectOnMatch() public void ExactMatcher_IsMatch_SinglePattern_RejectOnMatch()
{ {
// Assign // Assign
var matcher = new ExactMatcher(MatchBehaviour.RejectOnMatch, false, MatchOperator.Or, "cat"); var matcher = new ExactMatcher(MatchBehaviour.RejectOnMatch, false, false, MatchOperator.Or, "cat");
// Act // Act
double result = matcher.IsMatch("cat"); double result = matcher.IsMatch("cat");
@@ -139,4 +152,3 @@ namespace WireMock.Net.Tests.Matchers
Check.That(result).IsEqualTo(0.0); Check.That(result).IsEqualTo(0.0);
} }
} }
}

View File

@@ -13,8 +13,8 @@ using WireMock.Types;
using WireMock.Util; using WireMock.Util;
using Xunit; using Xunit;
namespace WireMock.Net.Tests.RequestMatchers namespace WireMock.Net.Tests.RequestMatchers;
{
public class RequestMessageBodyMatcherTests public class RequestMessageBodyMatcherTests
{ {
[Fact] [Fact]
@@ -429,39 +429,38 @@ namespace WireMock.Net.Tests.RequestMatchers
return new TheoryData<object, RequestMessageBodyMatcher, bool> return new TheoryData<object, RequestMessageBodyMatcher, bool>
{ {
// JSON match +++ // JSON match +++
{json, new RequestMessageBodyMatcher((object o) => ((dynamic) o).a == "b"), true}, {json, new RequestMessageBodyMatcher((object? o) => ((dynamic) o!).a == "b"), true},
{json, new RequestMessageBodyMatcher((string s) => s == json), true}, {json, new RequestMessageBodyMatcher((string? s) => s == json), true},
{json, new RequestMessageBodyMatcher((byte[] b) => b.SequenceEqual(Encoding.UTF8.GetBytes(json))), true}, {json, new RequestMessageBodyMatcher((byte[]? b) => b.SequenceEqual(Encoding.UTF8.GetBytes(json))), true},
// JSON no match --- // JSON no match ---
{json, new RequestMessageBodyMatcher((object o) => false), false}, {json, new RequestMessageBodyMatcher((object? o) => false), false},
{json, new RequestMessageBodyMatcher((string s) => false), false}, {json, new RequestMessageBodyMatcher((string? s) => false), false},
{json, new RequestMessageBodyMatcher((byte[] b) => false), false}, {json, new RequestMessageBodyMatcher((byte[]? b) => false), false},
{json, new RequestMessageBodyMatcher(), false }, {json, new RequestMessageBodyMatcher(), false },
// string match +++ // string match +++
{str, new RequestMessageBodyMatcher((object o) => o == null), true}, {str, new RequestMessageBodyMatcher((object? o) => o == null), true},
{str, new RequestMessageBodyMatcher((string s) => s == str), true}, {str, new RequestMessageBodyMatcher((string? s) => s == str), true},
{str, new RequestMessageBodyMatcher((byte[] b) => b.SequenceEqual(Encoding.UTF8.GetBytes(str))), true}, {str, new RequestMessageBodyMatcher((byte[]? b) => b.SequenceEqual(Encoding.UTF8.GetBytes(str))), true},
// string no match --- // string no match ---
{str, new RequestMessageBodyMatcher((object o) => false), false}, {str, new RequestMessageBodyMatcher((object? o) => false), false},
{str, new RequestMessageBodyMatcher((string s) => false), false}, {str, new RequestMessageBodyMatcher((string? s) => false), false},
{str, new RequestMessageBodyMatcher((byte[] b) => false), false}, {str, new RequestMessageBodyMatcher((byte[]? b) => false), false},
{str, new RequestMessageBodyMatcher(), false }, {str, new RequestMessageBodyMatcher(), false },
// binary match +++ // binary match +++
{bytes, new RequestMessageBodyMatcher((object o) => o == null), true}, {bytes, new RequestMessageBodyMatcher((object? o) => o == null), true},
{bytes, new RequestMessageBodyMatcher((string s) => s == null), true}, {bytes, new RequestMessageBodyMatcher((string? s) => s == null), true},
{bytes, new RequestMessageBodyMatcher((byte[] b) => b.SequenceEqual(bytes)), true}, {bytes, new RequestMessageBodyMatcher((byte[]? b) => b.SequenceEqual(bytes)), true},
// binary no match --- // binary no match ---
{bytes, new RequestMessageBodyMatcher((object o) => false), false}, {bytes, new RequestMessageBodyMatcher((object? o) => false), false},
{bytes, new RequestMessageBodyMatcher((string s) => false), false}, {bytes, new RequestMessageBodyMatcher((string? s) => false), false},
{bytes, new RequestMessageBodyMatcher((byte[] b) => false), false}, {bytes, new RequestMessageBodyMatcher((byte[]? b) => false), false},
{bytes, new RequestMessageBodyMatcher(), false }, {bytes, new RequestMessageBodyMatcher(), false },
}; };
} }
} }
} }
}

View File

@@ -80,7 +80,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test http://localhost/foo /foo POSt"); Check.That(response.Message.BodyData!.BodyAsString).Equals("test http://localhost/foo /foo POSt");
} }
[Theory] [Theory]
@@ -104,7 +104,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("url=http://localhost/a/b absoluteurl=http://localhost/wiremock/a/b path=/a/b absolutepath=/wiremock/a/b"); Check.That(response.Message.BodyData!.BodyAsString).Equals("url=http://localhost/a/b absoluteurl=http://localhost/wiremock/a/b path=/a/b absolutepath=/wiremock/a/b");
} }
[Fact] [Fact]
@@ -122,7 +122,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("a wiremock"); Check.That(response.Message.BodyData!.BodyAsString).Equals("a wiremock");
} }
[Theory(Skip = "Invalid token `OpenBracket`")] [Theory(Skip = "Invalid token `OpenBracket`")]
@@ -142,7 +142,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("a wiremock"); Check.That(response.Message.BodyData!.BodyAsString).Equals("a wiremock");
} }
[Fact] [Fact]
@@ -164,7 +164,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test keya=1,2 idx=1 idx=2 keyb=5"); Check.That(response.Message.BodyData!.BodyAsString).Equals("test keya=1,2 idx=1 idx=2 keyb=5");
} }
[Theory(Skip = "Invalid token `OpenBracket`")] [Theory(Skip = "Invalid token `OpenBracket`")]
@@ -188,7 +188,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test keya=1 idx=1 idx=2 keyb=5"); Check.That(response.Message.BodyData!.BodyAsString).Equals("test keya=1 idx=1 idx=2 keyb=5");
} }
[Fact] [Fact]
@@ -211,7 +211,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test"); Check.That(response.Message.BodyData!.BodyAsString).Equals("test");
Check.That(response.Message.StatusCode).Equals("400"); Check.That(response.Message.StatusCode).Equals("400");
} }
@@ -237,7 +237,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test"); Check.That(response.Message.BodyData!.BodyAsString).Equals("test");
Check.That(response.Message.StatusCode).Equals("400"); Check.That(response.Message.StatusCode).Equals("400");
} }
@@ -263,7 +263,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test"); Check.That(response.Message.BodyData!.BodyAsString).Equals("test");
Check.That(response.Message.StatusCode).Equals(null); Check.That(response.Message.StatusCode).Equals(null);
} }
@@ -331,7 +331,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test"); Check.That(response.Message.BodyData!.BodyAsString).Equals("test");
Check.That(response.Message.Headers).ContainsKey("x"); Check.That(response.Message.Headers).ContainsKey("x");
Check.That(response.Message.Headers["x"]).Contains("text/plain"); Check.That(response.Message.Headers["x"]).Contains("text/plain");
Check.That(response.Message.Headers["x"]).Contains("http://localhost/foo"); Check.That(response.Message.Headers["x"]).Contains("http://localhost/foo");
@@ -356,7 +356,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test"); Check.That(response.Message.BodyData!.BodyAsString).Equals("test");
Check.That(response.Message.Headers).ContainsKey("x"); Check.That(response.Message.Headers).ContainsKey("x");
Check.That(response.Message.Headers["x"]).Contains("text/plain"); Check.That(response.Message.Headers["x"]).Contains("text/plain");
Check.That(response.Message.Headers["x"]).Contains("http://localhost/foo"); Check.That(response.Message.Headers["x"]).Contains("http://localhost/foo");
@@ -384,7 +384,7 @@ public class ResponseWithTransformerTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsString).Equals("test http://localhost:1234 1234 http localhost"); Check.That(response.Message.BodyData!.BodyAsString).Equals("test http://localhost:1234 1234 http localhost");
} }
[Theory] [Theory]
@@ -644,7 +644,7 @@ public class ResponseWithTransformerTests
// Assert // Assert
Check.That(response.Message.BodyData.BodyAsFile).Equals(@"c:\1\test.xml"); Check.That(response.Message.BodyData.BodyAsFile).Equals(@"c:\1\test.xml");
Check.That(response.Message.BodyData.DetectedBodyType).Equals(BodyType.String); Check.That(response.Message.BodyData.DetectedBodyType).Equals(BodyType.String);
Check.That(response.Message.BodyData.BodyAsString).Equals("<xml MyUniqueNumber=\"1\"></xml>"); Check.That(response.Message.BodyData!.BodyAsString).Equals("<xml MyUniqueNumber=\"1\"></xml>");
} }
[Theory] [Theory]

View File

@@ -408,4 +408,24 @@ public class MatcherMapperTests
matcher.Value.Should().BeEquivalentTo(pattern); matcher.Value.Should().BeEquivalentTo(pattern);
matcher.Regex.Should().BeFalse(); matcher.Regex.Should().BeFalse();
} }
[Fact]
public void MatcherMapper_Map_MatcherModel_ExactMatcher_Pattern()
{
// Assign
var model = new MatcherModel
{
Name = "ExactMatcher",
Pattern = "p",
IgnoreCase = true
};
// Act
var matcher = (ExactMatcher)_sut.Map(model)!;
// Assert
matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch);
matcher.GetPatterns().Should().Contain("p");
matcher.IgnoreCase.Should().BeTrue();
}
} }

View File

@@ -46,7 +46,8 @@
"Matchers": [ "Matchers": [
{ {
"Name": "ExactMatcher", "Name": "ExactMatcher",
"Pattern": "p1-v" "Pattern": "p1-v",
"IgnoreCase": false
} }
] ]
}, },
@@ -55,7 +56,8 @@
"Matchers": [ "Matchers": [
{ {
"Name": "ExactMatcher", "Name": "ExactMatcher",
"Pattern": "p2-v" "Pattern": "p2-v",
"IgnoreCase": false
} }
] ]
} }

View File

@@ -10,9 +10,6 @@
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<ProjectGuid>{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}</ProjectGuid> <ProjectGuid>{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}</ProjectGuid>
<!--<SonarQubeTestProject>True</SonarQubeTestProject>
<SonarQubeExclude>True</SonarQubeExclude>-->
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>--> <!--<DelaySign>true</DelaySign>-->
@@ -38,7 +35,6 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<!--<PackageReference Include="Mapster" Version="7.2.0" />-->
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
@@ -53,17 +49,11 @@
<PackageReference Include="Moq" Version="4.17.2" /> <PackageReference Include="Moq" Version="4.17.2" />
<PackageReference Include="System.Threading" Version="4.3.0" /> <PackageReference Include="System.Threading" Version="4.3.0" />
<PackageReference Include="RestEase" Version="1.5.7" /> <PackageReference Include="RestEase" Version="1.5.7" />
<!--<PackageReference Include="RandomDataGenerator.Net" Version="1.0.14" />-->
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NFluent" Version="2.8.0" /> <PackageReference Include="NFluent" Version="2.8.0" />
<!--<PackageReference Include="OpenCover" Version="4.7.922" />-->
<!--<PackageReference Include="ReportGenerator" Version="4.8.1" />-->
<PackageReference Include="SimMetrics.Net" Version="1.0.5" /> <PackageReference Include="SimMetrics.Net" Version="1.0.5" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.19" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.19" />
<!--<PackageReference Include="StrongNamer" Version="0.2.5" />-->
<PackageReference Include="AnyOf" Version="0.3.0" /> <PackageReference Include="AnyOf" Version="0.3.0" />
<!--<PackageReference Include="TinyMapper" Version="3.0.3" />-->
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net461'"> <ItemGroup Condition="'$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net461'">