shill: power management framework, continued
PowerManager is a wrapper class around PowerManagerProxy that lets users
register interest in power state changes and to be notified via a callback.
Notifications of other events will be added later.
BUG=chromium-os:22407
TEST=Added new unit tests. Ran all shill unit tests. The new tests pass in
both DEBUG and NDEBUG modes.
Change-Id: I5a8baf545fcfefa1111963f7e5080f908297ee9f
Reviewed-on: https://gerrit.chromium.org/gerrit/15420
Commit-Ready: Gary Morain <gmorain@chromium.org>
Reviewed-by: Gary Morain <gmorain@chromium.org>
Tested-by: Gary Morain <gmorain@chromium.org>
diff --git a/power_manager_unittest.cc b/power_manager_unittest.cc
new file mode 100644
index 0000000..8254a06
--- /dev/null
+++ b/power_manager_unittest.cc
@@ -0,0 +1,152 @@
+// 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/scoped_ptr.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "shill/mock_callback.h"
+#include "shill/mock_power_manager_proxy.h"
+#include "shill/power_manager_proxy_interface.h"
+#include "shill/proxy_factory.h"
+
+using std::string;
+using testing::_;
+using testing::Test;
+
+namespace shill {
+
+typedef MockCallback<void(PowerManager::SuspendState)> MyMockCallback;
+
+namespace {
+
+class FakeProxyFactory : public ProxyFactory {
+ public:
+ FakeProxyFactory() : delegate_(NULL) {}
+
+ virtual PowerManagerProxyInterface *CreatePowerManagerProxy(
+ PowerManagerProxyDelegate *delegate) {
+ delegate_ = delegate;
+ return new MockPowerManagerProxy;
+ }
+ PowerManagerProxyDelegate *delegate() const { return delegate_; }
+
+ private:
+ PowerManagerProxyDelegate *delegate_;
+};
+
+} // namespace
+
+class PowerManagerTest : public Test {
+ public:
+ PowerManagerTest()
+ : power_manager_(&factory_),
+ delegate_(factory_.delegate()) { }
+
+ protected:
+ FakeProxyFactory factory_;
+ PowerManager power_manager_;
+ PowerManagerProxyDelegate *const delegate_;
+};
+
+TEST_F(PowerManagerTest, Add) {
+ const string kKey = "Zaphod";
+ MyMockCallback *mock_callback = NewMockCallback();
+ EXPECT_CALL(*mock_callback, OnRun(PowerManagerProxyDelegate::kOn));
+ power_manager_.AddStateChangeCallback(kKey, mock_callback);
+ factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
+}
+
+TEST_F(PowerManagerTest, AddMultipleRunMultiple) {
+ const string kKey1 = "Zaphod";
+ MyMockCallback *mock_callback1 = NewMockCallback();
+ EXPECT_CALL(*mock_callback1, OnRun(PowerManagerProxyDelegate::kOn));
+ EXPECT_CALL(*mock_callback1, OnRun(PowerManagerProxyDelegate::kMem));
+ power_manager_.AddStateChangeCallback(kKey1, mock_callback1);
+
+ const string kKey2 = "Beeblebrox";
+ MyMockCallback *mock_callback2 = NewMockCallback();
+ EXPECT_CALL(*mock_callback2, OnRun(PowerManagerProxyDelegate::kOn));
+ EXPECT_CALL(*mock_callback2, OnRun(PowerManagerProxyDelegate::kMem));
+ power_manager_.AddStateChangeCallback(kKey2, mock_callback2);
+
+ factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
+ factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kMem);
+}
+
+TEST_F(PowerManagerTest, Remove) {
+ const string kKey1 = "Zaphod";
+ MyMockCallback *mock_callback1 = NewMockCallback();
+ EXPECT_CALL(*mock_callback1, OnRun(PowerManagerProxyDelegate::kOn));
+ EXPECT_CALL(*mock_callback1, OnRun(PowerManagerProxyDelegate::kMem));
+ power_manager_.AddStateChangeCallback(kKey1, mock_callback1);
+
+ const string kKey2 = "Beeblebrox";
+ MyMockCallback *mock_callback2 = NewMockCallback();
+ EXPECT_CALL(*mock_callback2, OnRun(PowerManagerProxyDelegate::kOn));
+ EXPECT_CALL(*mock_callback2, OnRun(PowerManagerProxyDelegate::kMem)).Times(0);
+ power_manager_.AddStateChangeCallback(kKey2, mock_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, OnSuspendDelayIgnored) {
+ const string kKey = "Zaphod";
+ MyMockCallback *mock_callback = NewMockCallback();
+ EXPECT_CALL(*mock_callback, OnRun(_)).Times(0);
+ power_manager_.AddStateChangeCallback(kKey, mock_callback);
+ factory_.delegate()->OnSuspendDelay(99);
+}
+
+typedef PowerManagerTest PowerManagerDeathTest;
+
+TEST_F(PowerManagerDeathTest, AddDuplicateKey) {
+ const string kKey1 = "Zaphod";
+ MyMockCallback *mock_callback1 = NewMockCallback();
+ MyMockCallback *mock_callback2 = NewMockCallback();
+ power_manager_.AddStateChangeCallback(kKey1, mock_callback1);
+
+#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, mock_callback2),
+ "Inserting duplicate key");
+#else // NDEBUG
+ EXPECT_CALL(*mock_callback2, OnRun(PowerManagerProxyDelegate::kOn));
+ power_manager_.AddStateChangeCallback(kKey1, mock_callback2);
+ factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
+#endif // NDEBUG
+}
+
+TEST_F(PowerManagerDeathTest, RemoveUnknownKey) {
+ const string kKey1 = "Zaphod";
+ const string kKey2 = "Beeblebrox";
+ MyMockCallback *mock_callback1 = NewMockCallback();
+ power_manager_.AddStateChangeCallback(kKey1, mock_callback1);
+
+#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(*mock_callback1, OnRun(PowerManagerProxyDelegate::kOn));
+
+ // In non-debug mode, removing an unknown key does nothing.
+ power_manager_.RemoveStateChangeCallback(kKey2);
+ factory_.delegate()->OnPowerStateChanged(PowerManagerProxyDelegate::kOn);
+#endif // NDEBUG
+}
+
+} // namespace shill