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