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