diff --git a/examples/WireMock.Net.ConsoleApplication/Program.cs b/examples/WireMock.Net.ConsoleApplication/Program.cs
index af0d2d75..42401af4 100644
--- a/examples/WireMock.Net.ConsoleApplication/Program.cs
+++ b/examples/WireMock.Net.ConsoleApplication/Program.cs
@@ -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"))
diff --git a/src/WireMock.Net/Admin/Requests/LogRequestMatchModel.cs b/src/WireMock.Net/Admin/Requests/LogRequestMatchModel.cs
index 2540dc31..56adfe2d 100644
--- a/src/WireMock.Net/Admin/Requests/LogRequestMatchModel.cs
+++ b/src/WireMock.Net/Admin/Requests/LogRequestMatchModel.cs
@@ -11,7 +11,7 @@
///
/// The number of matches.
///
- public int Matched { get; set; }
+ public double MatchScore { get; set; }
///
/// Gets or sets the total number of matches.
@@ -27,7 +27,7 @@
///
/// true if this instance is perfect match; otherwise, false.
///
- public bool IsPerfectMatch => Matched == Total;
+ public bool IsPerfectMatch => MatchScore == Total;
///
/// Gets the match percentage.
@@ -35,6 +35,6 @@
///
/// The match percentage.
///
- public double MatchPercentage => Total == 0 ? 100 : 100.0 * Matched / Total;
+ public double MatchPercentage => Total == 0 ? 100 : 100.0 * MatchScore / Total;
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/IMatcher.cs b/src/WireMock.Net/Matchers/IMatcher.cs
index 073043e7..14ea4044 100644
--- a/src/WireMock.Net/Matchers/IMatcher.cs
+++ b/src/WireMock.Net/Matchers/IMatcher.cs
@@ -9,15 +9,19 @@
/// Determines whether the specified input is match.
///
/// The input.
- ///
- /// true if the specified input is match; otherwise, false.
- ///
- bool IsMatch(string input);
+ /// A value between 0.0 - 1.0 of the similarity.
+ double IsMatch(string input);
///
/// Gets the pattern.
///
/// Pattern
string GetPattern();
+
+ ///
+ /// Gets the name.
+ ///
+ /// Name
+ string GetName();
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/JSONPathMatcher.cs b/src/WireMock.Net/Matchers/JSONPathMatcher.cs
index 97f85004..09292540 100644
--- a/src/WireMock.Net/Matchers/JSONPathMatcher.cs
+++ b/src/WireMock.Net/Matchers/JSONPathMatcher.cs
@@ -8,7 +8,7 @@ namespace WireMock.Matchers
///
/// JSONPathMatcher
///
- ///
+ ///
public class JsonPathMatcher : IMatcher
{
private readonly string _pattern;
@@ -27,25 +27,23 @@ namespace WireMock.Matchers
///
/// Determines whether the specified input is match.
///
- /// The input.
- ///
- /// true if the specified input is match; otherwise, false.
- ///
- public bool IsMatch(string input)
+ /// The input string
+ /// A value between 0.0 - 1.0 of the similarity.
+ 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;
}
+
+ ///
+ /// Gets the name.
+ ///
+ /// Name
+ public string GetName()
+ {
+ return "JsonPathMatcher";
+ }
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/MatchScores.cs b/src/WireMock.Net/Matchers/MatchScores.cs
new file mode 100644
index 00000000..3410ca2b
--- /dev/null
+++ b/src/WireMock.Net/Matchers/MatchScores.cs
@@ -0,0 +1,33 @@
+namespace WireMock.Matchers
+{
+ ///
+ /// MatchScores
+ ///
+ public static class MatchScores
+ {
+ ///
+ /// The tolerance
+ ///
+ public const double Tolerance = 0.0001;
+
+ ///
+ /// The default mismatch score
+ ///
+ public const double Mismatch = 0.0;
+
+ ///
+ /// The default perfect match score
+ ///
+ public const double Perfect = 1.0;
+
+ ///
+ /// Convert a bool to the score.
+ ///
+ /// if set to true [value].
+ /// score
+ public static double ToScore(bool value)
+ {
+ return value ? Perfect : Mismatch;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/RegexMatcher.cs b/src/WireMock.Net/Matchers/RegexMatcher.cs
index dd3e6404..54ae243a 100644
--- a/src/WireMock.Net/Matchers/RegexMatcher.cs
+++ b/src/WireMock.Net/Matchers/RegexMatcher.cs
@@ -8,7 +8,7 @@ namespace WireMock.Matchers
///
/// Regular Expression Matcher
///
- ///
+ ///
public class RegexMatcher : IMatcher
{
private readonly string _pattern;
@@ -35,22 +35,20 @@ namespace WireMock.Matchers
///
/// Determines whether the specified input is match.
///
- /// The input.
- ///
- /// true if the specified input is match; otherwise, false.
- ///
- public bool IsMatch(string input)
+ /// The input string
+ /// A value between 0.0 - 1.0 of the similarity.
+ 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;
}
+
+ ///
+ /// Gets the name.
+ ///
+ ///
+ /// Name
+ ///
+ public virtual string GetName()
+ {
+ return "RegexMatcher";
+ }
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/Request/IRequestMatcher.cs b/src/WireMock.Net/Matchers/Request/IRequestMatcher.cs
index 7d892f2a..f724b1ba 100644
--- a/src/WireMock.Net/Matchers/Request/IRequestMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/IRequestMatcher.cs
@@ -13,8 +13,8 @@ namespace WireMock.Matchers.Request
/// The RequestMessage.
/// The RequestMatchResult.
///
- /// true if the specified RequestMessage is match; otherwise, false.
+ /// A value between 0.0 - 1.0 of the similarity.
///
- bool IsMatch([NotNull] RequestMessage requestMessage, [NotNull] RequestMatchResult requestMatchResult);
+ double IsMatch([NotNull] RequestMessage requestMessage, [NotNull] RequestMatchResult requestMatchResult);
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/Request/RequestMatchResult.cs b/src/WireMock.Net/Matchers/Request/RequestMatchResult.cs
index 2131c31b..bdc14ed8 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMatchResult.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMatchResult.cs
@@ -8,12 +8,12 @@ namespace WireMock.Matchers.Request
public class RequestMatchResult : IComparable
{
///
- /// Gets or sets the number of matches.
+ /// Gets or sets the matches score.
///
///
/// The number of matches.
///
- public int Matched { get; set; }
+ public double MatchScore { get; set; }
///
/// Gets or sets the total number of matches.
@@ -29,7 +29,7 @@ namespace WireMock.Matchers.Request
///
/// true if this instance is perfect match; otherwise, false.
///
- public bool IsPerfectMatch => Matched == Total;
+ public bool IsPerfectMatch => Math.Abs(MatchScore - Total) < MatchScores.Tolerance;
///
/// Gets the match percentage.
@@ -37,7 +37,7 @@ namespace WireMock.Matchers.Request
///
/// The match percentage.
///
- public double MatchPercentage => Total == 0 ? 100 : 100.0 * Matched / Total;
+ public double MatchPercentage => Total == 0 ? 1.0 : MatchScore / Total;
///
/// 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.
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs
index 3276d70a..63003951 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs
@@ -9,11 +9,6 @@ namespace WireMock.Matchers.Request
///
public class RequestMessageBodyMatcher : IRequestMatcher
{
- ///
- /// The body.
- ///
- private readonly string _body;
-
///
/// The body as byte[].
///
@@ -40,10 +35,8 @@ namespace WireMock.Matchers.Request
///
/// The body Regex pattern.
///
- public RequestMessageBodyMatcher([NotNull] string body)
+ public RequestMessageBodyMatcher([NotNull] string body) : this(new SimMetricsMatcher(body))
{
- Check.NotNull(body, nameof(body));
- _body = body;
}
///
@@ -100,37 +93,33 @@ namespace WireMock.Matchers.Request
/// The RequestMessage.
/// The RequestMatchResult.
///
- /// true if the specified RequestMessage is match; otherwise, false.
+ /// A value between 0.0 - 1.0 of the similarity.
///
- 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;
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs
index 68d1f79c..6182cbd9 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs
@@ -39,30 +39,29 @@ namespace WireMock.Matchers.Request
/// The RequestMessage.
/// The RequestMatchResult.
///
- /// true if the specified RequestMessage is match; otherwise, false.
+ /// A value between 0.0 - 1.0 of the similarity.
///
- public bool IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
+ public double IsMatch(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
- var list = new List();
+ var list = new List();
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();
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs
index 92e933e6..00274a15 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageCookieMatcher.cs
@@ -72,32 +72,32 @@ namespace WireMock.Matchers.Request
/// The RequestMessage.
/// The RequestMatchResult.
///
- /// true if the specified RequestMessage is match; otherwise, false.
+ /// A value between 0.0 - 1.0 of the similarity.
///
- 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));
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs
index 5dbb5e10..5bed5f3c 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageHeaderMatcher.cs
@@ -72,32 +72,32 @@ namespace WireMock.Matchers.Request
/// The RequestMessage.
/// The RequestMatchResult.
///
- /// true if the specified RequestMessage is match; otherwise, false.
+ /// A value between 0.0 - 1.0 of the similarity.
///
- 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));
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageMethodMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageMethodMatcher.cs
index fab35d62..272418e2 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageMethodMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageMethodMatcher.cs
@@ -32,22 +32,21 @@ namespace WireMock.Matchers.Request
/// The RequestMessage.
/// The RequestMatchResult.
///
- /// true if the specified RequestMessage is match; otherwise, false.
+ /// A value between 0.0 - 1.0 of the similarity.
///
- 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));
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs
index ea0a7102..a42fe4e5 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageParamMatcher.cs
@@ -61,26 +61,26 @@ namespace WireMock.Matchers.Request
/// The RequestMessage.
/// The RequestMatchResult.
///
- /// true if the specified RequestMessage is match; otherwise, false.
+ /// A value between 0.0 - 1.0 of the similarity.
///
- 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 values = requestMessage.GetParameter(Key);
+
+ return MatchScores.ToScore(values?.Intersect(Values).Count() == Values.Count());
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessagePathMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessagePathMatcher.cs
index a9baf374..e28004e6 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessagePathMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessagePathMatcher.cs
@@ -55,28 +55,27 @@ namespace WireMock.Matchers.Request
/// The RequestMessage.
/// The RequestMatchResult.
///
- /// true if the specified RequestMessage is match; otherwise, false.
+ /// A value between 0.0 - 1.0 of the similarity.
///
- 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;
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs
index 5e1a1767..c0a1c4d1 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs
@@ -55,28 +55,27 @@ namespace WireMock.Matchers.Request
/// The RequestMessage.
/// The RequestMatchResult.
///
- /// true if the specified RequestMessage is match; otherwise, false.
+ /// A value between 0.0 - 1.0 of the similarity.
///
- 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;
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/SimMetricsMatcher.cs b/src/WireMock.Net/Matchers/SimMetricsMatcher.cs
new file mode 100644
index 00000000..74f09d3a
--- /dev/null
+++ b/src/WireMock.Net/Matchers/SimMetricsMatcher.cs
@@ -0,0 +1,114 @@
+using JetBrains.Annotations;
+using SimMetrics.Net;
+using SimMetrics.Net.Metric;
+using WireMock.Validation;
+
+namespace WireMock.Matchers
+{
+ ///
+ /// SimMetricsMatcher
+ ///
+ ///
+ public class SimMetricsMatcher : IMatcher
+ {
+ private readonly string _pattern;
+ private readonly SimMetricType _simMetricType;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The pattern.
+ /// The SimMetric Type
+ public SimMetricsMatcher([NotNull] string pattern, SimMetricType simMetricType = SimMetricType.Levenstein)
+ {
+ Check.NotNull(pattern, nameof(pattern));
+
+ _pattern = pattern;
+ _simMetricType = simMetricType;
+ }
+
+ ///
+ /// Determines whether the specified input is match.
+ ///
+ /// The input string
+ /// A value between 0.0 - 1.0 of the similarity.
+ 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);
+ }
+ }
+
+ ///
+ /// Gets the pattern.
+ ///
+ /// Pattern
+ public string GetPattern()
+ {
+ return _pattern;
+ }
+
+ ///
+ /// Gets the name.
+ ///
+ /// Name
+ public string GetName()
+ {
+ return $"SimMetricsMatcher ({_simMetricType})";
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/WildcardMatcher.cs b/src/WireMock.Net/Matchers/WildcardMatcher.cs
index 1cc107e7..cb350f25 100644
--- a/src/WireMock.Net/Matchers/WildcardMatcher.cs
+++ b/src/WireMock.Net/Matchers/WildcardMatcher.cs
@@ -17,5 +17,16 @@ namespace WireMock.Matchers
public WildcardMatcher([NotNull] string pattern, bool ignoreCase = false) : base("^" + Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$", ignoreCase)
{
}
+
+ ///
+ /// Gets the name.
+ ///
+ ///
+ /// Name
+ ///
+ public new string GetName()
+ {
+ return "WildcardMatcher";
+ }
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Matchers/XPathMatcher.cs b/src/WireMock.Net/Matchers/XPathMatcher.cs
index b1a92c91..1e5af9ed 100644
--- a/src/WireMock.Net/Matchers/XPathMatcher.cs
+++ b/src/WireMock.Net/Matchers/XPathMatcher.cs
@@ -28,25 +28,23 @@ namespace WireMock.Matchers
///
/// Determines whether the specified input is match.
///
- /// The input.
- ///
- /// true if the specified input is match; otherwise, false.
- ///
- public bool IsMatch(string input)
+ /// The input string
+ /// A value between 0.0 - 1.0 of the similarity.
+ 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;
}
+
+ ///
+ /// Gets the name.
+ ///
+ ///
+ /// Name
+ ///
+ public string GetName()
+ {
+ return "XPathMatcher";
+ }
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
index 1334f005..a0e63fc3 100644
--- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs
+++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
@@ -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()
};
}
diff --git a/src/WireMock.Net/Server/FluentMockServer.cs b/src/WireMock.Net/Server/FluentMockServer.cs
index 3a27405a..8967fc30 100644
--- a/src/WireMock.Net/Server/FluentMockServer.cs
+++ b/src/WireMock.Net/Server/FluentMockServer.cs
@@ -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);
}
}
diff --git a/src/WireMock.Net/project.json b/src/WireMock.Net/project.json
index 65ba6292..482db0f0 100644
--- a/src/WireMock.Net/project.json
+++ b/src/WireMock.Net/project.json
@@ -29,6 +29,7 @@
},
"Handlebars.Net": "1.8.0",
"Newtonsoft.Json": "6.0.8",
+ "SimMetrics.Net": "1.0.1",
"XPath2": "1.0.3.1"
},