blob: cf8018139a6949d9a9bd7bf046394f48f578a4ba [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/thread_profiler.h"
#include "base/macros.h"
#include "base/test/bind_test_util.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class TestScheduler : public PeriodicSamplingScheduler {
public:
TestScheduler(base::TimeDelta sampling_duration,
double fraction_of_execution_time_to_sample)
: PeriodicSamplingScheduler(sampling_duration,
fraction_of_execution_time_to_sample,
kStartTime),
rand_double_value_(0.0) {
tick_clock_.SetNowTicks(kStartTime);
}
double RandDouble() const override { return rand_double_value_; }
base::TimeTicks Now() const override { return tick_clock_.NowTicks(); }
void SetRandDouble(double value) { rand_double_value_ = value; }
base::SimpleTestTickClock& tick_clock() { return tick_clock_; }
private:
static constexpr base::TimeTicks kStartTime = base::TimeTicks();
base::SimpleTestTickClock tick_clock_;
double rand_double_value_;
DISALLOW_COPY_AND_ASSIGN(TestScheduler);
};
constexpr base::TimeTicks TestScheduler::kStartTime;
} // namespace
TEST(ThreadProfilerTest, PeriodicSamplingScheduler) {
const base::TimeDelta sampling_duration = base::TimeDelta::FromSeconds(30);
const double fraction_of_execution_time_to_sample = 0.01;
const base::TimeDelta expected_period =
sampling_duration / fraction_of_execution_time_to_sample;
TestScheduler scheduler(sampling_duration,
fraction_of_execution_time_to_sample);
// The first collection should be exactly at the start time, since the random
// value is 0.0.
scheduler.SetRandDouble(0.0);
EXPECT_EQ(base::TimeDelta::FromSeconds(0),
scheduler.GetTimeToNextCollection());
// With a random value of 1.0 the second collection should be at the end of
// the second period.
scheduler.SetRandDouble(1.0);
EXPECT_EQ(2 * expected_period - sampling_duration,
scheduler.GetTimeToNextCollection());
// With a random value of 0.25 the second collection should be a quarter into
// the third period exclusive of the sampling duration.
scheduler.SetRandDouble(0.25);
EXPECT_EQ(2 * expected_period + 0.25 * (expected_period - sampling_duration),
scheduler.GetTimeToNextCollection());
}
TEST(ThreadProfilerTest, PeriodicSamplingSchedulerWithJumpInTimeTicks) {
const base::TimeDelta sampling_duration = base::TimeDelta::FromSeconds(30);
const double fraction_of_execution_time_to_sample = 0.01;
const base::TimeDelta expected_period =
sampling_duration / fraction_of_execution_time_to_sample;
TestScheduler scheduler(sampling_duration,
fraction_of_execution_time_to_sample);
// The first collection should be exactly at the start time, since the random
// value is 0.0.
scheduler.SetRandDouble(0.0);
EXPECT_EQ(base::TimeDelta::FromSeconds(0),
scheduler.GetTimeToNextCollection());
// Simulate a non-continuous jump in the current TimeTicks such that the next
// period would start before the current time. In this case the
// period start should be reset to the current time, and the next collection
// chosen within that period.
scheduler.tick_clock().Advance(expected_period +
base::TimeDelta::FromSeconds(1));
scheduler.SetRandDouble(0.5);
EXPECT_EQ(0.5 * (expected_period - sampling_duration),
scheduler.GetTimeToNextCollection());
}