public async Task SelectAsync_MultipleValidCandidatesInGroup_ReportsAmbiguity() { // Arrange var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), }; var scores = new int[] { 0, 1, 1 }; var candidateSet = CreateCandidateSet(endpoints, scores); candidateSet[0].IsValidCandidate = false; candidateSet[1].IsValidCandidate = true; candidateSet[2].IsValidCandidate = true; var(httpContext, feature) = CreateContext(); var selector = CreateSelector(); // Act var ex = await Assert.ThrowsAsync <AmbiguousMatchException>(() => selector.SelectAsync(httpContext, feature, candidateSet)); // Assert Assert.Equal( @"The request matched multiple endpoints. Matches: test: /test2 test: /test3", ex.Message); Assert.Null(feature.Endpoint); }
public InnerMatcher(string[] segments, MatcherEndpoint endpoint) { _segments = segments; Endpoint = endpoint; _candidates = new Candidate[] { new Candidate(endpoint), }; }
public async Task SelectAsync_RunsEndpointSelectorPolicies() { // Arrange var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), }; var scores = new int[] { 0, 0, 1 }; var candidateSet = CreateCandidateSet(endpoints, scores); var policy = new Mock <MatcherPolicy>(); policy .As <IEndpointSelectorPolicy>() .Setup(p => p.Apply(It.IsAny <HttpContext>(), It.IsAny <CandidateSet>())) .Callback <HttpContext, CandidateSet>((c, cs) => { cs[1].IsValidCandidate = false; }); candidateSet[0].IsValidCandidate = false; candidateSet[1].IsValidCandidate = true; candidateSet[2].IsValidCandidate = true; var(httpContext, feature) = CreateContext(); var selector = CreateSelector(policy.Object); // Act await selector.SelectAsync(httpContext, feature, candidateSet); // Assert Assert.Same(endpoints[2], feature.Endpoint); }
public async Task SelectAsync_ManyGroupsLastCandidate_ChoosesCandidate() { // Arrange var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test1"), CreateEndpoint("/test2"), CreateEndpoint("/test3"), CreateEndpoint("/test4"), CreateEndpoint("/test5"), }; var scores = new int[] { 0, 1, 2, 3, 4 }; var candidateSet = CreateCandidateSet(endpoints, scores); candidateSet[0].IsValidCandidate = false; candidateSet[1].IsValidCandidate = false; candidateSet[2].IsValidCandidate = false; candidateSet[3].IsValidCandidate = false; candidateSet[4].IsValidCandidate = true; var(httpContext, feature) = CreateContext(); var selector = CreateSelector(); // Act await selector.SelectAsync(httpContext, feature, candidateSet); // Assert Assert.Same(endpoints[4], feature.Endpoint); }
public void Create_CreatesCandidateSet(int count) { // Arrange var endpoints = new MatcherEndpoint[count]; for (var i = 0; i < endpoints.Length; i++) { endpoints[i] = CreateEndpoint($"/{i}"); } var builder = CreateDfaMatcherBuilder(); var candidates = builder.CreateCandidates(endpoints); // Act var candidateSet = new CandidateSet(candidates); // Assert for (var i = 0; i < candidateSet.Count; i++) { ref var state = ref candidateSet[i]; Assert.True(state.IsValidCandidate); Assert.Same(endpoints[i], state.Endpoint); Assert.Equal(candidates[i].Score, state.Score); Assert.Null(state.Values); }
public override Endpoint Build() { var matcherEndpoint = new MatcherEndpoint( Invoker, RoutePattern, Order, new EndpointMetadataCollection(Metadata), DisplayName); return(matcherEndpoint); }
public void Setup() { Endpoints = new MatcherEndpoint[1]; Endpoints[0] = CreateEndpoint("/plaintext"); Requests = new HttpContext[1]; Requests[0] = new DefaultHttpContext(); Requests[0].RequestServices = CreateServices(); Requests[0].Request.Path = "/plaintext"; _baseline = (TrivialMatcher)SetupMatcher(new TrivialMatcherBuilder()); _dfa = (DfaMatcher)SetupMatcher(CreateDfaMatcherBuilder()); }
private void SetupEndpoints() { Endpoints = new MatcherEndpoint[10]; Endpoints[0] = CreateEndpoint("/another-really-cool-entry"); Endpoints[1] = CreateEndpoint("/Some-Entry"); Endpoints[2] = CreateEndpoint("/a/path/with/more/segments"); Endpoints[3] = CreateEndpoint("/random/name"); Endpoints[4] = CreateEndpoint("/random/name2"); Endpoints[5] = CreateEndpoint("/random/name3"); Endpoints[6] = CreateEndpoint("/random/name4"); Endpoints[7] = CreateEndpoint("/plaintext1"); Endpoints[8] = CreateEndpoint("/plaintext2"); Endpoints[9] = CreateEndpoint("/plaintext"); }
public async Task SelectAsync_NoCandidates_DoesNothing() { // Arrange var endpoints = new MatcherEndpoint[] { }; var scores = new int[] { }; var candidateSet = CreateCandidateSet(endpoints, scores); var(httpContext, feature) = CreateContext(); var selector = CreateSelector(); // Act await selector.SelectAsync(httpContext, feature, candidateSet); // Assert Assert.Null(feature.Endpoint); }
public override Task SelectAsync( HttpContext httpContext, IEndpointFeature feature, CandidateSet candidateSet) { for (var i = 0; i < _selectorPolicies.Length; i++) { _selectorPolicies[i].Apply(httpContext, candidateSet); } MatcherEndpoint endpoint = null; RouteValueDictionary values = null; int?foundScore = null; for (var i = 0; i < candidateSet.Count; i++) { ref var state = ref candidateSet[i]; var isValid = state.IsValidCandidate; if (isValid && foundScore == null) { // This is the first match we've seen - speculatively assign it. endpoint = state.Endpoint; values = state.Values; foundScore = state.Score; } else if (isValid && foundScore < state.Score) { // This candidate is lower priority than the one we've seen // so far, we can stop. // // Don't worry about the 'null < state.Score' case, it returns false. break; } else if (isValid && foundScore == state.Score) { // This is the second match we've found of the same score, so there // must be an ambiguity. // // Don't worry about the 'null == state.Score' case, it returns false. ReportAmbiguity(candidateSet); // Unreachable, ReportAmbiguity always throws. throw new NotSupportedException(); } }
public void Setup() { Endpoints = new MatcherEndpoint[1]; Endpoints[0] = CreateEndpoint("/plaintext"); Requests = new HttpContext[1]; Requests[0] = new DefaultHttpContext(); Requests[0].RequestServices = CreateServices(); Requests[0].Request.Path = "/plaintext"; _baseline = (BarebonesMatcher)SetupMatcher(new BarebonesMatcherBuilder()); _dfa = SetupMatcher(CreateDfaMatcherBuilder()); _route = SetupMatcher(new RouteMatcherBuilder()); _tree = SetupMatcher(new TreeRouterMatcherBuilder()); _feature = new EndpointFeature(); }
public async Task SelectAsync_NoValidCandidates_DoesNothing() { // Arrange var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test"), }; var scores = new int[] { 0, }; var candidateSet = CreateCandidateSet(endpoints, scores); candidateSet[0].Values = new RouteValueDictionary(); candidateSet[0].IsValidCandidate = false; var(httpContext, feature) = CreateContext(); var selector = CreateSelector(); // Act await selector.SelectAsync(httpContext, feature, candidateSet); // Assert Assert.Null(feature.Endpoint); Assert.Null(feature.Values); }
public async Task SelectAsync_SingleCandidate_ChoosesCandidate() { // Arrange var endpoints = new MatcherEndpoint[] { CreateEndpoint("/test"), }; var scores = new int[] { 0, }; var candidateSet = CreateCandidateSet(endpoints, scores); candidateSet[0].Values = new RouteValueDictionary(); candidateSet[0].IsValidCandidate = true; var(httpContext, feature) = CreateContext(); var selector = CreateSelector(); // Act await selector.SelectAsync(httpContext, feature, candidateSet); // Assert Assert.Same(endpoints[0], feature.Endpoint); Assert.Same(endpoints[0].Invoker, feature.Invoker); Assert.NotNull(feature.Values); }
public void Matcher_Reinitializes_WhenDataSourceChanges() { // Arrange var dataSource = new DynamicEndpointDataSource(); var matcher = new DataSourceDependentMatcher(dataSource, TestMatcherBuilder.Create); var endpoint = new MatcherEndpoint( MatcherEndpoint.EmptyInvoker, RoutePatternFactory.Parse("a/b/c"), 0, EndpointMetadataCollection.Empty, "test"); // Act dataSource.AddEndpoint(endpoint); // Assert var inner = Assert.IsType <TestMatcher>(matcher.CurrentMatcher); Assert.Collection( inner.Endpoints, e => Assert.Same(endpoint, e)); }
public override void AddEndpoint(MatcherEndpoint endpoint) { _endpoints.Add(endpoint); }
public TrivialMatcher(MatcherEndpoint endpoint) { _endpoint = endpoint; _candidates = new Candidate[] { new Candidate(endpoint), }; }