@@ -923,6 +923,48 @@ public void BuildDfaTree_WithPolicies_AndBranches_BothPoliciesSkipped()
923923 Assert . Null ( a . PolicyEdges ) ;
924924 }
925925
926+ // Verifies that we sort the endpoints before calling into policies.
927+ //
928+ // The builder uses a different sort order when building the tree, vs when building the policy nodes. Policy
929+ // nodes should see an "absolute" order.
930+ [ Fact ]
931+ public void BuildDfaTree_WithPolicies_SortedAccordingToScore ( )
932+ {
933+ // Arrange
934+ //
935+ // These cases where chosen where the absolute order incontrolled explicitly by setting .Order, but
936+ // the precedence of segments is different, so these will be sorted into different orders when building
937+ // the tree.
938+ var policies = new MatcherPolicy [ ]
939+ {
940+ new TestMetadata1MatcherPolicy ( ) ,
941+ new TestMetadata2MatcherPolicy ( ) ,
942+ } ;
943+
944+ var builder = CreateDfaMatcherBuilder ( policies ) ;
945+
946+ ( ( TestMetadata1MatcherPolicy ) policies [ 0 ] ) . OnGetEdges = VerifyOrder ;
947+ ( ( TestMetadata2MatcherPolicy ) policies [ 1 ] ) . OnGetEdges = VerifyOrder ;
948+
949+ var endpoint1 = CreateEndpoint ( "/a/{**b}" , order : - 1 , metadata : new object [ ] { new TestMetadata1 ( 0 ) , new TestMetadata2 ( true ) , } ) ;
950+ builder . AddEndpoint ( endpoint1 ) ;
951+
952+ var endpoint2 = CreateEndpoint ( "/a/{b}/{**c}" , order : 0 , metadata : new object [ ] { new TestMetadata1 ( 1 ) , new TestMetadata2 ( true ) , } ) ;
953+ builder . AddEndpoint ( endpoint2 ) ;
954+
955+ var endpoint3 = CreateEndpoint ( "/a/b/{c}" , order : 1 , metadata : new object [ ] { new TestMetadata1 ( 1 ) , new TestMetadata2 ( false ) , } ) ;
956+ builder . AddEndpoint ( endpoint3 ) ;
957+
958+ // Act & Assert
959+ _ = builder . BuildDfaTree ( ) ;
960+
961+ void VerifyOrder ( IReadOnlyList < Endpoint > endpoints )
962+ {
963+ // The list should already be in sorted order, every time build is called.
964+ Assert . Equal ( endpoints , endpoints . OrderBy ( e => e , builder . Comparer ) ) ;
965+ }
966+ }
967+
926968 [ Fact ]
927969 public void BuildDfaTree_RequiredValues ( )
928970 {
@@ -1501,6 +1543,8 @@ private class TestMetadata1MatcherPolicy : MatcherPolicy, IEndpointComparerPolic
15011543
15021544 public IComparer < Endpoint > Comparer => EndpointMetadataComparer < TestMetadata1 > . Default ;
15031545
1546+ public Action < IReadOnlyList < Endpoint > > OnGetEdges { get ; set ; }
1547+
15041548 public bool AppliesToEndpoints ( IReadOnlyList < Endpoint > endpoints )
15051549 {
15061550 return endpoints . Any ( e => e . Metadata . GetMetadata < TestMetadata1 > ( ) != null ) ;
@@ -1513,6 +1557,7 @@ public PolicyJumpTable BuildJumpTable(int exitDestination, IReadOnlyList<PolicyJ
15131557
15141558 public IReadOnlyList < PolicyNodeEdge > GetEdges ( IReadOnlyList < Endpoint > endpoints )
15151559 {
1560+ OnGetEdges ? . Invoke ( endpoints ) ;
15161561 return endpoints
15171562 . GroupBy ( e => e . Metadata . GetMetadata < TestMetadata1 > ( ) . State )
15181563 . Select ( g => new PolicyNodeEdge ( g . Key , g . ToArray ( ) ) )
@@ -1540,6 +1585,9 @@ private class TestMetadata2MatcherPolicy : MatcherPolicy, IEndpointComparerPolic
15401585
15411586 public IComparer < Endpoint > Comparer => EndpointMetadataComparer < TestMetadata2 > . Default ;
15421587
1588+ public Action < IReadOnlyList < Endpoint > > OnGetEdges { get ; set ; }
1589+
1590+
15431591 public bool AppliesToEndpoints ( IReadOnlyList < Endpoint > endpoints )
15441592 {
15451593 return endpoints . Any ( e => e . Metadata . GetMetadata < TestMetadata2 > ( ) != null ) ;
@@ -1552,6 +1600,7 @@ public PolicyJumpTable BuildJumpTable(int exitDestination, IReadOnlyList<PolicyJ
15521600
15531601 public IReadOnlyList < PolicyNodeEdge > GetEdges ( IReadOnlyList < Endpoint > endpoints )
15541602 {
1603+ OnGetEdges ? . Invoke ( endpoints ) ;
15551604 return endpoints
15561605 . GroupBy ( e => e . Metadata . GetMetadata < TestMetadata2 > ( ) . State )
15571606 . Select ( g => new PolicyNodeEdge ( g . Key , g . ToArray ( ) ) )
0 commit comments