diff options
Diffstat (limited to 'src/Http/Routing/test/UnitTests/Template/TemplateParserTests.cs')
-rw-r--r-- | src/Http/Routing/test/UnitTests/Template/TemplateParserTests.cs | 1623 |
1 files changed, 811 insertions, 812 deletions
diff --git a/src/Http/Routing/test/UnitTests/Template/TemplateParserTests.cs b/src/Http/Routing/test/UnitTests/Template/TemplateParserTests.cs index 1fa3c16501..b10f084e0a 100644 --- a/src/Http/Routing/test/UnitTests/Template/TemplateParserTests.cs +++ b/src/Http/Routing/test/UnitTests/Template/TemplateParserTests.cs @@ -7,896 +7,859 @@ using System.Linq; using Microsoft.AspNetCore.Testing; using Xunit; -namespace Microsoft.AspNetCore.Routing.Template.Tests +namespace Microsoft.AspNetCore.Routing.Template.Tests; + +public class TemplateRouteParserTests { - public class TemplateRouteParserTests + [Fact] + public void Parse_SingleLiteral() { - [Fact] - public void Parse_SingleLiteral() - { - // Arrange - var template = "cool"; + // Arrange + var template = "cool"; - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool")); + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool")); - // Act - var actual = TemplateParser.Parse(template); + // Act + var actual = TemplateParser.Parse(template); - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_SingleParameter() - { - // Arrange - var template = "{p}"; + [Fact] + public void Parse_SingleParameter() + { + // Arrange + var template = "{p}"; - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add( - TemplatePart.CreateParameter("p", false, false, defaultValue: null, inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[0].Parts[0]); + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add( + TemplatePart.CreateParameter("p", false, false, defaultValue: null, inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[0].Parts[0]); - // Act - var actual = TemplateParser.Parse(template); + // Act + var actual = TemplateParser.Parse(template); - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_OptionalParameter() - { - // Arrange - var template = "{p?}"; + [Fact] + public void Parse_OptionalParameter() + { + // Arrange + var template = "{p?}"; - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add( - TemplatePart.CreateParameter("p", false, true, defaultValue: null, inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[0].Parts[0]); + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add( + TemplatePart.CreateParameter("p", false, true, defaultValue: null, inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[0].Parts[0]); - // Act - var actual = TemplateParser.Parse(template); + // Act + var actual = TemplateParser.Parse(template); - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_MultipleLiterals() - { - // Arrange - var template = "cool/awesome/super"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool")); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[1].Parts.Add(TemplatePart.CreateLiteral("awesome")); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[2].Parts.Add(TemplatePart.CreateLiteral("super")); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_MultipleLiterals() + { + // Arrange + var template = "cool/awesome/super"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool")); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[1].Parts.Add(TemplatePart.CreateLiteral("awesome")); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[2].Parts.Add(TemplatePart.CreateLiteral("super")); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_MultipleParameters() - { - // Arrange - var template = "{p1}/{p2}/{*p3}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[0].Parts[0]); - - expected.Segments.Add(new TemplateSegment()); - expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p2", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[1].Parts[0]); - - expected.Segments.Add(new TemplateSegment()); - expected.Segments[2].Parts.Add(TemplatePart.CreateParameter("p3", - true, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[2].Parts[0]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_MultipleParameters() + { + // Arrange + var template = "{p1}/{p2}/{*p3}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[0].Parts[0]); + + expected.Segments.Add(new TemplateSegment()); + expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p2", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[1].Parts[0]); + + expected.Segments.Add(new TemplateSegment()); + expected.Segments[2].Parts.Add(TemplatePart.CreateParameter("p3", + true, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[2].Parts[0]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_LP() - { - // Arrange - var template = "cool-{p1}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool-")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[0].Parts[1]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_LP() + { + // Arrange + var template = "cool-{p1}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool-")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[0].Parts[1]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_PL() - { - // Arrange - var template = "{p1}-cool"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[0].Parts[0]); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool-")); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_PL() + { + // Arrange + var template = "{p1}-cool"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[0].Parts[0]); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool-")); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_PLP() - { - // Arrange - var template = "{p1}-cool-{p2}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[0].Parts[0]); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool-")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[0].Parts[2]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_PLP() + { + // Arrange + var template = "{p1}-cool-{p2}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[0].Parts[0]); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool-")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[0].Parts[2]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_LPL() - { - // Arrange - var template = "cool-{p1}-awesome"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool-")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Parameters.Add(expected.Segments[0].Parts[1]); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("-awesome")); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_LPL() + { + // Arrange + var template = "cool-{p1}-awesome"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("cool-")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Parameters.Add(expected.Segments[0].Parts[1]); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral("-awesome")); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_OptionalParameterFollowingPeriod() - { - // Arrange - var template = "{p1}.{p2?}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", - false, - true, - defaultValue: null, - inlineConstraints: null)); - - expected.Parameters.Add(expected.Segments[0].Parts[0]); - expected.Parameters.Add(expected.Segments[0].Parts[2]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_OptionalParameterFollowingPeriod() + { + // Arrange + var template = "{p1}.{p2?}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", + false, + true, + defaultValue: null, + inlineConstraints: null)); + + expected.Parameters.Add(expected.Segments[0].Parts[0]); + expected.Parameters.Add(expected.Segments[0].Parts[2]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_ParametersFollowingPeriod() - { - // Arrange - var template = "{p1}.{p2}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", - false, - false, - defaultValue: null, - inlineConstraints: null)); - - expected.Parameters.Add(expected.Segments[0].Parts[0]); - expected.Parameters.Add(expected.Segments[0].Parts[2]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_ParametersFollowingPeriod() + { + // Arrange + var template = "{p1}.{p2}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", + false, + false, + defaultValue: null, + inlineConstraints: null)); + + expected.Parameters.Add(expected.Segments[0].Parts[0]); + expected.Parameters.Add(expected.Segments[0].Parts[2]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_ThreeParameters() - { - // Arrange - var template = "{p1}.{p2}.{p3?}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", - false, - false, - defaultValue: null, - inlineConstraints: null)); - - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p3", - false, - true, - defaultValue: null, - inlineConstraints: null)); - - - expected.Parameters.Add(expected.Segments[0].Parts[0]); - expected.Parameters.Add(expected.Segments[0].Parts[2]); - expected.Parameters.Add(expected.Segments[0].Parts[4]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_ThreeParameters() + { + // Arrange + var template = "{p1}.{p2}.{p3?}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", + false, + false, + defaultValue: null, + inlineConstraints: null)); + + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p3", + false, + true, + defaultValue: null, + inlineConstraints: null)); + + + expected.Parameters.Add(expected.Segments[0].Parts[0]); + expected.Parameters.Add(expected.Segments[0].Parts[2]); + expected.Parameters.Add(expected.Segments[0].Parts[4]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_ThreeParametersSeparatedByPeriod() - { - // Arrange - var template = "{p1}.{p2}.{p3}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", - false, - false, - defaultValue: null, - inlineConstraints: null)); - - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p3", - false, - false, - defaultValue: null, - inlineConstraints: null)); - - - expected.Parameters.Add(expected.Segments[0].Parts[0]); - expected.Parameters.Add(expected.Segments[0].Parts[2]); - expected.Parameters.Add(expected.Segments[0].Parts[4]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_ThreeParametersSeparatedByPeriod() + { + // Arrange + var template = "{p1}.{p2}.{p3}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", + false, + false, + defaultValue: null, + inlineConstraints: null)); + + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p3", + false, + false, + defaultValue: null, + inlineConstraints: null)); + + + expected.Parameters.Add(expected.Segments[0].Parts[0]); + expected.Parameters.Add(expected.Segments[0].Parts[2]); + expected.Parameters.Add(expected.Segments[0].Parts[4]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_MiddleSegment() - { - // Arrange - var template = "{p1}.{p2?}/{p3}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", - false, - true, - defaultValue: null, - inlineConstraints: null)); - - expected.Parameters.Add(expected.Segments[0].Parts[0]); - expected.Parameters.Add(expected.Segments[0].Parts[2]); - - expected.Segments.Add(new TemplateSegment()); - expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p3", - false, - false, - null, - null)); - expected.Parameters.Add(expected.Segments[1].Parts[0]); - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_MiddleSegment() + { + // Arrange + var template = "{p1}.{p2?}/{p3}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Segments[0].Parts.Add(TemplatePart.CreateLiteral(".")); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", + false, + true, + defaultValue: null, + inlineConstraints: null)); + + expected.Parameters.Add(expected.Segments[0].Parts[0]); + expected.Parameters.Add(expected.Segments[0].Parts[2]); + + expected.Segments.Add(new TemplateSegment()); + expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p3", + false, + false, + null, + null)); + expected.Parameters.Add(expected.Segments[1].Parts[0]); + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_LastSegment() - { - // Arrange - var template = "{p1}/{p2}.{p3?}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: null)); - - expected.Segments.Add(new TemplateSegment()); - expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p2", - false, - false, - defaultValue: null, - inlineConstraints: null)); - expected.Segments[1].Parts.Add(TemplatePart.CreateLiteral(".")); - expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p3", - false, - true, - null, - null)); - expected.Parameters.Add(expected.Segments[0].Parts[0]); - expected.Parameters.Add(expected.Segments[1].Parts[0]); - expected.Parameters.Add(expected.Segments[1].Parts[2]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_LastSegment() + { + // Arrange + var template = "{p1}/{p2}.{p3?}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: null)); + + expected.Segments.Add(new TemplateSegment()); + expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p2", + false, + false, + defaultValue: null, + inlineConstraints: null)); + expected.Segments[1].Parts.Add(TemplatePart.CreateLiteral(".")); + expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p3", + false, + true, + null, + null)); + expected.Parameters.Add(expected.Segments[0].Parts[0]); + expected.Parameters.Add(expected.Segments[1].Parts[0]); + expected.Parameters.Add(expected.Segments[1].Parts[2]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Fact] - public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_PeriodAfterSlash() - { - // Arrange - var template = "{p2}/.{p3?}"; - - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", - false, - false, - defaultValue: null, - inlineConstraints: null)); - - expected.Segments.Add(new TemplateSegment()); - expected.Segments[1].Parts.Add(TemplatePart.CreateLiteral(".")); - expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p3", - false, - true, - null, - null)); - expected.Parameters.Add(expected.Segments[0].Parts[0]); - expected.Parameters.Add(expected.Segments[1].Parts[1]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Fact] + public void Parse_ComplexSegment_OptionalParameterFollowingPeriod_PeriodAfterSlash() + { + // Arrange + var template = "{p2}/.{p3?}"; + + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + expected.Segments[0].Parts.Add(TemplatePart.CreateParameter("p2", + false, + false, + defaultValue: null, + inlineConstraints: null)); + + expected.Segments.Add(new TemplateSegment()); + expected.Segments[1].Parts.Add(TemplatePart.CreateLiteral(".")); + expected.Segments[1].Parts.Add(TemplatePart.CreateParameter("p3", + false, + true, + null, + null)); + expected.Parameters.Add(expected.Segments[0].Parts[0]); + expected.Parameters.Add(expected.Segments[1].Parts[1]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Theory] - [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}$)}", @"regex(^\d{3}-\d{3}-\d{4}$)")] // ssn - [InlineData(@"{p1:regex(^\d{{1,2}}\/\d{{1,2}}\/\d{{4}}$)}", @"regex(^\d{1,2}\/\d{1,2}\/\d{4}$)")] // date - [InlineData(@"{p1:regex(^\w+\@\w+\.\w+)}", @"regex(^\w+\@\w+\.\w+)")] // email - [InlineData(@"{p1:regex(([}}])\w+)}", @"regex(([}])\w+)")] // Not balanced } - [InlineData(@"{p1:regex(([{{(])\w+)}", @"regex(([{(])\w+)")] // Not balanced { - public void Parse_RegularExpressions(string template, string constraint) - { - // Arrange - var expected = new RouteTemplate(template, new List<TemplateSegment>()); - expected.Segments.Add(new TemplateSegment()); - var c = new InlineConstraint(constraint); - expected.Segments[0].Parts.Add( - TemplatePart.CreateParameter("p1", - false, - false, - defaultValue: null, - inlineConstraints: new List<InlineConstraint> { c })); - expected.Parameters.Add(expected.Segments[0].Parts[0]); - - // Act - var actual = TemplateParser.Parse(template); - - // Assert - Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); - } + [Theory] + [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}$)}", @"regex(^\d{3}-\d{3}-\d{4}$)")] // ssn + [InlineData(@"{p1:regex(^\d{{1,2}}\/\d{{1,2}}\/\d{{4}}$)}", @"regex(^\d{1,2}\/\d{1,2}\/\d{4}$)")] // date + [InlineData(@"{p1:regex(^\w+\@\w+\.\w+)}", @"regex(^\w+\@\w+\.\w+)")] // email + [InlineData(@"{p1:regex(([}}])\w+)}", @"regex(([}])\w+)")] // Not balanced } + [InlineData(@"{p1:regex(([{{(])\w+)}", @"regex(([{(])\w+)")] // Not balanced { + public void Parse_RegularExpressions(string template, string constraint) + { + // Arrange + var expected = new RouteTemplate(template, new List<TemplateSegment>()); + expected.Segments.Add(new TemplateSegment()); + var c = new InlineConstraint(constraint); + expected.Segments[0].Parts.Add( + TemplatePart.CreateParameter("p1", + false, + false, + defaultValue: null, + inlineConstraints: new List<InlineConstraint> { c })); + expected.Parameters.Add(expected.Segments[0].Parts[0]); + + // Act + var actual = TemplateParser.Parse(template); + + // Assert + Assert.Equal<RouteTemplate>(expected, actual, new TemplateEqualityComparer()); + } - [Theory] - [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}}$)}")] // extra } - [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}$)}}")] // extra } at the end - [InlineData(@"{{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}$)}")] // extra { at the beginning - [InlineData(@"{p1:regex(([}])\w+}")] // Not escaped } - [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}$)}")] // Not escaped } - [InlineData(@"{p1:regex(abc)")] - [ReplaceCulture] - public void Parse_RegularExpressions_Invalid(string template) - { - // Act and Assert - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse(template), - "There is an incomplete parameter in the route template. Check that each '{' character has a matching " + - "'}' character. (Parameter 'routeTemplate')"); - } + [Theory] + [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}}$)}")] // extra } + [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}$)}}")] // extra } at the end + [InlineData(@"{{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}}$)}")] // extra { at the beginning + [InlineData(@"{p1:regex(([}])\w+}")] // Not escaped } + [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{4}$)}")] // Not escaped } + [InlineData(@"{p1:regex(abc)")] + [ReplaceCulture] + public void Parse_RegularExpressions_Invalid(string template) + { + // Act and Assert + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse(template), + "There is an incomplete parameter in the route template. Check that each '{' character has a matching " + + "'}' character. (Parameter 'routeTemplate')"); + } - [Theory] - [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{{4}}$)}")] // extra { - [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{4}}$)}")] // Not escaped { - [ReplaceCulture] - public void Parse_RegularExpressions_Unescaped(string template) - { - // Act and Assert - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse(template), - "In a route parameter, '{' and '}' must be escaped with '{{' and '}}'. (Parameter 'routeTemplate')"); - } + [Theory] + [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{{{4}}$)}")] // extra { + [InlineData(@"{p1:regex(^\d{{3}}-\d{{3}}-\d{4}}$)}")] // Not escaped { + [ReplaceCulture] + public void Parse_RegularExpressions_Unescaped(string template) + { + // Act and Assert + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse(template), + "In a route parameter, '{' and '}' must be escaped with '{{' and '}}'. (Parameter 'routeTemplate')"); + } - [Theory] - [InlineData("{p1}.{p2?}.{p3}", "p2", ".")] - [InlineData("{p1?}{p2}", "p1", "{p2}")] - [InlineData("{p1?}{p2?}", "p1", "{p2?}")] - [InlineData("{p1}.{p2?})", "p2", ")")] - [InlineData("{foorb?}-bar-{z}", "foorb", "-bar-")] - [ReplaceCulture] - public void Parse_ComplexSegment_OptionalParameter_NotTheLastPart( - string template, - string parameter, - string invalid) - { - // Act and Assert - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse(template), - "An optional parameter must be at the end of the segment. In the segment '" + template + - "', optional parameter '" + parameter + "' is followed by '" + invalid + "'. (Parameter 'routeTemplate')"); - } + [Theory] + [InlineData("{p1}.{p2?}.{p3}", "p2", ".")] + [InlineData("{p1?}{p2}", "p1", "{p2}")] + [InlineData("{p1?}{p2?}", "p1", "{p2?}")] + [InlineData("{p1}.{p2?})", "p2", ")")] + [InlineData("{foorb?}-bar-{z}", "foorb", "-bar-")] + [ReplaceCulture] + public void Parse_ComplexSegment_OptionalParameter_NotTheLastPart( + string template, + string parameter, + string invalid) + { + // Act and Assert + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse(template), + "An optional parameter must be at the end of the segment. In the segment '" + template + + "', optional parameter '" + parameter + "' is followed by '" + invalid + "'. (Parameter 'routeTemplate')"); + } - [Theory] - [InlineData("{p1}-{p2?}", "-")] - [InlineData("{p1}..{p2?}", "..")] - [InlineData("..{p2?}", "..")] - [InlineData("{p1}.abc.{p2?}", ".abc.")] - [InlineData("{p1}{p2?}", "{p1}")] - [ReplaceCulture] - public void Parse_ComplexSegment_OptionalParametersSeparatedByPeriod_Invalid(string template, string parameter) - { - // Act and Assert - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse(template), - "In the segment '" + template + "', the optional parameter 'p2' is preceded by an invalid " + - "segment '" + parameter + "'. Only a period (.) can precede an optional parameter. (Parameter 'routeTemplate')"); - } + [Theory] + [InlineData("{p1}-{p2?}", "-")] + [InlineData("{p1}..{p2?}", "..")] + [InlineData("..{p2?}", "..")] + [InlineData("{p1}.abc.{p2?}", ".abc.")] + [InlineData("{p1}{p2?}", "{p1}")] + [ReplaceCulture] + public void Parse_ComplexSegment_OptionalParametersSeparatedByPeriod_Invalid(string template, string parameter) + { + // Act and Assert + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse(template), + "In the segment '" + template + "', the optional parameter 'p2' is preceded by an invalid " + + "segment '" + parameter + "'. Only a period (.) can precede an optional parameter. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_WithRepeatedParameter() - { - var ex = ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{Controller}.mvc/{id}/{controller}"), - "The route parameter name 'controller' appears more than one time in the route template. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_WithRepeatedParameter() + { + var ex = ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{Controller}.mvc/{id}/{controller}"), + "The route parameter name 'controller' appears more than one time in the route template. (Parameter 'routeTemplate')"); + } - [Theory] - [InlineData("123{a}abc{")] - [InlineData("123{a}abc}")] - [InlineData("xyz}123{a}abc}")] - [InlineData("{{p1}")] - [InlineData("{p1}}")] - [InlineData("p1}}p2{")] - [ReplaceCulture] - public void InvalidTemplate_WithMismatchedBraces(string template) - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse(template), - @"There is an incomplete parameter in the route template. Check that each '{' character has a " + - "matching '}' character. (Parameter 'routeTemplate')"); - } + [Theory] + [InlineData("123{a}abc{")] + [InlineData("123{a}abc}")] + [InlineData("xyz}123{a}abc}")] + [InlineData("{{p1}")] + [InlineData("{p1}}")] + [InlineData("p1}}p2{")] + [ReplaceCulture] + public void InvalidTemplate_WithMismatchedBraces(string template) + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse(template), + @"There is an incomplete parameter in the route template. Check that each '{' character has a " + + "matching '}' character. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_CannotHaveCatchAllInMultiSegment() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("123{a}abc{*moo}"), - "A path segment that contains more than one section, such as a literal section or a parameter, " + - "cannot contain a catch-all parameter. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_CannotHaveCatchAllInMultiSegment() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("123{a}abc{*moo}"), + "A path segment that contains more than one section, such as a literal section or a parameter, " + + "cannot contain a catch-all parameter. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_CannotHaveMoreThanOneCatchAll() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{*p1}/{*p2}"), - "A catch-all parameter can only appear as the last segment of the route template. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_CannotHaveMoreThanOneCatchAll() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{*p1}/{*p2}"), + "A catch-all parameter can only appear as the last segment of the route template. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_CannotHaveMoreThanOneCatchAllInMultiSegment() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{*p1}abc{*p2}"), - "A path segment that contains more than one section, such as a literal section or a parameter, " + - "cannot contain a catch-all parameter. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_CannotHaveMoreThanOneCatchAllInMultiSegment() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{*p1}abc{*p2}"), + "A path segment that contains more than one section, such as a literal section or a parameter, " + + "cannot contain a catch-all parameter. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_CannotHaveCatchAllWithNoName() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("foo/{*}"), - "The route parameter name '' is invalid. Route parameter names must be non-empty and cannot" + - " contain these characters: '{', '}', '/'. The '?' character marks a parameter as optional," + - " and can occur only at the end of the parameter. The '*' character marks a parameter as catch-all," + - " and can occur only at the start of the parameter. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_CannotHaveCatchAllWithNoName() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("foo/{*}"), + "The route parameter name '' is invalid. Route parameter names must be non-empty and cannot" + + " contain these characters: '{', '}', '/'. The '?' character marks a parameter as optional," + + " and can occur only at the end of the parameter. The '*' character marks a parameter as catch-all," + + " and can occur only at the start of the parameter. (Parameter 'routeTemplate')"); + } - [Theory] - [InlineData("{a*}", "a*")] - [InlineData("{*a*}", "a*")] - [InlineData("{*a*:int}", "a*")] - [InlineData("{*a*=5}", "a*")] - [InlineData("{*a*b=5}", "a*b")] - [InlineData("{p1?}.{p2/}/{p3}", "p2/")] - [InlineData("{p{{}", "p{")] - [InlineData("{p}}}", "p}")] - [InlineData("{p/}", "p/")] - [ReplaceCulture] - public void ParseRouteParameter_ThrowsIf_ParameterContainsSpecialCharacters( - string template, - string parameterName) - { - // Arrange - var expectedMessage = "The route parameter name '" + parameterName + "' is invalid. Route parameter " + - "names must be non-empty and cannot contain these characters: '{', '}', '/'. The '?' character " + - "marks a parameter as optional, and can occur only at the end of the parameter. The '*' character " + - "marks a parameter as catch-all, and can occur only at the start of the parameter."; - - // Act & Assert - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse(template), expectedMessage + " (Parameter 'routeTemplate')"); - } + [Theory] + [InlineData("{a*}", "a*")] + [InlineData("{*a*}", "a*")] + [InlineData("{*a*:int}", "a*")] + [InlineData("{*a*=5}", "a*")] + [InlineData("{*a*b=5}", "a*b")] + [InlineData("{p1?}.{p2/}/{p3}", "p2/")] + [InlineData("{p{{}", "p{")] + [InlineData("{p}}}", "p}")] + [InlineData("{p/}", "p/")] + [ReplaceCulture] + public void ParseRouteParameter_ThrowsIf_ParameterContainsSpecialCharacters( + string template, + string parameterName) + { + // Arrange + var expectedMessage = "The route parameter name '" + parameterName + "' is invalid. Route parameter " + + "names must be non-empty and cannot contain these characters: '{', '}', '/'. The '?' character " + + "marks a parameter as optional, and can occur only at the end of the parameter. The '*' character " + + "marks a parameter as catch-all, and can occur only at the start of the parameter."; + + // Act & Assert + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse(template), expectedMessage + " (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_CannotHaveConsecutiveOpenBrace() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("foo/{{p1}"), - "There is an incomplete parameter in the route template. Check that each '{' character has a " + - "matching '}' character. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_CannotHaveConsecutiveOpenBrace() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("foo/{{p1}"), + "There is an incomplete parameter in the route template. Check that each '{' character has a " + + "matching '}' character. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_CannotHaveConsecutiveCloseBrace() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("foo/{p1}}"), - "There is an incomplete parameter in the route template. Check that each '{' character has a " + - "matching '}' character. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_CannotHaveConsecutiveCloseBrace() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("foo/{p1}}"), + "There is an incomplete parameter in the route template. Check that each '{' character has a " + + "matching '}' character. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_SameParameterTwiceThrows() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{aaa}/{AAA}"), - "The route parameter name 'AAA' appears more than one time in the route template. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_SameParameterTwiceThrows() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{aaa}/{AAA}"), + "The route parameter name 'AAA' appears more than one time in the route template. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_SameParameterTwiceAndOneCatchAllThrows() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{aaa}/{*AAA}"), - "The route parameter name 'AAA' appears more than one time in the route template. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_SameParameterTwiceAndOneCatchAllThrows() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{aaa}/{*AAA}"), + "The route parameter name 'AAA' appears more than one time in the route template. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_InvalidParameterNameWithCloseBracketThrows() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{a}/{aa}a}/{z}"), - "There is an incomplete parameter in the route template. Check that each '{' character has a " + - "matching '}' character. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_InvalidParameterNameWithCloseBracketThrows() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{a}/{aa}a}/{z}"), + "There is an incomplete parameter in the route template. Check that each '{' character has a " + + "matching '}' character. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_InvalidParameterNameWithOpenBracketThrows() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{a}/{a{aa}/{z}"), - "In a route parameter, '{' and '}' must be escaped with '{{' and '}}'. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_InvalidParameterNameWithOpenBracketThrows() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{a}/{a{aa}/{z}"), + "In a route parameter, '{' and '}' must be escaped with '{{' and '}}'. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_InvalidParameterNameWithEmptyNameThrows() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{a}/{}/{z}"), - "The route parameter name '' is invalid. Route parameter names must be non-empty and cannot" + - " contain these characters: '{', '}', '/'. The '?' character marks a parameter as optional, and" + - " can occur only at the end of the parameter. The '*' character marks a parameter as catch-all," + - " and can occur only at the start of the parameter. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_InvalidParameterNameWithEmptyNameThrows() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{a}/{}/{z}"), + "The route parameter name '' is invalid. Route parameter names must be non-empty and cannot" + + " contain these characters: '{', '}', '/'. The '?' character marks a parameter as optional, and" + + " can occur only at the end of the parameter. The '*' character marks a parameter as catch-all," + + " and can occur only at the start of the parameter. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_InvalidParameterNameWithQuestionThrows() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{Controller}.mvc/{?}"), - "The route parameter name '' is invalid. Route parameter names must be non-empty and cannot" + - " contain these characters: '{', '}', '/'. The '?' character marks a parameter as optional, and" + - " can occur only at the end of the parameter. The '*' character marks a parameter as catch-all," + - " and can occur only at the start of the parameter. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_InvalidParameterNameWithQuestionThrows() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{Controller}.mvc/{?}"), + "The route parameter name '' is invalid. Route parameter names must be non-empty and cannot" + + " contain these characters: '{', '}', '/'. The '?' character marks a parameter as optional, and" + + " can occur only at the end of the parameter. The '*' character marks a parameter as catch-all," + + " and can occur only at the start of the parameter. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_ConsecutiveSeparatorsSlashSlashThrows() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{a}//{z}"), - "The route template separator character '/' cannot appear consecutively. It must be separated by " + - "either a parameter or a literal value. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_ConsecutiveSeparatorsSlashSlashThrows() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{a}//{z}"), + "The route template separator character '/' cannot appear consecutively. It must be separated by " + + "either a parameter or a literal value. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_WithCatchAllNotAtTheEndThrows() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("foo/{p1}/{*p2}/{p3}"), - "A catch-all parameter can only appear as the last segment of the route template. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_WithCatchAllNotAtTheEndThrows() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("foo/{p1}/{*p2}/{p3}"), + "A catch-all parameter can only appear as the last segment of the route template. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_RepeatedParametersThrows() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("foo/aa{p1}{p2}"), - "A path segment cannot contain two consecutive parameters. They must be separated by a '/' or by " + - "a literal string. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_RepeatedParametersThrows() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("foo/aa{p1}{p2}"), + "A path segment cannot contain two consecutive parameters. They must be separated by a '/' or by " + + "a literal string. (Parameter 'routeTemplate')"); + } - [Theory] - [InlineData("/foo")] - [InlineData("~/foo")] - public void ValidTemplate_CanStartWithSlashOrTildeSlash(string routeTemplate) - { - // Arrange & Act - var pattern = TemplateParser.Parse(routeTemplate); + [Theory] + [InlineData("/foo")] + [InlineData("~/foo")] + public void ValidTemplate_CanStartWithSlashOrTildeSlash(string routeTemplate) + { + // Arrange & Act + var pattern = TemplateParser.Parse(routeTemplate); - // Assert - Assert.Equal(routeTemplate, pattern.TemplateText); - } + // Assert + Assert.Equal(routeTemplate, pattern.TemplateText); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_CannotStartWithTilde() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("~foo"), - "The route template cannot start with a '~' character unless followed by a '/'. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_CannotStartWithTilde() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("~foo"), + "The route template cannot start with a '~' character unless followed by a '/'. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_CannotContainQuestionMark() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("foor?bar"), - "The literal section 'foor?bar' is invalid. Literal sections cannot contain the '?' character. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_CannotContainQuestionMark() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("foor?bar"), + "The literal section 'foor?bar' is invalid. Literal sections cannot contain the '?' character. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_ParameterCannotContainQuestionMark_UnlessAtEnd() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{foor?b}"), - "The route parameter name 'foor?b' is invalid. Route parameter names must be non-empty and cannot" + - " contain these characters: '{', '}', '/'. The '?' character marks a parameter as optional, and" + - " can occur only at the end of the parameter. The '*' character marks a parameter as catch-all," + - " and can occur only at the start of the parameter. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_ParameterCannotContainQuestionMark_UnlessAtEnd() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{foor?b}"), + "The route parameter name 'foor?b' is invalid. Route parameter names must be non-empty and cannot" + + " contain these characters: '{', '}', '/'. The '?' character marks a parameter as optional, and" + + " can occur only at the end of the parameter. The '*' character marks a parameter as catch-all," + + " and can occur only at the start of the parameter. (Parameter 'routeTemplate')"); + } - [Fact] - [ReplaceCulture] - public void InvalidTemplate_CatchAllMarkedOptional() - { - ExceptionAssert.Throws<ArgumentException>( - () => TemplateParser.Parse("{a}/{*b?}"), - "A catch-all parameter cannot be marked optional. (Parameter 'routeTemplate')"); - } + [Fact] + [ReplaceCulture] + public void InvalidTemplate_CatchAllMarkedOptional() + { + ExceptionAssert.Throws<ArgumentException>( + () => TemplateParser.Parse("{a}/{*b?}"), + "A catch-all parameter cannot be marked optional. (Parameter 'routeTemplate')"); + } - private class TemplateEqualityComparer : IEqualityComparer<RouteTemplate> + private class TemplateEqualityComparer : IEqualityComparer<RouteTemplate> + { + public bool Equals(RouteTemplate x, RouteTemplate y) { - public bool Equals(RouteTemplate x, RouteTemplate y) + if (x == null && y == null) + { + return true; + } + else if (x == null || y == null) + { + return false; + } + else { - if (x == null && y == null) + if (!string.Equals(x.TemplateText, y.TemplateText, StringComparison.Ordinal)) { - return true; + return false; } - else if (x == null || y == null) + + if (x.Segments.Count != y.Segments.Count) { return false; } - else - { - if (!string.Equals(x.TemplateText, y.TemplateText, StringComparison.Ordinal)) - { - return false; - } - if (x.Segments.Count != y.Segments.Count) - { - return false; - } - - for (var i = 0; i < x.Segments.Count; i++) - { - if (x.Segments[i].Parts.Count != y.Segments[i].Parts.Count) - { - return false; - } - - for (int j = 0; j < x.Segments[i].Parts.Count; j++) - { - if (!Equals(x.Segments[i].Parts[j], y.Segments[i].Parts[j])) - { - return false; - } - } - } - - if (x.Parameters.Count != y.Parameters.Count) + for (var i = 0; i < x.Segments.Count; i++) + { + if (x.Segments[i].Parts.Count != y.Segments[i].Parts.Count) { return false; } - for (var i = 0; i < x.Parameters.Count; i++) + for (int j = 0; j < x.Segments[i].Parts.Count; j++) { - if (!Equals(x.Parameters[i], y.Parameters[i])) + if (!Equals(x.Segments[i].Parts[j], y.Segments[i].Parts[j])) { return false; } } - - return true; - } - } - - private bool Equals(TemplatePart x, TemplatePart y) - { - if (x.IsLiteral != y.IsLiteral || - x.IsParameter != y.IsParameter || - x.IsCatchAll != y.IsCatchAll || - x.IsOptional != y.IsOptional || - !String.Equals(x.Name, y.Name, StringComparison.Ordinal) || - !String.Equals(x.Name, y.Name, StringComparison.Ordinal) || - (x.InlineConstraints == null && y.InlineConstraints != null) || - (x.InlineConstraints != null && y.InlineConstraints == null)) - { - return false; - } - - if (x.InlineConstraints == null && y.InlineConstraints == null) - { - return true; } - if (x.InlineConstraints.Count() != y.InlineConstraints.Count()) + if (x.Parameters.Count != y.Parameters.Count) { return false; } - foreach (var xconstraint in x.InlineConstraints) + for (var i = 0; i < x.Parameters.Count; i++) { - if (!y.InlineConstraints.Any<InlineConstraint>( - c => string.Equals(c.Constraint, xconstraint.Constraint, StringComparison.Ordinal))) + if (!Equals(x.Parameters[i], y.Parameters[i])) { return false; } @@ -904,11 +867,47 @@ namespace Microsoft.AspNetCore.Routing.Template.Tests return true; } + } + + private bool Equals(TemplatePart x, TemplatePart y) + { + if (x.IsLiteral != y.IsLiteral || + x.IsParameter != y.IsParameter || + x.IsCatchAll != y.IsCatchAll || + x.IsOptional != y.IsOptional || + !String.Equals(x.Name, y.Name, StringComparison.Ordinal) || + !String.Equals(x.Name, y.Name, StringComparison.Ordinal) || + (x.InlineConstraints == null && y.InlineConstraints != null) || + (x.InlineConstraints != null && y.InlineConstraints == null)) + { + return false; + } + + if (x.InlineConstraints == null && y.InlineConstraints == null) + { + return true; + } + + if (x.InlineConstraints.Count() != y.InlineConstraints.Count()) + { + return false; + } - public int GetHashCode(RouteTemplate obj) + foreach (var xconstraint in x.InlineConstraints) { - throw new NotImplementedException(); + if (!y.InlineConstraints.Any<InlineConstraint>( + c => string.Equals(c.Constraint, xconstraint.Constraint, StringComparison.Ordinal))) + { + return false; + } } + + return true; + } + + public int GetHashCode(RouteTemplate obj) + { + throw new NotImplementedException(); } } } |