tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestStreamingLexer.cpp (34023B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "gtest/gtest.h"
      6 
      7 #include "Common.h"
      8 #include "mozilla/Vector.h"
      9 #include "StreamingLexer.h"
     10 
     11 using namespace mozilla;
     12 using namespace mozilla::image;
     13 
     14 enum class TestState {
     15  ONE,
     16  TWO,
     17  THREE,
     18  UNBUFFERED,
     19  TRUNCATED_SUCCESS,
     20  TRUNCATED_FAILURE
     21 };
     22 
     23 void CheckLexedData(const char* aData, size_t aLength, size_t aOffset,
     24                    size_t aExpectedLength) {
     25  EXPECT_TRUE(aLength == aExpectedLength);
     26 
     27  for (size_t i = 0; i < aLength; ++i) {
     28    EXPECT_EQ(aData[i], char(aOffset + i + 1));
     29  }
     30 }
     31 
     32 LexerTransition<TestState> DoLex(TestState aState, const char* aData,
     33                                 size_t aLength) {
     34  switch (aState) {
     35    case TestState::ONE:
     36      CheckLexedData(aData, aLength, 0, 3);
     37      return Transition::To(TestState::TWO, 3);
     38    case TestState::TWO:
     39      CheckLexedData(aData, aLength, 3, 3);
     40      return Transition::To(TestState::THREE, 3);
     41    case TestState::THREE:
     42      CheckLexedData(aData, aLength, 6, 3);
     43      return Transition::TerminateSuccess();
     44    case TestState::TRUNCATED_SUCCESS:
     45      return Transition::TerminateSuccess();
     46    case TestState::TRUNCATED_FAILURE:
     47      return Transition::TerminateFailure();
     48    default:
     49      MOZ_CRASH("Unexpected or unhandled TestState");
     50  }
     51 }
     52 
     53 LexerTransition<TestState> DoLexWithUnbuffered(
     54    TestState aState, const char* aData, size_t aLength,
     55    Vector<char>& aUnbufferedVector) {
     56  switch (aState) {
     57    case TestState::ONE:
     58      CheckLexedData(aData, aLength, 0, 3);
     59      return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 3);
     60    case TestState::TWO:
     61      CheckLexedData(aUnbufferedVector.begin(), aUnbufferedVector.length(), 3,
     62                     3);
     63      return Transition::To(TestState::THREE, 3);
     64    case TestState::THREE:
     65      CheckLexedData(aData, aLength, 6, 3);
     66      return Transition::TerminateSuccess();
     67    case TestState::UNBUFFERED:
     68      EXPECT_TRUE(aLength <= 3);
     69      EXPECT_TRUE(aUnbufferedVector.append(aData, aLength));
     70      return Transition::ContinueUnbuffered(TestState::UNBUFFERED);
     71    default:
     72      MOZ_CRASH("Unexpected or unhandled TestState");
     73  }
     74 }
     75 
     76 LexerTransition<TestState> DoLexWithUnbufferedTerminate(TestState aState,
     77                                                        const char* aData,
     78                                                        size_t aLength) {
     79  switch (aState) {
     80    case TestState::ONE:
     81      CheckLexedData(aData, aLength, 0, 3);
     82      return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 3);
     83    case TestState::UNBUFFERED:
     84      return Transition::TerminateSuccess();
     85    default:
     86      MOZ_CRASH("Unexpected or unhandled TestState");
     87  }
     88 }
     89 
     90 LexerTransition<TestState> DoLexWithYield(TestState aState, const char* aData,
     91                                          size_t aLength) {
     92  switch (aState) {
     93    case TestState::ONE:
     94      CheckLexedData(aData, aLength, 0, 3);
     95      return Transition::ToAfterYield(TestState::TWO);
     96    case TestState::TWO:
     97      CheckLexedData(aData, aLength, 0, 3);
     98      return Transition::To(TestState::THREE, 6);
     99    case TestState::THREE:
    100      CheckLexedData(aData, aLength, 3, 6);
    101      return Transition::TerminateSuccess();
    102    default:
    103      MOZ_CRASH("Unexpected or unhandled TestState");
    104  }
    105 }
    106 
    107 LexerTransition<TestState> DoLexWithTerminateAfterYield(TestState aState,
    108                                                        const char* aData,
    109                                                        size_t aLength) {
    110  switch (aState) {
    111    case TestState::ONE:
    112      CheckLexedData(aData, aLength, 0, 3);
    113      return Transition::ToAfterYield(TestState::TWO);
    114    case TestState::TWO:
    115      return Transition::TerminateSuccess();
    116    default:
    117      MOZ_CRASH("Unexpected or unhandled TestState");
    118  }
    119 }
    120 
    121 LexerTransition<TestState> DoLexWithZeroLengthStates(TestState aState,
    122                                                     const char* aData,
    123                                                     size_t aLength) {
    124  switch (aState) {
    125    case TestState::ONE:
    126      EXPECT_TRUE(aLength == 0);
    127      return Transition::To(TestState::TWO, 0);
    128    case TestState::TWO:
    129      EXPECT_TRUE(aLength == 0);
    130      return Transition::To(TestState::THREE, 9);
    131    case TestState::THREE:
    132      CheckLexedData(aData, aLength, 0, 9);
    133      return Transition::TerminateSuccess();
    134    default:
    135      MOZ_CRASH("Unexpected or unhandled TestState");
    136  }
    137 }
    138 
    139 LexerTransition<TestState> DoLexWithZeroLengthStatesAtEnd(TestState aState,
    140                                                          const char* aData,
    141                                                          size_t aLength) {
    142  switch (aState) {
    143    case TestState::ONE:
    144      CheckLexedData(aData, aLength, 0, 9);
    145      return Transition::To(TestState::TWO, 0);
    146    case TestState::TWO:
    147      EXPECT_TRUE(aLength == 0);
    148      return Transition::To(TestState::THREE, 0);
    149    case TestState::THREE:
    150      EXPECT_TRUE(aLength == 0);
    151      return Transition::TerminateSuccess();
    152    default:
    153      MOZ_CRASH("Unexpected or unhandled TestState");
    154  }
    155 }
    156 
    157 LexerTransition<TestState> DoLexWithZeroLengthYield(TestState aState,
    158                                                    const char* aData,
    159                                                    size_t aLength) {
    160  switch (aState) {
    161    case TestState::ONE:
    162      EXPECT_EQ(0u, aLength);
    163      return Transition::ToAfterYield(TestState::TWO);
    164    case TestState::TWO:
    165      EXPECT_EQ(0u, aLength);
    166      return Transition::To(TestState::THREE, 9);
    167    case TestState::THREE:
    168      CheckLexedData(aData, aLength, 0, 9);
    169      return Transition::TerminateSuccess();
    170    default:
    171      MOZ_CRASH("Unexpected or unhandled TestState");
    172  }
    173 }
    174 
    175 LexerTransition<TestState> DoLexWithZeroLengthStatesUnbuffered(
    176    TestState aState, const char* aData, size_t aLength) {
    177  switch (aState) {
    178    case TestState::ONE:
    179      EXPECT_TRUE(aLength == 0);
    180      return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 0);
    181    case TestState::TWO:
    182      EXPECT_TRUE(aLength == 0);
    183      return Transition::To(TestState::THREE, 9);
    184    case TestState::THREE:
    185      CheckLexedData(aData, aLength, 0, 9);
    186      return Transition::TerminateSuccess();
    187    case TestState::UNBUFFERED:
    188      ADD_FAILURE() << "Should not enter zero-length unbuffered state";
    189      return Transition::TerminateFailure();
    190    default:
    191      MOZ_CRASH("Unexpected or unhandled TestState");
    192  }
    193 }
    194 
    195 LexerTransition<TestState> DoLexWithZeroLengthStatesAfterUnbuffered(
    196    TestState aState, const char* aData, size_t aLength) {
    197  switch (aState) {
    198    case TestState::ONE:
    199      EXPECT_TRUE(aLength == 0);
    200      return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED, 9);
    201    case TestState::TWO:
    202      EXPECT_TRUE(aLength == 0);
    203      return Transition::To(TestState::THREE, 0);
    204    case TestState::THREE:
    205      EXPECT_TRUE(aLength == 0);
    206      return Transition::TerminateSuccess();
    207    case TestState::UNBUFFERED:
    208      CheckLexedData(aData, aLength, 0, 9);
    209      return Transition::ContinueUnbuffered(TestState::UNBUFFERED);
    210    default:
    211      MOZ_CRASH("Unexpected or unhandled TestState");
    212  }
    213 }
    214 
    215 class ImageStreamingLexer : public ::testing::Test {
    216 public:
    217  // Note that mLexer is configured to enter TerminalState::FAILURE immediately
    218  // if the input data is truncated. We don't expect that to happen in most
    219  // tests, so we want to detect that issue. If a test needs a different
    220  // behavior, we create a special StreamingLexer just for that test.
    221  ImageStreamingLexer()
    222      : mLexer(Transition::To(TestState::ONE, 3),
    223               Transition::TerminateFailure()),
    224        mSourceBuffer(new SourceBuffer),
    225        mIterator(mSourceBuffer->Iterator()),
    226        mExpectNoResume(new ExpectNoResume),
    227        mCountResumes(new CountResumes) {}
    228 
    229 protected:
    230  void CheckTruncatedState(StreamingLexer<TestState>& aLexer,
    231                           TerminalState aExpectedTerminalState,
    232                           nsresult aCompletionStatus = NS_OK) {
    233    for (unsigned i = 0; i < 9; ++i) {
    234      if (i < 2) {
    235        mSourceBuffer->Append(mData + i, 1);
    236      } else if (i == 2) {
    237        mSourceBuffer->Complete(aCompletionStatus);
    238      }
    239 
    240      LexerResult result = aLexer.Lex(mIterator, mCountResumes, DoLex);
    241 
    242      if (i >= 2) {
    243        EXPECT_TRUE(result.is<TerminalState>());
    244        EXPECT_EQ(aExpectedTerminalState, result.as<TerminalState>());
    245      } else {
    246        EXPECT_TRUE(result.is<Yield>());
    247        EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    248      }
    249    }
    250 
    251    EXPECT_EQ(2u, mCountResumes->Count());
    252  }
    253 
    254  AutoInitializeImageLib mInit;
    255  const char mData[9]{1, 2, 3, 4, 5, 6, 7, 8, 9};
    256  StreamingLexer<TestState> mLexer;
    257  RefPtr<SourceBuffer> mSourceBuffer;
    258  SourceBufferIterator mIterator;
    259  RefPtr<ExpectNoResume> mExpectNoResume;
    260  RefPtr<CountResumes> mCountResumes;
    261 };
    262 
    263 TEST_F(ImageStreamingLexer, ZeroLengthData) {
    264  // Test a zero-length input.
    265  mSourceBuffer->Complete(NS_OK);
    266 
    267  LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLex);
    268 
    269  EXPECT_TRUE(result.is<TerminalState>());
    270  EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
    271 }
    272 
    273 TEST_F(ImageStreamingLexer, ZeroLengthDataUnbuffered) {
    274  // Test a zero-length input.
    275  mSourceBuffer->Complete(NS_OK);
    276 
    277  // Create a special StreamingLexer for this test because we want the first
    278  // state to be unbuffered.
    279  StreamingLexer<TestState> lexer(
    280      Transition::ToUnbuffered(TestState::ONE, TestState::UNBUFFERED,
    281                               sizeof(mData)),
    282      Transition::TerminateFailure());
    283 
    284  LexerResult result = lexer.Lex(mIterator, mExpectNoResume, DoLex);
    285  EXPECT_TRUE(result.is<TerminalState>());
    286  EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
    287 }
    288 
    289 TEST_F(ImageStreamingLexer, StartWithTerminal) {
    290  // Create a special StreamingLexer for this test because we want the first
    291  // state to be a terminal state. This doesn't really make sense, but we should
    292  // handle it.
    293  StreamingLexer<TestState> lexer(Transition::TerminateSuccess(),
    294                                  Transition::TerminateFailure());
    295  LexerResult result = lexer.Lex(mIterator, mExpectNoResume, DoLex);
    296  EXPECT_TRUE(result.is<TerminalState>());
    297  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    298 
    299  mSourceBuffer->Complete(NS_OK);
    300 }
    301 
    302 TEST_F(ImageStreamingLexer, SingleChunk) {
    303  // Test delivering all the data at once.
    304  mSourceBuffer->Append(mData, sizeof(mData));
    305  mSourceBuffer->Complete(NS_OK);
    306 
    307  LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLex);
    308 
    309  EXPECT_TRUE(result.is<TerminalState>());
    310  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    311 }
    312 
    313 TEST_F(ImageStreamingLexer, SingleChunkWithUnbuffered) {
    314  Vector<char> unbufferedVector;
    315 
    316  // Test delivering all the data at once.
    317  mSourceBuffer->Append(mData, sizeof(mData));
    318  mSourceBuffer->Complete(NS_OK);
    319 
    320  LexerResult result = mLexer.Lex(
    321      mIterator, mExpectNoResume,
    322      [&](TestState aState, const char* aData, size_t aLength) {
    323        return DoLexWithUnbuffered(aState, aData, aLength, unbufferedVector);
    324      });
    325 
    326  EXPECT_TRUE(result.is<TerminalState>());
    327  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    328 }
    329 
    330 TEST_F(ImageStreamingLexer, SingleChunkWithYield) {
    331  // Test delivering all the data at once.
    332  mSourceBuffer->Append(mData, sizeof(mData));
    333  mSourceBuffer->Complete(NS_OK);
    334 
    335  LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLexWithYield);
    336  ASSERT_TRUE(result.is<Yield>());
    337  EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    338 
    339  result = mLexer.Lex(mIterator, mExpectNoResume, DoLexWithYield);
    340  ASSERT_TRUE(result.is<TerminalState>());
    341  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    342 }
    343 
    344 TEST_F(ImageStreamingLexer, ChunkPerState) {
    345  // Test delivering in perfectly-sized chunks, one per state.
    346  for (unsigned i = 0; i < 3; ++i) {
    347    mSourceBuffer->Append(mData + 3 * i, 3);
    348    LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLex);
    349 
    350    if (i == 2) {
    351      EXPECT_TRUE(result.is<TerminalState>());
    352      EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    353    } else {
    354      EXPECT_TRUE(result.is<Yield>());
    355      EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    356    }
    357  }
    358 
    359  EXPECT_EQ(2u, mCountResumes->Count());
    360  mSourceBuffer->Complete(NS_OK);
    361 }
    362 
    363 TEST_F(ImageStreamingLexer, ChunkPerStateWithUnbuffered) {
    364  Vector<char> unbufferedVector;
    365 
    366  // Test delivering in perfectly-sized chunks, one per state.
    367  for (unsigned i = 0; i < 3; ++i) {
    368    mSourceBuffer->Append(mData + 3 * i, 3);
    369    LexerResult result = mLexer.Lex(
    370        mIterator, mCountResumes,
    371        [&](TestState aState, const char* aData, size_t aLength) {
    372          return DoLexWithUnbuffered(aState, aData, aLength, unbufferedVector);
    373        });
    374 
    375    if (i == 2) {
    376      EXPECT_TRUE(result.is<TerminalState>());
    377      EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    378    } else {
    379      EXPECT_TRUE(result.is<Yield>());
    380      EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    381    }
    382  }
    383 
    384  EXPECT_EQ(2u, mCountResumes->Count());
    385  mSourceBuffer->Complete(NS_OK);
    386 }
    387 
    388 TEST_F(ImageStreamingLexer, ChunkPerStateWithYield) {
    389  // Test delivering in perfectly-sized chunks, one per state.
    390  mSourceBuffer->Append(mData, 3);
    391  LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
    392  EXPECT_TRUE(result.is<Yield>());
    393  EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    394 
    395  result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
    396  EXPECT_TRUE(result.is<Yield>());
    397  EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    398 
    399  mSourceBuffer->Append(mData + 3, 6);
    400  result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
    401  EXPECT_TRUE(result.is<TerminalState>());
    402  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    403 
    404  EXPECT_EQ(1u, mCountResumes->Count());
    405  mSourceBuffer->Complete(NS_OK);
    406 }
    407 
    408 TEST_F(ImageStreamingLexer, ChunkPerStateWithUnbufferedYield) {
    409  size_t unbufferedCallCount = 0;
    410  Vector<char> unbufferedVector;
    411  auto lexerFunc = [&](TestState aState, const char* aData,
    412                       size_t aLength) -> LexerTransition<TestState> {
    413    switch (aState) {
    414      case TestState::ONE:
    415        CheckLexedData(aData, aLength, 0, 3);
    416        return Transition::ToUnbuffered(TestState::TWO, TestState::UNBUFFERED,
    417                                        3);
    418      case TestState::TWO:
    419        CheckLexedData(unbufferedVector.begin(), unbufferedVector.length(), 3,
    420                       3);
    421        return Transition::To(TestState::THREE, 3);
    422      case TestState::THREE:
    423        CheckLexedData(aData, aLength, 6, 3);
    424        return Transition::TerminateSuccess();
    425      case TestState::UNBUFFERED:
    426        switch (unbufferedCallCount) {
    427          case 0:
    428            CheckLexedData(aData, aLength, 3, 3);
    429            EXPECT_TRUE(unbufferedVector.append(aData, 2));
    430            unbufferedCallCount++;
    431 
    432            // Continue after yield, telling StreamingLexer we consumed 2 bytes.
    433            return Transition::ContinueUnbufferedAfterYield(
    434                TestState::UNBUFFERED, 2);
    435 
    436          case 1:
    437            CheckLexedData(aData, aLength, 5, 1);
    438            EXPECT_TRUE(unbufferedVector.append(aData, 1));
    439            unbufferedCallCount++;
    440 
    441            // Continue after yield, telling StreamingLexer we consumed 1 byte.
    442            // We should end up in the TWO state.
    443            return Transition::ContinueUnbuffered(TestState::UNBUFFERED);
    444        }
    445        ADD_FAILURE() << "Too many invocations of TestState::UNBUFFERED";
    446        return Transition::TerminateFailure();
    447      default:
    448        MOZ_CRASH("Unexpected or unhandled TestState");
    449    }
    450  };
    451 
    452  // Test delivering in perfectly-sized chunks, one per state.
    453  for (unsigned i = 0; i < 3; ++i) {
    454    mSourceBuffer->Append(mData + 3 * i, 3);
    455    LexerResult result = mLexer.Lex(mIterator, mCountResumes, lexerFunc);
    456 
    457    switch (i) {
    458      case 0:
    459        EXPECT_TRUE(result.is<Yield>());
    460        EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    461        EXPECT_EQ(0u, unbufferedCallCount);
    462        break;
    463 
    464      case 1:
    465        EXPECT_TRUE(result.is<Yield>());
    466        EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    467        EXPECT_EQ(1u, unbufferedCallCount);
    468 
    469        result = mLexer.Lex(mIterator, mCountResumes, lexerFunc);
    470        EXPECT_TRUE(result.is<Yield>());
    471        EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    472        EXPECT_EQ(2u, unbufferedCallCount);
    473        break;
    474 
    475      case 2:
    476        EXPECT_TRUE(result.is<TerminalState>());
    477        EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    478        break;
    479    }
    480  }
    481 
    482  EXPECT_EQ(2u, mCountResumes->Count());
    483  mSourceBuffer->Complete(NS_OK);
    484 
    485  LexerResult result = mLexer.Lex(mIterator, mCountResumes, lexerFunc);
    486  EXPECT_TRUE(result.is<TerminalState>());
    487  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    488 }
    489 
    490 TEST_F(ImageStreamingLexer, OneByteChunks) {
    491  // Test delivering in one byte chunks.
    492  for (unsigned i = 0; i < 9; ++i) {
    493    mSourceBuffer->Append(mData + i, 1);
    494    LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLex);
    495 
    496    if (i == 8) {
    497      EXPECT_TRUE(result.is<TerminalState>());
    498      EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    499    } else {
    500      EXPECT_TRUE(result.is<Yield>());
    501      EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    502    }
    503  }
    504 
    505  EXPECT_EQ(8u, mCountResumes->Count());
    506  mSourceBuffer->Complete(NS_OK);
    507 }
    508 
    509 TEST_F(ImageStreamingLexer, OneByteChunksWithUnbuffered) {
    510  Vector<char> unbufferedVector;
    511 
    512  // Test delivering in one byte chunks.
    513  for (unsigned i = 0; i < 9; ++i) {
    514    mSourceBuffer->Append(mData + i, 1);
    515    LexerResult result = mLexer.Lex(
    516        mIterator, mCountResumes,
    517        [&](TestState aState, const char* aData, size_t aLength) {
    518          return DoLexWithUnbuffered(aState, aData, aLength, unbufferedVector);
    519        });
    520 
    521    if (i == 8) {
    522      EXPECT_TRUE(result.is<TerminalState>());
    523      EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    524    } else {
    525      EXPECT_TRUE(result.is<Yield>());
    526      EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    527    }
    528  }
    529 
    530  EXPECT_EQ(8u, mCountResumes->Count());
    531  mSourceBuffer->Complete(NS_OK);
    532 }
    533 
    534 TEST_F(ImageStreamingLexer, OneByteChunksWithYield) {
    535  // Test delivering in one byte chunks.
    536  for (unsigned i = 0; i < 9; ++i) {
    537    mSourceBuffer->Append(mData + i, 1);
    538    LexerResult result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
    539 
    540    switch (i) {
    541      case 2:
    542        EXPECT_TRUE(result.is<Yield>());
    543        EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    544 
    545        result = mLexer.Lex(mIterator, mCountResumes, DoLexWithYield);
    546        EXPECT_TRUE(result.is<Yield>());
    547        EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    548        break;
    549 
    550      case 8:
    551        EXPECT_TRUE(result.is<TerminalState>());
    552        EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    553        break;
    554 
    555      default:
    556        EXPECT_TRUE(i < 9);
    557        EXPECT_TRUE(result.is<Yield>());
    558        EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    559    }
    560  }
    561 
    562  EXPECT_EQ(8u, mCountResumes->Count());
    563  mSourceBuffer->Complete(NS_OK);
    564 }
    565 
    566 TEST_F(ImageStreamingLexer, ZeroLengthState) {
    567  mSourceBuffer->Append(mData, sizeof(mData));
    568  mSourceBuffer->Complete(NS_OK);
    569 
    570  // Create a special StreamingLexer for this test because we want the first
    571  // state to be zero length.
    572  StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 0),
    573                                  Transition::TerminateFailure());
    574 
    575  LexerResult result =
    576      lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStates);
    577 
    578  EXPECT_TRUE(result.is<TerminalState>());
    579  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    580 }
    581 
    582 TEST_F(ImageStreamingLexer, ZeroLengthStatesAtEnd) {
    583  mSourceBuffer->Append(mData, sizeof(mData));
    584  mSourceBuffer->Complete(NS_OK);
    585 
    586  // Create a special StreamingLexer for this test because we want the first
    587  // state to consume the full input.
    588  StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 9),
    589                                  Transition::TerminateFailure());
    590 
    591  LexerResult result =
    592      lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthStatesAtEnd);
    593 
    594  EXPECT_TRUE(result.is<TerminalState>());
    595  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    596 }
    597 
    598 TEST_F(ImageStreamingLexer, ZeroLengthStateWithYield) {
    599  // Create a special StreamingLexer for this test because we want the first
    600  // state to be zero length.
    601  StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 0),
    602                                  Transition::TerminateFailure());
    603 
    604  mSourceBuffer->Append(mData, 3);
    605  LexerResult result =
    606      lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthYield);
    607  ASSERT_TRUE(result.is<Yield>());
    608  EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    609 
    610  result = lexer.Lex(mIterator, mCountResumes, DoLexWithZeroLengthYield);
    611  ASSERT_TRUE(result.is<Yield>());
    612  EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    613 
    614  mSourceBuffer->Append(mData + 3, sizeof(mData) - 3);
    615  mSourceBuffer->Complete(NS_OK);
    616  result = lexer.Lex(mIterator, mExpectNoResume, DoLexWithZeroLengthYield);
    617  ASSERT_TRUE(result.is<TerminalState>());
    618  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    619  EXPECT_EQ(1u, mCountResumes->Count());
    620 }
    621 
    622 TEST_F(ImageStreamingLexer, ZeroLengthStateWithUnbuffered) {
    623  mSourceBuffer->Append(mData, sizeof(mData));
    624  mSourceBuffer->Complete(NS_OK);
    625 
    626  // Create a special StreamingLexer for this test because we want the first
    627  // state to be both zero length and unbuffered.
    628  StreamingLexer<TestState> lexer(
    629      Transition::ToUnbuffered(TestState::ONE, TestState::UNBUFFERED, 0),
    630      Transition::TerminateFailure());
    631 
    632  LexerResult result = lexer.Lex(mIterator, mExpectNoResume,
    633                                 DoLexWithZeroLengthStatesUnbuffered);
    634 
    635  EXPECT_TRUE(result.is<TerminalState>());
    636  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    637 }
    638 
    639 TEST_F(ImageStreamingLexer, ZeroLengthStateAfterUnbuffered) {
    640  mSourceBuffer->Append(mData, sizeof(mData));
    641  mSourceBuffer->Complete(NS_OK);
    642 
    643  // Create a special StreamingLexer for this test because we want the first
    644  // state to be zero length.
    645  StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 0),
    646                                  Transition::TerminateFailure());
    647 
    648  LexerResult result = lexer.Lex(mIterator, mExpectNoResume,
    649                                 DoLexWithZeroLengthStatesAfterUnbuffered);
    650 
    651  EXPECT_TRUE(result.is<TerminalState>());
    652  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    653 }
    654 
    655 TEST_F(ImageStreamingLexer, ZeroLengthStateWithUnbufferedYield) {
    656  size_t unbufferedCallCount = 0;
    657  auto lexerFunc = [&](TestState aState, const char* aData,
    658                       size_t aLength) -> LexerTransition<TestState> {
    659    switch (aState) {
    660      case TestState::ONE:
    661        EXPECT_EQ(0u, aLength);
    662        return Transition::TerminateSuccess();
    663 
    664      case TestState::UNBUFFERED:
    665        switch (unbufferedCallCount) {
    666          case 0:
    667            CheckLexedData(aData, aLength, 0, 3);
    668            unbufferedCallCount++;
    669 
    670            // Continue after yield, telling StreamingLexer we consumed 0 bytes.
    671            return Transition::ContinueUnbufferedAfterYield(
    672                TestState::UNBUFFERED, 0);
    673 
    674          case 1:
    675            CheckLexedData(aData, aLength, 0, 3);
    676            unbufferedCallCount++;
    677 
    678            // Continue after yield, telling StreamingLexer we consumed 2 bytes.
    679            return Transition::ContinueUnbufferedAfterYield(
    680                TestState::UNBUFFERED, 2);
    681 
    682          case 2:
    683            EXPECT_EQ(1u, aLength);
    684            CheckLexedData(aData, aLength, 2, 1);
    685            unbufferedCallCount++;
    686 
    687            // Continue after yield, telling StreamingLexer we consumed 1 bytes.
    688            return Transition::ContinueUnbufferedAfterYield(
    689                TestState::UNBUFFERED, 1);
    690 
    691          case 3:
    692            CheckLexedData(aData, aLength, 3, 6);
    693            unbufferedCallCount++;
    694 
    695            // Continue after yield, telling StreamingLexer we consumed 6 bytes.
    696            // We should transition to TestState::ONE when we return from the
    697            // yield.
    698            return Transition::ContinueUnbufferedAfterYield(
    699                TestState::UNBUFFERED, 6);
    700        }
    701 
    702        ADD_FAILURE() << "Too many invocations of TestState::UNBUFFERED";
    703        return Transition::TerminateFailure();
    704 
    705      default:
    706        MOZ_CRASH("Unexpected or unhandled TestState");
    707    }
    708  };
    709 
    710  // Create a special StreamingLexer for this test because we want the first
    711  // state to be unbuffered.
    712  StreamingLexer<TestState> lexer(
    713      Transition::ToUnbuffered(TestState::ONE, TestState::UNBUFFERED,
    714                               sizeof(mData)),
    715      Transition::TerminateFailure());
    716 
    717  mSourceBuffer->Append(mData, 3);
    718  LexerResult result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
    719  ASSERT_TRUE(result.is<Yield>());
    720  EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    721  EXPECT_EQ(1u, unbufferedCallCount);
    722 
    723  result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
    724  ASSERT_TRUE(result.is<Yield>());
    725  EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    726  EXPECT_EQ(2u, unbufferedCallCount);
    727 
    728  result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
    729  ASSERT_TRUE(result.is<Yield>());
    730  EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    731  EXPECT_EQ(3u, unbufferedCallCount);
    732 
    733  result = lexer.Lex(mIterator, mCountResumes, lexerFunc);
    734  ASSERT_TRUE(result.is<Yield>());
    735  EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    736  EXPECT_EQ(3u, unbufferedCallCount);
    737 
    738  mSourceBuffer->Append(mData + 3, 6);
    739  mSourceBuffer->Complete(NS_OK);
    740  EXPECT_EQ(1u, mCountResumes->Count());
    741  result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
    742  ASSERT_TRUE(result.is<Yield>());
    743  EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    744  EXPECT_EQ(4u, unbufferedCallCount);
    745 
    746  result = lexer.Lex(mIterator, mExpectNoResume, lexerFunc);
    747  ASSERT_TRUE(result.is<TerminalState>());
    748  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    749 }
    750 
    751 TEST_F(ImageStreamingLexer, TerminateSuccess) {
    752  mSourceBuffer->Append(mData, sizeof(mData));
    753  mSourceBuffer->Complete(NS_OK);
    754 
    755  // Test that Terminate is "sticky".
    756  SourceBufferIterator iterator = mSourceBuffer->Iterator();
    757  LexerResult result =
    758      mLexer.Lex(iterator, mExpectNoResume,
    759                 [&](TestState aState, const char* aData, size_t aLength) {
    760                   EXPECT_TRUE(aState == TestState::ONE);
    761                   return Transition::TerminateSuccess();
    762                 });
    763  EXPECT_TRUE(result.is<TerminalState>());
    764  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    765 
    766  SourceBufferIterator iterator2 = mSourceBuffer->Iterator();
    767  result = mLexer.Lex(iterator2, mExpectNoResume,
    768                      [&](TestState aState, const char* aData, size_t aLength) {
    769                        EXPECT_TRUE(false);  // Shouldn't get here.
    770                        return Transition::TerminateFailure();
    771                      });
    772  EXPECT_TRUE(result.is<TerminalState>());
    773  EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    774 }
    775 
    776 TEST_F(ImageStreamingLexer, TerminateFailure) {
    777  mSourceBuffer->Append(mData, sizeof(mData));
    778  mSourceBuffer->Complete(NS_OK);
    779 
    780  // Test that Terminate is "sticky".
    781  SourceBufferIterator iterator = mSourceBuffer->Iterator();
    782  LexerResult result =
    783      mLexer.Lex(iterator, mExpectNoResume,
    784                 [&](TestState aState, const char* aData, size_t aLength) {
    785                   EXPECT_TRUE(aState == TestState::ONE);
    786                   return Transition::TerminateFailure();
    787                 });
    788  EXPECT_TRUE(result.is<TerminalState>());
    789  EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
    790 
    791  SourceBufferIterator iterator2 = mSourceBuffer->Iterator();
    792  result = mLexer.Lex(iterator2, mExpectNoResume,
    793                      [&](TestState aState, const char* aData, size_t aLength) {
    794                        EXPECT_TRUE(false);  // Shouldn't get here.
    795                        return Transition::TerminateFailure();
    796                      });
    797  EXPECT_TRUE(result.is<TerminalState>());
    798  EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
    799 }
    800 
    801 TEST_F(ImageStreamingLexer, TerminateUnbuffered) {
    802  // Test that Terminate works during an unbuffered read.
    803  for (unsigned i = 0; i < 9; ++i) {
    804    mSourceBuffer->Append(mData + i, 1);
    805    LexerResult result =
    806        mLexer.Lex(mIterator, mCountResumes, DoLexWithUnbufferedTerminate);
    807 
    808    if (i > 2) {
    809      EXPECT_TRUE(result.is<TerminalState>());
    810      EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    811    } else {
    812      EXPECT_TRUE(result.is<Yield>());
    813      EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    814    }
    815  }
    816 
    817  // We expect 3 resumes because TestState::ONE consumes 3 bytes and then
    818  // transitions to TestState::UNBUFFERED, which calls TerminateSuccess() as
    819  // soon as it receives a single byte. That's four bytes total,  which are
    820  // delivered one at a time, requiring 3 resumes.
    821  EXPECT_EQ(3u, mCountResumes->Count());
    822 
    823  mSourceBuffer->Complete(NS_OK);
    824 }
    825 
    826 TEST_F(ImageStreamingLexer, TerminateAfterYield) {
    827  // Test that Terminate works after yielding.
    828  for (unsigned i = 0; i < 9; ++i) {
    829    mSourceBuffer->Append(mData + i, 1);
    830    LexerResult result =
    831        mLexer.Lex(mIterator, mCountResumes, DoLexWithTerminateAfterYield);
    832 
    833    if (i > 2) {
    834      EXPECT_TRUE(result.is<TerminalState>());
    835      EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    836    } else if (i == 2) {
    837      EXPECT_TRUE(result.is<Yield>());
    838      EXPECT_EQ(Yield::OUTPUT_AVAILABLE, result.as<Yield>());
    839    } else {
    840      EXPECT_TRUE(result.is<Yield>());
    841      EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    842    }
    843  }
    844 
    845  // We expect 2 resumes because TestState::ONE consumes 3 bytes and then
    846  // yields. When the lexer resumes at TestState::TWO, which receives the same 3
    847  // bytes, TerminateSuccess() gets called immediately.  That's three bytes
    848  // total, which are delivered one at a time, requiring 2 resumes.
    849  EXPECT_EQ(2u, mCountResumes->Count());
    850 
    851  mSourceBuffer->Complete(NS_OK);
    852 }
    853 
    854 TEST_F(ImageStreamingLexer, SourceBufferImmediateComplete) {
    855  // Test calling SourceBuffer::Complete() without appending any data. This
    856  // causes the SourceBuffer to automatically have a failing completion status,
    857  // no matter what you pass, so we expect TerminalState::FAILURE below.
    858  mSourceBuffer->Complete(NS_OK);
    859 
    860  LexerResult result = mLexer.Lex(mIterator, mExpectNoResume, DoLex);
    861 
    862  EXPECT_TRUE(result.is<TerminalState>());
    863  EXPECT_EQ(TerminalState::FAILURE, result.as<TerminalState>());
    864 }
    865 
    866 TEST_F(ImageStreamingLexer, SourceBufferTruncatedTerminalStateSuccess) {
    867  // Test that using a terminal state (in this case TerminalState::SUCCESS) as a
    868  // truncated state works.
    869  StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 3),
    870                                  Transition::TerminateSuccess());
    871 
    872  CheckTruncatedState(lexer, TerminalState::SUCCESS);
    873 }
    874 
    875 TEST_F(ImageStreamingLexer, SourceBufferTruncatedTerminalStateFailure) {
    876  // Test that using a terminal state (in this case TerminalState::FAILURE) as a
    877  // truncated state works.
    878  StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 3),
    879                                  Transition::TerminateFailure());
    880 
    881  CheckTruncatedState(lexer, TerminalState::FAILURE);
    882 }
    883 
    884 TEST_F(ImageStreamingLexer, SourceBufferTruncatedStateReturningSuccess) {
    885  // Test that a truncated state that returns TerminalState::SUCCESS works. When
    886  // |lexer| discovers that the data is truncated, it invokes the
    887  // TRUNCATED_SUCCESS state, which returns TerminalState::SUCCESS.
    888  // CheckTruncatedState() verifies that this happens.
    889  StreamingLexer<TestState> lexer(
    890      Transition::To(TestState::ONE, 3),
    891      Transition::To(TestState::TRUNCATED_SUCCESS, 0));
    892 
    893  CheckTruncatedState(lexer, TerminalState::SUCCESS);
    894 }
    895 
    896 TEST_F(ImageStreamingLexer, SourceBufferTruncatedStateReturningFailure) {
    897  // Test that a truncated state that returns TerminalState::FAILURE works. When
    898  // |lexer| discovers that the data is truncated, it invokes the
    899  // TRUNCATED_FAILURE state, which returns TerminalState::FAILURE.
    900  // CheckTruncatedState() verifies that this happens.
    901  StreamingLexer<TestState> lexer(
    902      Transition::To(TestState::ONE, 3),
    903      Transition::To(TestState::TRUNCATED_FAILURE, 0));
    904 
    905  CheckTruncatedState(lexer, TerminalState::FAILURE);
    906 }
    907 
    908 TEST_F(ImageStreamingLexer, SourceBufferTruncatedFailingCompleteStatus) {
    909  // Test that calling SourceBuffer::Complete() with a failing status results in
    910  // an immediate TerminalState::FAILURE result. (Note that |lexer|'s truncated
    911  // state is TerminalState::SUCCESS, so if we ignore the failing status, the
    912  // test will fail.)
    913  StreamingLexer<TestState> lexer(Transition::To(TestState::ONE, 3),
    914                                  Transition::TerminateSuccess());
    915 
    916  CheckTruncatedState(lexer, TerminalState::FAILURE, NS_ERROR_FAILURE);
    917 }
    918 
    919 TEST_F(ImageStreamingLexer, NoSourceBufferResumable) {
    920  // Test delivering in one byte chunks with no IResumable.
    921  for (unsigned i = 0; i < 9; ++i) {
    922    mSourceBuffer->Append(mData + i, 1);
    923    LexerResult result = mLexer.Lex(mIterator, nullptr, DoLex);
    924 
    925    if (i == 8) {
    926      EXPECT_TRUE(result.is<TerminalState>());
    927      EXPECT_EQ(TerminalState::SUCCESS, result.as<TerminalState>());
    928    } else {
    929      EXPECT_TRUE(result.is<Yield>());
    930      EXPECT_EQ(Yield::NEED_MORE_DATA, result.as<Yield>());
    931    }
    932  }
    933 
    934  mSourceBuffer->Complete(NS_OK);
    935 }