PartialMapping : SimMetrics.Net

This commit is contained in:
Stef Heyenrath
2017-02-04 21:32:45 +01:00
parent ec2d105db2
commit 44f00cb9fa
22 changed files with 349 additions and 176 deletions

View File

@@ -20,53 +20,53 @@ namespace WireMock.Net.ConsoleApplication
server.AllowPartialMapping();
server
.Given(Request.Create().WithPath(p => p.Contains("x")).UsingGet())
.AtPriority(4)
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""Contains x with FUNC 200""}"));
//server
// .Given(Request.Create().WithPath(p => p.Contains("x")).UsingGet())
// .AtPriority(4)
// .RespondWith(Response.Create()
// .WithStatusCode(200)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""Contains x with FUNC 200""}"));
server
.Given(Request.Create().WithPath("/data").UsingPost().WithBody(b => b.Contains("e")))
.RespondWith(Response.Create()
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""data posted with FUNC 201""}"));
//server
// .Given(Request.Create().WithPath("/data").UsingPost().WithBody(b => b.Contains("e")))
// .RespondWith(Response.Create()
// .WithStatusCode(201)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""data posted with FUNC 201""}"));
server
.Given(Request.Create().WithPath("/data", "/ax").UsingPost().WithHeader("Content-Type", "application/json*"))
.RespondWith(Response.Create()
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""data posted with 201""}"));
//server
// .Given(Request.Create().WithPath("/data", "/ax").UsingPost().WithHeader("Content-Type", "application/json*"))
// .RespondWith(Response.Create()
// .WithStatusCode(201)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""data posted with 201""}"));
server
.Given(Request.Create().WithPath("/json").UsingPost().WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]")))
.RespondWith(Response.Create()
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""json posted with 201""}"));
//server
// .Given(Request.Create().WithPath("/json").UsingPost().WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]")))
// .RespondWith(Response.Create()
// .WithStatusCode(201)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""json posted with 201""}"));
server
.Given(Request.Create().WithPath("/json2").UsingPost().WithBody("x"))
.RespondWith(Response.Create()
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""json posted with x - 201""}"));
//server
// .Given(Request.Create().WithPath("/json2").UsingPost().WithBody("x"))
// .RespondWith(Response.Create()
// .WithStatusCode(201)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""json posted with x - 201""}"));
server
.Given(Request.Create().WithPath("/data").UsingDelete())
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""data deleted with 200""}"));
//server
// .Given(Request.Create().WithPath("/data").UsingDelete())
// .RespondWith(Response.Create()
// .WithStatusCode(200)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""data deleted with 200""}"));
server
.Given(Request.Create().WithPath("/nobody").UsingGet())
.RespondWith(Response.Create().WithDelay(TimeSpan.FromSeconds(1))
.WithStatusCode(200));
//server
// .Given(Request.Create().WithPath("/nobody").UsingGet())
// .RespondWith(Response.Create().WithDelay(TimeSpan.FromSeconds(1))
// .WithStatusCode(200));
server
.Given(Request.Create().WithPath("/partial").UsingGet().WithHeader("p", "p"))

View File

@@ -11,7 +11,7 @@
/// <value>
/// The number of matches.
/// </value>
public int Matched { get; set; }
public double MatchScore { get; set; }
/// <summary>
/// Gets or sets the total number of matches.
@@ -27,7 +27,7 @@
/// <value>
/// <c>true</c> if this instance is perfect match; otherwise, <c>false</c>.
/// </value>
public bool IsPerfectMatch => Matched == Total;
public bool IsPerfectMatch => MatchScore == Total;
/// <summary>
/// Gets the match percentage.
@@ -35,6 +35,6 @@
/// <value>
/// The match percentage.
/// </value>
public double MatchPercentage => Total == 0 ? 100 : 100.0 * Matched / Total;
public double MatchPercentage => Total == 0 ? 100 : 100.0 * MatchScore / Total;
}
}

View File

