chromium/chrome/browser/ash/power/cpu_data_collector_unittest.cc

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

#include <string>
#include <vector>

#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/time/time.h"
#include "chrome/browser/ash/power/cpu_data_collector.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {
namespace {

// The suffix path of fake CPU frequency file for cpu0.
constexpr char kTimeInStateSuffixPathCpu0[] = "cpu0/time_in_state";

// The suffix path of fake CPU frequency file for cpu1.
constexpr char kTimeInStateSuffixPathCpu1[] = "cpu1/time_in_state";

// The suffix path of fake CPU frequency file for all cpus.
constexpr char kAllTimeInStateSuffixPath[] = "all_time_in_state";

// The string content of the fake CPU frequency file for cpu0.
constexpr char kTimeInStateContentCpu0[] =
    "20000 30000000\n"
    "60000 90000\n"
    "100000 50000\n";

// The string content of the fake CPU frequency file for cpu1.
constexpr char kTimeInStateContentCpu1[] =
    "20000 31000000\n"
    "60000 91000\n"
    "100000 51000\n";

// The string content of the fake CPU frequency file for all CPUs.
constexpr char kAllTimeInStateContent[] =
    "freq\t\tcpu0\t\tcpu1\t\t\n"
    "20000\t\t30000000\t\t31000000\t\t\n"
    "60000\t\t90000\t\t91000\t\t\n"
    "100000\t\t50000\t\t51000\t\t\n";

// The string content of the fake CPU frequency file for all CPUs except one
// that reports "N/A" as the CPU/freq combinations that are invalid.
constexpr char kAllTimeInStateContentNA[] =
    "freq\t\tcpu0\t\tcpu1\t\tcpu2\t\t\n"
    "20000\t\t30000000\t\t31000000\t\tN/A\t\t\n"
    "60000\t\t90000\t\t91000\t\tN/A\t\t\n"
    "100000\t\t50000\t\t51000\t\tN/A\t\t\n";

// The string content of the fake CPU frequency file for all CPUs except one
// that does not report freq as the CPU is turned off.
constexpr char kAllTimeInStateContentOff[] =
    "freq\t\tcpu0\t\tcpu1\t\tcpu2\t\t\n"
    "20000\t\t30000000\t\t31000000\t\t\n"
    "60000\t\t90000\t\t91000\t\t\n"
    "100000\t\t50000\t\t51000\t\t\n";

}  // namespace

class CpuDataCollectorTest : public testing::Test {
 public:
  CpuDataCollectorTest()
      : kExpectedCpuFreqStateNames({"20", "60", "100"}),
        kExpectedTimeInStateCpu0({base::Milliseconds(300000000),
                                  base::Milliseconds(900000),
                                  base::Milliseconds(500000)}),
        kExpectedTimeInStateCpu1({base::Milliseconds(310000000),
                                  base::Milliseconds(910000),
                                  base::Milliseconds(510000)}) {}

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

  // testing::Test:
  void SetUp() override {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    time_in_state_path_cpu0_ =
        temp_dir_.GetPath().AppendASCII(kTimeInStateSuffixPathCpu0);
    time_in_state_path_cpu1_ =
        temp_dir_.GetPath().AppendASCII(kTimeInStateSuffixPathCpu1);
    all_time_in_state_path_ =
        temp_dir_.GetPath().AppendASCII(kAllTimeInStateSuffixPath);
  }

 protected:
  // Expected CPU frequency state names after calling |ReadCpuFreqTimeInState|
  // or |ReadCpuFreqAllTimeInState|
  const std::vector<std::string> kExpectedCpuFreqStateNames;

  // Expected time_in_state of sample for cpu0.
  const std::vector<base::TimeDelta> kExpectedTimeInStateCpu0;

  // Expected time_in_state of sample for cpu1.
  const std::vector<base::TimeDelta> kExpectedTimeInStateCpu1;

  base::ScopedTempDir temp_dir_;
  base::FilePath time_in_state_path_cpu0_;
  base::FilePath time_in_state_path_cpu1_;
  base::FilePath all_time_in_state_path_;
};

TEST_F(CpuDataCollectorTest, ReadCpuFreqTimeInState) {
  ASSERT_TRUE(base::CreateTemporaryFile(&time_in_state_path_cpu0_));
  ASSERT_TRUE(base::CreateTemporaryFile(&time_in_state_path_cpu1_));
  ASSERT_TRUE(
      base::WriteFile(time_in_state_path_cpu0_, kTimeInStateContentCpu0));
  ASSERT_TRUE(
      base::WriteFile(time_in_state_path_cpu1_, kTimeInStateContentCpu1));

  std::vector<std::string> cpu_freq_state_names;
  CpuDataCollector::StateOccupancySample freq_sample_cpu0;
  CpuDataCollector::StateOccupancySample freq_sample_cpu1;

  CpuDataCollector::ReadCpuFreqTimeInState(
      time_in_state_path_cpu0_, &cpu_freq_state_names, &freq_sample_cpu0);
  EXPECT_EQ(kExpectedCpuFreqStateNames, cpu_freq_state_names);
  EXPECT_EQ(kExpectedTimeInStateCpu0, freq_sample_cpu0.time_in_state);

  cpu_freq_state_names.clear();
  CpuDataCollector::ReadCpuFreqTimeInState(
      time_in_state_path_cpu1_, &cpu_freq_state_names, &freq_sample_cpu1);
  EXPECT_EQ(kExpectedCpuFreqStateNames, cpu_freq_state_names);
  EXPECT_EQ(kExpectedTimeInStateCpu1, freq_sample_cpu1.time_in_state);
}

