1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "media/cdm/ppapi/cdm_file_io_test.h" 6 7 #include "base/bind.h" 8 #include "base/callback_helpers.h" 9 #include "base/logging.h" 10 11 namespace media { 12 13 #define FILE_IO_DVLOG(level) DVLOG(level) << "File IO Test: " 14 15 const uint8 kData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 16 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; 17 const uint32 kDataSize = arraysize(kData); 18 19 const uint8 kBigData[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 20 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 21 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 22 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 23 0x00 }; 24 const uint32 kBigDataSize = arraysize(kBigData); 25 26 // Must be > kReadSize in cdm_file_io_impl.cc. 27 const uint32 kLargeDataSize = 20 * 1024 + 7; 28 29 // Macros to help add test cases/steps. 30 31 // |test_name| is also used as the file name. File name validity tests relies 32 // on this to work. 33 #define START_TEST_CASE(test_name) \ 34 do { \ 35 FileIOTest test_case(create_file_io_cb_, test_name); \ 36 CREATE_FILE_IO // Create FileIO for each test case. 37 38 #define ADD_TEST_STEP(type, status, data, data_size) \ 39 test_case.AddTestStep(FileIOTest::type, cdm::FileIOClient::status, \ 40 (data), (data_size)); 41 42 #define END_TEST_CASE \ 43 remaining_tests_.push_back(test_case); \ 44 } while(0); 45 46 #define CREATE_FILE_IO \ 47 ADD_TEST_STEP(ACTION_CREATE, kSuccess, NULL, 0) 48 49 #define OPEN_FILE \ 50 ADD_TEST_STEP(ACTION_OPEN, kSuccess, NULL, 0) 51 52 #define EXPECT_FILE_OPENED(status) \ 53 ADD_TEST_STEP(RESULT_OPEN, status, NULL, 0) 54 55 #define READ_FILE \ 56 ADD_TEST_STEP(ACTION_READ, kSuccess, NULL, 0) 57 58 #define EXPECT_FILE_READ(status, data, data_size) \ 59 ADD_TEST_STEP(RESULT_READ, status, data, data_size) 60 61 #define WRITE_FILE(data, data_size) \ 62 ADD_TEST_STEP(ACTION_WRITE, kSuccess, data, data_size) 63 64 #define EXPECT_FILE_WRITTEN(status) \ 65 ADD_TEST_STEP(RESULT_WRITE, status, NULL, 0) 66 67 #define CLOSE_FILE \ 68 ADD_TEST_STEP(ACTION_CLOSE, kSuccess, NULL, 0) 69 70 // FileIOTestRunner implementation. 71 72 FileIOTestRunner::FileIOTestRunner(const CreateFileIOCB& create_file_io_cb) 73 : create_file_io_cb_(create_file_io_cb), 74 total_num_tests_(0), 75 num_passed_tests_(0) { 76 // Generate |large_data_|. 77 large_data_.resize(kLargeDataSize); 78 for (size_t i = 0; i < kLargeDataSize; ++i) 79 large_data_[i] = i % kuint8max; 80 81 AddTests(); 82 } 83 84 FileIOTestRunner::~FileIOTestRunner() { 85 if (remaining_tests_.empty()) 86 return; 87 88 DCHECK_LT(num_passed_tests_, total_num_tests_); 89 FILE_IO_DVLOG(1) << "Not Finished (probably due to timeout). " 90 << num_passed_tests_ << " passed in " 91 << total_num_tests_ << " tests."; 92 } 93 94 // Note: Consecutive expectations (EXPECT*) can happen in any order. 95 void FileIOTestRunner::AddTests() { 96 START_TEST_CASE("/FileNameStartsWithForwardSlash") 97 OPEN_FILE 98 EXPECT_FILE_OPENED(kError) 99 END_TEST_CASE 100 101 START_TEST_CASE("FileNameContains/ForwardSlash") 102 OPEN_FILE 103 EXPECT_FILE_OPENED(kError) 104 END_TEST_CASE 105 106 START_TEST_CASE("\\FileNameStartsWithBackslash") 107 OPEN_FILE 108 EXPECT_FILE_OPENED(kError) 109 END_TEST_CASE 110 111 START_TEST_CASE("FileNameContains\\Backslash") 112 OPEN_FILE 113 EXPECT_FILE_OPENED(kError) 114 END_TEST_CASE 115 116 START_TEST_CASE("_FileNameStartsWithUnderscore") 117 OPEN_FILE 118 EXPECT_FILE_OPENED(kError) 119 END_TEST_CASE 120 121 START_TEST_CASE("FileNameContains_Underscore") 122 OPEN_FILE 123 EXPECT_FILE_OPENED(kSuccess) 124 END_TEST_CASE 125 126 START_TEST_CASE("ReadBeforeOpeningFile") 127 READ_FILE 128 EXPECT_FILE_READ(kError, NULL, 0) 129 END_TEST_CASE 130 131 START_TEST_CASE("WriteBeforeOpeningFile") 132 WRITE_FILE(kData, kDataSize) 133 EXPECT_FILE_WRITTEN(kError) 134 END_TEST_CASE 135 136 START_TEST_CASE("ReadBeforeFileOpened") 137 OPEN_FILE 138 READ_FILE 139 EXPECT_FILE_OPENED(kSuccess) 140 EXPECT_FILE_READ(kError, NULL, 0) 141 // After file opened, we can still do normal operations. 142 WRITE_FILE(kData, kDataSize) 143 EXPECT_FILE_WRITTEN(kSuccess) 144 READ_FILE 145 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 146 END_TEST_CASE 147 148 START_TEST_CASE("WriteBeforeFileOpened") 149 OPEN_FILE 150 WRITE_FILE(kData, kDataSize) 151 EXPECT_FILE_WRITTEN(kError) 152 EXPECT_FILE_OPENED(kSuccess) 153 // After file opened, we can still do normal operations. 154 WRITE_FILE(kData, kDataSize) 155 EXPECT_FILE_WRITTEN(kSuccess) 156 READ_FILE 157 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 158 END_TEST_CASE 159 160 START_TEST_CASE("ReadDuringPendingRead") 161 OPEN_FILE 162 EXPECT_FILE_OPENED(kSuccess) 163 WRITE_FILE(kData, kDataSize) 164 EXPECT_FILE_WRITTEN(kSuccess) 165 READ_FILE 166 READ_FILE 167 EXPECT_FILE_READ(kInUse, NULL, 0) 168 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 169 // Read again. 170 READ_FILE 171 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 172 END_TEST_CASE 173 174 START_TEST_CASE("ReadDuringPendingWrite") 175 OPEN_FILE 176 EXPECT_FILE_OPENED(kSuccess) 177 WRITE_FILE(kData, kDataSize) 178 READ_FILE 179 EXPECT_FILE_READ(kInUse, NULL, 0) 180 EXPECT_FILE_WRITTEN(kSuccess) 181 // Read again. 182 READ_FILE 183 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 184 END_TEST_CASE 185 186 START_TEST_CASE("WriteDuringPendingRead") 187 OPEN_FILE 188 EXPECT_FILE_OPENED(kSuccess) 189 READ_FILE 190 WRITE_FILE(kData, kDataSize) 191 EXPECT_FILE_WRITTEN(kInUse) 192 EXPECT_FILE_READ(kSuccess, NULL, 0) 193 // We can still do normal operations. 194 WRITE_FILE(kData, kDataSize) 195 EXPECT_FILE_WRITTEN(kSuccess) 196 READ_FILE 197 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 198 END_TEST_CASE 199 200 START_TEST_CASE("WriteDuringPendingWrite") 201 OPEN_FILE 202 EXPECT_FILE_OPENED(kSuccess) 203 WRITE_FILE(kData, kDataSize) 204 WRITE_FILE(kBigData, kBigDataSize) 205 EXPECT_FILE_WRITTEN(kInUse) 206 EXPECT_FILE_WRITTEN(kSuccess) 207 // Read to make sure original data (kData) is written. 208 READ_FILE 209 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 210 END_TEST_CASE 211 212 START_TEST_CASE("ReadFileThatDoesNotExist") 213 OPEN_FILE 214 EXPECT_FILE_OPENED(kSuccess) 215 READ_FILE 216 EXPECT_FILE_READ(kSuccess, NULL, 0) 217 END_TEST_CASE 218 219 START_TEST_CASE("WriteAndRead") 220 OPEN_FILE 221 EXPECT_FILE_OPENED(kSuccess) 222 WRITE_FILE(kData, kDataSize) 223 EXPECT_FILE_WRITTEN(kSuccess) 224 READ_FILE 225 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 226 END_TEST_CASE 227 228 START_TEST_CASE("WriteAndReadEmptyFile") 229 OPEN_FILE 230 EXPECT_FILE_OPENED(kSuccess) 231 WRITE_FILE(NULL, 0) 232 EXPECT_FILE_WRITTEN(kSuccess) 233 READ_FILE 234 EXPECT_FILE_READ(kSuccess, NULL, 0) 235 END_TEST_CASE 236 237 START_TEST_CASE("WriteAndReadLargeData") 238 OPEN_FILE 239 EXPECT_FILE_OPENED(kSuccess) 240 WRITE_FILE(&large_data_[0], kLargeDataSize) 241 EXPECT_FILE_WRITTEN(kSuccess) 242 READ_FILE 243 EXPECT_FILE_READ(kSuccess, &large_data_[0], kLargeDataSize) 244 END_TEST_CASE 245 246 START_TEST_CASE("OverwriteZeroBytes") 247 OPEN_FILE 248 EXPECT_FILE_OPENED(kSuccess) 249 WRITE_FILE(kData, kDataSize) 250 EXPECT_FILE_WRITTEN(kSuccess) 251 READ_FILE 252 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 253 WRITE_FILE(NULL, 0) 254 EXPECT_FILE_WRITTEN(kSuccess) 255 READ_FILE 256 EXPECT_FILE_READ(kSuccess, NULL, 0) 257 END_TEST_CASE 258 259 START_TEST_CASE("OverwriteWithSmallerData") 260 OPEN_FILE 261 EXPECT_FILE_OPENED(kSuccess) 262 WRITE_FILE(kBigData, kBigDataSize) 263 EXPECT_FILE_WRITTEN(kSuccess) 264 WRITE_FILE(kData, kDataSize) 265 EXPECT_FILE_WRITTEN(kSuccess) 266 READ_FILE 267 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 268 END_TEST_CASE 269 270 START_TEST_CASE("OverwriteWithLargerData") 271 OPEN_FILE 272 EXPECT_FILE_OPENED(kSuccess) 273 WRITE_FILE(kData, kDataSize) 274 EXPECT_FILE_WRITTEN(kSuccess) 275 WRITE_FILE(kBigData, kBigDataSize) 276 EXPECT_FILE_WRITTEN(kSuccess) 277 READ_FILE 278 EXPECT_FILE_READ(kSuccess, kBigData, kBigDataSize) 279 END_TEST_CASE 280 281 START_TEST_CASE("ReadExistingFile") 282 OPEN_FILE 283 EXPECT_FILE_OPENED(kSuccess) 284 WRITE_FILE(kData, kDataSize) 285 EXPECT_FILE_WRITTEN(kSuccess) 286 CLOSE_FILE 287 CREATE_FILE_IO 288 OPEN_FILE 289 EXPECT_FILE_OPENED(kSuccess) 290 READ_FILE 291 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 292 END_TEST_CASE 293 294 START_TEST_CASE("MultipleReadsAndWrites") 295 OPEN_FILE 296 EXPECT_FILE_OPENED(kSuccess) 297 // Read file which doesn't exist. 298 READ_FILE 299 EXPECT_FILE_READ(kSuccess, NULL, 0) 300 // Write kData to file. 301 WRITE_FILE(kData, kDataSize) 302 EXPECT_FILE_WRITTEN(kSuccess) 303 // Read file. 304 READ_FILE 305 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 306 // Read file again. 307 READ_FILE 308 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 309 // Overwrite file with large data. 310 WRITE_FILE(&large_data_[0], kLargeDataSize) 311 EXPECT_FILE_WRITTEN(kSuccess) 312 // Read file. 313 READ_FILE 314 EXPECT_FILE_READ(kSuccess, &large_data_[0], kLargeDataSize) 315 // Overwrite file with kData. 316 WRITE_FILE(kData, kDataSize) 317 EXPECT_FILE_WRITTEN(kSuccess) 318 // Read file. 319 READ_FILE 320 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 321 // Overwrite file with zero bytes. 322 WRITE_FILE(NULL, 0) 323 EXPECT_FILE_WRITTEN(kSuccess) 324 // Read file. 325 READ_FILE 326 EXPECT_FILE_READ(kSuccess, NULL, 0) 327 END_TEST_CASE 328 329 START_TEST_CASE("OpenAfterOpen") 330 OPEN_FILE 331 EXPECT_FILE_OPENED(kSuccess) 332 OPEN_FILE 333 EXPECT_FILE_OPENED(kError) 334 END_TEST_CASE 335 336 START_TEST_CASE("OpenDuringPendingOpen") 337 OPEN_FILE 338 OPEN_FILE 339 EXPECT_FILE_OPENED(kError) // The second Open() failed. 340 EXPECT_FILE_OPENED(kSuccess) // The first Open() succeeded. 341 END_TEST_CASE 342 343 START_TEST_CASE("ReopenFileInSeparateFileIO") 344 OPEN_FILE 345 EXPECT_FILE_OPENED(kSuccess) 346 WRITE_FILE(kData, kDataSize) 347 EXPECT_FILE_WRITTEN(kSuccess) 348 CREATE_FILE_IO // Create a second FileIO without closing the first one. 349 OPEN_FILE 350 EXPECT_FILE_OPENED(kInUse) 351 END_TEST_CASE 352 353 START_TEST_CASE("CloseAfterCreation") 354 CLOSE_FILE 355 END_TEST_CASE 356 357 START_TEST_CASE("CloseDuringPendingOpen") 358 OPEN_FILE 359 CLOSE_FILE 360 END_TEST_CASE 361 362 START_TEST_CASE("CloseDuringPendingWrite") 363 OPEN_FILE 364 EXPECT_FILE_OPENED(kSuccess) 365 // TODO(xhwang): Reenable this after http:://crbug.com/415401 is fixed. 366 // WRITE_FILE(kData, kDataSize) 367 CLOSE_FILE 368 END_TEST_CASE 369 370 START_TEST_CASE("CloseDuringPendingOverwriteWithLargerData") 371 OPEN_FILE 372 EXPECT_FILE_OPENED(kSuccess) 373 WRITE_FILE(kData, kDataSize) 374 EXPECT_FILE_WRITTEN(kSuccess) 375 // TODO(xhwang): Reenable this after http:://crbug.com/415401 is fixed. 376 // WRITE_FILE(kBigData, kBigDataSize) 377 CLOSE_FILE 378 // Write() didn't finish and the content of the file is not modified. 379 CREATE_FILE_IO 380 OPEN_FILE 381 EXPECT_FILE_OPENED(kSuccess) 382 READ_FILE 383 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 384 END_TEST_CASE 385 386 START_TEST_CASE("CloseDuringPendingOverwriteWithSmallerData") 387 OPEN_FILE 388 EXPECT_FILE_OPENED(kSuccess) 389 WRITE_FILE(kBigData, kBigDataSize) 390 EXPECT_FILE_WRITTEN(kSuccess) 391 // TODO(xhwang): Reenable this after http:://crbug.com/415401 is fixed. 392 // WRITE_FILE(kData, kDataSize) 393 CLOSE_FILE 394 // Write() didn't finish and the content of the file is not modified. 395 CREATE_FILE_IO 396 OPEN_FILE 397 EXPECT_FILE_OPENED(kSuccess) 398 READ_FILE 399 EXPECT_FILE_READ(kSuccess, kBigData, kBigDataSize) 400 END_TEST_CASE 401 402 START_TEST_CASE("CloseDuringPendingRead") 403 OPEN_FILE 404 EXPECT_FILE_OPENED(kSuccess) 405 WRITE_FILE(kData, kDataSize) 406 EXPECT_FILE_WRITTEN(kSuccess) 407 // TODO(xhwang): Reenable this after http:://crbug.com/415401 is fixed. 408 // READ_FILE 409 CLOSE_FILE 410 // Make sure the file is not modified. 411 CREATE_FILE_IO 412 OPEN_FILE 413 EXPECT_FILE_OPENED(kSuccess) 414 READ_FILE 415 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 416 END_TEST_CASE 417 418 START_TEST_CASE("StressTest") 419 for (int i = 0; i < 100; ++i) { 420 CREATE_FILE_IO 421 OPEN_FILE 422 EXPECT_FILE_OPENED(kSuccess) 423 WRITE_FILE(kData, kDataSize) 424 EXPECT_FILE_WRITTEN(kSuccess) 425 // TODO(xhwang): Reenable this after http:://crbug.com/415401 is fixed. 426 // WRITE_FILE(kBigData, kBigDataSize) 427 CLOSE_FILE 428 // Make sure the file is not modified. 429 CREATE_FILE_IO 430 OPEN_FILE 431 EXPECT_FILE_OPENED(kSuccess) 432 READ_FILE 433 EXPECT_FILE_READ(kSuccess, kData, kDataSize) 434 CLOSE_FILE 435 } 436 END_TEST_CASE 437 } 438 439 void FileIOTestRunner::RunAllTests(const CompletionCB& completion_cb) { 440 completion_cb_ = completion_cb; 441 total_num_tests_ = remaining_tests_.size(); 442 RunNextTest(); 443 } 444 445 void FileIOTestRunner::RunNextTest() { 446 if (remaining_tests_.empty()) { 447 FILE_IO_DVLOG(1) << num_passed_tests_ << " passed and " 448 << (total_num_tests_ - num_passed_tests_) << " failed in " 449 << total_num_tests_ << " tests."; 450 bool success = (num_passed_tests_ == total_num_tests_); 451 base::ResetAndReturn(&completion_cb_).Run(success); 452 return; 453 } 454 455 remaining_tests_.front().Run( 456 base::Bind(&FileIOTestRunner::OnTestComplete, base::Unretained(this))); 457 } 458 459 void FileIOTestRunner::OnTestComplete(bool success) { 460 if (success) 461 num_passed_tests_++; 462 remaining_tests_.pop_front(); 463 RunNextTest(); 464 } 465 466 // FileIOTest implementation. 467 468 FileIOTest::FileIOTest(const CreateFileIOCB& create_file_io_cb, 469 const std::string& test_name) 470 : create_file_io_cb_(create_file_io_cb), 471 test_name_(test_name) {} 472 473 FileIOTest::~FileIOTest() {} 474 475 void FileIOTest::AddTestStep( 476 StepType type, Status status, const uint8* data, uint32 data_size) { 477 test_steps_.push_back(TestStep(type, status, data, data_size)); 478 } 479 480 void FileIOTest::Run(const CompletionCB& completion_cb) { 481 FILE_IO_DVLOG(3) << "Run " << test_name_; 482 completion_cb_ = completion_cb; 483 DCHECK(!test_steps_.empty() && !IsResult(test_steps_.front())); 484 RunNextStep(); 485 } 486 487 void FileIOTest::OnOpenComplete(Status status) { 488 OnResult(TestStep(RESULT_OPEN, status, NULL, 0)); 489 } 490 491 void FileIOTest::OnReadComplete(Status status, 492 const uint8_t* data, 493 uint32_t data_size) { 494 OnResult(TestStep(RESULT_READ, status, data, data_size)); 495 } 496 497 void FileIOTest::OnWriteComplete(Status status) { 498 OnResult(TestStep(RESULT_WRITE, status, NULL, 0)); 499 } 500 501 bool FileIOTest::IsResult(const TestStep& test_step) { 502 switch (test_step.type) { 503 case RESULT_OPEN: 504 case RESULT_READ: 505 case RESULT_WRITE: 506 return true; 507 case ACTION_CREATE: 508 case ACTION_OPEN: 509 case ACTION_READ: 510 case ACTION_WRITE: 511 case ACTION_CLOSE: 512 return false; 513 } 514 NOTREACHED(); 515 return false; 516 } 517 518 bool FileIOTest::MatchesResult(const TestStep& a, const TestStep& b) { 519 DCHECK(IsResult(a) && IsResult(b)); 520 if (a.type != b.type || a.status != b.status) 521 return false; 522 523 if (a.type != RESULT_READ || a.status != cdm::FileIOClient::kSuccess) 524 return true; 525 526 return (a.data_size == b.data_size && 527 std::equal(a.data, a.data + a.data_size, b.data)); 528 } 529 530 void FileIOTest::RunNextStep() { 531 // Run all actions in the current action group. 532 while (!test_steps_.empty()) { 533 // Start to wait for test results when the next step is a test result. 534 if (IsResult(test_steps_.front())) 535 return; 536 537 TestStep test_step = test_steps_.front(); 538 test_steps_.pop_front(); 539 540 cdm::FileIO* file_io = file_io_stack_.empty()? NULL : file_io_stack_.top(); 541 542 switch (test_step.type) { 543 case ACTION_CREATE: 544 file_io = create_file_io_cb_.Run(this); 545 if (!file_io) { 546 FILE_IO_DVLOG(3) << "Cannot create FileIO object."; 547 OnTestComplete(false); 548 return; 549 } 550 file_io_stack_.push(file_io); 551 break; 552 case ACTION_OPEN: 553 // Use test name as the test file name. 554 file_io->Open(test_name_.data(), test_name_.size()); 555 break; 556 case ACTION_READ: 557 file_io->Read(); 558 break; 559 case ACTION_WRITE: 560 file_io->Write(test_step.data, test_step.data_size); 561 break; 562 case ACTION_CLOSE: 563 file_io->Close(); 564 file_io_stack_.pop(); 565 break; 566 default: 567 NOTREACHED(); 568 } 569 } 570 571 OnTestComplete(true); 572 } 573 574 void FileIOTest::OnResult(const TestStep& result) { 575 DCHECK(IsResult(result)); 576 if (!CheckResult(result)) { 577 OnTestComplete(false); 578 return; 579 } 580 581 RunNextStep(); 582 } 583 584 bool FileIOTest::CheckResult(const TestStep& result) { 585 if (test_steps_.empty() || !IsResult(test_steps_.front())) 586 return false; 587 588 // If there are multiple results expected, the order does not matter. 589 std::list<TestStep>::iterator iter = test_steps_.begin(); 590 for (; iter != test_steps_.end(); ++iter) { 591 if (!IsResult(*iter)) 592 return false; 593 594 if (!MatchesResult(*iter, result)) 595 continue; 596 597 test_steps_.erase(iter); 598 return true; 599 } 600 601 return false; 602 } 603 604 void FileIOTest::OnTestComplete(bool success) { 605 while (!file_io_stack_.empty()) { 606 file_io_stack_.top()->Close(); 607 file_io_stack_.pop(); 608 } 609 FILE_IO_DVLOG(3) << test_name_ << (success ? " PASSED" : " FAILED"); 610 base::ResetAndReturn(&completion_cb_).Run(success); 611 } 612 613 } // namespace media 614