@@ -9,15 +9,19 @@
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>
/// <c>true</c> if the specified input is match; otherwise, <c>false</c>.
/// </returns>
bool IsMatch(string input);
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
double IsMatch(string input);
/// <summary>
/// Gets the pattern.
/// </summary>
/// <returns>Pattern</returns>
string GetPattern();
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>Name</returns>
string GetName();
}
}

View File

@@ -8,7 +8,7 @@ namespace WireMock.Matchers
/// <summary>
/// JSONPathMatcher
/// </summary>
/// <seealso cref="WireMock.Matchers.IMatcher" />
/// <seealso cref="IMatcher" />
public class JsonPathMatcher : IMatcher
{
private readonly string _pattern;
@@ -27,25 +27,23 @@ namespace WireMock.Matchers
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>
/// <c>true</c> if the specified input is match; otherwise, <c>false</c>.
/// </returns>
public bool IsMatch(string input)
/// <param name="input">The input string</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
public double IsMatch(string input)
{
if (input == null)
return false;
return MatchScores.Mismatch;
try
{
JObject o = JObject.Parse(input);
JToken token = o.SelectToken(_pattern);
return token != null;
return MatchScores.ToScore(token != null);
}
catch (Exception)
{
return false;
return MatchScores.Mismatch;
}
}
@@ -57,5 +55,14 @@ namespace WireMock.Matchers
{
return _pattern;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>Name</returns>
public string GetName()
{
return "JsonPathMatcher";
}
}
}

View File

@@ -0,0 +1,33 @@
namespace WireMock.Matchers
{
/// <summary>
/// MatchScores
/// </summary>
public static class MatchScores
{
/// <summary>
/// The tolerance
/// </summary>
public const double Tolerance = 0.0001;
/// <summary>
/// The default mismatch score
/// </summary>
public const double Mismatch = 0.0;
/// <summary>
/// The default perfect match score
/// </summary>
public const double Perfect = 1.0;
/// <summary>
/// Convert a bool to the score.
/// </summary>
/// <param name="value">if set to <c>true</c> [value].</param>
/// <returns>score</returns>
public static double ToScore(bool value)
{
return value ? Perfect : Mismatch;
}
}
}

View File

@@ -8,7 +8,7 @@ namespace WireMock.Matchers
/// <summary>
/// Regular Expression Matcher
/// </summary>
/// <seealso cref="WireMock.Matchers.IMatcher" />
/// <seealso cref="IMatcher" />
public class RegexMatcher : IMatcher
{
private readonly string _pattern;
@@ -35,22 +35,20 @@ namespace WireMock.Matchers
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>
/// <c>true</c> if the specified input is match; otherwise, <c>false</c>.
/// </returns>
public bool IsMatch(string input)
/// <param name="input">The input string</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
public double IsMatch(string input)
{
if (input == null)
return false;
return MatchScores.Mismatch;
try
{
return _expression.IsMatch(input);
return MatchScores.ToScore(_expression.IsMatch(input));
}
catch (Exception)
{
return false;
return MatchScores.Mismatch;
}
}
@@ -62,5 +60,16 @@ namespace WireMock.Matchers
{
return _pattern;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>
/// Name
/// </returns>
public virtual string GetName()
{
return "RegexMatcher";
}
}
}

View File

@@ -13,8 +13,8 @@ namespace WireMock.Matchers.Request
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// <c>true</c> if the specified RequestMessage is match; otherwise, <c>false</c>.
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
bool IsMatch([NotNull] RequestMessage requestMessage, [NotNull] RequestMatchResult requestMatchResult);
double IsMatch([NotNull] RequestMessage requestMessage, [NotNull] RequestMatchResult requestMatchResult);
}
}

View File

