Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 47 additions & 16 deletions examples/WireMock.Net.Console.NET8/MainApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ private static void RunOnLocal()
}
}

public static void Run()
public static async Task RunAsync()
{
//RunSse();
//RunOnLocal();
Expand All @@ -290,25 +290,56 @@ public static void Run()

var server = WireMockServer.Start();

//server
// .Given(Request.Create()
// .WithPath("todos")
// .UsingGet()
// )
// .RespondWith(Response.Create()
// .WithBodyAsJson(todos.Values)
// );

//server
// .Given(Request.Create()
// .UsingGet()
// .WithPath("todos")
// .WithParam("id")
// )
// .RespondWith(Response.Create()
// .WithBodyAsJson(rm => todos[int.Parse(rm.Query!["id"].ToString())])
// );

var pX = 0.80;
server
.Given(Request.Create()
.WithPath("todos")
.UsingGet()
)
.RespondWith(Response.Create()
.WithBodyAsJson(todos.Values)
);
.Given(Request.Create().UsingGet().WithPath("/p"))
.WithProbability(pX)
.RespondWith(Response.Create().WithStatusCode(200).WithBody("X"));

server
.Given(Request.Create()
.UsingGet()
.WithPath("todos")
.WithParam("id")
)
.RespondWith(Response.Create()
.WithBodyAsJson(rm => todos[int.Parse(rm.Query!["id"].ToString())])
);
.Given(Request.Create().UsingGet().WithPath("/p"))
.RespondWith(Response.Create().WithStatusCode(200).WithBody("default"));

// Act
var requestUri = new Uri($"http://localhost:{server.Port}/p");
var c = server.CreateClient();
var xCount = 0;
var defaultCount = 0;
var tot = 1000;
for (var i = 0; i < tot; i++)
{
var response = await c.GetAsync(requestUri);
var value = await response.Content.ReadAsStringAsync();
if (value == "X")
{
xCount++;
}
else if (value == "default")
{
defaultCount++;
}
}
System.Console.WriteLine("X = {0} ; default = {1} ; pX = {2:0.00} ; valueX = {3:0.00}", xCount, defaultCount, pX, 1.0 * xCount / tot);
return;
using var httpAndHttpsWithPort = WireMockServer.Start(new WireMockServerSettings
{
HostingScheme = HostingScheme.HttpAndHttps,
Expand Down
5 changes: 3 additions & 2 deletions examples/WireMock.Net.Console.NET8/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using log4net;
using log4net.Config;
using log4net.Repository;
Expand All @@ -14,10 +15,10 @@ static class Program
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));

static void Main(params string[] args)
static async Task Main(params string[] args)
{
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));

MainApp.Run();
await MainApp.RunAsync();
}
}
34 changes: 17 additions & 17 deletions src/WireMock.Net.Minimal/Owin/MappingMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,10 @@

namespace WireMock.Owin;

