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 }