OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include <list> |
| 6 #include <vector> |
| 7 |
| 8 #include "base/basictypes.h" |
| 9 #include "base/bind.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" |
| 17 |
| 18 namespace chromecast { |
| 19 namespace media { |
| 20 |
| 21 namespace { |
| 22 |
| 23 struct MediaTaskRunnerTestContext { |
| 24 MediaTaskRunnerTestContext(); |
| 25 ~MediaTaskRunnerTestContext(); |
| 26 |
| 27 scoped_refptr<MediaTaskRunner> media_task_runner; |
| 28 |
| 29 bool is_pending_task; |
| 30 |
| 31 std::vector<base::TimeDelta> task_timestamp_list; |
| 32 |
| 33 size_t task_index; |
| 34 base::TimeDelta max_timestamp; |
| 35 }; |
| 36 |
| 37 MediaTaskRunnerTestContext::MediaTaskRunnerTestContext() { |
| 38 } |
| 39 |
| 40 MediaTaskRunnerTestContext::~MediaTaskRunnerTestContext() { |
| 41 } |
| 42 |
| 43 } // namespace |
| 44 |
| 45 class BalancedMediaTaskRunnerTest : public testing::Test { |
| 46 public: |
| 47 BalancedMediaTaskRunnerTest(); |
| 48 virtual ~BalancedMediaTaskRunnerTest(); |
| 49 |
| 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(); |
| 55 |
| 56 protected: |
| 57 // Expected task order based on their timestamps. |
| 58 std::list<base::TimeDelta> expected_task_timestamps_; |
| 59 |
| 60 private: |
| 61 void ScheduleTask(); |
| 62 void Task(size_t task_runner_id, base::TimeDelta timestamp); |
| 63 |
| 64 void OnTestTimeout(); |
| 65 |
| 66 scoped_refptr<BalancedMediaTaskRunnerFactory> media_task_runner_factory_; |
| 67 |
| 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_; |
| 73 |
| 74 // For each media task runner, keep a track of which task has already been |
| 75 // scheduled. |
| 76 std::vector<MediaTaskRunnerTestContext> contexts_; |
| 77 |
| 78 DISALLOW_COPY_AND_ASSIGN(BalancedMediaTaskRunnerTest); |
| 79 }; |
| 80 |
| 81 BalancedMediaTaskRunnerTest::BalancedMediaTaskRunnerTest() { |
| 82 } |
| 83 |
| 84 BalancedMediaTaskRunnerTest::~BalancedMediaTaskRunnerTest() { |
| 85 } |
| 86 |
| 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); |
| 93 |
| 94 scheduling_pattern_ = pattern; |
| 95 pattern_index_ = 0; |
| 96 |
| 97 // Setup each task runner. |
| 98 size_t n = timestamps_in_ms.size(); |
| 99 contexts_.resize(n); |
| 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]); |
| 111 } |
| 112 } |
| 113 |
| 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])); |
| 118 } |
| 119 } |
| 120 |
| 121 void BalancedMediaTaskRunnerTest::ProcessAllTasks() { |
| 122 base::MessageLoop::current()->PostDelayedTask( |
| 123 FROM_HERE, |
| 124 base::Bind(&BalancedMediaTaskRunnerTest::OnTestTimeout, |
| 125 base::Unretained(this)), |
| 126 base::TimeDelta::FromSeconds(5)); |
| 127 ScheduleTask(); |
| 128 } |
| 129 |
| 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()) |
| 134 has_task = true; |
| 135 } |
| 136 if (!has_task) { |
| 137 base::MessageLoop::current()->QuitWhenIdle(); |
| 138 return; |
| 139 } |
| 140 |
| 141 size_t next_pattern_index = |
| 142 (pattern_index_ + 1) % scheduling_pattern_.size(); |
| 143 |
| 144 size_t task_runner_id = scheduling_pattern_[pattern_index_]; |
| 145 MediaTaskRunnerTestContext& context = contexts_[task_runner_id]; |
| 146 |
| 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( |
| 153 FROM_HERE, |
| 154 base::Bind(&BalancedMediaTaskRunnerTest::ScheduleTask, |
| 155 base::Unretained(this))); |
| 156 return; |
| 157 } |
| 158 |
| 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]; |
| 164 } |
| 165 |
| 166 bool may_run = context.media_task_runner->PostMediaTask( |
| 167 FROM_HERE, |
| 168 base::Bind(&BalancedMediaTaskRunnerTest::Task, |
| 169 base::Unretained(this), |
| 170 task_runner_id, |
| 171 context.task_timestamp_list[context.task_index]), |
| 172 context.task_timestamp_list[context.task_index]); |
| 173 EXPECT_EQ(may_run, expected_may_run); |
| 174 |
| 175 if (may_run) |
| 176 context.is_pending_task = true; |
| 177 |
| 178 context.task_index++; |
| 179 pattern_index_ = next_pattern_index; |
| 180 base::MessageLoopProxy::current()->PostTask( |
| 181 FROM_HERE, |
| 182 base::Bind(&BalancedMediaTaskRunnerTest::ScheduleTask, |
| 183 base::Unretained(this))); |
| 184 } |
| 185 |
| 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(); |
| 191 |
| 192 contexts_[task_runner_id].is_pending_task = false; |
| 193 } |
| 194 |
| 195 void BalancedMediaTaskRunnerTest::OnTestTimeout() { |
| 196 ADD_FAILURE() << "Test timed out"; |
| 197 if (base::MessageLoop::current()) |
| 198 base::MessageLoop::current()->QuitWhenIdle(); |
| 199 } |
| 200 |
| 201 TEST_F(BalancedMediaTaskRunnerTest, OneTaskRunner) { |
| 202 scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); |
| 203 |
| 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)); |
| 209 |
| 210 // Scheduling pattern. |
| 211 std::vector<size_t> scheduling_pattern(1); |
| 212 scheduling_pattern[0] = 0; |
| 213 |
| 214 // Expected results. |
| 215 int expected_timestamps[] = {0, 10, 20, 30, 40, 50, 60, 70}; |
| 216 std::vector<int> expected_timestamps_ms(std::vector<int>( |
| 217 expected_timestamps, |
| 218 expected_timestamps + arraysize(expected_timestamps))); |
| 219 |
| 220 SetupTest(base::TimeDelta::FromMilliseconds(30), |
| 221 timestamps_ms, |
| 222 scheduling_pattern, |
| 223 expected_timestamps_ms); |
| 224 ProcessAllTasks(); |
| 225 message_loop->Run(); |
| 226 EXPECT_TRUE(expected_task_timestamps_.empty()); |
| 227 } |
| 228 |
| 229 TEST_F(BalancedMediaTaskRunnerTest, TwoTaskRunnerUnbalanced) { |
| 230 scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); |
| 231 |
| 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)); |
| 240 |
| 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)); |
| 245 |
| 246 // Expected results. |
| 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>( |
| 250 expected_timestamps, |
| 251 expected_timestamps + arraysize(expected_timestamps))); |
| 252 |
| 253 SetupTest(base::TimeDelta::FromMilliseconds(30), |
| 254 timestamps_ms, |
| 255 scheduling_pattern, |
| 256 expected_timestamps_ms); |
| 257 ProcessAllTasks(); |
| 258 message_loop->Run(); |
| 259 EXPECT_TRUE(expected_task_timestamps_.empty()); |
| 260 } |
| 261 |
| 262 } // namespace media |
| 263 } // namespace chromecast |
OLD | NEW |