diff --git a/examples/WireMock.Net.ConsoleApplication/Program.cs b/examples/WireMock.Net.ConsoleApplication/Program.cs index 9ef66261..10944199 100644 --- a/examples/WireMock.Net.ConsoleApplication/Program.cs +++ b/examples/WireMock.Net.ConsoleApplication/Program.cs @@ -46,7 +46,7 @@ namespace WireMock.Net.ConsoleApplication .WithBody(@"{ ""result"": ""data posted with FUNC 201""}")); server - .Given(Request.Create().WithUrl("/data").UsingPost()) + .Given(Request.Create().WithUrl("/data", "/ax").UsingPost()) .RespondWith(Response.Create() .WithStatusCode(201) .WithHeader("Content-Type", "application/json") diff --git a/src/WireMock/Matchers/RegexMatcher.cs b/src/WireMock/Matchers/RegexMatcher.cs index 8c5eb707..ad634bc0 100644 --- a/src/WireMock/Matchers/RegexMatcher.cs +++ b/src/WireMock/Matchers/RegexMatcher.cs @@ -17,7 +17,7 @@ namespace WireMock.Matchers /// Initializes a new instance of the class. /// /// The pattern. - public RegexMatcher([NotNull] string pattern) + public RegexMatcher([NotNull, RegexPattern] string pattern) { Check.NotNull(pattern, nameof(pattern)); diff --git a/src/WireMock/Matchers/Request/CompositeMatcherType.cs b/src/WireMock/Matchers/Request/CompositeMatcherType.cs new file mode 100644 index 00000000..3c15640f --- /dev/null +++ b/src/WireMock/Matchers/Request/CompositeMatcherType.cs @@ -0,0 +1,18 @@ +namespace WireMock.Matchers.Request +{ + /// + /// CompositeMatcherType + /// + public enum CompositeMatcherType + { + /// + /// And + /// + And = 0, + + /// + /// Or + /// + Or = 1 + } +} \ No newline at end of file diff --git a/src/WireMock/Matchers/Request/RequestMessageBodyMatcher.cs b/src/WireMock/Matchers/Request/RequestMessageBodyMatcher.cs index 261be42d..c67e74ff 100644 --- a/src/WireMock/Matchers/Request/RequestMessageBodyMatcher.cs +++ b/src/WireMock/Matchers/Request/RequestMessageBodyMatcher.cs @@ -10,7 +10,12 @@ namespace WireMock.Matchers.Request public class RequestMessageBodyMatcher : IRequestMatcher { /// - /// The bodyRegex. + /// The body. + /// + private readonly string _body; + + /// + /// The body as byte[]. /// private readonly byte[] _bodyData; @@ -35,10 +40,10 @@ namespace WireMock.Matchers.Request /// /// The body Regex pattern. /// - public RequestMessageBodyMatcher([NotNull, RegexPattern] string body) + public RequestMessageBodyMatcher([NotNull] string body) { Check.NotNull(body, nameof(body)); - _matcher = new RegexMatcher(body); + _body = body; } /// @@ -101,6 +106,9 @@ namespace WireMock.Matchers.Request if (_matcher != null) return _matcher.IsMatch(requestMessage.Body); + if (_body != null) + return requestMessage.Body == _body; + if (_bodyData != null) return requestMessage.BodyAsBytes == _bodyData; diff --git a/src/WireMock/Matchers/Request/RequestMessageCompositeMatcher.cs b/src/WireMock/Matchers/Request/RequestMessageCompositeMatcher.cs index 25cffda2..6b40aaa2 100644 --- a/src/WireMock/Matchers/Request/RequestMessageCompositeMatcher.cs +++ b/src/WireMock/Matchers/Request/RequestMessageCompositeMatcher.cs @@ -1,13 +1,16 @@ using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; namespace WireMock.Matchers.Request { /// /// The composite request matcher. /// - public abstract class RequestMessageCompositeMatcher : IRequestMatcher + public class RequestMessageCompositeMatcher : IRequestMatcher { + private readonly CompositeMatcherType _type; + /// /// Gets the request matchers. /// @@ -17,14 +20,13 @@ namespace WireMock.Matchers.Request public IEnumerable RequestMatchers { get; } /// - /// Initializes a new instance of the class. - /// The constructor. + /// Initializes a new instance of the class. /// - /// - /// The request matchers. - /// - protected RequestMessageCompositeMatcher(IEnumerable requestMatchers) + /// The request matchers. + /// The CompositeMatcherType type (Defaults to 'And') + public RequestMessageCompositeMatcher([NotNull] IEnumerable requestMatchers, CompositeMatcherType type = CompositeMatcherType.And) { + _type = type; RequestMatchers = requestMatchers; } @@ -37,7 +39,9 @@ namespace WireMock.Matchers.Request /// public bool IsMatch(RequestMessage requestMessage) { - return RequestMatchers.All(spec => spec.IsMatch(requestMessage)); + return _type == CompositeMatcherType.And ? + RequestMatchers.All(spec => spec.IsMatch(requestMessage)) : + RequestMatchers.Any(spec => spec.IsMatch(requestMessage)); } } } \ No newline at end of file diff --git a/src/WireMock/Matchers/Request/RequestMessageHeaderMatcher.cs b/src/WireMock/Matchers/Request/RequestMessageHeaderMatcher.cs index de865397..35cdbbc7 100644 --- a/src/WireMock/Matchers/Request/RequestMessageHeaderMatcher.cs +++ b/src/WireMock/Matchers/Request/RequestMessageHeaderMatcher.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; using JetBrains.Annotations; using WireMock.Validation; @@ -17,9 +16,9 @@ namespace WireMock.Matchers.Request private readonly string _name; /// - /// The patternRegex. + /// The matcher. /// - private readonly Regex _patternRegex; + private readonly IMatcher _matcher; /// /// The header function @@ -29,17 +28,16 @@ namespace WireMock.Matchers.Request /// /// Initializes a new instance of the class. /// - /// - /// The name. - /// - /// - /// The pattern. - /// + /// The name. + /// The pattern. /// The ignoreCase. - public RequestMessageHeaderMatcher([NotNull] string name, [NotNull, RegexPattern] string pattern, bool ignoreCase = true) + public RequestMessageHeaderMatcher([NotNull] string name, [NotNull] string pattern, bool ignoreCase = true) { + Check.NotNull(name, nameof(name)); + Check.NotNull(pattern, nameof(pattern)); + _name = name; - _patternRegex = ignoreCase ? new Regex(pattern, RegexOptions.IgnoreCase) : new Regex(pattern); + _matcher = new WildcardMatcher(pattern, ignoreCase); } /// @@ -63,11 +61,11 @@ namespace WireMock.Matchers.Request /// public bool IsMatch(RequestMessage requestMessage) { - if (_patternRegex == null) + if (_headerFunc != null) return _headerFunc(requestMessage.Headers); string headerValue = requestMessage.Headers[_name]; - return _patternRegex.IsMatch(headerValue); + return _matcher.IsMatch(headerValue); } } } \ No newline at end of file diff --git a/src/WireMock/Matchers/Request/RequestMessagePathMatcher.cs b/src/WireMock/Matchers/Request/RequestMessagePathMatcher.cs index 10596848..42fbfbc0 100644 --- a/src/WireMock/Matchers/Request/RequestMessagePathMatcher.cs +++ b/src/WireMock/Matchers/Request/RequestMessagePathMatcher.cs @@ -1,5 +1,4 @@ using System; -using System.Text.RegularExpressions; using JetBrains.Annotations; using WireMock.Validation; @@ -11,32 +10,45 @@ namespace WireMock.Matchers.Request public class RequestMessagePathMatcher : IRequestMatcher { /// - /// The pathRegex. + /// The matcher. /// - private readonly Regex _pathRegex; + private readonly string _path; /// - /// The url function + /// The matcher. + /// + private readonly IMatcher _matcher; + + /// + /// The path function /// private readonly Func _pathFunc; /// /// Initializes a new instance of the class. /// - /// - /// The path Regex pattern. - /// - public RequestMessagePathMatcher([NotNull, RegexPattern] string path) + /// The path. + public RequestMessagePathMatcher([NotNull] string path) { Check.NotNull(path, nameof(path)); - _pathRegex = new Regex(path); + _path = path; + } + + /// + /// Initializes a new instance of the class. + /// + /// The matcher. + public RequestMessagePathMatcher([NotNull] IMatcher matcher) + { + Check.NotNull(matcher, nameof(matcher)); + _matcher = matcher; } /// /// Initializes a new instance of the class. /// /// - /// The url func. + /// The path func. /// public RequestMessagePathMatcher([NotNull] Func func) { @@ -53,7 +65,16 @@ namespace WireMock.Matchers.Request /// public bool IsMatch(RequestMessage requestMessage) { - return _pathRegex?.IsMatch(requestMessage.Path) ?? _pathFunc(requestMessage.Path); + if (_path != null) + return string.CompareOrdinal(_path, requestMessage.Path) == 0; + + if (_matcher != null) + return _matcher.IsMatch(requestMessage.Path); + + if (_pathFunc != null) + return _pathFunc(requestMessage.Path); + + return false; } } } \ No newline at end of file diff --git a/src/WireMock/Matchers/Request/RequestMessageUrlMatcher.cs b/src/WireMock/Matchers/Request/RequestMessageUrlMatcher.cs index 88fb315a..cc0c26c9 100644 --- a/src/WireMock/Matchers/Request/RequestMessageUrlMatcher.cs +++ b/src/WireMock/Matchers/Request/RequestMessageUrlMatcher.cs @@ -1,5 +1,4 @@ using System; -using System.Text.RegularExpressions; using JetBrains.Annotations; using WireMock.Validation; @@ -11,9 +10,9 @@ namespace WireMock.Matchers.Request public class RequestMessageUrlMatcher : IRequestMatcher { /// - /// The urlRegex. + /// The matcher. /// - private readonly Regex _urlRegex; + private readonly IMatcher _matcher; /// /// The url function @@ -23,13 +22,20 @@ namespace WireMock.Matchers.Request /// /// Initializes a new instance of the class. /// - /// - /// The url Regex pattern. - /// - public RequestMessageUrlMatcher([NotNull, RegexPattern] string url) + /// The url. + public RequestMessageUrlMatcher([NotNull] string url) : this(new WildcardMatcher(url)) { - Check.NotNull(url, nameof(url)); - _urlRegex = new Regex(url); + _matcher = new WildcardMatcher(url); + } + + /// + /// Initializes a new instance of the class. + /// + /// The matcher. + public RequestMessageUrlMatcher([NotNull] IMatcher matcher) + { + Check.NotNull(matcher, nameof(matcher)); + _matcher = matcher; } /// @@ -38,7 +44,7 @@ namespace WireMock.Matchers.Request /// /// The url func. /// - public RequestMessageUrlMatcher(Func func) + public RequestMessageUrlMatcher([NotNull] Func func) { Check.NotNull(func, nameof(func)); _urlFunc = func; @@ -53,7 +59,13 @@ namespace WireMock.Matchers.Request /// public bool IsMatch(RequestMessage requestMessage) { - return _urlRegex?.IsMatch(requestMessage.Url) ?? _urlFunc(requestMessage.Url); + if (_matcher != null) + return _matcher.IsMatch(requestMessage.Path); + + if (_urlFunc != null) + return _urlFunc(requestMessage.Url); + + return false; } } } \ No newline at end of file diff --git a/src/WireMock/Matchers/WildcardMatcher.cs b/src/WireMock/Matchers/WildcardMatcher.cs new file mode 100644 index 00000000..8e005dd1 --- /dev/null +++ b/src/WireMock/Matchers/WildcardMatcher.cs @@ -0,0 +1,102 @@ +using JetBrains.Annotations; +using WireMock.Validation; + +namespace WireMock.Matchers +{ + /// + /// WildcardMatcher + /// + /// + public class WildcardMatcher : IMatcher + { + private readonly string _pattern; + private readonly bool _ignoreCase; + + /// + /// Initializes a new instance of the class. + /// + /// The pattern. + /// IgnoreCase + public WildcardMatcher([NotNull] string pattern, bool ignoreCase = false) + { + Check.NotNull(pattern, nameof(pattern)); + + _pattern = pattern; + _ignoreCase = ignoreCase; + } + + /// + /// Determines whether the specified input is match. + /// + /// The input. + /// + /// true if the specified input is match; otherwise, false. + /// + public bool IsMatch(string input) + { + return MatchWildcardString(_pattern, input); + } + + /// + /// Copy/paste from http://www.codeproject.com/Tips/57304/Use-wildcard-characters-and-to-compare-strings + /// + private bool MatchWildcardString(string pattern, string input) + { + if (input != null && _ignoreCase) + input = input.ToLower(); + + if (pattern != null && _ignoreCase) + pattern = pattern.ToLower(); + + if (string.CompareOrdinal(pattern, input) == 0) + { + return true; + } + + if (string.IsNullOrEmpty(input)) + { + return string.IsNullOrEmpty(pattern.Trim('*')); + } + + if (pattern.Length == 0) + { + return false; + } + + if (pattern[0] == '?') + { + return MatchWildcardString(pattern.Substring(1), input.Substring(1)); + } + + if (pattern[pattern.Length - 1] == '?') + { + return MatchWildcardString(pattern.Substring(0, pattern.Length - 1), input.Substring(0, input.Length - 1)); + } + + if (pattern[0] == '*') + { + if (MatchWildcardString(pattern.Substring(1), input)) + { + return true; + } + return MatchWildcardString(pattern, input.Substring(1)); + } + + if (pattern[pattern.Length - 1] == '*') + { + if (MatchWildcardString(pattern.Substring(0, pattern.Length - 1), input)) + { + return true; + } + return MatchWildcardString(pattern, input.Substring(0, input.Length - 1)); + } + + if (pattern[0] == input[0]) + { + return MatchWildcardString(pattern.Substring(1), input.Substring(1)); + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/WireMock/RequestBuilders/IHeadersRequestBuilder.cs b/src/WireMock/RequestBuilders/IHeadersRequestBuilder.cs index aa89763f..1d3bebc6 100644 --- a/src/WireMock/RequestBuilders/IHeadersRequestBuilder.cs +++ b/src/WireMock/RequestBuilders/IHeadersRequestBuilder.cs @@ -34,6 +34,6 @@ namespace WireMock.RequestBuilders /// /// The . /// - IHeadersRequestBuilder WithHeader([NotNull] Func, bool> func); + IHeadersRequestBuilder WithHeader([NotNull] params Func, bool>[] func); } } \ No newline at end of file diff --git a/src/WireMock/RequestBuilders/IUrlAndPathRequestBuilder.cs b/src/WireMock/RequestBuilders/IUrlAndPathRequestBuilder.cs index 532136f8..bc500fb5 100644 --- a/src/WireMock/RequestBuilders/IUrlAndPathRequestBuilder.cs +++ b/src/WireMock/RequestBuilders/IUrlAndPathRequestBuilder.cs @@ -1,5 +1,6 @@ using System; using JetBrains.Annotations; +using WireMock.Matchers; namespace WireMock.RequestBuilders { @@ -8,32 +9,46 @@ namespace WireMock.RequestBuilders /// public interface IUrlAndPathRequestBuilder : IVerbRequestBuilder { + /// + /// The with url. + /// + /// The matcher. + /// The . + IUrlAndPathRequestBuilder WithUrl([NotNull] IMatcher matcher); + /// /// The with url. /// /// The url. /// The . - IUrlAndPathRequestBuilder WithUrl([NotNull] string url); + IUrlAndPathRequestBuilder WithUrl([NotNull] params string[] url); /// /// The with url. /// /// The url func. /// The . - IUrlAndPathRequestBuilder WithUrl([NotNull] Func func); + IUrlAndPathRequestBuilder WithUrl([NotNull] params Func[] func); + + /// + /// The with path. + /// + /// The matcher. + /// The . + IUrlAndPathRequestBuilder WithPath([NotNull] IMatcher matcher); /// /// The with path. /// /// The path. /// The . - IUrlAndPathRequestBuilder WithPath([NotNull] string path); + IUrlAndPathRequestBuilder WithPath([NotNull] params string[] path); /// /// The with path. /// /// The path func. /// The . - IUrlAndPathRequestBuilder WithPath([NotNull] Func func); + IUrlAndPathRequestBuilder WithPath([NotNull] params Func[] func); } } \ No newline at end of file diff --git a/src/WireMock/RequestBuilders/Request.cs b/src/WireMock/RequestBuilders/Request.cs index 4018e07f..85f21bac 100644 --- a/src/WireMock/RequestBuilders/Request.cs +++ b/src/WireMock/RequestBuilders/Request.cs @@ -34,44 +34,76 @@ namespace WireMock.RequestBuilders /// /// The with url. /// - /// The url. + /// The matcher. /// The . - public IUrlAndPathRequestBuilder WithUrl(string url) + public IUrlAndPathRequestBuilder WithUrl(IMatcher matcher) { - _requestMatchers.Add(new RequestMessageUrlMatcher(url)); + _requestMatchers.Add(new RequestMessageUrlMatcher(matcher)); + return this; } /// /// The with url. /// - /// The url func. + /// The urls. /// The . - public IUrlAndPathRequestBuilder WithUrl(Func func) + public IUrlAndPathRequestBuilder WithUrl(params string[] urls) { - _requestMatchers.Add(new RequestMessageUrlMatcher(func)); + var or = new RequestMessageCompositeMatcher(urls.Select(url => new RequestMessageUrlMatcher(url)), CompositeMatcherType.Or); + _requestMatchers.Add(or); + + return this; + } + + /// + /// The with url. + /// + /// The url func. + /// The . + public IUrlAndPathRequestBuilder WithUrl(params Func[] funcs) + { + var or = new RequestMessageCompositeMatcher(funcs.Select(func => new RequestMessageUrlMatcher(func)), CompositeMatcherType.Or); + _requestMatchers.Add(or); + + return this; + } + + /// + /// The with url. + /// + /// The matcher. + /// The . + public IUrlAndPathRequestBuilder WithPath(IMatcher matcher) + { + _requestMatchers.Add(new RequestMessagePathMatcher(matcher)); + return this; } /// /// The with path. /// - /// The path. + /// The path. /// The . - public IUrlAndPathRequestBuilder WithPath(string path) + public IUrlAndPathRequestBuilder WithPath(params string[] paths) { - _requestMatchers.Add(new RequestMessagePathMatcher(path)); + var or = new RequestMessageCompositeMatcher(paths.Select(path => new RequestMessageUrlMatcher(path)), CompositeMatcherType.Or); + _requestMatchers.Add(or); + return this; } /// /// The with path. /// - /// The path func. + /// The path func. /// The . - public IUrlAndPathRequestBuilder WithPath(Func func) + public IUrlAndPathRequestBuilder WithPath(params Func[] funcs) { - _requestMatchers.Add(new RequestMessagePathMatcher(func)); + var or = new RequestMessageCompositeMatcher(funcs.Select(func => new RequestMessageUrlMatcher(func)), CompositeMatcherType.Or); + _requestMatchers.Add(or); + return this; } @@ -295,15 +327,15 @@ namespace WireMock.RequestBuilders /// /// The with header. /// - /// - /// The func. - /// + /// The func. /// /// The . /// - public IHeadersRequestBuilder WithHeader(Func, bool> func) + public IHeadersRequestBuilder WithHeader(params Func, bool>[] funcs) { - _requestMatchers.Add(new RequestMessageHeaderMatcher(func)); + var or = new RequestMessageCompositeMatcher(funcs.Select(func => new RequestMessageHeaderMatcher(func)), CompositeMatcherType.Or); + _requestMatchers.Add(or); + return this; } } diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs index 8d2559ce..c3b720f2 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs @@ -6,6 +6,7 @@ using System.Net.Http; using System.Threading.Tasks; using NFluent; using NUnit.Framework; +using WireMock.Matchers; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using WireMock.Server; @@ -113,7 +114,7 @@ namespace WireMock.Net.Tests await new HttpClient().GetAsync("http://localhost:" + _server.Port + "/bar"); // then - var result = _server.SearchLogsFor(Request.Create().WithUrl("/b.*")).ToList(); + var result = _server.SearchLogsFor(Request.Create().WithUrl(new RegexMatcher("^/b.*"))).ToList(); Check.That(result).HasSize(1); var requestLogged = result.First(); @@ -195,7 +196,7 @@ namespace WireMock.Net.Tests .WithUrl("/*")) .RespondWith(Response.Create() .WithBody(@"{ msg: ""Hello world!""}") - .WithDelay(TimeSpan.FromMilliseconds(2000))); + .WithDelay(TimeSpan.FromMilliseconds(200))); // when var watch = new Stopwatch(); @@ -204,7 +205,7 @@ namespace WireMock.Net.Tests watch.Stop(); // then - Check.That(watch.ElapsedMilliseconds).IsGreaterThan(2000); + Check.That(watch.ElapsedMilliseconds).IsGreaterThan(200); } [Test] @@ -212,12 +213,10 @@ namespace WireMock.Net.Tests { // given _server = FluentMockServer.Start(); - _server.AddRequestProcessingDelay(TimeSpan.FromMilliseconds(2000)); + _server.AddRequestProcessingDelay(TimeSpan.FromMilliseconds(200)); _server - .Given(Request.Create() - .WithUrl("/*")) - .RespondWith(Response.Create() - .WithBody(@"{ msg: ""Hello world!""}")); + .Given(Request.Create().WithUrl("/*")) + .RespondWith(Response.Create().WithBody(@"{ msg: ""Hello world!""}")); // when var watch = new Stopwatch(); @@ -226,7 +225,7 @@ namespace WireMock.Net.Tests watch.Stop(); // then - Check.That(watch.ElapsedMilliseconds).IsGreaterThan(2000); + Check.That(watch.ElapsedMilliseconds).IsGreaterThan(200); } [TearDown] diff --git a/test/WireMock.Net.Tests/RequestTests.cs b/test/WireMock.Net.Tests/RequestTests.cs index 3eee15a7..6b4ac7f2 100644 --- a/test/WireMock.Net.Tests/RequestTests.cs +++ b/test/WireMock.Net.Tests/RequestTests.cs @@ -26,11 +26,25 @@ namespace WireMock.Net.Tests Check.That(spec.IsMatch(request)).IsTrue(); } + [Test] + public void Should_specify_requests_matching_given_urls() + { + var requestBuilder = Request.Create().WithUrl("/x1", "/x2"); + + string bodyAsString = "whatever"; + byte[] body = Encoding.UTF8.GetBytes(bodyAsString); + var request1 = new RequestMessage(new Uri("http://localhost/x1"), "blabla", body, bodyAsString); + var request2 = new RequestMessage(new Uri("http://localhost/x2"), "blabla", body, bodyAsString); + + Check.That(requestBuilder.IsMatch(request1)).IsTrue(); + Check.That(requestBuilder.IsMatch(request2)).IsTrue(); + } + [Test] public void Should_specify_requests_matching_given_url_prefix() { // given - var spec = Request.Create().WithUrl("/foo*"); + var spec = Request.Create().WithUrl(new RegexMatcher("^/foo")); // when string bodyAsString = "whatever"; @@ -230,7 +244,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "whatever"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, new Dictionary { { "X-toto", "TaTaTa" } }); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, new Dictionary { { "X-toto", "TaTa" } }); // then Check.That(spec.IsMatch(request)).IsTrue(); @@ -252,10 +266,10 @@ namespace WireMock.Net.Tests } [Test] - public void Should_specify_requests_matching_given_body_as_regex() + public void Should_specify_requests_matching_given_body_as_wildcard() { // given - var spec = Request.Create().WithUrl("/foo").UsingAnyVerb().WithBody("H.*o"); + var spec = Request.Create().WithUrl("/foo").UsingAnyVerb().WithBody(new WildcardMatcher("H*o*")); // when string bodyAsString = "Hello world!"; diff --git a/test/WireMock.Net.Tests/WildcardMatcherTest.cs b/test/WireMock.Net.Tests/WildcardMatcherTest.cs new file mode 100644 index 00000000..2ecafd31 --- /dev/null +++ b/test/WireMock.Net.Tests/WildcardMatcherTest.cs @@ -0,0 +1,59 @@ +using NUnit.Framework; +using WireMock.Matchers; + +namespace WireMock.Net.Tests +{ + [TestFixture] + public class WildcardMatcherTest + { + [Test] + public void WildcardMatcher_patterns_positive() + { + var tests = new[] + { + new { p = "*", i = "" }, + new { p = "?", i = " " }, + new { p = "*", i = "a" }, + new { p = "*", i = "ab" }, + new { p = "?", i = "a" }, + new { p = "*?", i = "abc" }, + new { p = "?*", i = "abc" }, + new { p = "abc", i = "abc" }, + new { p = "abc*", i = "abc" }, + new { p = "abc*", i = "abcd" }, + new { p = "*abc*", i = "abc" }, + new { p = "*a*bc*", i = "abc" }, + new { p = "*a*b?", i = "aXXXbc" } + }; + foreach (var test in tests) + { + var matcher = new WildcardMatcher(test.p); + Assert.IsTrue(matcher.IsMatch(test.i), "p = " + test.p + ", i = " + test.i); + } + } + + [Test] + public void WildcardMatcher_patterns_negative() + { + var tests = new[] + { + new { p = "*a", i = ""}, + new { p = "a*", i = ""}, + new { p = "?", i = ""}, + new { p = "*b*", i = "a"}, + new { p = "b*a", i = "ab"}, + new { p = "??", i = "a"}, + new { p = "*?", i = ""}, + new { p = "??*", i = "a"}, + new { p = "*abc", i = "abX"}, + new { p = "*abc*", i = "Xbc"}, + new { p = "*a*bc*", i = "ac"} + }; + foreach (var test in tests) + { + var matcher = new WildcardMatcher(test.p); + Assert.IsFalse(matcher.IsMatch(test.i), "p = " + test.p + ", i = " + test.i); + } + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj index ffc630e3..4d6ea378 100644 --- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj +++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj @@ -67,6 +67,7 @@ +