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

base / profiler / periodic_sampling_scheduler_unittest.cc [blame]

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/profiler/periodic_sampling_scheduler.h"

#include "base/test/bind.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {
namespace {

class TestScheduler : public PeriodicSamplingScheduler {
 public:
  TestScheduler(TimeDelta sampling_duration,
                double fraction_of_execution_time_to_sample)
      : PeriodicSamplingScheduler(sampling_duration,
                                  fraction_of_execution_time_to_sample,
                                  kStartTime) {
    tick_clock_.SetNowTicks(kStartTime);
  }

  TestScheduler(const TestScheduler&) = delete;
  TestScheduler& operator=(const TestScheduler&) = delete;

  double RandDouble() const override { return rand_double_value_; }
  TimeTicks Now() const override { return tick_clock_.NowTicks(); }

  void SetRandDouble(double value) { rand_double_value_ = value; }
  SimpleTestTickClock& tick_clock() { return tick_clock_; }

 private:
  static constexpr TimeTicks kStartTime = TimeTicks();
  SimpleTestTickClock tick_clock_;
  double rand_double_value_ = 0.0;
};

constexpr TimeTicks TestScheduler::kStartTime;

TEST(PeriodicSamplingSchedulerTest, ScheduleCollections) {
  const TimeDelta sampling_duration = Seconds(30);
  const double fraction_of_execution_time_to_sample = 0.01;

  const 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(Seconds(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(PeriodicSamplingSchedulerTest, ScheduleWithJumpInTimeTicks) {
  const TimeDelta sampling_duration = Seconds(30);
  const double fraction_of_execution_time_to_sample = 0.01;

  const 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(Seconds(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 + Seconds(1));
  scheduler.SetRandDouble(0.5);
  EXPECT_EQ(0.5 * (expected_period - sampling_duration),
            scheduler.GetTimeToNextCollection());
}

}  // namespace
}  // namespace base