summaryrefslogtreecommitdiffstats
path: root/image/test/gtest/TestStreamingLexer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'image/test/gtest/TestStreamingLexer.cpp')
-rw-r--r--image/test/gtest/TestStreamingLexer.cpp973
1 files changed, 0 insertions, 973 deletions
diff --git a/image/test/gtest/TestStreamingLexer.cpp b/image/test/gtest/TestStreamingLexer.cpp
deleted file mode 100644
index 590b10e81..000000000
--- a/image/test/gtest/TestStreamingLexer.cpp
+++ /dev/null
@@ -1,973 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "gtest/gtest.h"
-
-#include "mozilla/Vector.h"
-#include "StreamingLexer.h"
-
-using namespace mozilla;
-using namespace mozilla::image;
-
-enum class TestState
-{
- ONE,
- TWO,
- THREE,
- UNBUFFERED,
- TRUNCATED_SUCCESS,
- TRUNCATED_FAILURE
-};
-
-void
-CheckLexedData(const char* aData,
- size_t aLength,
- size_t aOffset,
- size_t aExpectedLength)
-{
- EXPECT_TRUE(aLength == aExpectedLength);
-
- for (size_t i = 0; i < aLength; ++i) {
- EXPECT_EQ(aData[i], char(aOffset + i + 1));
- }
-}
-
-LexerTransition<TestState>
-DoLex(TestState aState, const char* aData, size_t aLength)
-{
- switch (aState) {
- case TestState::ONE:
- CheckLexedData(aData, aLength, 0, 3);
- return Transition::To(TestState::TWO, 3);
- case TestState::TWO:
- CheckLexedData(aData, aLength, 3, 3);
- return Transition::To(TestState::THREE, 3);
- case TestState::THREE:
- CheckLexedData(aData, aLength, 6, 3);
- return Transition::TerminateSuccess();
- case TestState::TRUNCATED_SUCCESS:
- return Transition::TerminateSuccess();
- case TestState::TRUNCATED_FAILURE:
- return Transition::TerminateFailure();
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-LexerTransition<TestState>
-DoLexWithUnbuffered(TestState aState, const char* aData, size_t aLength,
- Vector<char>& aUnbufferedVector)
-{
- switch (aState) {
- case TestState::ONE:
- CheckLexedData(aData, aLength, 0, 3);
- return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 3);
- case TestState::TWO:
- CheckLexedData(aUnbufferedVector.begin(), aUnbufferedVector.length(), 3, 3);
- return Transition::To(TestState::THREE, 3);
- case TestState::THREE:
- CheckLexedData(aData, aLength, 6, 3);
- return Transition::TerminateSuccess();
- case TestState::UNBUFFERED:
- EXPECT_TRUE(aLength <= 3);
- EXPECT_TRUE(aUnbufferedVector.append(aData, aLength));
- return Transition::ContinueUnbuffered(TestState::UNBUFFERED);
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-LexerTransition<TestState>
-DoLexWithUnbufferedTerminate(TestState aState, const char* aData, size_t aLength)
-{
- switch (aState) {
- case TestState::ONE:
- CheckLexedData(aData, aLength, 0, 3);
- return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 3);
- case TestState::UNBUFFERED:
- return Transition::TerminateSuccess();
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-LexerTransition<TestState>
-DoLexWithYield(TestState aState, const char* aData, size_t aLength)
-{
- switch (aState) {
- case TestState::ONE:
- CheckLexedData(aData, aLength, 0, 3);
- return Transition::ToAfterYield(TestState::TWO);
- case TestState::TWO:
- CheckLexedData(aData, aLength, 0, 3);
- return Transition::To(TestState::THREE, 6);
- case TestState::THREE:
- CheckLexedData(aData, aLength, 3, 6);
- return Transition::TerminateSuccess();
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-LexerTransition<TestState>
-DoLexWithTerminateAfterYield(TestState aState, const char* aData, size_t aLength)
-{
- switch (aState) {
- case TestState::ONE:
- CheckLexedData(aData, aLength, 0, 3);
- return Transition::ToAfterYield(TestState::TWO);
- case TestState::TWO:
- return Transition::TerminateSuccess();
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-LexerTransition<TestState>
-DoLexWithZeroLengthStates(TestState aState, const char* aData, size_t aLength)
-{
- switch (aState) {
- case TestState::ONE:
- EXPECT_TRUE(aLength == 0);
- return Transition::To(TestState::TWO, 0);
- case TestState::TWO:
- EXPECT_TRUE(aLength == 0);
- return Transition::To(TestState::THREE, 9);
- case TestState::THREE:
- CheckLexedData(aData, aLength, 0, 9);
- return Transition::TerminateSuccess();
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-LexerTransition<TestState>
-DoLexWithZeroLengthStatesAtEnd(TestState aState, const char* aData, size_t aLength)
-{
- switch (aState) {
- case TestState::ONE:
- CheckLexedData(aData, aLength, 0, 9);
- return Transition::To(TestState::TWO, 0);
- case TestState::TWO:
- EXPECT_TRUE(aLength == 0);
- return Transition::To(TestState::THREE, 0);
- case TestState::THREE:
- EXPECT_TRUE(aLength == 0);
- return Transition::TerminateSuccess();
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-LexerTransition<TestState>
-DoLexWithZeroLengthYield(TestState aState, const char* aData, size_t aLength)
-{
- switch (aState) {
- case TestState::ONE:
- EXPECT_EQ(0u, aLength);
- return Transition::ToAfterYield(TestState::TWO);
- case TestState::TWO:
- EXPECT_EQ(0u, aLength);
- return Transition::To(TestState::THREE, 9);
- case TestState::THREE:
- CheckLexedData(aData, aLength, 0, 9);
- return Transition::TerminateSuccess();
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-LexerTransition<TestState>
-DoLexWithZeroLengthStatesUnbuffered(TestState aState,
- const char* aData,
- size_t aLength)
-{
- switch (aState) {
- case TestState::ONE:
- EXPECT_TRUE(aLength == 0);
- return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 0);
- case TestState::TWO:
- EXPECT_TRUE(aLength == 0);
- return Transition::To(TestState::THREE, 9);
- case TestState::THREE:
- CheckLexedData(aData, aLength, 0, 9);
- return Transition::TerminateSuccess();
- case TestState::UNBUFFERED:
- ADD_FAILURE() << "Should not enter zero-length unbuffered state";
- return Transition::TerminateFailure();
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-LexerTransition<TestState>
-DoLexWithZeroLengthStatesAfterUnbuffered(TestState aState,
- const char* aData,
- size_t aLength)
-{
- switch (aState) {
- case TestState::ONE:
- EXPECT_TRUE(aLength == 0);
- return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 9);
- case TestState::TWO:
- EXPECT_TRUE(aLength == 0);
- return Transition::To(TestState::THREE, 0);
- case TestState::THREE:
- EXPECT_TRUE(aLength == 0);
- return Transition::TerminateSuccess();
- case TestState::UNBUFFERED:
- CheckLexedData(aData, aLength, 0, 9);
- return Transition::ContinueUnbuffered(TestState::UNBUFFERED);
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
-}
-
-class ImageStreamingLexer : public ::testing::Test
-{
-public:
- // Note that mLexer is configured to enter TerminalState::FAILURE immediately
- // if the input data is truncated. We don't expect that to happen in most
- // tests, so we want to detect that issue. If a test needs a different
- // behavior, we create a special StreamingLexer just for that test.
- ImageStreamingLexer()
- : mLexer(Transition::To(TestState::ONE, 3), Transition::TerminateFailure())
- , mSourceBuffer(new SourceBuffer)
- , mIterator(mSourceBuffer->Iterator())
- , mExpectNoResume(new ExpectNoResume)
- , mCountResumes(new CountResumes)
- { }
-
-protected:
- void CheckTruncatedState(StreamingLexer<TestState>& aLexer,
- TerminalState aExpectedTerminalState,
- nsresult aCompletionStatus = NS_OK)
- {
- for (unsigned i = 0; i < 9; ++i) {
- if (i < 2) {
- mSourceBuffer->Append(mData + i, 1);
- } else if (i == 2) {
- mSourceBuffer->Complete(aCompletionStatus);
- }
-
- LexerResult result = aLexer.Lex(mIterator, mCountResumes, DoLex);
-
- if (i >= 2) {
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(aExpectedTerminalState, result.as<TerminalState>());
- } else {
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- }
- }
-
- EXPECT_EQ(2u, mCountResumes->Count());
- }
-
- AutoInitializeImageLib mInit;
- const char mData[9] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
- StreamingLexer<TestState> mLexer;
- RefPtr<SourceBuffer> mSourceBuffer;
- SourceBufferIterator mIterator;
- RefPtr<ExpectNoResume> mExpectNoResume;
- RefPtr<CountResumes> mCountResumes;
-};
-
-TEST_F(ImageStreamingLexer, ZeroLengthData)
-{
- // Test a zero-length input.
- mSourceBuffer->Complete(NS_OK);
-
- LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLex);
-
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, ZeroLengthDataUnbuffered)
-{
- // Test a zero-length input.
- mSourceBuffer->Complete(NS_OK);
-
- // Create a special StreamingLexer for this test because we want the first
- // state to be unbuffered.
- StreamingLexer<TestState> lexer(Transition::ToUnbuffered(TestState::ONE,
- TestState::UNBUFFERED,
- sizeof(mData)),
- Transition::TerminateFailure());
-
- LexerResult result = lexer.Lex(mIterator, mExpectNoResume, DoLex);
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, StartWithTerminal)
-{
- // Create a special StreamingLexer for this test because we want the first
- // state to be a terminal state. This doesn't really make sense, but we should
- // handle it.
- StreamingLexer<TestState> lexer(Transition::TerminateSuccess(),
- Transition::TerminateFailure());
- LexerResult result = lexer.Lex(mIterator, mExpectNoResume, DoLex);
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-
- mSourceBuffer->Complete(NS_OK);
-}
-
-TEST_F(ImageStreamingLexer, SingleChunk)
-{
- // Test delivering all the data at once.
- mSourceBuffer->Append(mData, sizeof(mData));
- mSourceBuffer->Complete(NS_OK);
-
- LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLex);
-
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, SingleChunkWithUnbuffered)
-{
- Vector<char> unbufferedVector;
-
- // Test delivering all the data at once.
- mSourceBuffer->Append(mData, sizeof(mData));
- mSourceBuffer->Complete(NS_OK);
-
- LexerResult result =
- mLexer.Lex(mIterator, mExpectNoResume,
- [&](TestState aState, const char* aData, size_t aLength) {
- return DoLexWithUnbuffered(aState, aData, aLength, unbufferedVector);
- });
-
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, SingleChunkWithYield)
-{
- // Test delivering all the data at once.
- mSourceBuffer->Append(mData, sizeof(mData));
- mSourceBuffer->Complete(NS_OK);
-
- LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLexWithYield);
- ASSERT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
-
- result = mLexer.Lex(mIterator, mExpectNoResume, DoLexWithYield);
- ASSERT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, ChunkPerState)
-{
- // Test delivering in perfectly-sized chunks, one per state.
- for (unsigned i = 0; i < 3; ++i) {
- mSourceBuffer->Append(mData + 3 * i, 3);
- LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLex);
-
- if (i == 2) {
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- } else {
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- }
- }
-
- EXPECT_EQ(2u, mCountResumes->Count());
- mSourceBuffer->Complete(NS_OK);
-}
-
-TEST_F(ImageStreamingLexer, ChunkPerStateWithUnbuffered)
-{
- Vector<char> unbufferedVector;
-
- // Test delivering in perfectly-sized chunks, one per state.
- for (unsigned i = 0; i < 3; ++i) {
- mSourceBuffer->Append(mData + 3 * i, 3);
- LexerResult result =
- mLexer.Lex(mIterator, mCountResumes,
- [&](TestState aState, const char* aData, size_t aLength) {
- return DoLexWithUnbuffered(aState, aData, aLength, unbufferedVector);
- });
-
- if (i == 2) {
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- } else {
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- }
- }
-
- EXPECT_EQ(2u, mCountResumes->Count());
- mSourceBuffer->Complete(NS_OK);
-}
-
-TEST_F(ImageStreamingLexer, ChunkPerStateWithYield)
-{
- // Test delivering in perfectly-sized chunks, one per state.
- mSourceBuffer->Append(mData, 3);
- LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
-
- result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
-
- mSourceBuffer->Append(mData + 3, 6);
- result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-
- EXPECT_EQ(1u, mCountResumes->Count());
- mSourceBuffer->Complete(NS_OK);
-}
-
-TEST_F(ImageStreamingLexer, ChunkPerStateWithUnbufferedYield)
-{
- size_t unbufferedCallCount = 0;
- Vector<char> unbufferedVector;
- auto lexerFunc = [&](TestState aState, const char* aData, size_t aLength)
- -> LexerTransition<TestState> {
- switch (aState) {
- case TestState::ONE:
- CheckLexedData(aData, aLength, 0, 3);
- return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 3);
- case TestState::TWO:
- CheckLexedData(unbufferedVector.begin(), unbufferedVector.length(), 3, 3);
- return Transition::To(TestState::THREE, 3);
- case TestState::THREE:
- CheckLexedData(aData, aLength, 6, 3);
- return Transition::TerminateSuccess();
- case TestState::UNBUFFERED:
- switch (unbufferedCallCount) {
- case 0:
- CheckLexedData(aData, aLength, 3, 3);
- EXPECT_TRUE(unbufferedVector.append(aData, 2));
- unbufferedCallCount++;
-
- // Continue after yield, telling StreamingLexer we consumed 2 bytes.
- return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 2);
-
- case 1:
- CheckLexedData(aData, aLength, 5, 1);
- EXPECT_TRUE(unbufferedVector.append(aData, 1));
- unbufferedCallCount++;
-
- // Continue after yield, telling StreamingLexer we consumed 1 byte.
- // We should end up in the TWO state.
- return Transition::ContinueUnbuffered(TestState::UNBUFFERED);
- }
- ADD_FAILURE() << "Too many invocations of TestState::UNBUFFERED";
- return Transition::TerminateFailure();
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
- };
-
- // Test delivering in perfectly-sized chunks, one per state.
- for (unsigned i = 0; i < 3; ++i) {
- mSourceBuffer->Append(mData + 3 * i, 3);
- LexerResult result = mLexer.Lex(mIterator, mCountResumes, lexerFunc);
-
- switch (i) {
- case 0:
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- EXPECT_EQ(0u, unbufferedCallCount);
- break;
-
- case 1:
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
- EXPECT_EQ(1u, unbufferedCallCount);
-
- result = mLexer.Lex(mIterator, mCountResumes, lexerFunc);
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- EXPECT_EQ(2u, unbufferedCallCount);
- break;
-
- case 2:
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- break;
- }
- }
-
- EXPECT_EQ(2u, mCountResumes->Count());
- mSourceBuffer->Complete(NS_OK);
-
- LexerResult result = mLexer.Lex(mIterator, mCountResumes, lexerFunc);
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, OneByteChunks)
-{
- // Test delivering in one byte chunks.
- for (unsigned i = 0; i < 9; ++i) {
- mSourceBuffer->Append(mData + i, 1);
- LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLex);
-
- if (i == 8) {
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- } else {
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- }
- }
-
- EXPECT_EQ(8u, mCountResumes->Count());
- mSourceBuffer->Complete(NS_OK);
-}
-
-TEST_F(ImageStreamingLexer, OneByteChunksWithUnbuffered)
-{
- Vector<char> unbufferedVector;
-
- // Test delivering in one byte chunks.
- for (unsigned i = 0; i < 9; ++i) {
- mSourceBuffer->Append(mData + i, 1);
- LexerResult result =
- mLexer.Lex(mIterator, mCountResumes,
- [&](TestState aState, const char* aData, size_t aLength) {
- return DoLexWithUnbuffered(aState, aData, aLength, unbufferedVector);
- });
-
- if (i == 8) {
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- } else {
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- }
- }
-
- EXPECT_EQ(8u, mCountResumes->Count());
- mSourceBuffer->Complete(NS_OK);
-}
-
-TEST_F(ImageStreamingLexer, OneByteChunksWithYield)
-{
- // Test delivering in one byte chunks.
- for (unsigned i = 0; i < 9; ++i) {
- mSourceBuffer->Append(mData + i, 1);
- LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
-
- switch (i) {
- case 2:
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
-
- result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- break;
-
- case 8:
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- break;
-
- default:
- EXPECT_TRUE(i < 9);
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- }
- }
-
- EXPECT_EQ(8u, mCountResumes->Count());
- mSourceBuffer->Complete(NS_OK);
-}
-
-TEST_F(ImageStreamingLexer, ZeroLengthState)
-{
- mSourceBuffer->Append(mData, sizeof(mData));
- mSourceBuffer->Complete(NS_OK);
-
- // Create a special StreamingLexer for this test because we want the first
- // state to be zero length.
- StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 0),
- Transition::TerminateFailure());
-
- LexerResult result =
- lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStates);
-
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, ZeroLengthStatesAtEnd)
-{
- mSourceBuffer->Append(mData, sizeof(mData));
- mSourceBuffer->Complete(NS_OK);
-
- // Create a special StreamingLexer for this test because we want the first
- // state to consume the full input.
- StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 9),
- Transition::TerminateFailure());
-
- LexerResult result =
- lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStatesAtEnd);
-
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, ZeroLengthStateWithYield)
-{
- // Create a special StreamingLexer for this test because we want the first
- // state to be zero length.
- StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 0),
- Transition::TerminateFailure());
-
- mSourceBuffer->Append(mData, 3);
- LexerResult result =
- lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthYield);
- ASSERT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
-
- result = lexer.Lex(mIterator, mCountResumes, DoLexWithZeroLengthYield);
- ASSERT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
-
- mSourceBuffer->Append(mData + 3, sizeof(mData) - 3);
- mSourceBuffer->Complete(NS_OK);
- result = lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthYield);
- ASSERT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- EXPECT_EQ(1u, mCountResumes->Count());
-}
-
-TEST_F(ImageStreamingLexer, ZeroLengthStateWithUnbuffered)
-{
- mSourceBuffer->Append(mData, sizeof(mData));
- mSourceBuffer->Complete(NS_OK);
-
- // Create a special StreamingLexer for this test because we want the first
- // state to be both zero length and unbuffered.
- StreamingLexer<TestState> lexer(Transition::ToUnbuffered(TestState::ONE,
- TestState::UNBUFFERED,
- 0),
- Transition::TerminateFailure());
-
- LexerResult result =
- lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStatesUnbuffered);
-
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, ZeroLengthStateAfterUnbuffered)
-{
- mSourceBuffer->Append(mData, sizeof(mData));
- mSourceBuffer->Complete(NS_OK);
-
- // Create a special StreamingLexer for this test because we want the first
- // state to be zero length.
- StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 0),
- Transition::TerminateFailure());
-
- LexerResult result =
- lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStatesAfterUnbuffered);
-
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, ZeroLengthStateWithUnbufferedYield)
-{
- size_t unbufferedCallCount = 0;
- auto lexerFunc = [&](TestState aState, const char* aData, size_t aLength)
- -> LexerTransition<TestState> {
- switch (aState) {
- case TestState::ONE:
- EXPECT_EQ(0u, aLength);
- return Transition::TerminateSuccess();
-
- case TestState::UNBUFFERED:
- switch (unbufferedCallCount) {
- case 0:
- CheckLexedData(aData, aLength, 0, 3);
- unbufferedCallCount++;
-
- // Continue after yield, telling StreamingLexer we consumed 0 bytes.
- return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 0);
-
- case 1:
- CheckLexedData(aData, aLength, 0, 3);
- unbufferedCallCount++;
-
- // Continue after yield, telling StreamingLexer we consumed 2 bytes.
- return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 2);
-
- case 2:
- EXPECT_EQ(1u, aLength);
- CheckLexedData(aData, aLength, 2, 1);
- unbufferedCallCount++;
-
- // Continue after yield, telling StreamingLexer we consumed 1 bytes.
- return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 1);
-
- case 3:
- CheckLexedData(aData, aLength, 3, 6);
- unbufferedCallCount++;
-
- // Continue after yield, telling StreamingLexer we consumed 6 bytes.
- // We should transition to TestState::ONE when we return from the
- // yield.
- return Transition::ContinueUnbufferedAfterYield(TestState::UNBUFFERED, 6);
- }
-
- ADD_FAILURE() << "Too many invocations of TestState::UNBUFFERED";
- return Transition::TerminateFailure();
-
- default:
- MOZ_CRASH("Unexpected or unhandled TestState");
- }
- };
-
- // Create a special StreamingLexer for this test because we want the first
- // state to be unbuffered.
- StreamingLexer<TestState> lexer(Transition::ToUnbuffered(TestState::ONE,
- TestState::UNBUFFERED,
- sizeof(mData)),
- Transition::TerminateFailure());
-
- mSourceBuffer->Append(mData, 3);
- LexerResult result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
- ASSERT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
- EXPECT_EQ(1u, unbufferedCallCount);
-
- result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
- ASSERT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
- EXPECT_EQ(2u, unbufferedCallCount);
-
- result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
- ASSERT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
- EXPECT_EQ(3u, unbufferedCallCount);
-
- result = lexer.Lex(mIterator, mCountResumes, lexerFunc);
- ASSERT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- EXPECT_EQ(3u, unbufferedCallCount);
-
- mSourceBuffer->Append(mData + 3, 6);
- mSourceBuffer->Complete(NS_OK);
- EXPECT_EQ(1u, mCountResumes->Count());
- result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
- ASSERT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
- EXPECT_EQ(4u, unbufferedCallCount);
-
- result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
- ASSERT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, TerminateSuccess)
-{
- mSourceBuffer->Append(mData, sizeof(mData));
- mSourceBuffer->Complete(NS_OK);
-
- // Test that Terminate is "sticky".
- SourceBufferIterator iterator = mSourceBuffer->Iterator();
- LexerResult result =
- mLexer.Lex(iterator, mExpectNoResume,
- [&](TestState aState, const char* aData, size_t aLength) {
- EXPECT_TRUE(aState == TestState::ONE);
- return Transition::TerminateSuccess();
- });
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-
- SourceBufferIterator iterator2 = mSourceBuffer->Iterator();
- result =
- mLexer.Lex(iterator2, mExpectNoResume,
- [&](TestState aState, const char* aData, size_t aLength) {
- EXPECT_TRUE(false); // Shouldn't get here.
- return Transition::TerminateFailure();
- });
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, TerminateFailure)
-{
- mSourceBuffer->Append(mData, sizeof(mData));
- mSourceBuffer->Complete(NS_OK);
-
- // Test that Terminate is "sticky".
- SourceBufferIterator iterator = mSourceBuffer->Iterator();
- LexerResult result =
- mLexer.Lex(iterator, mExpectNoResume,
- [&](TestState aState, const char* aData, size_t aLength) {
- EXPECT_TRUE(aState == TestState::ONE);
- return Transition::TerminateFailure();
- });
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
-
- SourceBufferIterator iterator2 = mSourceBuffer->Iterator();
- result =
- mLexer.Lex(iterator2, mExpectNoResume,
- [&](TestState aState, const char* aData, size_t aLength) {
- EXPECT_TRUE(false); // Shouldn't get here.
- return Transition::TerminateFailure();
- });
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, TerminateUnbuffered)
-{
- // Test that Terminate works during an unbuffered read.
- for (unsigned i = 0; i < 9; ++i) {
- mSourceBuffer->Append(mData + i, 1);
- LexerResult result =
- mLexer.Lex(mIterator, mCountResumes, DoLexWithUnbufferedTerminate);
-
- if (i > 2) {
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- } else {
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- }
- }
-
- // We expect 3 resumes because TestState::ONE consumes 3 bytes and then
- // transitions to TestState::UNBUFFERED, which calls TerminateSuccess() as
- // soon as it receives a single byte. That's four bytes total, which are
- // delivered one at a time, requiring 3 resumes.
- EXPECT_EQ(3u, mCountResumes->Count());
-
- mSourceBuffer->Complete(NS_OK);
-}
-
-TEST_F(ImageStreamingLexer, TerminateAfterYield)
-{
- // Test that Terminate works after yielding.
- for (unsigned i = 0; i < 9; ++i) {
- mSourceBuffer->Append(mData + i, 1);
- LexerResult result =
- mLexer.Lex(mIterator, mCountResumes, DoLexWithTerminateAfterYield);
-
- if (i > 2) {
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- } else if (i == 2) {
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
- } else {
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- }
- }
-
- // We expect 2 resumes because TestState::ONE consumes 3 bytes and then
- // yields. When the lexer resumes at TestState::TWO, which receives the same 3
- // bytes, TerminateSuccess() gets called immediately. That's three bytes
- // total, which are delivered one at a time, requiring 2 resumes.
- EXPECT_EQ(2u, mCountResumes->Count());
-
- mSourceBuffer->Complete(NS_OK);
-}
-
-TEST_F(ImageStreamingLexer, SourceBufferImmediateComplete)
-{
- // Test calling SourceBuffer::Complete() without appending any data. This
- // causes the SourceBuffer to automatically have a failing completion status,
- // no matter what you pass, so we expect TerminalState::FAILURE below.
- mSourceBuffer->Complete(NS_OK);
-
- LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLex);
-
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
-}
-
-TEST_F(ImageStreamingLexer, SourceBufferTruncatedTerminalStateSuccess)
-{
- // Test that using a terminal state (in this case TerminalState::SUCCESS) as a
- // truncated state works.
- StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 3),
- Transition::TerminateSuccess());
-
- CheckTruncatedState(lexer, TerminalState::SUCCESS);
-}
-
-TEST_F(ImageStreamingLexer, SourceBufferTruncatedTerminalStateFailure)
-{
- // Test that using a terminal state (in this case TerminalState::FAILURE) as a
- // truncated state works.
- StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 3),
- Transition::TerminateFailure());
-
- CheckTruncatedState(lexer, TerminalState::FAILURE);
-}
-
-TEST_F(ImageStreamingLexer, SourceBufferTruncatedStateReturningSuccess)
-{
- // Test that a truncated state that returns TerminalState::SUCCESS works. When
- // |lexer| discovers that the data is truncated, it invokes the
- // TRUNCATED_SUCCESS state, which returns TerminalState::SUCCESS.
- // CheckTruncatedState() verifies that this happens.
- StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 3),
- Transition::To(TestState::TRUNCATED_SUCCESS, 0));
-
- CheckTruncatedState(lexer, TerminalState::SUCCESS);
-}
-
-TEST_F(ImageStreamingLexer, SourceBufferTruncatedStateReturningFailure)
-{
- // Test that a truncated state that returns TerminalState::FAILURE works. When
- // |lexer| discovers that the data is truncated, it invokes the
- // TRUNCATED_FAILURE state, which returns TerminalState::FAILURE.
- // CheckTruncatedState() verifies that this happens.
- StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 3),
- Transition::To(TestState::TRUNCATED_FAILURE, 0));
-
- CheckTruncatedState(lexer, TerminalState::FAILURE);
-}
-
-TEST_F(ImageStreamingLexer, SourceBufferTruncatedFailingCompleteStatus)
-{
- // Test that calling SourceBuffer::Complete() with a failing status results in
- // an immediate TerminalState::FAILURE result. (Note that |lexer|'s truncated
- // state is TerminalState::SUCCESS, so if we ignore the failing status, the
- // test will fail.)
- StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 3),
- Transition::TerminateSuccess());
-
- CheckTruncatedState(lexer, TerminalState::FAILURE, NS_ERROR_FAILURE);
-}
-
-TEST_F(ImageStreamingLexer, NoSourceBufferResumable)
-{
- // Test delivering in one byte chunks with no IResumable.
- for (unsigned i = 0; i < 9; ++i) {
- mSourceBuffer->Append(mData + i, 1);
- LexerResult result = mLexer.Lex(mIterator, nullptr, DoLex);
-
- if (i == 8) {
- EXPECT_TRUE(result.is<TerminalState>());
- EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
- } else {
- EXPECT_TRUE(result.is<Yield>());
- EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
- }
- }
-
- mSourceBuffer->Complete(NS_OK);
-}