Home | History | Annotate | Download | only in ppapi
      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 = 9 * 1024 + 7;
     28 
     29 // Macros to help add test cases/steps.
     30 #define START_TEST_CASE(test_name)                                     \
     31   do {                                                                 \
     32     FileIOTest test_case(create_file_io_cb_, "FileIOTest." test_name); \
     33     CREATE_FILE_IO  // Create FileIO for each test case.
     34 
     35 #define ADD_TEST_STEP(type, status, data, data_size)                   \
     36     test_case.AddTestStep(FileIOTest::type, cdm::FileIOClient::status, \
     37                           (data), (data_size));
     38 
     39 #define END_TEST_CASE                 \
     40     remaining_tests_.push_back(test_case); \
     41   } while(0);
     42 
     43 #define CREATE_FILE_IO \
     44   ADD_TEST_STEP(ACTION_CREATE, kSuccess, NULL, 0)
     45 
     46 #define OPEN_FILE \
     47   ADD_TEST_STEP(ACTION_OPEN, kSuccess, NULL, 0)
     48 
     49 #define EXPECT_FILE_OPENED(status) \
     50   ADD_TEST_STEP(RESULT_OPEN, status, NULL, 0)
     51 
     52 #define READ_FILE \
     53   ADD_TEST_STEP(ACTION_READ, kSuccess, NULL, 0)
     54 
     55 #define EXPECT_FILE_READ(status, data, data_size) \
     56   ADD_TEST_STEP(RESULT_READ, status, data, data_size)
     57 
     58 #define WRITE_FILE(data, data_size) \
     59   ADD_TEST_STEP(ACTION_WRITE, kSuccess, data, data_size)
     60 
     61 #define EXPECT_FILE_WRITTEN(status) \
     62   ADD_TEST_STEP(RESULT_WRITE, status, NULL, 0)
     63 
     64 #define CLOSE_FILE \
     65   ADD_TEST_STEP(ACTION_CLOSE, kSuccess, NULL, 0)
     66 
     67 // FileIOTestRunner implementation.
     68 
     69 FileIOTestRunner::FileIOTestRunner(const CreateFileIOCB& create_file_io_cb)
     70     : create_file_io_cb_(create_file_io_cb),
     71       total_num_tests_(0),
     72       num_passed_tests_(0) {
     73   // Generate |large_data_|.
     74   large_data_.resize(kLargeDataSize);
     75   for (size_t i = 0; i < kLargeDataSize; ++i)
     76     large_data_[i] = i % kuint8max;
     77 
     78   AddTests();
     79 }
     80 
     81 FileIOTestRunner::~FileIOTestRunner() {
     82   if (remaining_tests_.empty())
     83     return;
     84 
     85   DCHECK_LT(num_passed_tests_, total_num_tests_);
     86   FILE_IO_DVLOG(1) << "Not Finished (probably due to timeout). "
     87                    << num_passed_tests_ << " passed in "
     88                    << total_num_tests_ << " tests.";
     89 }
     90 
     91 // Note: Consecutive expectations (EXPECT*) can happen in any order.
     92 void FileIOTestRunner::AddTests() {
     93   START_TEST_CASE("ReadBeforeOpeningFile")
     94     READ_FILE
     95     EXPECT_FILE_READ(kError, NULL, 0)
     96   END_TEST_CASE
     97 
     98   START_TEST_CASE("WriteBeforeOpeningFile")
     99     WRITE_FILE(kData, kDataSize)
    100     EXPECT_FILE_WRITTEN(kError)
    101   END_TEST_CASE
    102 
    103   START_TEST_CASE("ReadBeforeFileOpened")
    104     OPEN_FILE
    105     READ_FILE
    106     EXPECT_FILE_OPENED(kSuccess)
    107     EXPECT_FILE_READ(kError, NULL, 0)
    108   END_TEST_CASE
    109 
    110   START_TEST_CASE("WriteBeforeFileOpened")
    111     OPEN_FILE
    112     WRITE_FILE(kData, kDataSize)
    113     EXPECT_FILE_WRITTEN(kError)
    114     EXPECT_FILE_OPENED(kSuccess)
    115   END_TEST_CASE
    116 
    117   START_TEST_CASE("ReadDuringPendingRead")
    118     OPEN_FILE
    119     EXPECT_FILE_OPENED(kSuccess)
    120     WRITE_FILE(kData, kDataSize)
    121     EXPECT_FILE_WRITTEN(kSuccess)
    122     READ_FILE
    123     READ_FILE
    124     EXPECT_FILE_READ(kInUse, NULL, 0)
    125     EXPECT_FILE_READ(kSuccess, kData, kDataSize)
    126   END_TEST_CASE
    127 
    128   START_TEST_CASE("ReadDuringPendingWrite")
    129     OPEN_FILE
    130     EXPECT_FILE_OPENED(kSuccess)
    131     WRITE_FILE(kData, kDataSize)
    132     READ_FILE
    133     EXPECT_FILE_READ(kInUse, NULL, 0)
    134     EXPECT_FILE_WRITTEN(kSuccess)
    135   END_TEST_CASE
    136 
    137   START_TEST_CASE("WriteDuringPendingRead")
    138     OPEN_FILE
    139     EXPECT_FILE_OPENED(kSuccess)
    140     READ_FILE
    141     WRITE_FILE(kData, kDataSize)
    142     EXPECT_FILE_WRITTEN(kInUse)
    143     EXPECT_FILE_READ(kSuccess, NULL, 0)
    144   END_TEST_CASE
    145 
    146   START_TEST_CASE("WriteDuringPendingWrite")
    147     OPEN_FILE
    148     EXPECT_FILE_OPENED(kSuccess)
    149     WRITE_FILE(kData, kDataSize)
    150     WRITE_FILE(kBigData, kBigDataSize)
    151     EXPECT_FILE_WRITTEN(kInUse)
    152     EXPECT_FILE_WRITTEN(kSuccess)
    153   END_TEST_CASE
    154 
    155   START_TEST_CASE("ReadEmptyFile")
    156     OPEN_FILE
    157     EXPECT_FILE_OPENED(kSuccess)
    158     READ_FILE
    159     EXPECT_FILE_READ(kSuccess, NULL, 0)
    160   END_TEST_CASE
    161 
    162   START_TEST_CASE("WriteAndRead")
    163     OPEN_FILE
    164     EXPECT_FILE_OPENED(kSuccess)
    165     WRITE_FILE(kData, kDataSize)
    166     EXPECT_FILE_WRITTEN(kSuccess)
    167     READ_FILE
    168     EXPECT_FILE_READ(kSuccess, kData, kDataSize)
    169   END_TEST_CASE
    170 
    171   START_TEST_CASE("WriteZeroBytes")
    172     OPEN_FILE
    173     EXPECT_FILE_OPENED(kSuccess)
    174     WRITE_FILE(NULL, 0)
    175     EXPECT_FILE_WRITTEN(kSuccess)
    176     READ_FILE
    177     EXPECT_FILE_READ(kSuccess, NULL, 0)
    178   END_TEST_CASE
    179 
    180   START_TEST_CASE("WriteAndReadLargeData")
    181     OPEN_FILE
    182     EXPECT_FILE_OPENED(kSuccess)
    183     WRITE_FILE(&large_data_[0], kLargeDataSize)
    184     EXPECT_FILE_WRITTEN(kSuccess)
    185     READ_FILE
    186     EXPECT_FILE_READ(kSuccess, &large_data_[0], kLargeDataSize)
    187   END_TEST_CASE
    188 
    189   START_TEST_CASE("OverwriteZeroBytes")
    190     OPEN_FILE
    191     EXPECT_FILE_OPENED(kSuccess)
    192     WRITE_FILE(kData, kDataSize)
    193     EXPECT_FILE_WRITTEN(kSuccess)
    194     READ_FILE
    195     EXPECT_FILE_READ(kSuccess, kData, kDataSize)
    196     WRITE_FILE(NULL, 0)
    197     EXPECT_FILE_WRITTEN(kSuccess)
    198     READ_FILE
    199     EXPECT_FILE_READ(kSuccess, NULL, 0)
    200   END_TEST_CASE
    201 
    202   START_TEST_CASE("OverwriteWithSmallerData")
    203     OPEN_FILE
    204     EXPECT_FILE_OPENED(kSuccess)
    205     WRITE_FILE(kBigData, kBigDataSize)
    206     EXPECT_FILE_WRITTEN(kSuccess)
    207     WRITE_FILE(kData, kDataSize)
    208     EXPECT_FILE_WRITTEN(kSuccess)
    209     READ_FILE
    210     EXPECT_FILE_READ(kSuccess, kData, kDataSize)
    211   END_TEST_CASE
    212 
    213   START_TEST_CASE("OverwriteWithLargerData")
    214     OPEN_FILE
    215     EXPECT_FILE_OPENED(kSuccess)
    216     WRITE_FILE(kData, kDataSize)
    217     EXPECT_FILE_WRITTEN(kSuccess)
    218     WRITE_FILE(kBigData, kBigDataSize)
    219     EXPECT_FILE_WRITTEN(kSuccess)
    220     READ_FILE
    221     EXPECT_FILE_READ(kSuccess, kBigData, kBigDataSize)
    222   END_TEST_CASE
    223 
    224   START_TEST_CASE("ReadExistingFile")
    225     OPEN_FILE
    226     EXPECT_FILE_OPENED(kSuccess)
    227     WRITE_FILE(kData, kDataSize)
    228     EXPECT_FILE_WRITTEN(kSuccess)
    229     CLOSE_FILE
    230     CREATE_FILE_IO
    231     OPEN_FILE
    232     EXPECT_FILE_OPENED(kSuccess)
    233     READ_FILE
    234     EXPECT_FILE_READ(kSuccess, kData, kDataSize)
    235   END_TEST_CASE
    236 
    237   START_TEST_CASE("ReopenFileInTheSameFileIO")
    238     OPEN_FILE
    239     OPEN_FILE
    240     EXPECT_FILE_OPENED(kError)  // The second Open() failed.
    241     EXPECT_FILE_OPENED(kSuccess)  // The first Open() succeeded.
    242   END_TEST_CASE
    243 
    244   START_TEST_CASE("ReopenFileInSeparateFileIO")
    245     OPEN_FILE
    246     EXPECT_FILE_OPENED(kSuccess)
    247     WRITE_FILE(kData, kDataSize)
    248     EXPECT_FILE_WRITTEN(kSuccess)
    249     CREATE_FILE_IO  // Create a second FileIO without closing the first one.
    250     OPEN_FILE
    251     EXPECT_FILE_OPENED(kInUse)
    252   END_TEST_CASE
    253 
    254   START_TEST_CASE("CloseAfterCreation")
    255     CLOSE_FILE
    256   END_TEST_CASE
    257 
    258   START_TEST_CASE("CloseDuringPendingOpen")
    259     OPEN_FILE
    260     CLOSE_FILE
    261   END_TEST_CASE
    262 
    263   START_TEST_CASE("CloseDuringPendingWrite")
    264     OPEN_FILE
    265     EXPECT_FILE_OPENED(kSuccess)
    266     WRITE_FILE(kData, kDataSize)
    267     CLOSE_FILE
    268   END_TEST_CASE
    269 
    270   START_TEST_CASE("CloseDuringPendingRead")
    271     OPEN_FILE
    272     EXPECT_FILE_OPENED(kSuccess)
    273     WRITE_FILE(kData, kDataSize)
    274     EXPECT_FILE_WRITTEN(kSuccess)
    275     READ_FILE
    276     CLOSE_FILE
    277   END_TEST_CASE
    278 }
    279 
    280 void FileIOTestRunner::RunAllTests(const CompletionCB& completion_cb) {
    281   completion_cb_ = completion_cb;
    282   total_num_tests_ = remaining_tests_.size();
    283   RunNextTest();
    284 }
    285 
    286 void FileIOTestRunner::RunNextTest() {
    287   if (remaining_tests_.empty()) {
    288     FILE_IO_DVLOG(1) << num_passed_tests_ << " passed and "
    289                      << (total_num_tests_ - num_passed_tests_) << " failed in "
    290                      << total_num_tests_ << " tests.";
    291     bool success = (num_passed_tests_ == total_num_tests_);
    292     base::ResetAndReturn(&completion_cb_).Run(success);
    293     return;
    294   }
    295 
    296   remaining_tests_.front().Run(
    297       base::Bind(&FileIOTestRunner::OnTestComplete, base::Unretained(this)));
    298 }
    299 
    300 void FileIOTestRunner::OnTestComplete(bool success) {
    301   if (success)
    302     num_passed_tests_++;
    303   remaining_tests_.pop_front();
    304   RunNextTest();
    305 }
    306 
    307 // FileIOTest implementation.
    308 
    309 FileIOTest::FileIOTest(const CreateFileIOCB& create_file_io_cb,
    310                        const std::string& test_name)
    311     : create_file_io_cb_(create_file_io_cb),
    312       test_name_(test_name) {}
    313 
    314 FileIOTest::~FileIOTest() {}
    315 
    316 void FileIOTest::AddTestStep(
    317     StepType type, Status status, const uint8* data, uint32 data_size) {
    318   test_steps_.push_back(TestStep(type, status, data, data_size));
    319 }
    320 
    321 void FileIOTest::Run(const CompletionCB& completion_cb) {
    322   FILE_IO_DVLOG(3) << "Run " << test_name_;
    323   completion_cb_ = completion_cb;
    324   DCHECK(!test_steps_.empty() && !IsResult(test_steps_.front()));
    325   RunNextStep();
    326 }
    327 
    328 void FileIOTest::OnOpenComplete(Status status) {
    329   OnResult(TestStep(RESULT_OPEN, status, NULL, 0));
    330 }
    331 
    332 void FileIOTest::OnReadComplete(Status status,
    333                                 const uint8_t* data,
    334                                 uint32_t data_size) {
    335   OnResult(TestStep(RESULT_READ, status, data, data_size));
    336 }
    337 
    338 void FileIOTest::OnWriteComplete(Status status) {
    339   OnResult(TestStep(RESULT_WRITE, status, NULL, 0));
    340 }
    341 
    342 bool FileIOTest::IsResult(const TestStep& test_step) {
    343   switch (test_step.type) {
    344     case RESULT_OPEN:
    345     case RESULT_READ:
    346     case RESULT_WRITE:
    347       return true;
    348     case ACTION_CREATE:
    349     case ACTION_OPEN:
    350     case ACTION_READ:
    351     case ACTION_WRITE:
    352     case ACTION_CLOSE:
    353       return false;
    354   }
    355   NOTREACHED();
    356   return false;
    357 }
    358 
    359 bool FileIOTest::MatchesResult(const TestStep& a, const TestStep& b) {
    360   DCHECK(IsResult(a) && IsResult(b));
    361   if (a.type != b.type || a.status != b.status)
    362     return false;
    363 
    364   if (a.type != RESULT_READ || a.status != cdm::FileIOClient::kSuccess)
    365     return true;
    366 
    367   return (a.data_size == a.data_size &&
    368           std::equal(a.data, a.data + a.data_size, b.data));
    369 }
    370 
    371 void FileIOTest::RunNextStep() {
    372   // Run all actions in the current action group.
    373   while (!test_steps_.empty()) {
    374     // Start to wait for test results when the next step is a test result.
    375     if (IsResult(test_steps_.front()))
    376       return;
    377 
    378     TestStep test_step = test_steps_.front();
    379     test_steps_.pop_front();
    380 
    381     cdm::FileIO* file_io = file_io_stack_.empty()? NULL : file_io_stack_.top();
    382 
    383     switch (test_step.type) {
    384       case ACTION_CREATE:
    385         file_io = create_file_io_cb_.Run(this);
    386         if (!file_io) {
    387           FILE_IO_DVLOG(3) << "Cannot create FileIO object.";
    388           OnTestComplete(false);
    389           return;
    390         }
    391         file_io_stack_.push(file_io);
    392         break;
    393       case ACTION_OPEN:
    394         // Use test name as the test file name.
    395         file_io->Open(test_name_.data(), test_name_.size());
    396         break;
    397       case ACTION_READ:
    398         file_io->Read();
    399         break;
    400       case ACTION_WRITE:
    401         file_io->Write(test_step.data, test_step.data_size);
    402         break;
    403       case ACTION_CLOSE:
    404         file_io->Close();
    405         file_io_stack_.pop();
    406         break;
    407       default:
    408         NOTREACHED();
    409     }
    410   }
    411 
    412   OnTestComplete(true);
    413 }
    414 
    415 void FileIOTest::OnResult(const TestStep& result) {
    416   DCHECK(IsResult(result));
    417   if (!CheckResult(result)) {
    418     OnTestComplete(false);
    419     return;
    420   }
    421 
    422   RunNextStep();
    423 }
    424 
    425 bool FileIOTest::CheckResult(const TestStep& result) {
    426   if (test_steps_.empty() || !IsResult(test_steps_.front()))
    427     return false;
    428 
    429   // If there are multiple results expected, the order does not matter.
    430   std::list<TestStep>::iterator iter = test_steps_.begin();
    431   for (; iter != test_steps_.end(); ++iter) {
    432     if (!IsResult(*iter))
    433       return false;
    434 
    435     if (!MatchesResult(*iter, result))
    436       continue;
    437 
    438     test_steps_.erase(iter);
    439     return true;
    440   }
    441 
    442   return false;
    443 }
    444 
    445 void FileIOTest::OnTestComplete(bool success) {
    446   while (!file_io_stack_.empty()) {
    447     file_io_stack_.top()->Close();
    448     file_io_stack_.pop();
    449   }
    450   FILE_IO_DVLOG(3) << test_name_ << (success ? " PASSED" : " FAILED");
    451   base::ResetAndReturn(&completion_cb_).Run(success);
    452 }
    453 
    454 }  // namespace media
    455