@@ -8,12 +8,12 @@ namespace WireMock.Matchers.Request
public class RequestMatchResult : IComparable
{
/// <summary>
/// Gets or sets the number of matches.
/// Gets or sets the matches score.
/// </summary>
/// <value>
/// The number of matches.
/// </value>
public int Matched { get; set; }
public double MatchScore { get; set; }
/// <summary>
/// Gets or sets the total number of matches.
@@ -29,7 +29,7 @@ namespace WireMock.Matchers.Request
/// <value>
/// <c>true</c> if this instance is perfect match; otherwise, <c>false</c>.
/// </value>
public bool IsPerfectMatch => Matched == Total;
public bool IsPerfectMatch => Math.Abs(MatchScore - Total) < MatchScores.Tolerance;
/// <summary>
/// Gets the match percentage.
@@ -37,7 +37,7 @@ namespace WireMock.Matchers.Request
/// <value>
/// The match percentage.
/// </value>
public double MatchPercentage => Total == 0 ? 100 : 100.0 * Matched / Total;
public double MatchPercentage => Total == 0 ? 1.0 : MatchScore / Total;
/// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.

View File

@@ -9,11 +9,6 @@ namespace WireMock.Matchers.Request
/// </summary>
public class RequestMessageBodyMatcher : IRequestMatcher
{
/// <summary>
/// The body.
/// </summary>
private readonly string _body;
/// <summary>
/// The body as byte[].
/// </summary>
@@ -40,10 +35,8 @@ namespace WireMock.Matchers.Request
/// <param name="body">
/// The body Regex pattern.
/// </param>
public RequestMessageBodyMatcher([NotNull] string body)
public RequestMessageBodyMatcher([NotNull] string body) : this(new SimMetricsMatcher(body))
{
Check.NotNull(body, nameof(body));
_body = body;
}
/// <summary>
@@ -100,37 +93,33 @@ namespace WireMock.Matchers.Request
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// <c>true</c> if the specified RequestMessage is match; otherwise, <c>false</c>.
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
public bool IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
bool isMatch = IsMatch(requestMessage);
if (isMatch)
requestMatchResult.Matched++;
double score = IsMatch(requestMessage);
requestMatchResult.MatchScore += score;
requestMatchResult.Total++;
return isMatch;
return score;
}
private bool IsMatch(RequestMessage requestMessage)
private double IsMatch(RequestMessage requestMessage)
{
if (Matcher != null)
return Matcher.IsMatch(requestMessage.Body);
if (_body != null)
return requestMessage.Body == _body;
if (_bodyData != null)
return requestMessage.BodyAsBytes == _bodyData;
return MatchScores.ToScore(requestMessage.BodyAsBytes == _bodyData);
if (Func != null)
return requestMessage.Body != null && Func(requestMessage.Body);
return MatchScores.ToScore(requestMessage.Body != null && Func(requestMessage.Body));
if (DataFunc != null && requestMessage.BodyAsBytes != null)
return requestMessage.BodyAsBytes != null && DataFunc(requestMessage.BodyAsBytes);
return MatchScores.ToScore(requestMessage.BodyAsBytes != null && DataFunc(requestMessage.BodyAsBytes));
return false;
return MatchScores.Mismatch;
}
}
}

View File

@@ -39,30 +39,29 @@ namespace WireMock.Matchers.Request
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// <c>true</c> if the specified RequestMessage is match; otherwise, <c>false</c>.
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
public bool IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
var list = new List<bool>();
var list = new List<double>();
if (_type == CompositeMatcherType.And)
{
foreach (var requestMatcher in RequestMatchers)
{
bool isMatch = requestMatcher.IsMatch(requestMessage, requestMatchResult);
list.Add(isMatch);
double score = requestMatcher.IsMatch(requestMessage, requestMatchResult);
list.Add(score);
}
return list.All(match => match);
return list.Sum() / list.Count;
}
//var orRequestMatchResult = new RequestMatchResult();
foreach (var requestMatcher in RequestMatchers)
{
bool isMatch = requestMatcher.IsMatch(requestMessage, requestMatchResult);
list.Add(isMatch);
double score = requestMatcher.IsMatch(requestMessage, requestMatchResult);
list.Add(score);
}
return list.Any(match => match);
return list.Max();
}
}
}

View File

