1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
media / cdm / library_cdm / clear_key_cdm / cdm_file_io_test.h [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_CDM_LIBRARY_CDM_CLEAR_KEY_CDM_CDM_FILE_IO_TEST_H_
#define MEDIA_CDM_LIBRARY_CDM_CLEAR_KEY_CDM_CDM_FILE_IO_TEST_H_
#include <stddef.h>
#include <stdint.h>
#include <list>
#include <memory>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/containers/stack.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "media/cdm/api/content_decryption_module.h"
namespace media {
using CompletionCB = base::OnceCallback<void(bool success)>;
using CreateFileIOCB =
base::RepeatingCallback<cdm::FileIO*(cdm::FileIOClient* client)>;
// A customizable test class that tests cdm::FileIO implementation.
// - To create a test, call AddTestStep() to add a test step. A test step can be
// either an action to make (use ACTION_* types), or a result to verify (use
// RESULT_* types).
// - To run the test, simply call Run() with a completion callback. The result
// will be reported in the completion callback when the test is finished.
//
// The following rules apply to the test steps:
// - Test steps are ordered (with the exception that results in a result group
// is not ordered).
// - Consecutive action steps form an "action group". Consecutively result
// steps form a "result group". An action group is followed by a result
// group and vice versa.
// - A test must start with an action group.
// - To process an action group, the test runner runs (and clears) all steps
// in the group in the order they were added. Then it waits for test
// results.
// - When a cdm::FileIOClient method is called, the test runner compares the
// result with all results in the current result group. If no result in that
// group matches the test result, the test fails. Otherwise, the matching
// result is cleared from the group. If the group is empty, the test runner
// starts to process the next action group. Otherwise, the test runner keeps
// waiting for the next test result.
// - After all steps are cleared, the test passes.
class FileIOTest : public cdm::FileIOClient {
public:
// Types of allowed test steps:
// - ACTION_* specifies the next step to test.
// - RESULT_* specifies the expected result of the previous step(s).
enum StepType {
ACTION_CREATE,
ACTION_OPEN, // |test_name_| will be used used as the file name to open.
RESULT_OPEN,
ACTION_READ,
RESULT_READ,
ACTION_WRITE,
RESULT_WRITE,
ACTION_CLOSE // If ACTION_CLOSE is not specified, FileIO::Close() will be
// automatically called at the end of the test.
};
FileIOTest(const CreateFileIOCB& create_file_io_cb,
const std::string& test_name);
FileIOTest(const FileIOTest&) = delete;
FileIOTest& operator=(const FileIOTest&) = delete;
~FileIOTest() override;
// Adds a test step in this test. |this| object doesn't take the ownership of
// |data|, which should be valid throughout the lifetime of |this| object.
void AddTestStep(StepType type,
Status status,
const uint8_t* data,
uint32_t data_size);
// Adds a test step in this test that expects a successful read of either
// |data| or |data2|. |this| object doesn't take the ownership of |data| or
// |data2|, which should be valid throughout the lifetime of |this| object.
void AddResultReadEither(Status status,
const uint8_t* data,
uint32_t data_size,
const uint8_t* data2,
uint32_t data2_size);
// Runs this test case and returns the test result through |completion_cb|.
void Run(CompletionCB completion_cb);
private:
struct TestStep {
// |this| object doesn't take the ownership of |data| or |data2|, which
// should be valid throughout the lifetime of |this| object.
TestStep(StepType type,
Status status,
const uint8_t* data = nullptr,
uint32_t data_size = 0,
const uint8_t* data2 = nullptr,
uint32_t data2_size = 0)
: type(type),
status(status),
data(data),
data_size(data_size),
data2(data2),
data2_size(data2_size) {}
StepType type;
// Expected status for RESULT* steps.
Status status;
// Data to write in ACTION_WRITE, or read data in RESULT_READ.
const uint8_t* data;
uint32_t data_size;
// Alternate read data in RESULT_READ, if |data2| != nullptr.
const uint8_t* data2;
uint32_t data2_size;
};
// Returns whether |test_step| is a RESULT_* step.
static bool IsResult(const TestStep& test_step);
// Returns whether two results match.
static bool MatchesResult(const TestStep& a, const TestStep& b);
// cdm::FileIOClient implementation.
void OnOpenComplete(Status status) override;
void OnReadComplete(Status status,
const uint8_t* data,
uint32_t data_size) override;
void OnWriteComplete(Status status) override;
// Runs the next step in this test case.
void RunNextStep();
void OnResult(const TestStep& result);
// Checks whether the test result matches this step. This can only be called
// when this step is a RESULT_* step.
bool CheckResult(const TestStep& result);
void OnTestComplete(bool success);
CreateFileIOCB create_file_io_cb_;
CompletionCB completion_cb_;
std::string test_name_;
std::list<TestStep> test_steps_;
// All opened cdm::FileIO objects. We keep multiple cdm::FileIO objects open
// so that we can test multiple cdm::FileIO objects accessing the same file.
// In the current implementation, all ACTION_* are performed on the latest
// opened cdm::FileIO object, hence the stack.
base::stack<raw_ptr<cdm::FileIO, CtnExperimental>> file_io_stack_;
};
// Tests cdm::FileIO implementation.
class FileIOTestRunner {
public:
explicit FileIOTestRunner(const CreateFileIOCB& create_file_io_cb);
FileIOTestRunner(const FileIOTestRunner&) = delete;
FileIOTestRunner& operator=(const FileIOTestRunner&) = delete;
~FileIOTestRunner();
void AddTests();
// Run all tests. When tests are completed, the result will be reported in the
// |completion_cb|.
void RunAllTests(CompletionCB completion_cb);
private:
void OnTestComplete(bool success);
void RunNextTest();
CreateFileIOCB create_file_io_cb_;
CompletionCB completion_cb_;
std::list<std::unique_ptr<FileIOTest>> remaining_tests_;
std::vector<uint8_t> large_data_;
size_t total_num_tests_ = 0; // Total number of tests.
size_t num_passed_tests_ = 0; // Number of passed tests.
};
} // namespace media
#endif // MEDIA_CDM_LIBRARY_CDM_CLEAR_KEY_CDM_CDM_FILE_IO_TEST_H_