chromium/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager_unittest.cc

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

#include "chrome/browser/performance_manager/public/user_tuning/battery_saver_mode_manager.h"

#include <memory>
#include <utility>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/power_monitor/battery_state_sampler.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_source.h"
#include "base/run_loop.h"
#include "base/test/power_monitor_test_utils.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/values.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/fake_freezing_delegate.h"
#include "chrome/browser/performance_manager/test_support/fake_power_monitor_source.h"
#include "components/performance_manager/public/features.h"
#include "components/performance_manager/public/user_tuning/prefs.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/common/content_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/constants/ash_features.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "dbus/mock_bus.h"
#include "dbus/mock_object_proxy.h"
#include "dbus/object_path.h"
#endif

namespace performance_manager::user_tuning {
namespace {

class QuitRunLoopObserverBase : public performance_manager::user_tuning::
                                    BatterySaverModeManager::Observer {};

class QuitRunLoopOnBSMChangeObserver : public QuitRunLoopObserverBase {};

class QuitRunLoopOnPowerStateChangeObserver : public QuitRunLoopObserverBase {};

class MockObserver : public performance_manager::user_tuning::
                         BatterySaverModeManager::Observer {};

#if !BUILDFLAG(IS_CHROMEOS_ASH)

base::BatteryLevelProvider::BatteryState CreateBatteryState(
    bool under_threshold) {}

#else  // BUILDFLAG(IS_CHROMEOS_ASH)

class ScopedFakePowerManagerClientLifetime {
 public:
  ScopedFakePowerManagerClientLifetime() {
    chromeos::PowerManagerClient::InitializeFake();
  }

  ~ScopedFakePowerManagerClientLifetime() {
    chromeos::PowerManagerClient::Shutdown();
  }
};

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

}  // namespace

class BatterySaverModeManagerTest : public ::testing::Test {};

// Battery Saver is controlled by the OS on ChromeOS
#if !BUILDFLAG(IS_CHROMEOS_ASH)

TEST_F(BatterySaverModeManagerTest, TemporaryBatterySaver) {}

TEST_F(BatterySaverModeManagerTest, TemporaryBatterySaverTurnsOffWhenPlugged) {}

TEST_F(BatterySaverModeManagerTest, BatterySaverModePref) {}

TEST_F(BatterySaverModeManagerTest, InvalidPrefInStore) {}

TEST_F(BatterySaverModeManagerTest, EnabledOnBatteryPower) {}

TEST_F(BatterySaverModeManagerTest, LowBatteryThresholdRaised) {}

TEST_F(BatterySaverModeManagerTest, BSMEnabledUnderThreshold) {}

TEST_F(BatterySaverModeManagerTest, HasBatteryChanged) {}

TEST_F(BatterySaverModeManagerTest,
       BatteryPercentageWithoutFullChargedCapacity) {}

#else   // BUILDFLAG(IS_CHROMEOS_ASH)

TEST_F(BatterySaverModeManagerTest, ManagedFromPowerManager) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(ash::features::kBatterySaver);

  StartManager();
  EXPECT_FALSE(manager()->IsBatterySaverActive());
  EXPECT_FALSE(throttling_enabled());
  EXPECT_FALSE(child_process_tuning_enabled());
  EXPECT_FALSE(freezing_enabled());

  base::RunLoop run_loop;
  std::unique_ptr<QuitRunLoopOnBSMChangeObserver> observer =
      std::make_unique<QuitRunLoopOnBSMChangeObserver>(run_loop.QuitClosure());
  manager()->AddObserver(observer.get());

  // Request to enable PowerManager's BSM
  power_manager::SetBatterySaverModeStateRequest proto;
  proto.set_enabled(true);
  chromeos::PowerManagerClient::Get()->SetBatterySaverModeState(proto);

  run_loop.Run();
  manager()->RemoveObserver(observer.get());

  EXPECT_TRUE(manager()->IsBatterySaverActive());
  EXPECT_FALSE(manager()->IsBatterySaverModeEnabled());
  EXPECT_TRUE(throttling_enabled());
  EXPECT_TRUE(child_process_tuning_enabled());
  EXPECT_TRUE(freezing_enabled());
}

TEST_F(BatterySaverModeManagerTest,
       StartsEnabledIfAlreadyEnabledInPowerManager) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(ash::features::kBatterySaver);

  // Request to enable PowerManager's BSM
  power_manager::SetBatterySaverModeStateRequest proto;
  proto.set_enabled(true);
  chromeos::PowerManagerClient::Get()->SetBatterySaverModeState(proto);

  StartManager();

  // It's fine to install the observer after the manager is created, as long as
  // it's done before the runloop runs
  base::RunLoop run_loop;
  std::unique_ptr<QuitRunLoopOnBSMChangeObserver> observer =
      std::make_unique<QuitRunLoopOnBSMChangeObserver>(run_loop.QuitClosure());
  manager()->AddObserver(observer.get());

  run_loop.Run();
  manager()->RemoveObserver(observer.get());

  EXPECT_TRUE(manager()->IsBatterySaverActive());
  EXPECT_TRUE(throttling_enabled());
  EXPECT_TRUE(child_process_tuning_enabled());
  EXPECT_TRUE(freezing_enabled());
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

}  // namespace performance_manager::user_tuning