@@ -72,32 +72,32 @@ namespace WireMock.Matchers.Request
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// <c>true</c> if the specified RequestMessage is match; otherwise, <c>false</c>.
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
public bool IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
bool isMatch = IsMatch(requestMessage);
if (isMatch)
requestMatchResult.Matched++;
double score = IsMatch(requestMessage);
requestMatchResult.MatchScore += score;
requestMatchResult.Total++;
return isMatch;
return score;
}
private bool IsMatch(RequestMessage requestMessage)
private double IsMatch(RequestMessage requestMessage)
{
if (Funcs != null)
return requestMessage.Cookies != null && Funcs.Any(cf => cf(requestMessage.Cookies));
return MatchScores.ToScore(requestMessage.Cookies != null && Funcs.Any(cf => cf(requestMessage.Cookies)));
if (requestMessage.Cookies == null)
return false;
return MatchScores.Mismatch;
if (!requestMessage.Cookies.ContainsKey(Name))
return false;
return MatchScores.Mismatch;
string headerValue = requestMessage.Cookies[Name];
return Matchers.Any(m => m.IsMatch(headerValue));
string value = requestMessage.Cookies[Name];
return Matchers.Max(m => m.IsMatch(value));
}
}
}

View File

@@ -72,32 +72,32 @@ namespace WireMock.Matchers.Request
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// <c>true</c> if the specified RequestMessage is match; otherwise, <c>false</c>.
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
public bool IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
bool isMatch = IsMatch(requestMessage);
if (isMatch)
requestMatchResult.Matched++;
double score = IsMatch(requestMessage);
requestMatchResult.MatchScore += score;
requestMatchResult.Total++;
return isMatch;
return score;
}
private bool IsMatch(RequestMessage requestMessage)
private double IsMatch(RequestMessage requestMessage)
{
if (Funcs != null)
return requestMessage.Headers != null && Funcs.Any(hf => hf(requestMessage.Headers));
return MatchScores.ToScore(requestMessage.Headers != null && Funcs.Any(hf => hf(requestMessage.Headers)));
if (requestMessage.Headers == null)
return false;
return MatchScores.Mismatch;
if (!requestMessage.Headers.ContainsKey(Name))
return false;
return MatchScores.Mismatch;
string headerValue = requestMessage.Headers[Name];
return Matchers.Any(m => m.IsMatch(headerValue));
return Matchers.Max(m => m.IsMatch(headerValue));
}
}
}

View File

@@ -32,22 +32,21 @@ namespace WireMock.Matchers.Request
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// <c>true</c> if the specified RequestMessage is match; otherwise, <c>false</c>.
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
public bool IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
bool isMatch = IsMatch(requestMessage);
if (isMatch)
requestMatchResult.Matched++;
double score = IsMatch(requestMessage);
requestMatchResult.MatchScore += score;
requestMatchResult.Total++;
return isMatch;
return score;
}
private bool IsMatch(RequestMessage requestMessage)
private double IsMatch(RequestMessage requestMessage)
{
return Methods.Contains(requestMessage.Method);
return MatchScores.ToScore(Methods.Contains(requestMessage.Method));
}
}
}

View File

@@ -61,26 +61,26 @@ namespace WireMock.Matchers.Request
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// <c>true</c> if the specified RequestMessage is match; otherwise, <c>false</c>.
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
public bool IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
bool isMatch = IsMatch(requestMessage);
if (isMatch)
requestMatchResult.Matched++;
double score = IsMatch(requestMessage);
requestMatchResult.MatchScore += score;
requestMatchResult.Total++;
return isMatch;
return score;
}
private bool IsMatch(RequestMessage requestMessage)
private double IsMatch(RequestMessage requestMessage)
{
if (Funcs != null)
return requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query));
return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query)));
var values = requestMessage.GetParameter(Key);
return values?.Intersect(Values).Count() == Values.Count();
List<string> values = requestMessage.GetParameter(Key);
return MatchScores.ToScore(values?.Intersect(Values).Count() == Values.Count());
}
}
}

View File

