forked from tomkuijsten/restup
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request tomkuijsten#93 from Jark/feature-add-validation-fo…
…r-unique-urls Added validation for unique URIs
- Loading branch information
Showing
10 changed files
with
262 additions
and
13 deletions.
There are no files selected for viewing
105 changes: 105 additions & 0 deletions
105
src/WebServer.UnitTests/Rest/RestRouteHandlerTests.UriFormatValidation.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
using Restup.HttpMessage.Models.Schemas; | ||
using Restup.Webserver.Attributes; | ||
using Restup.Webserver.Models.Contracts; | ||
using Restup.Webserver.Models.Schemas; | ||
using Restup.Webserver.Rest; | ||
using Restup.Webserver.UnitTests.TestHelpers; | ||
using System; | ||
using System.Threading.Tasks; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
|
||
namespace Restup.Webserver.UnitTests.Rest | ||
{ | ||
[TestClass] | ||
public class RestRouteHandlerTests_UriFormatValidation | ||
{ | ||
private RestRouteHandler restHandler; | ||
|
||
[TestInitialize()] | ||
public void Initialize() | ||
{ | ||
restHandler = new RestRouteHandler(); | ||
} | ||
|
||
private class TwoUriFormatWithSameNameAndMethodController | ||
{ | ||
[UriFormat("/Get")] | ||
public IGetResponse Get() => new GetResponse(GetResponse.ResponseStatus.OK); | ||
|
||
[UriFormat("/Get")] | ||
public IGetResponse Get2() => new GetResponse(GetResponse.ResponseStatus.OK); | ||
} | ||
|
||
[TestMethod] | ||
public async Task RegisterController_OneControllerWithTwoMethodsWithSameNameAndMethod_ThrowsException() | ||
{ | ||
AssertRegisterControllerThrows<TwoUriFormatWithSameNameAndMethodController>(); | ||
await AssertHandleRequest("/Get", HttpMethod.GET, HttpResponseStatus.BadRequest); | ||
} | ||
|
||
private class OnePostMethodController | ||
{ | ||
[UriFormat("/Post")] | ||
public IPostResponse Post() => new PostResponse(PostResponse.ResponseStatus.Created); | ||
} | ||
|
||
[TestMethod] | ||
public async Task RegisterController_OneControllerRegisteredTwice_ThrowsException() | ||
{ | ||
restHandler.RegisterController<OnePostMethodController>(); | ||
await AssertHandleRequest("/Post", HttpMethod.POST, HttpResponseStatus.Created); | ||
AssertRegisterControllerThrows<OnePostMethodController>(); | ||
await AssertHandleRequest("/Post", HttpMethod.POST, HttpResponseStatus.Created); | ||
} | ||
|
||
private class OnePostMethodWithParameterizedConstructorController | ||
{ | ||
[UriFormat("/Post")] | ||
public IPostResponse Post() => new PostResponse(PostResponse.ResponseStatus.Created); | ||
|
||
public OnePostMethodWithParameterizedConstructorController(string param) | ||
{ | ||
} | ||
} | ||
|
||
[TestMethod] | ||
public async Task RegisterController_OneParameterizedControllerRegisteredTwice_ThrowsException() | ||
{ | ||
restHandler.RegisterController<OnePostMethodWithParameterizedConstructorController>("param"); | ||
await AssertHandleRequest("/Post", HttpMethod.POST, HttpResponseStatus.Created); | ||
AssertRegisterControllerThrows<OnePostMethodWithParameterizedConstructorController>("param"); | ||
await AssertHandleRequest("/Post", HttpMethod.POST, HttpResponseStatus.Created); | ||
} | ||
|
||
[TestMethod] | ||
public async Task RegisterController_TwoDifferentControllersWithSimilarlyNamedMethodsAndVerbs_ThrowsException() | ||
{ | ||
restHandler.RegisterController<OnePostMethodController>(); | ||
await AssertHandleRequest("/Post", HttpMethod.POST, HttpResponseStatus.Created); | ||
AssertRegisterControllerThrows<OnePostMethodWithParameterizedConstructorController>("param"); | ||
await AssertHandleRequest("/Post", HttpMethod.POST, HttpResponseStatus.Created); | ||
} | ||
|
||
private void AssertRegisterControllerThrows<T>(params string[] args) where T : class | ||
{ | ||
Assert.ThrowsException<Exception>(() => | ||
restHandler.RegisterController<T>(args) | ||
); | ||
} | ||
|
||
private void AssertRegisterControllerThrows<T>() where T : class | ||
{ | ||
Assert.ThrowsException<Exception>(() => | ||
restHandler.RegisterController<T>() | ||
); | ||
} | ||
|
||
private async Task AssertHandleRequest(string uri, HttpMethod method, HttpResponseStatus expectedStatus) | ||
{ | ||
var request = Utils.CreateHttpRequest(uri: new Uri(uri, UriKind.Relative), method: method); | ||
var result = await restHandler.HandleRequest(request); | ||
|
||
Assert.AreEqual(expectedStatus, result.ResponseStatus); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Restup.WebServer | ||
{ | ||
internal class Constants | ||
{ | ||
public const int HashCodePrime = 397; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
|
||
namespace Restup.Webserver.Rest | ||
{ | ||
internal class RestControllerMethodInfoValidator | ||
{ | ||
private readonly UniqueMatchUriAndVerbRestControllerMethodInfoComparer _uniqueMatchUriAndVerbComparer; | ||
|
||
public RestControllerMethodInfoValidator() | ||
{ | ||
_uniqueMatchUriAndVerbComparer = new UniqueMatchUriAndVerbRestControllerMethodInfoComparer(); | ||
} | ||
|
||
public void Validate<T>(ImmutableArray<RestControllerMethodInfo> existingRestMethodCollection, | ||
IList<RestControllerMethodInfo> restControllerMethodInfos) | ||
{ | ||
foreach (var restControllerMethodInfo in restControllerMethodInfos) | ||
{ | ||
// if the existing rest method collection already contains the rest controller method to be added | ||
// or if the rest controller method infos to be added contains more than one rest method info with the same path | ||
// then throw an exception | ||
if (existingRestMethodCollection.Contains(restControllerMethodInfo, _uniqueMatchUriAndVerbComparer) | ||
|| restControllerMethodInfos.Count(x => _uniqueMatchUriAndVerbComparer.Equals(x, restControllerMethodInfo)) > 1) | ||
{ | ||
throw new Exception($"Can't register route for controller {typeof(T)}, UriFormat with {restControllerMethodInfo.MatchUri} and {restControllerMethodInfo.Verb} since this would cause multiple routes to be registered on the same name."); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Restup.WebServer; | ||
|
||
namespace Restup.Webserver.Rest | ||
{ | ||
internal class UniqueMatchUriAndVerbRestControllerMethodInfoComparer : IEqualityComparer<RestControllerMethodInfo> | ||
{ | ||
private readonly PathPartsAndParametersParsedUriComparer _parsedUriComparer; | ||
|
||
public UniqueMatchUriAndVerbRestControllerMethodInfoComparer() | ||
{ | ||
_parsedUriComparer = new PathPartsAndParametersParsedUriComparer(); | ||
} | ||
|
||
public bool Equals(RestControllerMethodInfo x, RestControllerMethodInfo y) | ||
{ | ||
return _parsedUriComparer.Equals(x.MatchUri, y.MatchUri) && x.Verb == y.Verb; | ||
} | ||
|
||
public int GetHashCode(RestControllerMethodInfo obj) | ||
{ | ||
unchecked | ||
{ | ||
return ((obj.MatchUri?.GetHashCode() ?? 0) * Constants.HashCodePrime) ^ (int)obj.Verb; | ||
} | ||
} | ||
|
||
internal class PathPartsAndParametersParsedUriComparer : IEqualityComparer<ParsedUri> | ||
{ | ||
public bool Equals(ParsedUri x, ParsedUri y) | ||
{ | ||
return x.PathParts.SequenceEqual(y.PathParts) && x.Parameters.SequenceEqual(y.Parameters); | ||
} | ||
|
||
public int GetHashCode(ParsedUri obj) | ||
{ | ||
unchecked | ||
{ | ||
return ((obj.Parameters?.GetHashCode() ?? 0) * Constants.HashCodePrime) ^ (obj.PathParts?.GetHashCode() ?? 0); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.