Adds mod_rewrite tests, small refactors to exception messages and types
This commit is contained in:
parent
d1ab35db87
commit
73e0d531e0
|
|
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
FlagType flag;
|
||||
if (!_ruleFlagLookup.TryGetValue(hasPayload[0], out flag))
|
||||
{
|
||||
throw new FormatException($"Unrecognized flag: {hasPayload[0]}");
|
||||
throw new FormatException($"Unrecognized flag: '{hasPayload[0]}'");
|
||||
}
|
||||
|
||||
if (hasPayload.Length == 2)
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
else
|
||||
{
|
||||
// illegal escape of a character
|
||||
throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));
|
||||
throw new FormatException(Resources.FormatError_InputParserInvalidInteger(context.Template, context.Index));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,27 +29,19 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
return null;
|
||||
}
|
||||
var context = new ParserContext(rule);
|
||||
if (!context.Next())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
context.Next();
|
||||
|
||||
var tokens = new List<string>();
|
||||
context.Mark();
|
||||
while (true)
|
||||
{
|
||||
if (!context.Next())
|
||||
{
|
||||
// End of string. Capture.
|
||||
break;
|
||||
}
|
||||
else if (context.Current == Escape)
|
||||
if (context.Current == Escape)
|
||||
{
|
||||
// Need to progress such that the next character is not evaluated.
|
||||
if (!context.Next())
|
||||
{
|
||||
// Means that a character was not escaped appropriately Ex: "foo\"
|
||||
throw new FormatException("Invalid escaper character in string " + rule);
|
||||
throw new FormatException($"Invalid escaper character in string: {rule}");
|
||||
}
|
||||
}
|
||||
else if (context.Current == Space || context.Current == Tab)
|
||||
|
|
@ -68,14 +60,21 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ModRewrite
|
|||
}
|
||||
}
|
||||
context.Mark();
|
||||
context.Back();
|
||||
}
|
||||
}
|
||||
if (!context.Next())
|
||||
{
|
||||
// End of string. Capture.
|
||||
break;
|
||||
}
|
||||
}
|
||||
var done = context.Capture();
|
||||
if (!string.IsNullOrEmpty(done))
|
||||
{
|
||||
tokens.Add(done);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
||||
{
|
||||
public class ConditionActionTest
|
||||
public class ConditionPatternParserTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(">hey", OperationType.Greater, "hey", ConditionType.StringComp)]
|
||||
|
|
@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[InlineData(">=hey", OperationType.GreaterEqual, "hey", ConditionType.StringComp)]
|
||||
[InlineData("<=hey", OperationType.LessEqual, "hey", ConditionType.StringComp)]
|
||||
[InlineData("=hey", OperationType.Equal, "hey", ConditionType.StringComp)]
|
||||
public void ConditionParser_CheckStringComp(string condition, OperationType operation, string variable, ConditionType conditionType)
|
||||
public void ConditionPatternParser_CheckStringComp(string condition, OperationType operation, string variable, ConditionType conditionType)
|
||||
{
|
||||
var results = new ConditionPatternParser().ParseActionCondition(condition);
|
||||
|
||||
|
|
@ -23,12 +24,12 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionParser_CheckRegexEqual()
|
||||
public void ConditionPatternParser_CheckRegexEqual()
|
||||
{
|
||||
var condition = @"(.*)";
|
||||
var results = new ConditionPatternParser().ParseActionCondition(condition);
|
||||
|
||||
var expected = new ParsedModRewriteInput { ConditionType = ConditionType.Regex, Operand = "(.*)", Invert = false };
|
||||
var expected = new ParsedModRewriteInput { ConditionType = ConditionType.Regex, Operand = "(.*)", Invert = false };
|
||||
Assert.True(CompareConditions(results, expected));
|
||||
}
|
||||
|
||||
|
|
@ -42,11 +43,11 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[InlineData("-s", OperationType.Size, ConditionType.PropertyTest)]
|
||||
[InlineData("-U", OperationType.ExistingUrl, ConditionType.PropertyTest)]
|
||||
[InlineData("-x", OperationType.Executable, ConditionType.PropertyTest)]
|
||||
public void ConditionParser_CheckFileOperations(string condition, OperationType operation, ConditionType cond)
|
||||
public void ConditionPatternParser_CheckFileOperations(string condition, OperationType operation, ConditionType cond)
|
||||
{
|
||||
var results = new ConditionPatternParser().ParseActionCondition(condition);
|
||||
|
||||
var expected = new ParsedModRewriteInput { ConditionType = cond, OperationType = operation , Invert = false };
|
||||
var expected = new ParsedModRewriteInput { ConditionType = cond, OperationType = operation, Invert = false };
|
||||
Assert.True(CompareConditions(results, expected));
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +61,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[InlineData("!-s", OperationType.Size, ConditionType.PropertyTest)]
|
||||
[InlineData("!-U", OperationType.ExistingUrl, ConditionType.PropertyTest)]
|
||||
[InlineData("!-x", OperationType.Executable, ConditionType.PropertyTest)]
|
||||
public void ConditionParser_CheckFileOperationsInverted(string condition, OperationType operation, ConditionType cond)
|
||||
public void ConditionPatternParser_CheckFileOperationsInverted(string condition, OperationType operation, ConditionType cond)
|
||||
{
|
||||
var results = new ConditionPatternParser().ParseActionCondition(condition);
|
||||
|
||||
|
|
@ -75,7 +76,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
[InlineData("-le1", OperationType.LessEqual, "1", ConditionType.IntComp)]
|
||||
[InlineData("-eq1", OperationType.Equal, "1", ConditionType.IntComp)]
|
||||
[InlineData("-ne1", OperationType.NotEqual, "1", ConditionType.IntComp)]
|
||||
public void ConditionParser_CheckIntComp(string condition, OperationType operation, string variable, ConditionType cond)
|
||||
public void ConditionPatternParser_CheckIntComp(string condition, OperationType operation, string variable, ConditionType cond)
|
||||
{
|
||||
var results = new ConditionPatternParser().ParseActionCondition(condition);
|
||||
|
||||
|
|
@ -83,7 +84,22 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
Assert.True(CompareConditions(results, expected));
|
||||
}
|
||||
|
||||
// TODO negative tests
|
||||
[Theory]
|
||||
[InlineData("", "Unrecognized parameter type: '', terminated at string index: '0'")]
|
||||
[InlineData("!", "Unrecognized parameter type: '!', terminated at string index: '1'")]
|
||||
[InlineData(">", "Unrecognized parameter type: '>', terminated at string index: '1'")]
|
||||
[InlineData("<", "Unrecognized parameter type: '<', terminated at string index: '1'")]
|
||||
[InlineData("=", "Unrecognized parameter type: '=', terminated at string index: '1'")]
|
||||
[InlineData(">=", "Unrecognized parameter type: '>=', terminated at string index: '2'")]
|
||||
[InlineData("<=", "Unrecognized parameter type: '<=', terminated at string index: '2'")]
|
||||
[InlineData("-a", "Unrecognized parameter type: '-a', terminated at string index: '1'")]
|
||||
[InlineData("-gewow", "Unrecognized parameter type: '-gewow', terminated at string index: '3'")]
|
||||
public void ConditionPatternParser_AssertBadInputThrowsFormatException(string input, string expected)
|
||||
{
|
||||
var ex = Assert.Throws<FormatException>(() => new ConditionPatternParser().ParseActionCondition(input));
|
||||
Assert.Equal(expected, ex.Message);
|
||||
}
|
||||
|
||||
private bool CompareConditions(ParsedModRewriteInput i1, ParsedModRewriteInput i2)
|
||||
{
|
||||
if (i1.OperationType != i2.OperationType ||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite;
|
||||
|
|
@ -47,6 +48,24 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
Assert.True(DictionaryContentsEqual(results.FlagDictionary, expected.FlagDictionary));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("]", "Flags should start and end with square brackets: [flags]")]
|
||||
[InlineData("[", "Flags should start and end with square brackets: [flags]")]
|
||||
[InlineData("[R, L]", "Unrecognized flag: ' L'")] // cannot have spaces after ,
|
||||
[InlineData("[RL]", "Unrecognized flag: 'RL'")]
|
||||
public void FlagParser_AssertFormatErrorWhenFlagsArePoorlyConstructed(string input, string expected)
|
||||
{
|
||||
var ex = Assert.Throws<FormatException>(() => new FlagParser().Parse(input));
|
||||
Assert.Equal(expected, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FlagParser_AssertArgumentExceptionWhenFlagsAreNullOrEmpty()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => new FlagParser().Parse(null));
|
||||
Assert.Throws<ArgumentNullException>(() => new FlagParser().Parse(string.Empty));
|
||||
}
|
||||
|
||||
public bool DictionaryContentsEqual<TKey, TValue>(IDictionary<TKey, TValue> dictionary, IDictionary<TKey, TValue> other)
|
||||
{
|
||||
return (other ?? new Dictionary<TKey, TValue>())
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
public class FormatExceptionTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(@"RewriteCond 1 2\", @"Invalid escaper character in string RewriteCond 1 2\")]
|
||||
[InlineData(@"RewriteCond 1 2\", @"Invalid escaper character in string: RewriteCond 1 2\")]
|
||||
[InlineData("BadExpression 1 2 3 4", "Could not parse the mod_rewrite file. Message: 'Too many tokens on line'. Line number '1'.")]
|
||||
[InlineData("RewriteCond % 2", "Could not parse the mod_rewrite file. Line number '1'.")]
|
||||
[InlineData("RewriteCond %{ 2", "Could not parse the mod_rewrite file. Line number '1'.")]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite;
|
||||
using Xunit;
|
||||
|
|
@ -31,9 +32,45 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
|
|||
|
||||
var expected = new List<string>();
|
||||
expected.Add("RewriteCond");
|
||||
expected.Add(@"%{HTTPS}\ what"); // TODO maybe just have the space here? talking point
|
||||
expected.Add(@"%{HTTPS}\ what");
|
||||
expected.Add("!-f");
|
||||
Assert.Equal(tokens,expected);
|
||||
Assert.Equal(tokens, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tokenize_CheckWhiteSpaceDirectlyFollowedByEscapeCharacter_CorrectSplit()
|
||||
{
|
||||
var testString = @"RewriteCond %{HTTPS} \ what !-f";
|
||||
var tokens = new Tokenizer().Tokenize(testString);
|
||||
|
||||
var expected = new List<string>();
|
||||
expected.Add(@"RewriteCond");
|
||||
expected.Add(@"%{HTTPS}");
|
||||
expected.Add(@"\ what");
|
||||
expected.Add(@"!-f");
|
||||
Assert.Equal(tokens, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tokenize_CheckWhiteSpaceAtEndOfString_CorrectSplit()
|
||||
{
|
||||
var testString = @"RewriteCond %{HTTPS} \ what !-f ";
|
||||
var tokens = new Tokenizer().Tokenize(testString);
|
||||
|
||||
var expected = new List<string>();
|
||||
expected.Add(@"RewriteCond");
|
||||
expected.Add(@"%{HTTPS}");
|
||||
expected.Add(@"\ what");
|
||||
expected.Add(@"!-f");
|
||||
Assert.Equal(expected, tokens);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tokenize_AssertFormatExceptionWhenEscapeCharacterIsAtEndOfString()
|
||||
{
|
||||
|
||||
var ex = Assert.Throws<FormatException>(() => new Tokenizer().Tokenize("\\"));
|
||||
Assert.Equal(@"Invalid escaper character in string: \", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.ModRewrite;
|
||||
using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Rewrite
|
||||
{
|
||||
public class TestStringParserTests
|
||||
{
|
||||
[Fact]
|
||||
public void ConditionParser_SingleServerVariable()
|
||||
{
|
||||
var serverVar = "%{HTTPS}";
|
||||
|
||||
var result = new TestStringParser().Parse(serverVar);
|
||||
|
||||
var list = new List<PatternSegment>();
|
||||
list.Add(new IsHttpsModSegment());
|
||||
var expected = new Pattern(list);
|
||||
AssertPatternsEqual(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionParser_MultipleServerVariables()
|
||||
{
|
||||
var serverVar = "%{HTTPS}%{REQUEST_URI}";
|
||||
var result = new TestStringParser().Parse(serverVar);
|
||||
|
||||
var list = new List<PatternSegment>();
|
||||
list.Add(new IsHttpsModSegment());
|
||||
list.Add(new UrlSegment());
|
||||
var expected = new Pattern(list);
|
||||
AssertPatternsEqual(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionParser_ParseLiteral()
|
||||
{
|
||||
var serverVar = "Hello!";
|
||||
var result = new TestStringParser().Parse(serverVar);
|
||||
|
||||
var list = new List<PatternSegment>();
|
||||
list.Add(new LiteralSegment(serverVar));
|
||||
var expected = new Pattern(list);
|
||||
AssertPatternsEqual(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionParser_ParseConditionParameters()
|
||||
{
|
||||
var serverVar = "%1";
|
||||
var result = new TestStringParser().Parse(serverVar);
|
||||
|
||||
var list = new List<PatternSegment>();
|
||||
list.Add(new ConditionMatchSegment(1));
|
||||
var expected = new Pattern(list);
|
||||
AssertPatternsEqual(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionParser_ParseMultipleConditionParameters()
|
||||
{
|
||||
var serverVar = "%1%2";
|
||||
var result = new TestStringParser().Parse(serverVar);
|
||||
|
||||
var list = new List<PatternSegment>();
|
||||
list.Add(new ConditionMatchSegment(1));
|
||||
list.Add(new ConditionMatchSegment(2));
|
||||
var expected = new Pattern(list);
|
||||
AssertPatternsEqual(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionParser_ParseRuleVariable()
|
||||
{
|
||||
var serverVar = "$1";
|
||||
var result = new TestStringParser().Parse(serverVar);
|
||||
|
||||
var list = new List<PatternSegment>();
|
||||
list.Add(new RuleMatchSegment(1));
|
||||
var expected = new Pattern(list);
|
||||
AssertPatternsEqual(expected, result);
|
||||
}
|
||||
[Fact]
|
||||
public void ConditionParser_ParseMultipleRuleVariables()
|
||||
{
|
||||
var serverVar = "$1$2";
|
||||
var result = new TestStringParser().Parse(serverVar);
|
||||
|
||||
var list = new List<PatternSegment>();
|
||||
list.Add(new RuleMatchSegment(1));
|
||||
list.Add(new RuleMatchSegment(2));
|
||||
var expected = new Pattern(list);
|
||||
AssertPatternsEqual(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionParser_ParserComplexRequest()
|
||||
{
|
||||
var serverVar = "%{HTTPS}/$1";
|
||||
var result = new TestStringParser().Parse(serverVar);
|
||||
|
||||
var list = new List<PatternSegment>();
|
||||
list.Add(new IsHttpsModSegment());
|
||||
list.Add(new LiteralSegment("/"));
|
||||
list.Add(new RuleMatchSegment(1));
|
||||
var expected = new Pattern(list);
|
||||
AssertPatternsEqual(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"%}", "Cannot parse '%}' to integer at string index: '1'")] // no } at end
|
||||
[InlineData(@"%{", "Missing close brace for parameter at string index: '2'")] // no closing }
|
||||
[InlineData(@"%a", "Cannot parse '%a' to integer at string index: '1'")] // invalid character after %
|
||||
[InlineData(@"$a", "Cannot parse '$a' to integer at string index: '1'")] // invalid character after $
|
||||
[InlineData(@"%{asdf", "Missing close brace for parameter at string index: '6'")] // no closing } with characters
|
||||
public void ConditionParser_Bad(string testString, string expected)
|
||||
{
|
||||
var ex = Assert.Throws<FormatException>(() => new TestStringParser().Parse(testString));
|
||||
Assert.Equal(ex.Message, expected);
|
||||
}
|
||||
|
||||
private void AssertPatternsEqual(Pattern p1, Pattern p2)
|
||||
{
|
||||
Assert.Equal(p1.PatternSegments.Count, p2.PatternSegments.Count);
|
||||
|
||||
for (int i = 0; i < p1.PatternSegments.Count; i++)
|
||||
{
|
||||
var s1 = p1.PatternSegments[i];
|
||||
var s2 = p2.PatternSegments[i];
|
||||
|
||||
Assert.Equal(s1.GetType(), s2.GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue