1 // Copyright 2014 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.
8 #include "base/basictypes.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/threading/thread.h"
13 #include "base/time/time.h"
14 #include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
15 #include "chromecast/media/cma/base/media_task_runner.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 namespace chromecast
{
23 struct MediaTaskRunnerTestContext
{
24 MediaTaskRunnerTestContext();
25 ~MediaTaskRunnerTestContext();
27 scoped_refptr
<MediaTaskRunner
> media_task_runner
;
31 std::vector
<base::TimeDelta
> task_timestamp_list
;
34 base::TimeDelta max_timestamp
;
37 MediaTaskRunnerTestContext::MediaTaskRunnerTestContext() {
40 MediaTaskRunnerTestContext::~MediaTaskRunnerTestContext() {
45 class BalancedMediaTaskRunnerTest
: public testing::Test
{
47 BalancedMediaTaskRunnerTest();
48 ~BalancedMediaTaskRunnerTest() override
;
50 void SetupTest(base::TimeDelta max_delta
,
51 const std::vector
<std::vector
<int> >& timestamps_in_ms
,
52 const std::vector
<size_t>& pattern
,
53 const std::vector
<int>& expected_task_timestamps_ms
);
54 void ProcessAllTasks();
57 // Expected task order based on their timestamps.
58 std::list
<base::TimeDelta
> expected_task_timestamps_
;
62 void Task(size_t task_runner_id
, base::TimeDelta timestamp
);
66 scoped_refptr
<BalancedMediaTaskRunnerFactory
> media_task_runner_factory_
;
68 // Schedule first a task on media task runner #scheduling_pattern[0]
69 // then a task on media task runner #scheduling_pattern[1] and so on.
70 // Wrap around when reaching the end of the pattern.
71 std::vector
<size_t> scheduling_pattern_
;
72 size_t pattern_index_
;
74 // For each media task runner, keep a track of which task has already been
76 std::vector
<MediaTaskRunnerTestContext
> contexts_
;
78 DISALLOW_COPY_AND_ASSIGN(BalancedMediaTaskRunnerTest
);
81 BalancedMediaTaskRunnerTest::BalancedMediaTaskRunnerTest() {
84 BalancedMediaTaskRunnerTest::~BalancedMediaTaskRunnerTest() {
87 void BalancedMediaTaskRunnerTest::SetupTest(
88 base::TimeDelta max_delta
,
89 const std::vector
<std::vector
<int> >& timestamps_in_ms
,
90 const std::vector
<size_t>& pattern
,
91 const std::vector
<int>& expected_task_timestamps_ms
) {
92 media_task_runner_factory_
= new BalancedMediaTaskRunnerFactory(max_delta
);
94 scheduling_pattern_
= pattern
;
97 // Setup each task runner.
98 size_t n
= timestamps_in_ms
.size();
100 for (size_t k
= 0; k
< n
; k
++) {
101 contexts_
[k
].media_task_runner
=
102 media_task_runner_factory_
->CreateMediaTaskRunner(
103 base::MessageLoopProxy::current());
104 contexts_
[k
].is_pending_task
= false;
105 contexts_
[k
].task_index
= 0;
106 contexts_
[k
].task_timestamp_list
.resize(
107 timestamps_in_ms
[k
].size());
108 for (size_t i
= 0; i
< timestamps_in_ms
[k
].size(); i
++) {
109 contexts_
[k
].task_timestamp_list
[i
] =
110 base::TimeDelta::FromMilliseconds(timestamps_in_ms
[k
][i
]);
114 // Expected task order (for tasks that are actually run).
115 for (size_t k
= 0; k
< expected_task_timestamps_ms
.size(); k
++) {
116 expected_task_timestamps_
.push_back(
117 base::TimeDelta::FromMilliseconds(expected_task_timestamps_ms
[k
]));
121 void BalancedMediaTaskRunnerTest::ProcessAllTasks() {
122 base::MessageLoop::current()->PostDelayedTask(
124 base::Bind(&BalancedMediaTaskRunnerTest::OnTestTimeout
,
125 base::Unretained(this)),
126 base::TimeDelta::FromSeconds(5));
130 void BalancedMediaTaskRunnerTest::ScheduleTask() {
131 bool has_task
= false;
132 for (size_t k
= 0; k
< contexts_
.size(); k
++) {
133 if (contexts_
[k
].task_index
< contexts_
[k
].task_timestamp_list
.size())
137 base::MessageLoop::current()->QuitWhenIdle();
141 size_t next_pattern_index
=
142 (pattern_index_
+ 1) % scheduling_pattern_
.size();
144 size_t task_runner_id
= scheduling_pattern_
[pattern_index_
];
145 MediaTaskRunnerTestContext
& context
= contexts_
[task_runner_id
];
147 // Check whether all tasks have been scheduled for that task runner
148 // or if there is already one pending task.
149 if (context
.task_index
>= context
.task_timestamp_list
.size() ||
150 context
.is_pending_task
) {
151 pattern_index_
= next_pattern_index
;
152 base::MessageLoopProxy::current()->PostTask(
154 base::Bind(&BalancedMediaTaskRunnerTest::ScheduleTask
,
155 base::Unretained(this)));
159 bool expected_may_run
= false;
160 if (context
.task_timestamp_list
[context
.task_index
] >=
161 context
.max_timestamp
) {
162 expected_may_run
= true;
163 context
.max_timestamp
= context
.task_timestamp_list
[context
.task_index
];
166 bool may_run
= context
.media_task_runner
->PostMediaTask(
168 base::Bind(&BalancedMediaTaskRunnerTest::Task
,
169 base::Unretained(this),
171 context
.task_timestamp_list
[context
.task_index
]),
172 context
.task_timestamp_list
[context
.task_index
]);
173 EXPECT_EQ(may_run
, expected_may_run
);
176 context
.is_pending_task
= true;
178 context
.task_index
++;
179 pattern_index_
= next_pattern_index
;
180 base::MessageLoopProxy::current()->PostTask(
182 base::Bind(&BalancedMediaTaskRunnerTest::ScheduleTask
,
183 base::Unretained(this)));
186 void BalancedMediaTaskRunnerTest::Task(
187 size_t task_runner_id
, base::TimeDelta timestamp
) {
188 ASSERT_FALSE(expected_task_timestamps_
.empty());
189 EXPECT_EQ(timestamp
, expected_task_timestamps_
.front());
190 expected_task_timestamps_
.pop_front();
192 contexts_
[task_runner_id
].is_pending_task
= false;
195 void BalancedMediaTaskRunnerTest::OnTestTimeout() {
196 ADD_FAILURE() << "Test timed out";
197 if (base::MessageLoop::current())
198 base::MessageLoop::current()->QuitWhenIdle();
201 TEST_F(BalancedMediaTaskRunnerTest
, OneTaskRunner
) {
202 scoped_ptr
<base::MessageLoop
> message_loop(new base::MessageLoop());
204 // Timestamps of tasks for the single task runner.
205 int timestamps0_ms
[] = {0, 10, 20, 30, 40, 30, 50, 60, 20, 30, 70};
206 std::vector
<std::vector
<int> > timestamps_ms(1);
207 timestamps_ms
[0] = std::vector
<int>(
208 timestamps0_ms
, timestamps0_ms
+ arraysize(timestamps0_ms
));
210 // Scheduling pattern.
211 std::vector
<size_t> scheduling_pattern(1);
212 scheduling_pattern
[0] = 0;
215 int expected_timestamps
[] = {0, 10, 20, 30, 40, 50, 60, 70};
216 std::vector
<int> expected_timestamps_ms(std::vector
<int>(
218 expected_timestamps
+ arraysize(expected_timestamps
)));
220 SetupTest(base::TimeDelta::FromMilliseconds(30),
223 expected_timestamps_ms
);
226 EXPECT_TRUE(expected_task_timestamps_
.empty());
229 TEST_F(BalancedMediaTaskRunnerTest
, TwoTaskRunnerUnbalanced
) {
230 scoped_ptr
<base::MessageLoop
> message_loop(new base::MessageLoop());
232 // Timestamps of tasks for the 2 task runners.
233 int timestamps0_ms
[] = {0, 10, 20, 30, 40, 30, 50, 60, 20, 30, 70};
234 int timestamps1_ms
[] = {5, 15, 25, 35, 45, 35, 55, 65, 25, 35, 75};
235 std::vector
<std::vector
<int> > timestamps_ms(2);
236 timestamps_ms
[0] = std::vector
<int>(
237 timestamps0_ms
, timestamps0_ms
+ arraysize(timestamps0_ms
));
238 timestamps_ms
[1] = std::vector
<int>(
239 timestamps1_ms
, timestamps1_ms
+ arraysize(timestamps1_ms
));
241 // Scheduling pattern.
242 size_t pattern
[] = {1, 0, 0, 0, 0};
243 std::vector
<size_t> scheduling_pattern
= std::vector
<size_t>(
244 pattern
, pattern
+ arraysize(pattern
));
247 int expected_timestamps
[] = {
248 5, 0, 10, 20, 30, 15, 40, 25, 50, 35, 60, 45, 70, 55, 65, 75 };
249 std::vector
<int> expected_timestamps_ms(std::vector
<int>(
251 expected_timestamps
+ arraysize(expected_timestamps
)));
253 SetupTest(base::TimeDelta::FromMilliseconds(30),
256 expected_timestamps_ms
);
259 EXPECT_TRUE(expected_task_timestamps_
.empty());
263 } // namespace chromecast