internal class MappingMatcher : IMappingMatcher
internal class MappingMatcher(IWireMockMiddlewareOptions options, IRandomizerDoubleBetween0And1 randomizerDoubleBetween0And1) : IMappingMatcher
{
private readonly IWireMockMiddlewareOptions _options;
private readonly IRandomizerDoubleBetween0And1 _randomizerDoubleBetween0And1;

public MappingMatcher(IWireMockMiddlewareOptions options, IRandomizerDoubleBetween0And1 randomizerDoubleBetween0And1)
{
_options = Guard.NotNull(options);
_randomizerDoubleBetween0And1 = Guard.NotNull(randomizerDoubleBetween0And1);
}
private readonly IWireMockMiddlewareOptions _options = Guard.NotNull(options);
private readonly IRandomizerDoubleBetween0And1 _randomizerDoubleBetween0And1 = Guard.NotNull(randomizerDoubleBetween0And1);

public (MappingMatcherResult? Match, MappingMatcherResult? Partial) FindBestMatch(RequestMessage request)
{
Expand All @@ -28,7 +22,7 @@ public MappingMatcher(IWireMockMiddlewareOptions options, IRandomizerDoubleBetwe

var mappings = _options.Mappings.Values
.Where(m => m.TimeSettings.IsValid())
.Where(m => m.Probability is null || m.Probability <= _randomizerDoubleBetween0And1.Generate())
.Where(m => m.Probability is null || _randomizerDoubleBetween0And1.Generate() <= m.Probability)
.ToArray();

foreach (var mapping in mappings)
Expand All @@ -41,18 +35,18 @@ public MappingMatcher(IWireMockMiddlewareOptions options, IRandomizerDoubleBetwe

var exceptions = mappingMatcherResult.RequestMatchResult.MatchDetails
.Where(md => md.Exception != null)
.Select(md => md.Exception)
.Select(md => md.Exception!)
.ToArray();

if (!exceptions.Any())
if (exceptions.Length == 0)
{
possibleMappings.Add(mappingMatcherResult);
}
else if (!request.AbsolutePath.StartsWith("/__admin", StringComparison.OrdinalIgnoreCase))
{
foreach (var ex in exceptions)
{
LogException(mapping, ex!);
LogException(mapping, ex);
}
}
}
Expand All @@ -62,14 +56,16 @@ public MappingMatcher(IWireMockMiddlewareOptions options, IRandomizerDoubleBetwe
}
}

var partialMappings = possibleMappings
var partialMatches = possibleMappings
.Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
.OrderBy(m => m.RequestMatchResult)
.ThenBy(m => m.RequestMatchResult.TotalNumber)
.ThenBy(m => m.Mapping.Priority)
.ThenByDescending(m => m.Mapping.Probability)
.ThenByDescending(m => m.Mapping.UpdatedAt)
.ToList();
var partialMatch = partialMappings.FirstOrDefault(pm => pm.RequestMatchResult.AverageTotalScore > 0.0);
.Where(pm => pm.RequestMatchResult.AverageTotalScore > 0.0)
.ToArray();
var partialMatch = partialMatches.FirstOrDefault();

if (_options.AllowPartialMapping == true)
{
Expand All @@ -78,7 +74,11 @@ public MappingMatcher(IWireMockMiddlewareOptions options, IRandomizerDoubleBetwe

var match = possibleMappings
.Where(m => m.RequestMatchResult.IsPerfectMatch)
.OrderBy(m => m.Mapping.Priority).ThenBy(m => m.RequestMatchResult).ThenByDescending(m => m.Mapping.UpdatedAt)
.OrderBy(m => m.Mapping.Priority)
.ThenBy(m => m.RequestMatchResult)
.ThenBy(m => m.RequestMatchResult.TotalNumber)
.ThenByDescending(m => m.Mapping.Probability)
.ThenByDescending(m => m.Mapping.UpdatedAt)
.FirstOrDefault();

return (match, partialMatch);
Expand Down
57 changes: 39 additions & 18 deletions test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using WireMock.Models;
using WireMock.Owin;
using WireMock.Services;
using WireMock.Util;
using Xunit;

namespace WireMock.Net.Tests.Owin;
Expand All @@ -26,7 +25,7 @@ public MappingMatcherTests()
_optionsMock = new Mock<IWireMockMiddlewareOptions>();
_optionsMock.SetupAllProperties();
_optionsMock.Setup(o => o.Mappings).Returns(new ConcurrentDictionary<Guid, IMapping>());
_optionsMock.Setup(o => o.LogEntries).Returns(new ConcurrentObservableCollection<LogEntry>());
_optionsMock.Setup(o => o.LogEntries).Returns([]);
_optionsMock.Setup(o => o.Scenarios).Returns(new ConcurrentDictionary<string, ScenarioState>());

var loggerMock = new Mock<IWireMockLogger>();
Expand All @@ -35,7 +34,7 @@ public MappingMatcherTests()
_optionsMock.Setup(o => o.Logger).Returns(loggerMock.Object);

_randomizerDoubleBetween0And1Mock = new Mock<IRandomizerDoubleBetween0And1>();
_randomizerDoubleBetween0And1Mock.Setup(r => r.Generate()).Returns(0.0);
_randomizerDoubleBetween0And1Mock.Setup(r => r.Generate()).Returns(0.5);

_sut = new MappingMatcher(_optionsMock.Object, _randomizerDoubleBetween0And1Mock.Object);
}
Expand Down Expand Up @@ -84,8 +83,8 @@ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_ShouldRe
var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
var mappings = InitMappings
(
(guid1, new[] { 0.1 }, null),
(guid2, new[] { 1.0 }, null)
(guid1, [0.1], null),
(guid2, [1.0], null)
);
_optionsMock.Setup(o => o.Mappings).Returns(mappings);

Expand All @@ -112,8 +111,8 @@ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_AndNoExa
var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
var mappings = InitMappings
(
(guid1, new[] { 0.1 }, null),
(guid2, new[] { 0.9 }, null)
(guid1, [0.1], null),
(guid2, [0.9], null)
);
_optionsMock.Setup(o => o.Mappings).Returns(mappings);

Expand All @@ -139,8 +138,8 @@ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsTrue_ShouldRet

_optionsMock.SetupGet(o => o.AllowPartialMapping).Returns(true);
var mappings = InitMappings(
(guid1, new[] { 0.1 }, null),
(guid2, new[] { 0.9 }, null)
(guid1, [0.1], null),
(guid2, [0.9], null)
);
_optionsMock.Setup(o => o.Mappings).Returns(mappings);

Expand All @@ -166,8 +165,8 @@ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_And_With
var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
var mappings = InitMappings(
(guid1, new[] { 1.0 }, null),
(guid2, new[] { 1.0, 1.0 }, null)
(guid1, [1.0], null),
(guid2, [1.0, 1.0], null)
);
_optionsMock.Setup(o => o.Mappings).Returns(mappings);

Expand All @@ -187,15 +186,15 @@ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_And_With
}

[Fact]
public void MappingMatcher_FindBestMatch_WhenProbabilityFailsFirst_ShouldReturnSecondMatch()
public void MappingMatcher_FindBestMatch_WhenProbabilityDoesNotMatch_ShouldReturnNormalMatch()
{
// Assign
var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
var withProbability = Guid.Parse("00000000-0000-0000-0000-000000000001");
var noProbability = Guid.Parse("00000000-0000-0000-0000-000000000002");
var mappings = InitMappings
(
(guid1, new[] { 1.0 }, 1.0),
(guid2, new[] { 1.0 }, null)
(withProbability, [1.0], 0.4),
(noProbability, [1.0], null)
);
_optionsMock.Setup(o => o.Mappings).Returns(mappings);

Expand All @@ -206,8 +205,30 @@ public void MappingMatcher_FindBestMatch_WhenProbabilityFailsFirst_ShouldReturnS

// Assert
result.Match.Should().NotBeNull();
result.Match!.Mapping.Guid.Should().Be(guid2);
result.Match.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
result.Match!.Mapping.Guid.Should().Be(noProbability);
}

[Fact]
public void MappingMatcher_FindBestMatch_WhenProbabilityDoesMatch_ShouldReturnProbabilityMatch()
{
// Assign
var withProbability = Guid.Parse("00000000-0000-0000-0000-000000000001");
var noProbability = Guid.Parse("00000000-0000-0000-0000-000000000002");
var mappings = InitMappings
(
(withProbability, [1.0], 0.6),
(noProbability, [1.0], null)
);
_optionsMock.Setup(o => o.Mappings).Returns(mappings);

var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");

// Act
var result = _sut.FindBestMatch(request);

// Assert
result.Match.Should().NotBeNull();
result.Match!.Mapping.Guid.Should().Be(withProbability);
}

private static ConcurrentDictionary<Guid, IMapping> InitMappings(params (Guid guid, double[] scores, double? probability)[] matches)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public async Task WireMockServer_WithProbability()
var response = await server.CreateClient().GetAsync(requestUri).ConfigureAwait(false);

// Assert
Assert.True(new[] { HttpStatusCode.OK, HttpStatusCode.InternalServerError }.Contains(response.StatusCode));
Assert.Contains(response.StatusCode, [HttpStatusCode.OK, HttpStatusCode.InternalServerError]);

server.Stop();
}
Expand Down
Loading