TEST_F(CpuDataCollectorTest, ReadCpuFreqAllTimeInState) {
  ASSERT_TRUE(base::CreateTemporaryFile(&all_time_in_state_path_));
  ASSERT_TRUE(base::WriteFile(all_time_in_state_path_, kAllTimeInStateContent));

  std::vector<std::string> cpu_freq_state_names;
  std::vector<CpuDataCollector::StateOccupancySample> freq_samples;
  CpuDataCollector::StateOccupancySample freq_sample_cpu0;
  CpuDataCollector::StateOccupancySample freq_sample_cpu1;
  // |ReadCpuFreqAllTimeInState| only collects samples for CPUs that are online.
  freq_sample_cpu0.cpu_online = true;
  freq_sample_cpu1.cpu_online = true;
  freq_samples.push_back(freq_sample_cpu0);
  freq_samples.push_back(freq_sample_cpu1);

  CpuDataCollector::ReadCpuFreqAllTimeInState(
      2, all_time_in_state_path_, &cpu_freq_state_names, &freq_samples);
  EXPECT_EQ(kExpectedCpuFreqStateNames, cpu_freq_state_names);
  EXPECT_EQ(kExpectedTimeInStateCpu0, freq_samples[0].time_in_state);
  EXPECT_EQ(kExpectedTimeInStateCpu1, freq_samples[1].time_in_state);
}

TEST_F(CpuDataCollectorTest, ReadCpuFreqAllTimeInStateNA) {
  ASSERT_TRUE(base::CreateTemporaryFile(&all_time_in_state_path_));
  ASSERT_TRUE(
      base::WriteFile(all_time_in_state_path_, kAllTimeInStateContentNA));

  std::vector<std::string> cpu_freq_state_names;
  std::vector<CpuDataCollector::StateOccupancySample> freq_samples;
  CpuDataCollector::StateOccupancySample freq_sample_cpu0;
  CpuDataCollector::StateOccupancySample freq_sample_cpu1;
  CpuDataCollector::StateOccupancySample freq_sample_cpu2;
  // |ReadCpuFreqAllTimeInState| only collects samples for CPUs that are online.
  freq_sample_cpu0.cpu_online = true;
  freq_sample_cpu1.cpu_online = true;
  freq_sample_cpu2.cpu_online = true;
  freq_samples.push_back(freq_sample_cpu0);
  freq_samples.push_back(freq_sample_cpu1);
  freq_samples.push_back(freq_sample_cpu2);

  CpuDataCollector::ReadCpuFreqAllTimeInState(
      3, all_time_in_state_path_, &cpu_freq_state_names, &freq_samples);
  EXPECT_EQ(kExpectedCpuFreqStateNames, cpu_freq_state_names);
  EXPECT_EQ(kExpectedTimeInStateCpu0, freq_samples[0].time_in_state);
  EXPECT_EQ(kExpectedTimeInStateCpu1, freq_samples[1].time_in_state);
  EXPECT_TRUE(freq_samples[2].time_in_state.empty());
}

TEST_F(CpuDataCollectorTest, ReadCpuFreqAllTimeInStateOff) {
  ASSERT_TRUE(base::CreateTemporaryFile(&all_time_in_state_path_));
  ASSERT_TRUE(
      base::WriteFile(all_time_in_state_path_, kAllTimeInStateContentOff));

  std::vector<std::string> cpu_freq_state_names;
  std::vector<CpuDataCollector::StateOccupancySample> freq_samples;
  CpuDataCollector::StateOccupancySample freq_sample_cpu0;
  CpuDataCollector::StateOccupancySample freq_sample_cpu1;
  CpuDataCollector::StateOccupancySample freq_sample_cpu2;
  // |ReadCpuFreqAllTimeInState| only collects samples for CPUs that are online.
  freq_sample_cpu0.cpu_online = true;
  freq_sample_cpu1.cpu_online = true;
  freq_sample_cpu2.cpu_online = false;
  freq_samples.push_back(freq_sample_cpu0);
  freq_samples.push_back(freq_sample_cpu1);
  freq_samples.push_back(freq_sample_cpu2);

  CpuDataCollector::ReadCpuFreqAllTimeInState(
      2, all_time_in_state_path_, &cpu_freq_state_names, &freq_samples);
  EXPECT_EQ(kExpectedCpuFreqStateNames, cpu_freq_state_names);
  EXPECT_EQ(kExpectedTimeInStateCpu0, freq_samples[0].time_in_state);
  EXPECT_EQ(kExpectedTimeInStateCpu1, freq_samples[1].time_in_state);
  EXPECT_TRUE(freq_samples[2].time_in_state.empty());
}

}  // namespace ash