diff --git a/src/Microsoft.AspNet.Razor/Tokenizer/Tokenizer.cs b/src/Microsoft.AspNet.Razor/Tokenizer/Tokenizer.cs
index 242c7db1e4..a334bc818e 100644
--- a/src/Microsoft.AspNet.Razor/Tokenizer/Tokenizer.cs
+++ b/src/Microsoft.AspNet.Razor/Tokenizer/Tokenizer.cs
@@ -10,7 +10,6 @@ using System.Globalization;
#endif
using System.Linq;
using System.Text;
-using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.Text;
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
@@ -223,7 +222,10 @@ namespace Microsoft.AspNet.Razor.Tokenizer
return Transition(EndSymbol(RazorCommentType), StartState);
}
- private bool Lookahead(string expected, bool takeIfMatch, bool caseSensitive)
+ ///
+ /// Internal for unit testing
+ ///
+ internal bool Lookahead(string expected, bool takeIfMatch, bool caseSensitive)
{
Func filter = c => c;
if (!caseSensitive)
@@ -240,7 +242,7 @@ namespace Microsoft.AspNet.Razor.Tokenizer
string oldBuffer = null;
if (takeIfMatch)
{
- Buffer.ToString();
+ oldBuffer = Buffer.ToString();
}
using (LookaheadToken lookahead = Source.BeginLookahead())
diff --git a/test/Microsoft.AspNet.Razor.Test/Tokenizer/TokenizerLookaheadTest.cs b/test/Microsoft.AspNet.Razor.Test/Tokenizer/TokenizerLookaheadTest.cs
index 4f76d102c7..abdf02f942 100644
--- a/test/Microsoft.AspNet.Razor.Test/Tokenizer/TokenizerLookaheadTest.cs
+++ b/test/Microsoft.AspNet.Razor.Test/Tokenizer/TokenizerLookaheadTest.cs
@@ -1,7 +1,10 @@
// 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.IO;
+using System.Text;
using Microsoft.AspNet.Razor.Text;
using Microsoft.AspNet.Razor.Tokenizer;
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
@@ -11,6 +14,51 @@ namespace Microsoft.AspNet.Razor.Test.Tokenizer
{
public class TokenizerLookaheadTest : HtmlTokenizerTestBase
{
+ [Fact]
+ public void Lookahead_MaintainsExistingBufferWhenRejected()
+ {
+ // Arrange
+ var tokenizer = new ExposedTokenizer("01234");
+ tokenizer.Buffer.Append("pre-existing values");
+
+ // Act
+ var result = tokenizer.Lookahead("0x", takeIfMatch: true, caseSensitive: true);
+
+ // Assert
+ Assert.False(result);
+ Assert.Equal("pre-existing values", tokenizer.Buffer.ToString(), StringComparer.Ordinal);
+ }
+
+ [Fact]
+ public void Lookahead_AddsToExistingBufferWhenSuccessfulAndTakeIfMatchIsTrue()
+ {
+ // Arrange
+ var tokenizer = new ExposedTokenizer("0x1234");
+ tokenizer.Buffer.Append("pre-existing values");
+
+ // Act
+ var result = tokenizer.Lookahead("0x", takeIfMatch: true, caseSensitive: true);
+
+ // Assert
+ Assert.True(result);
+ Assert.Equal("pre-existing values0x", tokenizer.Buffer.ToString(), StringComparer.Ordinal);
+ }
+
+ [Fact]
+ public void Lookahead_MaintainsExistingBufferWhenSuccessfulAndTakeIfMatchIsFalse()
+ {
+ // Arrange
+ var tokenizer = new ExposedTokenizer("0x1234");
+ tokenizer.Buffer.Append("pre-existing values");
+
+ // Act
+ var result = tokenizer.Lookahead("0x", takeIfMatch: false, caseSensitive: true);
+
+ // Assert
+ Assert.True(result);
+ Assert.Equal("pre-existing values", tokenizer.Buffer.ToString(), StringComparer.Ordinal);
+ }
+
[Fact]
public void After_Cancelling_Lookahead_Tokenizer_Returns_Same_Tokens_As_It_Did_Before_Lookahead()
{
@@ -38,5 +86,62 @@ namespace Microsoft.AspNet.Razor.Test.Tokenizer
}
Assert.Equal(new HtmlSymbol(4, 0, 4, ">", HtmlSymbolType.CloseAngle), tokenizer.NextSymbol());
}
+
+ private class ExposedTokenizer : Tokenizer
+ {
+ public ExposedTokenizer(string input)
+ : base(new SeekableTextReader(new StringReader(input)))
+ {
+ }
+
+ public new StringBuilder Buffer
+ {
+ get
+ {
+ return base.Buffer;
+ }
+ }
+
+ public override CSharpSymbolType RazorCommentStarType
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public override CSharpSymbolType RazorCommentTransitionType
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public override CSharpSymbolType RazorCommentType
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ protected override State StartState
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ protected override CSharpSymbol CreateSymbol(
+ SourceLocation start,
+ string content,
+ CSharpSymbolType type,
+ IEnumerable errors)
+ {
+ throw new NotImplementedException();
+ }
+ }
}
}