@@ -55,28 +55,27 @@ namespace WireMock.Matchers.Request
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// <c>true</c> if the specified RequestMessage is match; otherwise, <c>false</c>.
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
public bool IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
bool isMatch = IsMatch(requestMessage);
if (isMatch)
requestMatchResult.Matched++;
double score = IsMatch(requestMessage);
requestMatchResult.MatchScore += score;
requestMatchResult.Total++;
return isMatch;
return score;
}
private bool IsMatch(RequestMessage requestMessage)
private double IsMatch(RequestMessage requestMessage)
{
if (Matchers != null)
return Matchers.Any(matcher => matcher.IsMatch(requestMessage.Path));
return Matchers.Max(m => m.IsMatch(requestMessage.Path));
if (Funcs != null)
return requestMessage.Path != null && Funcs.Any(func => func(requestMessage.Path));
return MatchScores.ToScore(requestMessage.Path != null && Funcs.Any(func => func(requestMessage.Path)));
return false;
return MatchScores.Mismatch;
}
}
}

View File

@@ -55,28 +55,27 @@ namespace WireMock.Matchers.Request
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// <c>true</c> if the specified RequestMessage is match; otherwise, <c>false</c>.
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
public bool IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
bool isMatch = IsMatch(requestMessage);
if (isMatch)
requestMatchResult.Matched++;
double score = IsMatch(requestMessage);
requestMatchResult.MatchScore += score;
requestMatchResult.Total++;
return isMatch;
return score;
}
private bool IsMatch(RequestMessage requestMessage)
private double IsMatch(RequestMessage requestMessage)
{
if (Matchers != null)
return Matchers.Any(matcher => matcher.IsMatch(requestMessage.Url));
return Matchers.Max(matcher => matcher.IsMatch(requestMessage.Url));
if (Funcs != null)
return requestMessage.Url != null && Funcs.Any(func => func(requestMessage.Url));
return MatchScores.ToScore(requestMessage.Url != null && Funcs.Any(func => func(requestMessage.Url)));
return false;
return MatchScores.Mismatch;
}
}
}

View File

