This commit is contained in:
Stef Heyenrath
2017-02-05 10:25:19 +01:00
parent 44f00cb9fa
commit 8231b25805
10 changed files with 152 additions and 73 deletions

View File

@@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Newtonsoft.Json;
using WireMock.Matchers;
using WireMock.RequestBuilders;
@@ -20,62 +21,64 @@ 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("/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("/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("/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(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("/partial").UsingGet().WithHeader("p", "p"))
.Given(Request.Create().WithPath("/data").UsingPost().WithBody(b => b.Contains("e")))
.AtPriority(999)
.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("/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("/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("/partial").UsingPost().WithBody(new SimMetricsMatcher("cat")))
.RespondWith(Response.Create().WithStatusCode(200).WithBody("partial = 200"));
// http://localhost:8080/any/any?start=1000&stop=1&stop=2
server
.Given(Request.Create().WithPath("/*").UsingGet())
.WithGuid(Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05"))
.AtPriority(server.Mappings.Count() + 1)
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithHeader("Content-Type", "application/json")

View File

@@ -37,6 +37,10 @@
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SimMetrics.Net, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\SimMetrics.Net.1.0.1.0\lib\net45\SimMetrics.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="WireMock.Net">

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
<package id="SimMetrics.Net" version="1.0.1.0" targetFramework="net452" />
</packages>

View File

@@ -31,6 +31,14 @@ namespace WireMock.Admin.Requests
/// </value>
public LogResponseModel Response { get; set; }
/// <summary>
/// Gets or sets the mapping unique identifier.
/// </summary>
/// <value>
/// The mapping unique identifier.
/// </value>
public Guid? MappingGuid { get; set; }
/// <summary>
/// Gets or sets the request match result.
/// </summary>

View File

@@ -39,5 +39,13 @@ namespace WireMock.Logging
/// The request match result.
/// </value>
public RequestMatchResult RequestMatchResult { get; set; }
/// <summary>
/// Gets or sets the mapping unique identifier.
/// </summary>
/// <value>
/// The mapping unique identifier.
/// </value>
public Guid? MappingGuid { get; set; }
}
}

View File

@@ -108,7 +108,7 @@ namespace WireMock.Matchers
/// <returns>Name</returns>
public string GetName()
{
return $"SimMetricsMatcher ({_simMetricType})";
return $"SimMetricsMatcher.{_simMetricType}";
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SimMetrics.Net;
using WireMock.Admin.Mappings;
using WireMock.Admin.Requests;
using WireMock.Logging;
@@ -11,6 +12,7 @@ using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Util;
namespace WireMock.Server
{
@@ -203,11 +205,12 @@ namespace WireMock.Server
BodyOriginal = logEntry.ResponseMessage.BodyOriginal,
Headers = logEntry.ResponseMessage.Headers
},
RequestMatchResult = new LogRequestMatchModel
MappingGuid = logEntry.MappingGuid,
RequestMatchResult = logEntry.RequestMatchResult != null ? new LogRequestMatchModel
{
MatchScore = logEntry.RequestMatchResult.MatchScore,
Total = logEntry.RequestMatchResult.Total
}
} : null
};
}
@@ -222,26 +225,31 @@ namespace WireMock.Server
private IRequestBuilder InitRequestBuilder(MappingModel mappingModel)
{
IRequestBuilder requestBuilder = Request.Create();
string path = mappingModel.Request.Path as string;
if (path != null)
requestBuilder = requestBuilder.WithPath(path);
else
if (mappingModel.Request.Path != null)
{
JToken pathToken = (JToken)mappingModel.Request.Path;
PathModel pathModel = pathToken.ToObject<PathModel>();
if (pathModel?.Matchers != null)
requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(Map).ToArray());
string path = mappingModel.Request.Path as string;
if (path != null)
requestBuilder = requestBuilder.WithPath(path);
else
{
var pathModel = JsonUtils.ParseJTokenToObject<PathModel>(mappingModel.Request.Path);
if (pathModel?.Matchers != null)
requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(Map).ToArray());
}
}
string url = mappingModel.Request.Url as string;
if (url != null)
requestBuilder = requestBuilder.WithUrl(url);
else
if (mappingModel.Request.Url != null)
{
JToken urlToken = (JToken)mappingModel.Request.Url;
UrlModel urlModel = urlToken.ToObject<UrlModel>();
if (urlModel?.Matchers != null)
requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(Map).ToArray());
string url = mappingModel.Request.Url as string;
if (url != null)
requestBuilder = requestBuilder.WithUrl(url);
else
{
var urlModel = JsonUtils.ParseJTokenToObject<UrlModel>(mappingModel.Request.Url);
if (urlModel?.Matchers != null)
requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(Map).ToArray());
}
}
if (mappingModel.Request.Methods != null)
@@ -412,7 +420,11 @@ namespace WireMock.Server
if (matcher == null)
return null;
switch (matcher.Name)
var parts = matcher.Name.Split('.');
string matcherName = parts[0];
string matcherType = parts.Length > 1 ? parts[1] : null;
switch (matcherName)
{
case "RegexMatcher":
return new RegexMatcher(matcher.Pattern);
@@ -423,8 +435,18 @@ namespace WireMock.Server
case "XPathMatcher":
return new XPathMatcher(matcher.Pattern);
default:
case "WildcardMatcher":
return new WildcardMatcher(matcher.Pattern, matcher.IgnoreCase == true);
case "SimMetricsMatcher":
SimMetricType type = SimMetricType.Levenstein;
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported.");
return new SimMetricsMatcher(matcher.Pattern, type);
default:
throw new NotSupportedException($"Matcher '{matcherName}' is not supported.");
}
}

View File

@@ -331,6 +331,7 @@ namespace WireMock.Server
var request = _requestMapper.Map(ctx.Request);
ResponseMessage response = null;
Mapping targetMapping = null;
RequestMatchResult requestMatchResult = null;
try
{
@@ -338,15 +339,19 @@ namespace WireMock.Server
.Select(m => new { Mapping = m, MatchResult = m.IsRequestHandled(request) })
.ToList();
Mapping targetMapping;
if (_allowPartialMapping)
{
var orderedMappings = possibleMatchingMappings
.OrderBy(m => m.Mapping.Priority)
.ThenBy(m => m.MatchResult)
.Where(pm =>
(pm.Mapping.Provider is DynamicResponseProvider && pm.MatchResult.IsPerfectMatch) ||
!(pm.Mapping.Provider is DynamicResponseProvider)
)
.OrderBy(m => m.MatchResult)
.ThenBy(m => m.Mapping.Priority)
.ToList();
var bestPartialMatch = orderedMappings.FirstOrDefault();
targetMapping = bestPartialMatch?.Mapping;
requestMatchResult = bestPartialMatch?.MatchResult;
}
@@ -388,6 +393,7 @@ namespace WireMock.Server
Guid = Guid.NewGuid(),
RequestMessage = request,
ResponseMessage = response,
MappingGuid = targetMapping?.Guid,
RequestMatchResult = requestMatchResult
};

View File

@@ -0,0 +1,19 @@
using Newtonsoft.Json.Linq;
namespace WireMock.Util
{
internal static class JsonUtils
{
public static T ParseJTokenToObject<T>(object value)
{
if (value == null)
return default(T);
JToken token = value as JToken;
if (token == null)
return default(T);
return token.ToObject<T>();
}
}
}