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