@@ -0,0 +1,114 @@
using JetBrains.Annotations;
using SimMetrics.Net;
using SimMetrics.Net.Metric;
using WireMock.Validation;
namespace WireMock.Matchers
{
/// <summary>
/// SimMetricsMatcher
/// </summary>
/// <seealso cref="IMatcher" />
public class SimMetricsMatcher : IMatcher
{
private readonly string _pattern;
private readonly SimMetricType _simMetricType;
/// <summary>
/// Initializes a new instance of the <see cref="SimMetricsMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="simMetricType">The SimMetric Type</param>
public SimMetricsMatcher([NotNull] string pattern, SimMetricType simMetricType = SimMetricType.Levenstein)
{
Check.NotNull(pattern, nameof(pattern));
_pattern = pattern;
_simMetricType = simMetricType;
}
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input string</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
public double IsMatch(string input)
{
switch (_simMetricType)
{
case SimMetricType.BlockDistance:
var sim2 = new BlockDistance();
return sim2.GetSimilarity(_pattern, input);
case SimMetricType.ChapmanLengthDeviation:
var sim3 = new ChapmanLengthDeviation();
return sim3.GetSimilarity(_pattern, input);
case SimMetricType.CosineSimilarity:
var sim4 = new CosineSimilarity();
return sim4.GetSimilarity(_pattern, input);
case SimMetricType.DiceSimilarity:
var sim5 = new DiceSimilarity();
return sim5.GetSimilarity(_pattern, input);
case SimMetricType.EuclideanDistance:
var sim6 = new EuclideanDistance();
return sim6.GetSimilarity(_pattern, input);
case SimMetricType.JaccardSimilarity:
var sim7 = new JaccardSimilarity();
return sim7.GetSimilarity(_pattern, input);
case SimMetricType.Jaro:
var sim8 = new Jaro();
return sim8.GetSimilarity(_pattern, input);
case SimMetricType.JaroWinkler:
var sim9 = new JaroWinkler();
return sim9.GetSimilarity(_pattern, input);
case SimMetricType.MatchingCoefficient:
var sim10 = new MatchingCoefficient();
return sim10.GetSimilarity(_pattern, input);
case SimMetricType.MongeElkan:
var sim11 = new MongeElkan();
return sim11.GetSimilarity(_pattern, input);
case SimMetricType.NeedlemanWunch:
var sim12 = new NeedlemanWunch();
return sim12.GetSimilarity(_pattern, input);
case SimMetricType.OverlapCoefficient:
var sim13 = new OverlapCoefficient();
return sim13.GetSimilarity(_pattern, input);
case SimMetricType.QGramsDistance:
var sim14 = new QGramsDistance();
return sim14.GetSimilarity(_pattern, input);
case SimMetricType.SmithWaterman:
var sim15 = new SmithWaterman();
return sim15.GetSimilarity(_pattern, input);
case SimMetricType.SmithWatermanGotoh:
var sim16 = new SmithWatermanGotoh();
return sim16.GetSimilarity(_pattern, input);
case SimMetricType.SmithWatermanGotohWindowedAffine:
var sim17 = new SmithWatermanGotohWindowedAffine();
return sim17.GetSimilarity(_pattern, input);
case SimMetricType.ChapmanMeanLength:
var sim18 = new ChapmanMeanLength();
return sim18.GetSimilarity(_pattern, input);
default:
var sim1 = new Levenstein();
return sim1.GetSimilarity(_pattern, input);
}
}
/// <summary>
/// Gets the pattern.
/// </summary>
/// <returns>Pattern</returns>
public string GetPattern()
{
return _pattern;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>Name</returns>
public string GetName()
{
return $"SimMetricsMatcher ({_simMetricType})";
}
}
}

View File

@@ -17,5 +17,16 @@ namespace WireMock.Matchers
public WildcardMatcher([NotNull] string pattern, bool ignoreCase = false) : base("^" + Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$", ignoreCase)
{
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>
/// Name
/// </returns>
public new string GetName()
{
return "WildcardMatcher";
}
}
}

View File

@@ -28,25 +28,23 @@ namespace WireMock.Matchers
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>
/// <c>true</c> if the specified input is match; otherwise, <c>false</c>.
/// </returns>
public bool IsMatch(string input)
/// <param name="input">The input string</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
public double IsMatch(string input)
{
if (input == null)
return false;
return MatchScores.Mismatch;
try
{
var nav = new XmlDocument { InnerXml = input }.CreateNavigator();
object result = nav.XPath2Evaluate($"boolean({_pattern})");
return true.Equals(result);
return MatchScores.ToScore(true.Equals(result));
}
catch (Exception)
{
return false;
return MatchScores.Mismatch;
}
}
@@ -58,5 +56,16 @@ namespace WireMock.Matchers
{
return _pattern;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>
/// Name
/// </returns>
public string GetName()
{
return "XPathMatcher";
}
}
}

View File

@@ -205,7 +205,7 @@ namespace WireMock.Server
},
RequestMatchResult = new LogRequestMatchModel
{
Matched = logEntry.RequestMatchResult.Matched,
MatchScore = logEntry.RequestMatchResult.MatchScore,
Total = logEntry.RequestMatchResult.Total
}
};
@@ -392,7 +392,7 @@ namespace WireMock.Server
return new MatcherModel
{
Name = matcher.GetType().Name,
Name = matcher.GetName(),
Pattern = matcher.GetPattern()
};
}

View File

@@ -246,7 +246,7 @@ namespace WireMock.Server
lock (((ICollection)_logEntries).SyncRoot)
{
var requestMatchResult = new RequestMatchResult();
return _logEntries.Where(log => matcher.IsMatch(log.RequestMessage, requestMatchResult));
return _logEntries.Where(log => matcher.IsMatch(log.RequestMessage, requestMatchResult) > 0.99);
}
}

View File

@@ -29,6 +29,7 @@
},
"Handlebars.Net": "1.8.0",
"Newtonsoft.Json": "6.0.8",
"SimMetrics.Net": "1.0.1",
"XPath2": "1.0.3.1"
},