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