Chromium Code Reviews| Index: components/scheduler/renderer/queueing_time_estimator_unittest.cc |
| diff --git a/components/scheduler/renderer/queueing_time_estimator_unittest.cc b/components/scheduler/renderer/queueing_time_estimator_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ea6fdbcdf71f444fa0d93112f9d441466746e472 |
| --- /dev/null |
| +++ b/components/scheduler/renderer/queueing_time_estimator_unittest.cc |
| @@ -0,0 +1,155 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
|
Sami
2016/04/20 09:51:27
++year
tdresser
2016/04/20 15:13:33
Done.
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/test/simple_test_tick_clock.h" |
| +#include "components/scheduler/base/test_time_source.h" |
| +#include "components/scheduler/renderer/queueing_time_estimator.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace scheduler { |
| + |
| +class QueueingTimeEstimatorTest : public testing::Test { |
| + public: |
| + QueueingTimeEstimatorTest() {} |
| + ~QueueingTimeEstimatorTest() override {} |
| + |
| + void SetUp() override { |
| + test_time_source_.reset(new TestTimeSource(&clock_)); |
| + } |
| + |
| + base::SimpleTestTickClock clock_; |
| + scoped_ptr<TestTimeSource> test_time_source_; |
| +}; |
| + |
| +class TestQueueingTimeEstimatorClient |
| + : public QueueingTimeEstimator::QueueingTimeEstimatorClient { |
| + public: |
| + void OnQueueingTimeForWindowEstimated( |
| + base::TimeDelta queueing_time) override { |
| + expected_queueing_times_.push_back(queueing_time); |
| + } |
| + const std::vector<base::TimeDelta>& expected_queueing_times() { |
| + return expected_queueing_times_; |
| + } |
| + |
| + private: |
| + std::vector<base::TimeDelta> expected_queueing_times_; |
| +}; |
| + |
| +class QueueingTimeEstimatorForTest : public QueueingTimeEstimator { |
| + public: |
| + QueueingTimeEstimatorForTest(TestQueueingTimeEstimatorClient* client, |
| + TestTimeSource* test_time_source, |
| + base::TimeDelta window_duration) |
| + : QueueingTimeEstimator(client, test_time_source, window_duration) {} |
| +}; |
| + |
| +// Three tasks of one second each, all within a 5 second window. Expected |
| +// queueing time is the probability of falling into one of these tasks (3/5), |
| +// multiplied by the expected queueing time within a task (0.5 seconds). Thus we |
| +// expect a queueing time of 0.3 seconds. |
| +TEST_F(QueueingTimeEstimatorTest, AllTasksWithinWindow) { |
| + TestQueueingTimeEstimatorClient client; |
| + QueueingTimeEstimatorForTest estimator(&client, test_time_source_.get(), |
| + base::TimeDelta::FromSeconds(5)); |
| + base::PendingTask task(FROM_HERE, base::Closure()); |
| + |
| + for (int i = 0; i < 3; ++i) { |
| + estimator.WillProcessTask(task); |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(1000)); |
| + estimator.DidProcessTask(task); |
| + |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(500)); |
| + } |
| + |
| + // Flush the data by adding a task in the next window. |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(5000)); |
| + estimator.WillProcessTask(task); |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(500)); |
| + estimator.DidProcessTask(task); |
| + |
| + EXPECT_THAT(client.expected_queueing_times(), |
| + testing::ElementsAre(base::TimeDelta::FromMilliseconds(300))); |
| +} |
| + |
| +// One 20 second long task, starting 3 seconds into the first window. |
| +// Window 1: Probability of being within task = 2/5. Expected delay within task: |
| +// avg(20, 18). Total expected queueing time = 7.6s. |
| +// Window 2: Probability of being within task = 1. Expected delay within task: |
| +// avg(18, 13). Total expected queueing time = 15.5s. |
| +// Window 5: Probability of being within task = 3/5. Expected delay within task: |
| +// avg(3, 0). Total expected queueing time = 0.9s. |
| +TEST_F(QueueingTimeEstimatorTest, MultiWindowTask) { |
| + TestQueueingTimeEstimatorClient client; |
| + QueueingTimeEstimatorForTest estimator(&client, test_time_source_.get(), |
| + base::TimeDelta::FromSeconds(5)); |
| + base::PendingTask task(FROM_HERE, base::Closure()); |
| + |
| + estimator.WillProcessTask(task); |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(0)); |
| + estimator.DidProcessTask(task); |
| + |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(3000)); |
| + |
| + estimator.WillProcessTask(task); |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(20000)); |
| + estimator.DidProcessTask(task); |
| + |
| + // Flush the data by adding a task in the next window. |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(5000)); |
| + estimator.WillProcessTask(task); |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(500)); |
| + estimator.DidProcessTask(task); |
| + |
| + EXPECT_THAT(client.expected_queueing_times(), |
| + testing::ElementsAre(base::TimeDelta::FromMilliseconds(7600), |
| + base::TimeDelta::FromMilliseconds(15500), |
| + base::TimeDelta::FromMilliseconds(10500), |
| + base::TimeDelta::FromMilliseconds(5500), |
| + base::TimeDelta::FromMilliseconds(900))); |
| +} |
| + |
| +/*TEST_F(QueueingTimeEstimatorTest, Clear) { |
|
tdresser
2016/04/19 17:23:46
I don't think we should clear this estimator on na
Sami
2016/04/20 09:51:27
Not clearing it should give more accurate results
tdresser
2016/04/20 15:13:33
Acknowledged.
|
| + QueueingTimeEstimatorForTest estimator(test_time_source_.get(), 1, 100); |
| + base::PendingTask task(FROM_HERE, base::Closure()); |
| + |
| + estimator.WillProcessTask(task); |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(500)); |
| + estimator.DidProcessTask(task); |
| + |
| + estimator.Clear(); |
| + |
| + EXPECT_EQ(base::TimeDelta(), estimator.expected_task_duration()); |
| + }*/ |
| + |
| +// A single task with a nested message loop. The top level task lasts 4 seconds. |
| +// Probability of landing within this task = 4/5, expected queueing time within |
| +// this task = 2s. Total expected queueing time = 1.6. |
| +TEST_F(QueueingTimeEstimatorTest, NestedRunLoop) { |
| + TestQueueingTimeEstimatorClient client; |
| + QueueingTimeEstimatorForTest estimator(&client, test_time_source_.get(), |
| + base::TimeDelta::FromSeconds(5)); |
| + base::PendingTask task(FROM_HERE, base::Closure()); |
| + |
| + // Make sure we ignore the tasks inside the nested run loop. |
| + estimator.WillProcessTask(task); |
| + estimator.WillProcessTask(task); |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(2000)); |
| + estimator.DidProcessTask(task); |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(2000)); |
| + estimator.DidProcessTask(task); |
| + |
| + // Flush the data by adding a task in the next window. |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(5000)); |
| + estimator.WillProcessTask(task); |
| + clock_.Advance(base::TimeDelta::FromMilliseconds(500)); |
| + estimator.DidProcessTask(task); |
| + |
| + EXPECT_THAT(client.expected_queueing_times(), |
| + testing::ElementsAre(base::TimeDelta::FromMilliseconds(1600))); |
| +} |
| + |
| +} // namespace scheduler |