#include "chromeos/ash/components/throttle/throttle_service.h"
#include <utility>
#include "content/public/test/test_browser_context.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace ash {
namespace {
constexpr const char kFirstObserverName[] = "o1";
constexpr const char kSecondObserverName[] = "o2";
class TestObserver : public ThrottleService::ServiceObserver {
public:
TestObserver() = default;
~TestObserver() override = default;
void OnThrottle(bool was_throttled) override {
last_was_throttled_ = was_throttled;
++update_count_;
}
int GetUpdateCountAndReset() {
const int update_count = update_count_;
update_count_ = 0;
return update_count;
}
bool last_was_throttled() const { return last_was_throttled_; }
private:
int update_count_ = 0;
bool last_was_throttled_ = false;
TestObserver(TestObserver const&) = delete;
TestObserver& operator=(TestObserver const&) = delete;
};
}
class TestThrottleService : public ThrottleService {
public:
using ThrottleService::ThrottleService;
size_t throttle_instance_count() const { return throttle_instance_count_; }
size_t uma_count() { return record_uma_counter_; }
bool last_should_throttle() const { return last_should_throttle_; }
const std::string& last_recorded_observer_name() {
return last_recorded_observer_name_;
}
private:
void ThrottleInstance(bool should_throttle) override {
++throttle_instance_count_;
last_should_throttle_ = should_throttle;
}
void RecordCpuRestrictionDisabledUMA(const std::string& observer_name,
base::TimeDelta delta) override {
++record_uma_counter_;
last_recorded_observer_name_ = observer_name;
}
size_t throttle_instance_count_{0};
size_t record_uma_counter_{0};
std::string last_recorded_observer_name_;
bool last_should_throttle_ = false;
};
class ThrottleServiceTest : public testing::Test {
public:
ThrottleServiceTest() {
std::vector<std::unique_ptr<ThrottleObserver>> observers;
observers.push_back(std::make_unique<ThrottleObserver>(kFirstObserverName));
observers.push_back(
std::make_unique<ThrottleObserver>(kSecondObserverName));
service_.SetObserversForTesting(std::move(observers));
}
ThrottleServiceTest(const ThrottleServiceTest&) = delete;
ThrottleServiceTest& operator=(const ThrottleServiceTest&) = delete;
protected:
TestThrottleService* service() { return &service_; }
private:
content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext browser_context_;
TestThrottleService service_{&browser_context_};
};
TEST_F(ThrottleServiceTest, TestConstructDestruct) {}
TEST_F(ThrottleServiceTest, TestOnObserverStateChanged) {
EXPECT_EQ(0U, service()->throttle_instance_count());
service()->NotifyObserverStateChangedForTesting();
EXPECT_EQ(1U, service()->throttle_instance_count());
EXPECT_TRUE(service()->last_should_throttle());
service()->observers_for_testing()[0]->SetActive(true);
EXPECT_EQ(2U, service()->throttle_instance_count());
EXPECT_FALSE(service()->last_should_throttle());
service()->observers_for_testing()[1]->SetActive(true);
EXPECT_EQ(2U, service()->throttle_instance_count());
EXPECT_FALSE(service()->last_should_throttle());
service()->observers_for_testing()[1]->SetActive(false);
EXPECT_EQ(2U, service()->throttle_instance_count());
EXPECT_FALSE(service()->last_should_throttle());
service()->observers_for_testing()[0]->SetActive(false);
EXPECT_EQ(3U, service()->throttle_instance_count());
EXPECT_TRUE(service()->last_should_throttle());
}
TEST_F(ThrottleServiceTest, RecordCpuRestrictionDisabledUMA) {
EXPECT_EQ(0U, service()->uma_count());
service()->observers_for_testing()[0]->SetActive(true);
EXPECT_EQ(0U, service()->uma_count());
service()->observers_for_testing()[1]->SetActive(true);
EXPECT_EQ(0U, service()->uma_count());
service()->observers_for_testing()[0]->SetActive(false);
EXPECT_EQ(1U, service()->uma_count());
EXPECT_EQ(service()->observers_for_testing()[0]->name(),
service()->last_recorded_observer_name());
service()->observers_for_testing()[0]->SetActive(true);
EXPECT_EQ(2U, service()->uma_count());
EXPECT_EQ(service()->observers_for_testing()[1]->name(),
service()->last_recorded_observer_name());
service()->observers_for_testing()[1]->SetActive(false);
service()->observers_for_testing()[0]->SetActive(false);
EXPECT_EQ(3U, service()->uma_count());
EXPECT_EQ(service()->observers_for_testing()[0]->name(),
service()->last_recorded_observer_name());
}
TEST_F(ThrottleServiceTest, TestEnforced) {
service()->observers_for_testing()[0]->SetActive(false);
service()->observers_for_testing()[1]->SetActive(true);
EXPECT_FALSE(service()->should_throttle());
service()->observers_for_testing()[0]->SetEnforced(true);
EXPECT_TRUE(service()->should_throttle());
service()->observers_for_testing()[0]->SetEnforced(false);
EXPECT_FALSE(service()->should_throttle());
}
TEST_F(ThrottleServiceTest, TestObservers) {
TestObserver test_observer;
service()->AddServiceObserver(&test_observer);
EXPECT_EQ(0, test_observer.GetUpdateCountAndReset());
service()->observers_for_testing()[1]->SetActive(true);
EXPECT_FALSE(service()->should_throttle());
EXPECT_FALSE(test_observer.last_was_throttled());
EXPECT_EQ(1, test_observer.GetUpdateCountAndReset());
service()->observers_for_testing()[0]->SetActive(true);
EXPECT_FALSE(service()->should_throttle());
EXPECT_FALSE(test_observer.last_was_throttled());
EXPECT_EQ(0, test_observer.GetUpdateCountAndReset());
service()->observers_for_testing()[0]->SetActive(false);
EXPECT_EQ(0, test_observer.GetUpdateCountAndReset());
service()->observers_for_testing()[1]->SetActive(false);
EXPECT_TRUE(service()->should_throttle());
EXPECT_TRUE(test_observer.last_was_throttled());
EXPECT_EQ(1, test_observer.GetUpdateCountAndReset());
service()->RemoveServiceObserver(&test_observer);
service()->observers_for_testing()[1]->SetActive(true);
EXPECT_FALSE(service()->should_throttle());
EXPECT_EQ(0, test_observer.GetUpdateCountAndReset());
}
TEST_F(ThrottleServiceTest, TestGetObserverByName) {
auto* first_observer = service()->GetObserverByName(kFirstObserverName);
auto* second_observer = service()->GetObserverByName(kSecondObserverName);
EXPECT_NE(nullptr, first_observer);
EXPECT_NE(nullptr, second_observer);
EXPECT_NE(first_observer, second_observer);
EXPECT_EQ(nullptr, service()->GetObserverByName("NonExistentObserverName"));
}
}