Skip to content

Commit

Permalink
feat: set up uri matcher for reusability so we can more simply add ot…
Browse files Browse the repository at this point in the history
…her types of matchers that check portions of the URI, like path/route values, etc.
  • Loading branch information
skwasjer committed Sep 7, 2024
1 parent 89c7c3f commit 7c211f8
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 17 deletions.
5 changes: 5 additions & 0 deletions src/MockHttp/Matchers/Patterns/IPatternMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@

internal interface IPatternMatcher<in T>
{
/// <summary>
/// Tests if the specified <paramref name="value" /> matches the pattern.
/// </summary>
/// <param name="value">The value to test.</param>
/// <returns>Returns true if the value matches the pattern; otherwise returns false.</returns>
bool IsMatch(T value);
}
14 changes: 0 additions & 14 deletions src/MockHttp/Matchers/Patterns/PatternMatcher.cs

This file was deleted.

4 changes: 2 additions & 2 deletions src/MockHttp/Matchers/Patterns/RegexPatternMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace MockHttp.Matchers.Patterns;

internal class RegexPatternMatcher : PatternMatcher
internal class RegexPatternMatcher : IPatternMatcher<string>
{
public RegexPatternMatcher
(
Expand All @@ -24,7 +24,7 @@ public RegexPatternMatcher(Regex regex)
internal Regex Regex { get; }

/// <inheritdoc />
public override bool IsMatch(string value)
public virtual bool IsMatch(string value)
{
return Regex.IsMatch(value);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Diagnostics;
using MockHttp.Http;

namespace MockHttp.Matchers.Patterns;

[DebuggerDisplay($"{{{nameof(_originalUri)}}}")]
internal sealed class RelativeOrAbsoluteUriPatternMatcher : UriPatternMatcher
{
private readonly Uri _originalUri;
private readonly Uri _uri;

public RelativeOrAbsoluteUriPatternMatcher(Uri uri)
{
_originalUri = uri;
_uri = uri.EnsureIsRooted();
}

public override bool IsMatch(Uri value)
{
return IsAbsoluteUriMatch(value) || IsRelativeUriMatch(value);
}

private bool IsAbsoluteUriMatch(Uri uri)
{
return _uri.IsAbsoluteUri && uri.Equals(_uri);
}

private bool IsRelativeUriMatch(Uri uri)
{
return !_uri.IsAbsoluteUri
&& uri.IsBaseOf(_uri)
&& uri.ToString().EndsWith(_uri.ToString(), StringComparison.Ordinal);
}
}
6 changes: 6 additions & 0 deletions src/MockHttp/Matchers/Patterns/UriPatternMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace MockHttp.Matchers.Patterns;

internal abstract class UriPatternMatcher : IPatternMatcher<Uri>
{
public abstract bool IsMatch(Uri value);
}
19 changes: 19 additions & 0 deletions src/MockHttp/Matchers/Patterns/UriStringPatternMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace MockHttp.Matchers.Patterns;

internal class UriStringPatternMatcher : UriPatternMatcher
{
private readonly Func<Uri, string> _selector;
private readonly IPatternMatcher<string> _stringPatternMatcher;

public UriStringPatternMatcher(Func<Uri, string> selector, IPatternMatcher<string> stringPatternMatcher)
{
_selector = selector ?? throw new ArgumentNullException(nameof(selector));
_stringPatternMatcher = stringPatternMatcher ?? throw new ArgumentNullException(nameof(stringPatternMatcher));
}

public override bool IsMatch(Uri value)
{
string v = _selector(value);
return _stringPatternMatcher.IsMatch(v);
}
}
2 changes: 1 addition & 1 deletion src/MockHttp/Matchers/RequestUriMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class RequestUriMatcher : HttpRequestMatcher
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly string _formattedUri;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly PatternMatcher? _uriPatternMatcher;
private readonly WildcardPatternMatcher? _uriPatternMatcher;

/// <summary>
/// Initializes a new instance of the <see cref="RequestUriMatcher" /> class using specified <paramref name="uri" />.
Expand Down
59 changes: 59 additions & 0 deletions src/MockHttp/Matchers/UriMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System.Runtime.CompilerServices;
using MockHttp.Matchers.Patterns;
using MockHttp.Responses;

namespace MockHttp.Matchers;

/// <summary>
/// Matches a request by the URI.
/// </summary>
public class UriMatcher : HttpRequestMatcher
{
private readonly IPatternMatcher<Uri> _patternMatcher;
private readonly string _name;
private readonly string _patternDescription;

/// <summary>
/// Initializes a new instance of the <see cref="UriMatcher" /> class.
/// </summary>
/// <param name="patternMatcher">A matcher implementation that validates the URI.</param>
/// <param name="patternDescription">A description of the pattern.</param>
/// <param name="name">The name of this matcher.</param>
/// <exception cref="ArgumentNullException">Thrown when a required argument is <see langword="null" />.</exception>
internal UriMatcher
(
IPatternMatcher<Uri> patternMatcher,
string patternDescription,
[CallerMemberName] string? name = null
)
{
_patternMatcher = patternMatcher ?? throw new ArgumentNullException(nameof(patternMatcher));
_patternDescription = patternDescription ?? throw new ArgumentNullException(nameof(patternDescription));

name ??= GetType().Name;
if (name.EndsWith("Matcher", StringComparison.Ordinal))
{
name = name.Remove(name.Length - "Matcher".Length);
}

_name = name;
}

/// <inheritdoc />
public override bool IsMatch(MockHttpRequestContext requestContext)
{
if (requestContext is null)
{
throw new ArgumentNullException(nameof(requestContext));
}

Uri? uri = requestContext.Request.RequestUri;
return uri is not null && _patternMatcher.IsMatch(uri);
}

/// <inheritdoc />
public override string ToString()
{
return $"{_name}: '{_patternDescription}'";
}
}

0 comments on commit 7c211f8

Please sign in to comment.