chromium/tools/mac/power/power_sampler/sampling_controller_unittest.cc

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

#include "tools/mac/power/power_sampler/sampling_controller.h"

#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "tools/mac/power/power_sampler/monitor.h"
#include "tools/mac/power/power_sampler/sampler.h"

namespace power_sampler {

namespace {

using testing::_;
using testing::DoAll;
using testing::ElementsAre;
using testing::Return;
using testing::SaveArg;
using testing::StrictMock;

class TestSampler : public Sampler {
 public:
  explicit TestSampler(const char* name, double sample = 0.0)
      : name_(name), sample_(sample) {}

  std::string GetName() override { return name_; }

  DatumNameUnits GetDatumNameUnits() override {
    DatumNameUnits datum_name_units;
    datum_name_units.insert(std::make_pair(name_, name_));
    return datum_name_units;
  }

  Sample GetSample(base::TimeTicks sample_time) override {
    Sample sample;
    sample.emplace(name_, sample_);
    return sample;
  }

 private:
  const std::string name_;
  const double sample_;
};

class LenientMockMonitor : public Monitor {
 public:
  LenientMockMonitor() = default;
  ~LenientMockMonitor() override = default;

  MOCK_METHOD(void,
              OnStartSession,
              ((const base::flat_map<DataColumnKey, std::string>&)));
  MOCK_METHOD(bool,
              OnSample,
              (base::TimeTicks sample_time, const DataRow& data_row));
  MOCK_METHOD(void, OnEndSession, ());
};
using MockMonitor = StrictMock<LenientMockMonitor>;

}  // namespace

TEST(SamplingControllerTest, AddSampler) {
  SamplingController controller;
  EXPECT_TRUE(controller.AddSampler(std::make_unique<TestSampler>("foo")));
  EXPECT_TRUE(controller.AddSampler(std::make_unique<TestSampler>("bar")));
  EXPECT_FALSE(controller.AddSampler(std::make_unique<TestSampler>("bar")));
}

TEST(SamplingControllerTest, CallsSamplersAndMonitors) {
  base::test::SingleThreadTaskEnvironment task_environment{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};

  SamplingController controller;
  EXPECT_TRUE(controller.AddSampler(std::make_unique<TestSampler>("foo", 1.0)));
  EXPECT_TRUE(controller.AddSampler(std::make_unique<TestSampler>("bar", 2.0)));

  controller.StartSession();
  // No monitors to end the session.
  EXPECT_FALSE(controller.OnSamplingEvent());
  controller.EndSession();

  auto mock_monitor = std::make_unique<MockMonitor>();
  MockMonitor* monitor = mock_monitor.get();
  controller.AddMonitor(std::move(mock_monitor));

  EXPECT_CALL(*monitor, OnStartSession(_));
  controller.StartSession();

  base::TimeTicks first_now = base::TimeTicks::Now();
  DataRow last_seen_data_row;
  EXPECT_CALL(*monitor, OnSample(first_now, _))
      .WillOnce(DoAll(SaveArg<1>(&last_seen_data_row), Return(false)));
  EXPECT_FALSE(controller.OnSamplingEvent());

  EXPECT_THAT(last_seen_data_row,
              ElementsAre(std::make_pair(DataColumnKey{"bar", "bar"}, 2.0),
                          std::make_pair(DataColumnKey{"foo", "foo"}, 1.0)));

  last_seen_data_row.clear();

  task_environment.FastForwardBy(base::Milliseconds(1500));
  base::TimeTicks second_now = base::TimeTicks::Now();
  // Terminate the sampling session on the next sample.
  EXPECT_CALL(*monitor, OnSample(second_now, _))
      .WillOnce(DoAll(SaveArg<1>(&last_seen_data_row), Return(true)));
  EXPECT_TRUE(controller.OnSamplingEvent());
  // We still expect the same samples.
  EXPECT_THAT(last_seen_data_row,
              ElementsAre(std::make_pair(DataColumnKey{"bar", "bar"}, 2.0),
                          std::make_pair(DataColumnKey{"foo", "foo"}, 1.0)));

  EXPECT_CALL(*monitor, OnEndSession());
  controller.EndSession();
}

}  // namespace power_sampler