Fix some SonarCloud issues (#1058)

* Fix some SonarCloud issues

* added some xml comments
This commit is contained in:
Stef Heyenrath
2024-02-17 13:32:28 +01:00
committed by GitHub
parent 6ac95cf57d
commit 97a749d54a
12 changed files with 348 additions and 302 deletions
@@ -2,22 +2,34 @@ using Stef.Validation;
using WireMock.Server; using WireMock.Server;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace WireMock.FluentAssertions namespace WireMock.FluentAssertions;
/// <summary>
/// Provides assertion methods to verify the number of calls made to a WireMock server.
/// This class is used in the context of FluentAssertions.
/// </summary>
public class WireMockANumberOfCallsAssertions
{ {
public class WireMockANumberOfCallsAssertions private readonly IWireMockServer _server;
private readonly int _callsCount;
/// <summary>
/// Initializes a new instance of the <see cref="WireMockANumberOfCallsAssertions"/> class.
/// </summary>
/// <param name="server">The WireMock server to assert against.</param>
/// <param name="callsCount">The expected number of calls to assert.</param>
public WireMockANumberOfCallsAssertions(IWireMockServer server, int callsCount)
{ {
private readonly IWireMockServer _server; _server = Guard.NotNull(server);
private readonly int _callsCount; _callsCount = callsCount;
}
public WireMockANumberOfCallsAssertions(IWireMockServer server, int callsCount) /// <summary>
{ /// Returns an instance of <see cref="WireMockAssertions"/> which can be used to assert the expected number of calls.
_server = Guard.NotNull(server); /// </summary>
_callsCount = callsCount; /// <returns>A <see cref="WireMockAssertions"/> instance for asserting the number of calls to the server.</returns>
} public WireMockAssertions Calls()
{
public WireMockAssertions Calls() return new WireMockAssertions(_server, _callsCount);
{
return new WireMockAssertions(_server, _callsCount);
}
} }
} }
@@ -2,50 +2,49 @@ using FluentAssertions.Primitives;
using WireMock.Server; using WireMock.Server;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace WireMock.FluentAssertions namespace WireMock.FluentAssertions;
/// <summary>
/// Contains a number of methods to assert that the <see cref="IWireMockServer"/> is in the expected state.
/// </summary>
public class WireMockReceivedAssertions : ReferenceTypeAssertions<IWireMockServer, WireMockReceivedAssertions>
{ {
/// <summary> /// <summary>
/// Contains a number of methods to assert that the <see cref="IWireMockServer"/> is in the expected state. /// Create a WireMockReceivedAssertions.
/// </summary> /// </summary>
public class WireMockReceivedAssertions : ReferenceTypeAssertions<IWireMockServer, WireMockReceivedAssertions> /// <param name="server">The <see cref="IWireMockServer"/>.</param>
public WireMockReceivedAssertions(IWireMockServer server) : base(server)
{ {
/// <summary>
/// Create a WireMockReceivedAssertions.
/// </summary>
/// <param name="server">The <see cref="IWireMockServer"/>.</param>
public WireMockReceivedAssertions(IWireMockServer server) : base(server)
{
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received no calls.
/// </summary>
/// <returns><see cref="WireMockAssertions"/></returns>
public WireMockAssertions HaveReceivedNoCalls()
{
return new WireMockAssertions(Subject, 0);
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received a call.
/// </summary>
/// <returns><see cref="WireMockAssertions"/></returns>
public WireMockAssertions HaveReceivedACall()
{
return new WireMockAssertions(Subject, null);
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received n-calls.
/// </summary>
/// <param name="callsCount"></param>
/// <returns><see cref="WireMockANumberOfCallsAssertions"/></returns>
public WireMockANumberOfCallsAssertions HaveReceived(int callsCount)
{
return new WireMockANumberOfCallsAssertions(Subject, callsCount);
}
/// <inheritdoc />
protected override string Identifier => "wiremockserver";
} }
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received no calls.
/// </summary>
/// <returns><see cref="WireMockAssertions"/></returns>
public WireMockAssertions HaveReceivedNoCalls()
{
return new WireMockAssertions(Subject, 0);
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received a call.
/// </summary>
/// <returns><see cref="WireMockAssertions"/></returns>
public WireMockAssertions HaveReceivedACall()
{
return new WireMockAssertions(Subject, null);
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received n-calls.
/// </summary>
/// <param name="callsCount"></param>
/// <returns><see cref="WireMockANumberOfCallsAssertions"/></returns>
public WireMockANumberOfCallsAssertions HaveReceived(int callsCount)
{
return new WireMockANumberOfCallsAssertions(Subject, callsCount);
}
/// <inheritdoc />
protected override string Identifier => "wiremockserver";
} }
@@ -11,47 +11,47 @@ public interface IWireMockOpenApiParserExampleValues
/// <summary> /// <summary>
/// An example value for a Boolean. /// An example value for a Boolean.
/// </summary> /// </summary>
bool Boolean { get; set; } bool Boolean { get; }
/// <summary> /// <summary>
/// An example value for an Integer. /// An example value for an Integer.
/// </summary> /// </summary>
int Integer { get; set; } int Integer { get; }
/// <summary> /// <summary>
/// An example value for a Float. /// An example value for a Float.
/// </summary> /// </summary>
float Float { get; set; } float Float { get; }
/// <summary> /// <summary>
/// An example value for a Double. /// An example value for a Double.
/// </summary> /// </summary>
double Double { get; set; } double Double { get; }
/// <summary> /// <summary>
/// An example value for a Date. /// An example value for a Date.
/// </summary> /// </summary>
Func<DateTime> Date { get; set; } Func<DateTime> Date { get; }
/// <summary> /// <summary>
/// An example value for a DateTime. /// An example value for a DateTime.
/// </summary> /// </summary>
Func<DateTime> DateTime { get; set; } Func<DateTime> DateTime { get; }
/// <summary> /// <summary>
/// An example value for Bytes. /// An example value for Bytes.
/// </summary> /// </summary>
byte[] Bytes { get; set; } byte[] Bytes { get; }
/// <summary> /// <summary>
/// An example value for a Object. /// An example value for a Object.
/// </summary> /// </summary>
object Object { get; set; } object Object { get; }
/// <summary> /// <summary>
/// An example value for a String. /// An example value for a String.
/// </summary> /// </summary>
string String { get; set; } string String { get; }
/// <summary> /// <summary>
/// OpenApi Schema to generate dynamic examples more accurate /// OpenApi Schema to generate dynamic examples more accurate
@@ -11,31 +11,31 @@ namespace WireMock.Net.OpenApiParser.Settings;
public class WireMockOpenApiParserDynamicExampleValues : IWireMockOpenApiParserExampleValues public class WireMockOpenApiParserDynamicExampleValues : IWireMockOpenApiParserExampleValues
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual bool Boolean { get => RandomizerFactory.GetRandomizer(new FieldOptionsBoolean()).Generate() ?? true; set { } } public virtual bool Boolean => RandomizerFactory.GetRandomizer(new FieldOptionsBoolean()).Generate() ?? true;
/// <inheritdoc /> /// <inheritdoc />
public virtual int Integer { get => RandomizerFactory.GetRandomizer(new FieldOptionsInteger()).Generate() ?? 42; set { } } public virtual int Integer => RandomizerFactory.GetRandomizer(new FieldOptionsInteger()).Generate() ?? 42;
/// <inheritdoc /> /// <inheritdoc />
public virtual float Float { get => RandomizerFactory.GetRandomizer(new FieldOptionsFloat()).Generate() ?? 4.2f; set { } } public virtual float Float => RandomizerFactory.GetRandomizer(new FieldOptionsFloat()).Generate() ?? 4.2f;
/// <inheritdoc /> /// <inheritdoc />
public virtual double Double { get => RandomizerFactory.GetRandomizer(new FieldOptionsDouble()).Generate() ?? 4.2d; set { } } public virtual double Double => RandomizerFactory.GetRandomizer(new FieldOptionsDouble()).Generate() ?? 4.2d;
/// <inheritdoc /> /// <inheritdoc />
public virtual Func<DateTime> Date { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow.Date; } set { } } public virtual Func<DateTime> Date { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow.Date; } }
/// <inheritdoc /> /// <inheritdoc />
public virtual Func<DateTime> DateTime { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow; } set { } } public virtual Func<DateTime> DateTime { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow; } }
/// <inheritdoc /> /// <inheritdoc />
public virtual byte[] Bytes { get => RandomizerFactory.GetRandomizer(new FieldOptionsBytes()).Generate(); set { } } public virtual byte[] Bytes => RandomizerFactory.GetRandomizer(new FieldOptionsBytes()).Generate();
/// <inheritdoc /> /// <inheritdoc />
public virtual object Object { get; set; } = "example-object"; public virtual object Object => "example-object";
/// <inheritdoc /> /// <inheritdoc />
public virtual string String { get => RandomizerFactory.GetRandomizer(new FieldOptionsTextRegex { Pattern = @"^[0-9]{2}[A-Z]{5}[0-9]{2}" }).Generate() ?? "example-string"; set { } } public virtual string String => RandomizerFactory.GetRandomizer(new FieldOptionsTextRegex { Pattern = @"^[0-9]{2}[A-Z]{5}[0-9]{2}" }).Generate() ?? "example-string";
/// <inheritdoc /> /// <inheritdoc />
public virtual OpenApiSchema? Schema { get; set; } public virtual OpenApiSchema? Schema { get; set; }
@@ -9,31 +9,31 @@ namespace WireMock.Net.OpenApiParser.Settings;
public class WireMockOpenApiParserExampleValues : IWireMockOpenApiParserExampleValues public class WireMockOpenApiParserExampleValues : IWireMockOpenApiParserExampleValues
{ {
/// <inheritdoc /> /// <inheritdoc />
public virtual bool Boolean { get; set; } = true; public virtual bool Boolean => true;
/// <inheritdoc /> /// <inheritdoc />
public virtual int Integer { get; set; } = 42; public virtual int Integer => 42;
/// <inheritdoc /> /// <inheritdoc />
public virtual float Float { get; set; } = 4.2f; public virtual float Float => 4.2f;
/// <inheritdoc /> /// <inheritdoc />
public virtual double Double { get; set; } = 4.2d; public virtual double Double => 4.2d;
/// <inheritdoc /> /// <inheritdoc />
public virtual Func<DateTime> Date { get; set; } = () => System.DateTime.UtcNow.Date; public virtual Func<DateTime> Date { get; } = () => System.DateTime.UtcNow.Date;
/// <inheritdoc /> /// <inheritdoc />
public virtual Func<DateTime> DateTime { get; set; } = () => System.DateTime.UtcNow; public virtual Func<DateTime> DateTime { get; } = () => System.DateTime.UtcNow;
/// <inheritdoc /> /// <inheritdoc />
public virtual byte[] Bytes { get; set; } = { 48, 49, 50 }; public virtual byte[] Bytes { get; } = { 48, 49, 50 };
/// <inheritdoc /> /// <inheritdoc />
public virtual object Object { get; set; } = "example-object"; public virtual object Object => "example-object";
/// <inheritdoc /> /// <inheritdoc />
public virtual string String { get; set; } = "example-string"; public virtual string String => "example-string";
/// <inheritdoc /> /// <inheritdoc />
public virtual OpenApiSchema? Schema { get; set; } = new(); public virtual OpenApiSchema? Schema { get; set; } = new();
+102 -103
View File
@@ -14,97 +14,97 @@ using WireMock.Owin.Mappers;
using WireMock.Services; using WireMock.Services;
using WireMock.Util; using WireMock.Util;
namespace WireMock.Owin namespace WireMock.Owin;
internal partial class AspNetCoreSelfHost : IOwinSelfHost
{ {
internal partial class AspNetCoreSelfHost : IOwinSelfHost private const string CorsPolicyName = "WireMock.Net - Policy";
private readonly CancellationTokenSource _cts = new();
private readonly IWireMockMiddlewareOptions _wireMockMiddlewareOptions;
private readonly IWireMockLogger _logger;
private readonly HostUrlOptions _urlOptions;
private Exception _runningException;
private IWebHost _host;
public bool IsStarted { get; private set; }
public List<string> Urls { get; } = new();
public List<int> Ports { get; } = new();
public Exception RunningException => _runningException;
public AspNetCoreSelfHost(IWireMockMiddlewareOptions wireMockMiddlewareOptions, HostUrlOptions urlOptions)
{ {
private const string CorsPolicyName = "WireMock.Net - Policy"; Guard.NotNull(wireMockMiddlewareOptions);
Guard.NotNull(urlOptions);
private readonly CancellationTokenSource _cts = new CancellationTokenSource(); _logger = wireMockMiddlewareOptions.Logger ?? new WireMockConsoleLogger();
private readonly IWireMockMiddlewareOptions _wireMockMiddlewareOptions;
private readonly IWireMockLogger _logger;
private readonly HostUrlOptions _urlOptions;
private Exception _runningException; _wireMockMiddlewareOptions = wireMockMiddlewareOptions;
private IWebHost _host; _urlOptions = urlOptions;
}
public bool IsStarted { get; private set; } public Task StartAsync()
{
var builder = new WebHostBuilder();
public List<string> Urls { get; } = new(); // Workaround for https://github.com/WireMock-Net/WireMock.Net/issues/292
// On some platforms, AppContext.BaseDirectory is null, which causes WebHostBuilder to fail if ContentRoot is not
public List<int> Ports { get; } = new(); // specified (even though we don't actually use that base path mechanism, since we have our own way of configuring
// a filesystem handler).
public Exception RunningException => _runningException; if (string.IsNullOrEmpty(AppContext.BaseDirectory))
public AspNetCoreSelfHost(IWireMockMiddlewareOptions wireMockMiddlewareOptions, HostUrlOptions urlOptions)
{ {
Guard.NotNull(wireMockMiddlewareOptions); builder.UseContentRoot(Directory.GetCurrentDirectory());
Guard.NotNull(urlOptions);
_logger = wireMockMiddlewareOptions.Logger ?? new WireMockConsoleLogger();
_wireMockMiddlewareOptions = wireMockMiddlewareOptions;
_urlOptions = urlOptions;
} }
public Task StartAsync() _host = builder
{ .UseSetting("suppressStatusMessages", "True") // https://andrewlock.net/suppressing-the-startup-and-shutdown-messages-in-asp-net-core/
var builder = new WebHostBuilder(); .ConfigureAppConfigurationUsingEnvironmentVariables()
.ConfigureServices(services =>
// Workaround for https://github.com/WireMock-Net/WireMock.Net/issues/292
// On some platforms, AppContext.BaseDirectory is null, which causes WebHostBuilder to fail if ContentRoot is not
// specified (even though we don't actually use that base path mechanism, since we have our own way of configuring
// a filesystem handler).
if (string.IsNullOrEmpty(AppContext.BaseDirectory))
{ {
builder.UseContentRoot(Directory.GetCurrentDirectory()); services.AddSingleton(_wireMockMiddlewareOptions);
} services.AddSingleton<IMappingMatcher, MappingMatcher>();
services.AddSingleton<IRandomizerDoubleBetween0And1, RandomizerDoubleBetween0And1>();
_host = builder services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
.UseSetting("suppressStatusMessages", "True") // https://andrewlock.net/suppressing-the-startup-and-shutdown-messages-in-asp-net-core/ services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
.ConfigureAppConfigurationUsingEnvironmentVariables() services.AddSingleton<IGuidUtils, GuidUtils>();
.ConfigureServices(services =>
{
services.AddSingleton(_wireMockMiddlewareOptions);
services.AddSingleton<IMappingMatcher, MappingMatcher>();
services.AddSingleton<IRandomizerDoubleBetween0And1, RandomizerDoubleBetween0And1>();
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
services.AddSingleton<IGuidUtils, GuidUtils>();
#if NETCOREAPP3_1 || NET5_0_OR_GREATER #if NETCOREAPP3_1 || NET5_0_OR_GREATER
AddCors(services); AddCors(services);
#endif #endif
_wireMockMiddlewareOptions.AdditionalServiceRegistration?.Invoke(services); _wireMockMiddlewareOptions.AdditionalServiceRegistration?.Invoke(services);
}) })
.Configure(appBuilder => .Configure(appBuilder =>
{ {
appBuilder.UseMiddleware<GlobalExceptionMiddleware>(); appBuilder.UseMiddleware<GlobalExceptionMiddleware>();
#if NETCOREAPP3_1 || NET5_0_OR_GREATER #if NETCOREAPP3_1 || NET5_0_OR_GREATER
UseCors(appBuilder); UseCors(appBuilder);
#endif #endif
_wireMockMiddlewareOptions.PreWireMockMiddlewareInit?.Invoke(appBuilder); _wireMockMiddlewareOptions.PreWireMockMiddlewareInit?.Invoke(appBuilder);
appBuilder.UseMiddleware<WireMockMiddleware>(); appBuilder.UseMiddleware<WireMockMiddleware>();
_wireMockMiddlewareOptions.PostWireMockMiddlewareInit?.Invoke(appBuilder); _wireMockMiddlewareOptions.PostWireMockMiddlewareInit?.Invoke(appBuilder);
}) })
.UseKestrel(options => .UseKestrel(options =>
{ {
SetKestrelOptionsLimits(options); SetKestrelOptionsLimits(options);
SetHttpsAndUrls(options, _wireMockMiddlewareOptions, _urlOptions.GetDetails()); SetHttpsAndUrls(options, _wireMockMiddlewareOptions, _urlOptions.GetDetails());
}) })
.ConfigureKestrelServerOptions() .ConfigureKestrelServerOptions()
#if NETSTANDARD1_3 #if NETSTANDARD1_3
.UseUrls(_urlOptions.GetDetails().Select(u => u.Url).ToArray()) .UseUrls(_urlOptions.GetDetails().Select(u => u.Url).ToArray())
#endif #endif
.Build(); .Build();
return RunHost(_cts.Token); return RunHost(_cts.Token);
} }
private Task RunHost(CancellationToken token) private Task RunHost(CancellationToken token)
{ {
@@ -129,60 +129,59 @@ namespace WireMock.Owin
Ports.Add(port); Ports.Add(port);
} }
IsStarted = true; IsStarted = true;
}); });
#if NETSTANDARD1_3 #if NETSTANDARD1_3
_logger.Info("Server using netstandard1.3"); _logger.Info("Server using netstandard1.3");
#elif NETSTANDARD2_0 #elif NETSTANDARD2_0
_logger.Info("Server using netstandard2.0"); _logger.Info("Server using netstandard2.0");
#elif NETSTANDARD2_1 #elif NETSTANDARD2_1
_logger.Info("Server using netstandard2.1"); _logger.Info("Server using netstandard2.1");
#elif NETCOREAPP3_1 #elif NETCOREAPP3_1
_logger.Info("Server using .NET Core App 3.1"); _logger.Info("Server using .NET Core App 3.1");
#elif NET5_0 #elif NET5_0
_logger.Info("Server using .NET 5.0"); _logger.Info("Server using .NET 5.0");
#elif NET6_0 #elif NET6_0
_logger.Info("Server using .NET 6.0"); _logger.Info("Server using .NET 6.0");
#elif NET7_0 #elif NET7_0
_logger.Info("Server using .NET 7.0"); _logger.Info("Server using .NET 7.0");
#elif NET8_0 #elif NET8_0
_logger.Info("Server using .NET 8.0"); _logger.Info("Server using .NET 8.0");
#elif NET46 #elif NET46
_logger.Info("Server using .NET Framework 4.6.1 or higher"); _logger.Info("Server using .NET Framework 4.6.1 or higher");
#endif #endif
#if NETSTANDARD1_3 #if NETSTANDARD1_3
return Task.Run(() => return Task.Run(() =>
{
_host.Run(token);
});
#else
return _host.RunAsync(token);
#endif
}
catch (Exception e)
{ {
_runningException = e; _host.Run(token);
_logger.Error(e.ToString()); });
#else
IsStarted = false; return _host.RunAsync(token);
#endif
return Task.CompletedTask;
}
} }
catch (Exception e)
public Task StopAsync()
{ {
_cts.Cancel(); _runningException = e;
_logger.Error(e.ToString());
IsStarted = false; IsStarted = false;
#if NETSTANDARD1_3
return Task.FromResult(true); return Task.CompletedTask;
#else
return _host.StopAsync();
#endif
} }
} }
public Task StopAsync()
{
_cts.Cancel();
IsStarted = false;
#if NETSTANDARD1_3
return Task.CompletedTask;
#else
return _host.StopAsync();
#endif
}
} }
#endif #endif
@@ -23,17 +23,17 @@ public partial class Request
} }
/// <inheritdoc /> /// <inheritdoc />
public IRequestBuilder WithClientIP(params string[] paths) public IRequestBuilder WithClientIP(params string[] clientIPs)
{ {
return WithClientIP(MatchOperator.Or, paths); return WithClientIP(MatchOperator.Or, clientIPs);
} }
/// <inheritdoc /> /// <inheritdoc />
public IRequestBuilder WithClientIP(MatchOperator matchOperator, params string[] paths) public IRequestBuilder WithClientIP(MatchOperator matchOperator, params string[] clientIPs)
{ {
Guard.NotNullOrEmpty(paths); Guard.NotNullOrEmpty(clientIPs);
_requestMatchers.Add(new RequestMessageClientIPMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, paths)); _requestMatchers.Add(new RequestMessageClientIPMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, clientIPs));
return this; return this;
} }
@@ -111,11 +111,11 @@ public partial class WireMockServer
Given(Request.Create().WithPath(AdminScenariosNameWithResetMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset)); Given(Request.Create().WithPath(AdminScenariosNameWithResetMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset));
// __admin/files/{filename} // __admin/files/{filename}
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePost)); Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePost));
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingPut()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePut)); Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingPut()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePut));
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileGet)); Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileGet));
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingHead()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileHead)); Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingHead()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileHead));
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileDelete)); Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileDelete));
// __admin/openapi // __admin/openapi
Given(Request.Create().WithPath($"{AdminOpenApi}/convert").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(OpenApiConvertToMappings)); Given(Request.Create().WithPath($"{AdminOpenApi}/convert").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(OpenApiConvertToMappings));
@@ -6,111 +6,120 @@ using WireMock.Matchers;
using WireMock.Types; using WireMock.Types;
using WireMock.Util; using WireMock.Util;
namespace WireMock.Server namespace WireMock.Server;
public partial class WireMockServer
{ {
public partial class WireMockServer private static readonly RegexMatcher AdminFilesFilenamePathMatcher = new(@"^\/__admin\/files\/.*$");
private static readonly Encoding[] FileBodyIsString = { Encoding.UTF8, Encoding.ASCII };
#region Files/{filename}
private IResponseMessage FilePost(IRequestMessage requestMessage)
{ {
private readonly RegexMatcher _adminFilesFilenamePathMatcher = new RegexMatcher(@"^\/__admin\/files\/.*$"); if (requestMessage.BodyAsBytes is null)
private static readonly Encoding[] FileBodyIsString = { Encoding.UTF8, Encoding.ASCII };
#region Files/{filename}
private IResponseMessage FilePost(IRequestMessage requestMessage)
{ {
string filename = GetFileNameFromRequestMessage(requestMessage); return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
string mappingFolder = _settings.FileSystemHandler.GetMappingFolder();
if (!_settings.FileSystemHandler.FolderExists(mappingFolder))
{
_settings.FileSystemHandler.CreateFolder(mappingFolder);
}
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
return ResponseMessageBuilder.Create(200, "File created");
} }
private IResponseMessage FilePut(IRequestMessage requestMessage) var filename = GetFileNameFromRequestMessage(requestMessage);
var mappingFolder = _settings.FileSystemHandler.GetMappingFolder();
if (!_settings.FileSystemHandler.FolderExists(mappingFolder))
{ {
string filename = GetFileNameFromRequestMessage(requestMessage); _settings.FileSystemHandler.CreateFolder(mappingFolder);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist, updating file will be skipped.", filename);
return ResponseMessageBuilder.Create(404, "File is not found");
}
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
return ResponseMessageBuilder.Create(200, "File updated");
} }
private IResponseMessage FileGet(IRequestMessage requestMessage) _settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
{
string filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename)) return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File created");
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(404, "File is not found");
}
byte[] bytes = _settings.FileSystemHandler.ReadFile(filename);
var response = new ResponseMessage
{
StatusCode = 200,
BodyData = new BodyData
{
BodyAsBytes = bytes,
DetectedBodyType = BodyType.Bytes,
DetectedBodyTypeFromContentType = BodyType.None
}
};
if (BytesEncodingUtils.TryGetEncoding(bytes, out var encoding) && FileBodyIsString.Select(x => x.Equals(encoding)).Any())
{
response.BodyData.DetectedBodyType = BodyType.String;
response.BodyData.BodyAsString = encoding.GetString(bytes);
}
return response;
}
/// <summary>
/// Checks if file exists.
/// Note: Response is returned with no body as a head request doesn't accept a body, only the status code.
/// </summary>
/// <param name="requestMessage">The request message.</param>
private IResponseMessage FileHead(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound);
}
return ResponseMessageBuilder.Create(HttpStatusCode.NoContent);
}
private IResponseMessage FileDelete(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(404, "File is not deleted");
}
_settings.FileSystemHandler.DeleteFile(filename);
return ResponseMessageBuilder.Create(200, "File deleted.");
}
private string GetFileNameFromRequestMessage(IRequestMessage requestMessage)
{
return Path.GetFileName(requestMessage.Path.Substring(AdminFiles.Length + 1));
}
#endregion
} }
private IResponseMessage FilePut(IRequestMessage requestMessage)
{
if (requestMessage.BodyAsBytes is null)
{
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
}
var filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist, updating file will be skipped.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not found");
}
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File updated");
}
private IResponseMessage FileGet(IRequestMessage requestMessage)
{
var filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not found");
}
var bytes = _settings.FileSystemHandler.ReadFile(filename);
var response = new ResponseMessage
{
StatusCode = 200,
BodyData = new BodyData
{
BodyAsBytes = bytes,
DetectedBodyType = BodyType.Bytes,
DetectedBodyTypeFromContentType = BodyType.None
}
};
if (BytesEncodingUtils.TryGetEncoding(bytes, out var encoding) && FileBodyIsString.Select(x => x.Equals(encoding)).Any())
{
response.BodyData.DetectedBodyType = BodyType.String;
response.BodyData.BodyAsString = encoding.GetString(bytes);
}
return response;
}
/// <summary>
/// Checks if file exists.
/// Note: Response is returned with no body as a head request doesn't accept a body, only the status code.
/// </summary>
/// <param name="requestMessage">The request message.</param>
private IResponseMessage FileHead(IRequestMessage requestMessage)
{
var filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound);
}
return ResponseMessageBuilder.Create(HttpStatusCode.NoContent);
}
private IResponseMessage FileDelete(IRequestMessage requestMessage)
{
var filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not deleted");
}
_settings.FileSystemHandler.DeleteFile(filename);
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File deleted.");
}
private static string GetFileNameFromRequestMessage(IRequestMessage requestMessage)
{
return Path.GetFileName(requestMessage.Path.Substring(AdminFiles.Length + 1));
}
#endregion
} }
@@ -79,7 +79,7 @@ public partial class WireMockServer
private NotifyCollectionChangedEventHandler? _logEntriesChanged; private NotifyCollectionChangedEventHandler? _logEntriesChanged;
private void LogEntries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) private void LogEntries_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{ {
if (_logEntriesChanged is { }) if (_logEntriesChanged is { })
{ {
@@ -1,20 +1,48 @@
using System;
using Stef.Validation;
using WireMock.Matchers; using WireMock.Matchers;
namespace WireMock.Settings; namespace WireMock.Settings;
public class ProxySaveMappingSetting<T> /// <summary>
/// Represents settings for saving a proxy mapping with a non-nullable value and a specific match behaviour.
/// </summary>
/// <typeparam name="T">The non-nullable type of the value associated with the proxy save mapping setting.</typeparam>
public class ProxySaveMappingSetting<T> where T : notnull
{ {
public MatchBehaviour MatchBehaviour { get; } = MatchBehaviour.AcceptOnMatch; /// <summary>
/// Gets the match behaviour for the proxy save mapping setting.
/// </summary>
/// <value>The match behaviour which determines how matches are evaluated.</value>
public MatchBehaviour MatchBehaviour { get; }
/// <summary>
/// Gets the non-nullable value associated with the proxy save mapping setting.
/// </summary>
/// <value>The value of type <typeparamref name="T"/>.</value>
public T Value { get; } public T Value { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ProxySaveMappingSetting{T}"/> class with specified non-nullable value and match behaviour.
/// </summary>
/// <param name="value">The non-nullable value of type <typeparamref name="T"/>.</param>
/// <param name="matchBehaviour">The match behaviour (optional, default is <c>MatchBehaviour.AcceptOnMatch</c>.</param>
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="value"/> is null.</exception>
public ProxySaveMappingSetting(T value, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) public ProxySaveMappingSetting(T value, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{ {
Value = value; Value = Guard.NotNull(value);
MatchBehaviour = matchBehaviour; MatchBehaviour = matchBehaviour;
} }
/// <summary>
/// Converts a non-nullable value of type <typeparamref name="T"/> to a <see cref="ProxySaveMappingSetting{T}"/> implicitly.
/// </summary>
/// <param name="value">The non-nullable value to convert.</param>
public static implicit operator ProxySaveMappingSetting<T>(T value) => new(value); public static implicit operator ProxySaveMappingSetting<T>(T value) => new(value);
public static implicit operator T(ProxySaveMappingSetting<T> @this) => @this.Value; /// <summary>
/// Converts a <see cref="ProxySaveMappingSetting{T}"/> to its underlying non-nullable value of type <typeparamref name="T"/> implicitly.
/// </summary>
/// <param name="instance">The <see cref="ProxySaveMappingSetting{T}"/> to convert.</param>
public static implicit operator T(ProxySaveMappingSetting<T> instance) => instance.Value;
} }
+3 -4
View File
@@ -121,8 +121,7 @@ internal static class CSharpFormatter
JTokenType.Boolean => jValue.Value != null ? string.Format(CultureInfo.InvariantCulture, "{0}", jValue.Value).ToLower() : Null, JTokenType.Boolean => jValue.Value != null ? string.Format(CultureInfo.InvariantCulture, "{0}", jValue.Value).ToLower() : Null,
JTokenType.Null => Null, JTokenType.Null => Null,
JTokenType.Undefined => Null, JTokenType.Undefined => Null,
JTokenType.Date when jValue.Value is DateTime dateValue => JTokenType.Date when jValue.Value is DateTime dateValue => $"DateTime.Parse({ToCSharpStringLiteral(dateValue.ToString("s"))})",
$"DateTime.Parse({ToCSharpStringLiteral(dateValue.ToString("s"))})",
_ => $"UNHANDLED_CASE: {jValue.Type}" _ => $"UNHANDLED_CASE: {jValue.Type}"
}, },
_ => $"UNHANDLED_CASE: {token}" _ => $"UNHANDLED_CASE: {token}"
@@ -140,12 +139,12 @@ internal static class CSharpFormatter
if (value.Contains('\n')) if (value.Contains('\n'))
{ {
var escapedValue = value?.Replace("\"", "\"\"") ?? string.Empty; var escapedValue = value.Replace("\"", "\"\"");
return $"@\"{escapedValue}\""; return $"@\"{escapedValue}\"";
} }
else else
{ {
var escapedValue = value?.Replace("\"", "\\\"") ?? string.Empty; var escapedValue = value.Replace("\"", "\\\"");
return $"\"{escapedValue}\""; return $"\"{escapedValue}\"";
} }
} }