#include "chrome/browser/metrics/power/battery_discharge_reporter.h"
#include <memory>
#include "base/power_monitor/battery_level_provider.h"
#include "base/power_monitor/battery_state_sampler.h"
#include "base/power_monitor/sampling_event_source.h"
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/metrics/power/power_metrics.h"
#include "chrome/browser/metrics/usage_scenario/usage_scenario_data_store.h"
#include "chrome/browser/performance_manager/public/user_tuning/battery_saver_mode_manager.h"
#include "chrome/browser/performance_manager/test_support/fake_child_process_tuning_delegate.h"
#include "chrome/browser/performance_manager/test_support/fake_frame_throttling_delegate.h"
#include "chrome/browser/performance_manager/test_support/test_user_performance_tuning_manager_environment.h"
#include "components/performance_manager/public/user_tuning/prefs.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
constexpr const char* kBatteryDischargeModeHistogramName = …;
constexpr const char* kBatteryDischargeModeTenMinutesHistogramName = …;
constexpr const char* kBatteryDischargeRateMilliwattsHistogramName = …;
constexpr const char* kBatteryDischargeRateMilliwattsTenMinutesHistogramName = …;
constexpr const char* kBatteryDischargeRateRelativeHistogramName = …;
constexpr base::TimeDelta kTolerableDrift = …;
constexpr int kFullBatteryChargeLevel = …;
constexpr int kHalfBatteryChargeLevel = …;
std::optional<base::BatteryLevelProvider::BatteryState> MakeBatteryState(
int current_capacity) { … }
struct HistogramSampleExpectation { … };
void ExpectHistogramSamples(
base::HistogramTester* histogram_tester,
const std::vector<const char*>& suffixes,
const std::vector<HistogramSampleExpectation>& expectations) { … }
class NoopSamplingEventSource : public base::SamplingEventSource { … };
class NoopBatteryLevelProvider : public base::BatteryLevelProvider { … };
class TestUsageScenarioDataStoreImpl : public UsageScenarioDataStoreImpl { … };
}
class BatteryDischargeReporterTest : public testing::Test { … };
TEST_F(BatteryDischargeReporterTest, Simple_BatterySaverInactive) { … }
TEST_F(BatteryDischargeReporterTest, Simple_BatterySaverActive) { … }
TEST_F(BatteryDischargeReporterTest, BatteryDischargeCaptureIsTooLate) { … }
TEST_F(BatteryDischargeReporterTest, BatteryDischargeCaptureIsLate) { … }
TEST_F(BatteryDischargeReporterTest, BatteryDischargeCaptureIsTooEarly) { … }
TEST_F(BatteryDischargeReporterTest, BatteryDischargeCaptureIsEarly) { … }
TEST_F(BatteryDischargeReporterTest, FullChargedCapacityIncreased) { … }
TEST_F(BatteryDischargeReporterTest, RetrievalError) { … }
TEST_F(BatteryDischargeReporterTest, StateChanged_Battery) { … }
TEST_F(BatteryDischargeReporterTest, StateChanged_PluggedIn) { … }
TEST_F(BatteryDischargeReporterTest, NoBattery) { … }
TEST_F(BatteryDischargeReporterTest, PluggedIn) { … }
TEST_F(BatteryDischargeReporterTest, MultipleBatteries) { … }
TEST_F(BatteryDischargeReporterTest, InsufficientResolution) { … }
#if BUILDFLAG(IS_MAC)
TEST_F(BatteryDischargeReporterTest, MacFullyCharged) {
TestBatteryDischargeMode(
base::BatteryLevelProvider::BatteryState{
.battery_count = 1,
.is_external_power_connected = false,
.current_capacity = 100,
.full_charged_capacity = 100,
.charge_unit = base::BatteryLevelProvider::BatteryLevelUnit::kMWh,
},
base::BatteryLevelProvider::BatteryState{
.battery_count = 1,
.is_external_power_connected = false,
.current_capacity = 99,
.full_charged_capacity = 100,
.charge_unit = base::BatteryLevelProvider::BatteryLevelUnit::kMWh,
},
BatteryDischargeMode::kMacFullyCharged);
}
#endif
TEST_F(BatteryDischargeReporterTest, FullChargedCapacityIsZero) { … }
TEST_F(BatteryDischargeReporterTest, BatteryLevelIncreased) { … }
#if BUILDFLAG(IS_WIN)
TEST_F(BatteryDischargeReporterTest, BatteryDischargeGranularity) {
TestUsageScenarioDataStoreImpl usage_scenario_data_store;
BatteryDischargeReporter battery_discharge_reporter(
environment_.battery_state_sampler(), &usage_scenario_data_store);
const int64_t kGranularityMilliwattHours = 10;
const int64_t kGranularityRelative = 100;
const auto kBatteryState = base::BatteryLevelProvider::BatteryState{
.battery_count = 1,
.is_external_power_connected = false,
.current_capacity = 500,
.full_charged_capacity = 1000,
.charge_unit = base::BatteryLevelProvider::BatteryLevelUnit::kMWh,
.battery_discharge_granularity = kGranularityMilliwattHours,
};
battery_discharge_reporter.OnBatteryStateSampled(kBatteryState);
task_environment_.FastForwardBy(base::Minutes(1));
battery_discharge_reporter.OnBatteryStateSampled(kBatteryState);
histogram_tester_.ExpectUniqueSample(
"Power.BatteryDischargeGranularityMilliwattHours2",
kGranularityMilliwattHours, 1);
histogram_tester_.ExpectUniqueSample(
"Power.BatteryDischargeGranularityRelative2", kGranularityRelative, 1);
}
TEST_F(BatteryDischargeReporterTest, TenMinutesInterval) {
TestUsageScenarioDataStoreImpl usage_scenario_data_store;
BatteryDischargeReporter battery_discharge_reporter(
environment_.battery_state_sampler(), &usage_scenario_data_store);
{
base::HistogramTester tester;
battery_discharge_reporter.OnBatteryStateSampled(
MakeBatteryState(kHalfBatteryChargeLevel));
for (int i = 0; i < 9; ++i) {
task_environment_.FastForwardBy(base::Minutes(1));
battery_discharge_reporter.OnBatteryStateSampled(
MakeBatteryState(kHalfBatteryChargeLevel - 2));
tester.ExpectTotalCount(kBatteryDischargeModeTenMinutesHistogramName, 0);
tester.ExpectTotalCount(
kBatteryDischargeRateMilliwattsTenMinutesHistogramName, 0);
}
task_environment_.FastForwardBy(base::Minutes(1));
battery_discharge_reporter.OnBatteryStateSampled(
MakeBatteryState(kHalfBatteryChargeLevel - 100));
const int64_t kExpectedDischargeRate_mW = 600;
tester.ExpectUniqueSample(kBatteryDischargeModeTenMinutesHistogramName,
BatteryDischargeMode::kDischarging, 1);
tester.ExpectUniqueSample(
kBatteryDischargeRateMilliwattsTenMinutesHistogramName,
kExpectedDischargeRate_mW, 1);
}
{
base::HistogramTester tester;
task_environment_.FastForwardBy(base::Minutes(10));
battery_discharge_reporter.OnBatteryStateSampled(
MakeBatteryState(kHalfBatteryChargeLevel - 300));
const int64_t kExpectedDischargeRate_mW = 1200;
tester.ExpectUniqueSample(kBatteryDischargeModeTenMinutesHistogramName,
BatteryDischargeMode::kDischarging, 1);
tester.ExpectUniqueSample(
kBatteryDischargeRateMilliwattsTenMinutesHistogramName,
kExpectedDischargeRate_mW, 1);
}
{
base::HistogramTester tester;
task_environment_.FastForwardBy(base::Minutes(11));
battery_discharge_reporter.OnBatteryStateSampled(
MakeBatteryState(kHalfBatteryChargeLevel - 400));
tester.ExpectUniqueSample(kBatteryDischargeModeTenMinutesHistogramName,
BatteryDischargeMode::kInvalidInterval, 1);
tester.ExpectTotalCount(
kBatteryDischargeRateMilliwattsTenMinutesHistogramName, 0);
}
}
#endif