blob: 42b85c6ec2e45481c68845717429c0d41a20bcd2 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shill/power_manager.h"
#include <string>
#include <base/bind.h>
#include <base/memory/scoped_ptr.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "shill/mock_event_dispatcher.h"
#include "shill/mock_power_manager_proxy.h"
#include "shill/power_manager_proxy_interface.h"
#include "shill/proxy_factory.h"
using base::Bind;
using base::Unretained;
using std::map;
using std::string;
using testing::_;
using testing::Return;
using testing::Test;
namespace shill {
namespace {
class FakeProxyFactory : public ProxyFactory {
public:
FakeProxyFactory()
: delegate_(NULL),
proxy_(new MockPowerManagerProxy) {}
virtual PowerManagerProxyInterface *CreatePowerManagerProxy(
PowerManagerProxyDelegate *delegate) {
delegate_ = delegate;
return proxy_;
}
PowerManagerProxyDelegate *delegate() const { return delegate_; }
MockPowerManagerProxy *proxy() const { return proxy_; }
private:
PowerManagerProxyDelegate *delegate_;
MockPowerManagerProxy *const proxy_;
};
} // namespace
class PowerManagerTest : public Test {
public:
static const char kKey1[];
static const char kKey2[];
static const int kSuspendId1 = 123;
static const int kSuspendId2 = 456;
PowerManagerTest()
: power_manager_(&dispatcher_, &factory_),
delegate_(factory_.delegate()) {
state_change_callback1_ =
Bind(&PowerManagerTest::StateChangeAction1, Unretained(this));
state_change_callback2_ =
Bind(&PowerManagerTest::StateChangeAction2, Unretained(this));
suspend_delay_callback1_ =
Bind(&PowerManagerTest::SuspendDelayAction1, Unretained(this));
suspend_delay_callback2_ =
Bind(&PowerManagerTest::SuspendDelayAction2, Unretained(this));
}
MOCK_METHOD1(StateChangeAction1, void(PowerManager::SuspendState));
MOCK_METHOD1(StateChangeAction2, void(PowerManager::SuspendState));
MOCK_METHOD1(SuspendDelayAction1, void(int));
MOCK_METHOD1(SuspendDelayAction2, void(int));
protected:
void OnSuspendImminent(int suspend_id) {
EXPECT_CALL(dispatcher_,
PostDelayedTask(_, PowerManager::kSuspendTimeoutMilliseconds));
factory_.delegate()->OnSuspendImminent(suspend_id);
EXPECT_EQ(PowerManagerProxyDelegate::kSuspending,
power_manager_.power_state());
}
void OnSuspendTimeout() {
power_manager_.OnSuspendTimeout();
}
MockEventDispatcher dispatcher_;
FakeProxyFactory factory_;
PowerManager power_manager_;
PowerManagerProxyDelegate *const delegate_;
PowerManager::PowerStateCallback state_change_callback1_;
PowerManager::PowerStateCallback state_change_callback2_;
PowerManager::SuspendDelayCallback suspend_delay_callback1_;
PowerManager::SuspendDelayCallback suspend_delay_callback2_;
};
const char PowerManagerTest::kKey1[] = "Zaphod";
const char PowerManagerTest::kKey2[] = "Beeblebrox";
TEST_F(PowerManagerTest, OnPowerStateChanged) {
EXPECT_EQ(PowerManagerProxyDelegate::kUnknown, power_manager_.power_state());
power_manager_.OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
EXPECT_EQ(PowerManagerProxyDelegate::kOn, power_manager_.power_state());
}
TEST_F(PowerManagerTest, AddStateChangeCallback) {
EXPECT_CALL(*this, StateChangeAction1(PowerManagerProxyDelegate::kOn));
power_manager_.AddStateChangeCallback(kKey1, state_change_callback1_);
factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
power_manager_.RemoveStateChangeCallback(kKey1);
}
TEST_F(PowerManagerTest, AddSuspendDelayCallback) {
EXPECT_CALL(*this, SuspendDelayAction1(kSuspendId1));
power_manager_.AddSuspendDelayCallback(kKey1, suspend_delay_callback1_);
EXPECT_EQ(PowerManagerProxyDelegate::kUnknown, power_manager_.power_state());
OnSuspendImminent(kSuspendId1);
power_manager_.RemoveSuspendDelayCallback(kKey1);
}
TEST_F(PowerManagerTest, AddMultipleStateChangeRunMultiple) {
EXPECT_CALL(*this, StateChangeAction1(PowerManagerProxyDelegate::kOn));
EXPECT_CALL(*this, StateChangeAction1(PowerManagerProxyDelegate::kMem));
power_manager_.AddStateChangeCallback(kKey1, state_change_callback1_);
EXPECT_CALL(*this, StateChangeAction2(PowerManagerProxyDelegate::kOn));
EXPECT_CALL(*this, StateChangeAction2(PowerManagerProxyDelegate::kMem));
power_manager_.AddStateChangeCallback(kKey2, state_change_callback2_);
factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kMem);
}
TEST_F(PowerManagerTest, AddMultipleSuspendDelayRunMultiple) {
EXPECT_CALL(*this, SuspendDelayAction1(kSuspendId1));
EXPECT_CALL(*this, SuspendDelayAction1(kSuspendId2));
power_manager_.AddSuspendDelayCallback(kKey1, suspend_delay_callback1_);
EXPECT_CALL(*this, SuspendDelayAction2(kSuspendId1));
EXPECT_CALL(*this, SuspendDelayAction2(kSuspendId2));
power_manager_.AddSuspendDelayCallback(kKey2, suspend_delay_callback2_);
OnSuspendImminent(kSuspendId1);
OnSuspendImminent(kSuspendId2);
}
TEST_F(PowerManagerTest, RemoveStateChangeCallback) {
EXPECT_CALL(*this, StateChangeAction1(PowerManagerProxyDelegate::kOn));
EXPECT_CALL(*this, StateChangeAction1(PowerManagerProxyDelegate::kMem));
power_manager_.AddStateChangeCallback(kKey1, state_change_callback1_);
EXPECT_CALL(*this, StateChangeAction2(PowerManagerProxyDelegate::kOn));
EXPECT_CALL(*this, StateChangeAction2(PowerManagerProxyDelegate::kMem))
.Times(0);
power_manager_.AddStateChangeCallback(kKey2, state_change_callback2_);
factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
power_manager_.RemoveStateChangeCallback(kKey2);
factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kMem);
power_manager_.RemoveStateChangeCallback(kKey1);
factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
}
TEST_F(PowerManagerTest, RemoveSuspendDelayCallback) {
EXPECT_CALL(*this, SuspendDelayAction1(kSuspendId1));
EXPECT_CALL(*this, SuspendDelayAction1(kSuspendId2));
power_manager_.AddSuspendDelayCallback(kKey1, suspend_delay_callback1_);
EXPECT_CALL(*this, SuspendDelayAction2(kSuspendId1));
EXPECT_CALL(*this, SuspendDelayAction2(kSuspendId2)).Times(0);
power_manager_.AddSuspendDelayCallback(kKey2, suspend_delay_callback2_);
OnSuspendImminent(kSuspendId1);
power_manager_.RemoveSuspendDelayCallback(kKey2);
OnSuspendImminent(kSuspendId2);
power_manager_.RemoveSuspendDelayCallback(kKey1);
OnSuspendImminent(kSuspendId1);
}
typedef PowerManagerTest PowerManagerDeathTest;
TEST_F(PowerManagerDeathTest, AddStateChangeCallbackDuplicateKey) {
power_manager_.AddStateChangeCallback(
kKey1, Bind(&PowerManagerTest::StateChangeAction1, Unretained(this)));
#ifndef NDEBUG
// Adding another callback with the same key is an error and causes a crash in
// debug mode.
EXPECT_DEATH(power_manager_.AddStateChangeCallback(
kKey1, Bind(&PowerManagerTest::StateChangeAction2, Unretained(this))),
"Inserting duplicate key");
#else // NDEBUG
EXPECT_CALL(*this, StateChangeAction2(PowerManagerProxyDelegate::kOn));
power_manager_.AddStateChangeCallback(
kKey1, Bind(&PowerManagerTest::StateChangeAction2, Unretained(this)));
factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
#endif // NDEBUG
}
TEST_F(PowerManagerDeathTest, RemoveStateChangeCallbackUnknownKey) {
power_manager_.AddStateChangeCallback(
kKey1, Bind(&PowerManagerTest::StateChangeAction1, Unretained(this)));
#ifndef NDEBUG
// Attempting to remove a callback key that was not added is an error and
// crashes in debug mode.
EXPECT_DEATH(power_manager_.RemoveStateChangeCallback(kKey2),
"Removing unknown key");
#else // NDEBUG
EXPECT_CALL(*this, StateChangeAction1(PowerManagerProxyDelegate::kOn));
// In non-debug mode, removing an unknown key does nothing.
power_manager_.RemoveStateChangeCallback(kKey2);
factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
#endif // NDEBUG
}
TEST_F(PowerManagerTest, RegisterSuspendDelay) {
const base::TimeDelta kTimeout = base::TimeDelta::FromMilliseconds(100);
const char kDescription[] = "description";
int delay_id = 0;
EXPECT_CALL(*factory_.proxy(), RegisterSuspendDelay(kTimeout, kDescription,
&delay_id))
.WillOnce(Return(true));
EXPECT_TRUE(power_manager_.RegisterSuspendDelay(kTimeout, kDescription,
&delay_id));
}
TEST_F(PowerManagerTest, UnregisterSuspendDelay) {
const int kDelayId = 123;
EXPECT_CALL(*factory_.proxy(), UnregisterSuspendDelay(kDelayId))
.WillOnce(Return(true));
EXPECT_TRUE(power_manager_.UnregisterSuspendDelay(kDelayId));
}
TEST_F(PowerManagerTest, ReportSuspendReadiness) {
const int kDelayId = 678;
const int kSuspendId = 12345;
EXPECT_CALL(*factory_.proxy(), ReportSuspendReadiness(kDelayId, kSuspendId))
.WillOnce(Return(true));
EXPECT_TRUE(power_manager_.ReportSuspendReadiness(kDelayId, kSuspendId));
}
TEST_F(PowerManagerTest, OnSuspendTimeout) {
EXPECT_EQ(PowerManagerProxyDelegate::kUnknown, power_manager_.power_state());
OnSuspendTimeout();
EXPECT_EQ(PowerManagerProxyDelegate::kOn, power_manager_.power_state());
}
} // namespace shill