a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
268 lines
8.6 KiB
C#
268 lines
8.6 KiB
C#
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
using System.IO;
|
|
using System.Web.Razor.Text;
|
|
using Xunit;
|
|
using Assert = Microsoft.TestCommon.AssertEx;
|
|
|
|
namespace System.Web.Razor.Test.Text
|
|
{
|
|
public class BufferingTextReaderTest : LookaheadTextReaderTestBase
|
|
{
|
|
private const string TestString = "abcdefg";
|
|
|
|
private class DisposeTestMockTextReader : TextReader
|
|
{
|
|
public bool Disposed { get; set; }
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
Disposed = true;
|
|
}
|
|
}
|
|
|
|
protected override LookaheadTextReader CreateReader(string testString)
|
|
{
|
|
return new BufferingTextReader(new StringReader(testString));
|
|
}
|
|
|
|
[Fact]
|
|
public void ConstructorRequiresNonNullSourceReader()
|
|
{
|
|
Assert.ThrowsArgumentNull(() => new BufferingTextReader(null), "source");
|
|
}
|
|
|
|
[Fact]
|
|
public void PeekReturnsCurrentCharacterWithoutAdvancingPosition()
|
|
{
|
|
RunPeekTest("abc", peekAt: 2);
|
|
}
|
|
|
|
[Fact]
|
|
public void PeekReturnsNegativeOneAtEndOfSourceReader()
|
|
{
|
|
RunPeekTest("abc", peekAt: 3);
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadReturnsCurrentCharacterAndAdvancesToNextCharacter()
|
|
{
|
|
RunReadTest("abc", readAt: 2);
|
|
}
|
|
|
|
[Fact]
|
|
public void EndingLookaheadReturnsReaderToPreviousLocation()
|
|
{
|
|
RunLookaheadTest("abcdefg", "abcb",
|
|
Read,
|
|
Lookahead(
|
|
Read,
|
|
Read),
|
|
Read);
|
|
}
|
|
|
|
[Fact]
|
|
public void MultipleLookaheadsCanBePerformed()
|
|
{
|
|
RunLookaheadTest("abcdefg", "abcbcdc",
|
|
Read,
|
|
Lookahead(
|
|
Read,
|
|
Read),
|
|
Read,
|
|
Lookahead(
|
|
Read,
|
|
Read),
|
|
Read);
|
|
}
|
|
|
|
[Fact]
|
|
public void LookaheadsCanBeNested()
|
|
{
|
|
RunLookaheadTest("abcdefg", "abcdefebc",
|
|
Read, // Appended: "a" Reader: "bcdefg"
|
|
Lookahead( // Reader: "bcdefg"
|
|
Read, // Appended: "b" Reader: "cdefg";
|
|
Read, // Appended: "c" Reader: "defg";
|
|
Read, // Appended: "d" Reader: "efg";
|
|
Lookahead( // Reader: "efg"
|
|
Read, // Appended: "e" Reader: "fg";
|
|
Read // Appended: "f" Reader: "g";
|
|
), // Reader: "efg"
|
|
Read // Appended: "e" Reader: "fg";
|
|
), // Reader: "bcdefg"
|
|
Read, // Appended: "b" Reader: "cdefg";
|
|
Read); // Appended: "c" Reader: "defg";
|
|
}
|
|
|
|
[Fact]
|
|
public void SourceLocationIsZeroWhenInitialized()
|
|
{
|
|
RunSourceLocationTest("abcdefg", SourceLocation.Zero, checkAt: 0);
|
|
}
|
|
|
|
[Fact]
|
|
public void CharacterAndAbsoluteIndicesIncreaseAsCharactersAreRead()
|
|
{
|
|
RunSourceLocationTest("abcdefg", new SourceLocation(4, 0, 4), checkAt: 4);
|
|
}
|
|
|
|
[Fact]
|
|
public void CharacterAndAbsoluteIndicesIncreaseAsSlashRInTwoCharacterNewlineIsRead()
|
|
{
|
|
RunSourceLocationTest("f\r\nb", new SourceLocation(2, 0, 2), checkAt: 2);
|
|
}
|
|
|
|
[Fact]
|
|
public void CharacterIndexResetsToZeroAndLineIndexIncrementsWhenSlashNInTwoCharacterNewlineIsRead()
|
|
{
|
|
RunSourceLocationTest("f\r\nb", new SourceLocation(3, 1, 0), checkAt: 3);
|
|
}
|
|
|
|
[Fact]
|
|
public void CharacterIndexResetsToZeroAndLineIndexIncrementsWhenSlashRInSingleCharacterNewlineIsRead()
|
|
{
|
|
RunSourceLocationTest("f\rb", new SourceLocation(2, 1, 0), checkAt: 2);
|
|
}
|
|
|
|
[Fact]
|
|
public void CharacterIndexResetsToZeroAndLineIndexIncrementsWhenSlashNInSingleCharacterNewlineIsRead()
|
|
{
|
|
RunSourceLocationTest("f\nb", new SourceLocation(2, 1, 0), checkAt: 2);
|
|
}
|
|
|
|
[Fact]
|
|
public void EndingLookaheadResetsRawCharacterAndLineIndexToValuesWhenLookaheadBegan()
|
|
{
|
|
RunEndLookaheadUpdatesSourceLocationTest();
|
|
}
|
|
|
|
[Fact]
|
|
public void OnceBufferingBeginsReadsCanContinuePastEndOfBuffer()
|
|
{
|
|
RunLookaheadTest("abcdefg", "abcbcdefg",
|
|
Read,
|
|
Lookahead(Read(2)),
|
|
Read(2),
|
|
ReadToEnd);
|
|
}
|
|
|
|
[Fact]
|
|
public void DisposeDisposesSourceReader()
|
|
{
|
|
RunDisposeTest(r => r.Dispose());
|
|
}
|
|
|
|
[Fact]
|
|
public void CloseDisposesSourceReader()
|
|
{
|
|
RunDisposeTest(r => r.Close());
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadWithBufferSupportsLookahead()
|
|
{
|
|
RunBufferReadTest((reader, buffer, index, count) => reader.Read(buffer, index, count));
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadBlockSupportsLookahead()
|
|
{
|
|
RunBufferReadTest((reader, buffer, index, count) => reader.ReadBlock(buffer, index, count));
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadLineSupportsLookahead()
|
|
{
|
|
RunReadUntilTest(r => r.ReadLine(), expectedRaw: 8, expectedChar: 0, expectedLine: 2);
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadToEndSupportsLookahead()
|
|
{
|
|
RunReadUntilTest(r => r.ReadToEnd(), expectedRaw: 11, expectedChar: 3, expectedLine: 2);
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadLineMaintainsCorrectCharacterPosition()
|
|
{
|
|
RunSourceLocationTest("abc\r\ndef", new SourceLocation(5, 1, 0), r => r.ReadLine());
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadToEndWorksAsInNormalTextReader()
|
|
{
|
|
RunReadToEndTest();
|
|
}
|
|
|
|
[Fact]
|
|
public void CancelBacktrackStopsNextEndLookaheadFromBacktracking()
|
|
{
|
|
RunLookaheadTest("abcdefg", "abcdefg",
|
|
Lookahead(
|
|
Read(2),
|
|
CancelBacktrack
|
|
),
|
|
ReadToEnd);
|
|
}
|
|
|
|
[Fact]
|
|
public void CancelBacktrackThrowsInvalidOperationExceptionIfCalledOutsideOfLookahead()
|
|
{
|
|
RunCancelBacktrackOutsideLookaheadTest();
|
|
}
|
|
|
|
[Fact]
|
|
public void CancelBacktrackOnlyCancelsBacktrackingForInnermostNestedLookahead()
|
|
{
|
|
RunLookaheadTest("abcdefg", "abcdabcdefg",
|
|
Lookahead(
|
|
Read(2),
|
|
Lookahead(
|
|
Read,
|
|
CancelBacktrack
|
|
),
|
|
Read
|
|
),
|
|
ReadToEnd);
|
|
}
|
|
|
|
[Fact]
|
|
public void BacktrackBufferIsClearedWhenEndReachedAndNoCurrentLookaheads()
|
|
{
|
|
// Arrange
|
|
StringReader source = new StringReader(TestString);
|
|
BufferingTextReader reader = new BufferingTextReader(source);
|
|
|
|
reader.Read(); // Reader: "bcdefg"
|
|
using (reader.BeginLookahead())
|
|
{
|
|
reader.Read(); // Reader: "cdefg"
|
|
} // Reader: "bcdefg"
|
|
reader.Read(); // Reader: "cdefg"
|
|
Assert.NotNull(reader.Buffer); // Verify our assumption that the buffer still exists
|
|
|
|
// Act
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.False(reader.Buffering, "The buffer was not reset when the end was reached");
|
|
Assert.Equal(0, reader.Buffer.Length);
|
|
}
|
|
|
|
private static void RunDisposeTest(Action<LookaheadTextReader> triggerAction)
|
|
{
|
|
// Arrange
|
|
DisposeTestMockTextReader source = new DisposeTestMockTextReader();
|
|
LookaheadTextReader reader = new BufferingTextReader(source);
|
|
|
|
// Act
|
|
triggerAction(reader);
|
|
|
|
// Assert
|
|
Assert.True(source.Disposed);
|
|
}
|
|
}
|
|
}
|