// Copyright (c) 2012 The Chromium 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 "base/system_monitor/system_monitor.h" #include "base/file_path.h" #include "base/message_loop.h" #include "base/test/mock_devices_changed_observer.h" #include "base/utf_string_conversions.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace { class PowerTest : public SystemMonitor::PowerObserver { public: PowerTest() : power_state_changes_(0), suspends_(0), resumes_(0) { } // PowerObserver callbacks. virtual void OnPowerStateChange(bool on_battery_power) OVERRIDE { power_state_changes_++; } virtual void OnSuspend() OVERRIDE { suspends_++; } virtual void OnResume() OVERRIDE { resumes_++; } // Test status counts. int power_state_changes() { return power_state_changes_; } int suspends() { return suspends_; } int resumes() { return resumes_; } private: int power_state_changes_; // Count of OnPowerStateChange notifications. int suspends_; // Count of OnSuspend notifications. int resumes_; // Count of OnResume notifications. }; class SystemMonitorTest : public testing::Test { protected: SystemMonitorTest() { #if defined(OS_MACOSX) // This needs to happen before SystemMonitor's ctor. SystemMonitor::AllocateSystemIOPorts(); #endif system_monitor_.reset(new SystemMonitor); } virtual ~SystemMonitorTest() {} MessageLoop message_loop_; scoped_ptr system_monitor_; DISALLOW_COPY_AND_ASSIGN(SystemMonitorTest); }; TEST_F(SystemMonitorTest, PowerNotifications) { const int kObservers = 5; PowerTest test[kObservers]; for (int index = 0; index < kObservers; ++index) system_monitor_->AddPowerObserver(&test[index]); // Send a bunch of power changes. Since the battery power hasn't // actually changed, we shouldn't get notifications. for (int index = 0; index < 5; index++) { system_monitor_->ProcessPowerMessage(SystemMonitor::POWER_STATE_EVENT); EXPECT_EQ(test[0].power_state_changes(), 0); } // Sending resume when not suspended should have no effect. system_monitor_->ProcessPowerMessage(SystemMonitor::RESUME_EVENT); message_loop_.RunUntilIdle(); EXPECT_EQ(test[0].resumes(), 0); // Pretend we suspended. system_monitor_->ProcessPowerMessage(SystemMonitor::SUSPEND_EVENT); message_loop_.RunUntilIdle(); EXPECT_EQ(test[0].suspends(), 1); // Send a second suspend notification. This should be suppressed. system_monitor_->ProcessPowerMessage(SystemMonitor::SUSPEND_EVENT); message_loop_.RunUntilIdle(); EXPECT_EQ(test[0].suspends(), 1); // Pretend we were awakened. system_monitor_->ProcessPowerMessage(SystemMonitor::RESUME_EVENT); message_loop_.RunUntilIdle(); EXPECT_EQ(test[0].resumes(), 1); // Send a duplicate resume notification. This should be suppressed. system_monitor_->ProcessPowerMessage(SystemMonitor::RESUME_EVENT); message_loop_.RunUntilIdle(); EXPECT_EQ(test[0].resumes(), 1); } TEST_F(SystemMonitorTest, DeviceChangeNotifications) { const int kObservers = 5; const string16 kDeviceName = ASCIIToUTF16("media device"); const std::string kDeviceId1 = "1"; const std::string kDeviceId2 = "2"; testing::Sequence mock_sequencer[kObservers]; MockDevicesChangedObserver observers[kObservers]; for (int index = 0; index < kObservers; ++index) { system_monitor_->AddDevicesChangedObserver(&observers[index]); EXPECT_CALL(observers[index], OnDevicesChanged(SystemMonitor::DEVTYPE_UNKNOWN)) .Times(3) .InSequence(mock_sequencer[index]); EXPECT_CALL(observers[index], OnRemovableStorageAttached(kDeviceId1, kDeviceName, testing::_)) .InSequence(mock_sequencer[index]); EXPECT_CALL(observers[index], OnRemovableStorageDetached(kDeviceId1)) .InSequence(mock_sequencer[index]); EXPECT_CALL(observers[index], OnRemovableStorageDetached(kDeviceId2)) .Times(0).InSequence(mock_sequencer[index]); } system_monitor_->ProcessDevicesChanged(SystemMonitor::DEVTYPE_UNKNOWN); message_loop_.RunUntilIdle(); system_monitor_->ProcessDevicesChanged(SystemMonitor::DEVTYPE_UNKNOWN); system_monitor_->ProcessDevicesChanged(SystemMonitor::DEVTYPE_UNKNOWN); message_loop_.RunUntilIdle(); system_monitor_->ProcessRemovableStorageAttached(kDeviceId1, kDeviceName, FILE_PATH_LITERAL("path")); message_loop_.RunUntilIdle(); system_monitor_->ProcessRemovableStorageDetached(kDeviceId1); system_monitor_->ProcessRemovableStorageDetached(kDeviceId2); message_loop_.RunUntilIdle(); } TEST_F(SystemMonitorTest, GetAttachedRemovableStorageEmpty) { std::vector devices = system_monitor_->GetAttachedRemovableStorage(); EXPECT_EQ(0U, devices.size()); } TEST_F(SystemMonitorTest, GetAttachedRemovableStorageAttachDetach) { const std::string kDeviceId1 = "42"; const string16 kDeviceName1 = ASCIIToUTF16("test"); const FilePath kDevicePath1(FILE_PATH_LITERAL("/testfoo")); system_monitor_->ProcessRemovableStorageAttached(kDeviceId1, kDeviceName1, kDevicePath1.value()); message_loop_.RunUntilIdle(); std::vector devices = system_monitor_->GetAttachedRemovableStorage(); ASSERT_EQ(1U, devices.size()); EXPECT_EQ(kDeviceId1, devices[0].device_id); EXPECT_EQ(kDeviceName1, devices[0].name); EXPECT_EQ(kDevicePath1.value(), devices[0].location); const std::string kDeviceId2 = "44"; const string16 kDeviceName2 = ASCIIToUTF16("test2"); const FilePath kDevicePath2(FILE_PATH_LITERAL("/testbar")); system_monitor_->ProcessRemovableStorageAttached(kDeviceId2, kDeviceName2, kDevicePath2.value()); message_loop_.RunUntilIdle(); devices = system_monitor_->GetAttachedRemovableStorage(); ASSERT_EQ(2U, devices.size()); EXPECT_EQ(kDeviceId1, devices[0].device_id); EXPECT_EQ(kDeviceName1, devices[0].name); EXPECT_EQ(kDevicePath1.value(), devices[0].location); EXPECT_EQ(kDeviceId2, devices[1].device_id); EXPECT_EQ(kDeviceName2, devices[1].name); EXPECT_EQ(kDevicePath2.value(), devices[1].location); system_monitor_->ProcessRemovableStorageDetached(kDeviceId1); message_loop_.RunUntilIdle(); devices = system_monitor_->GetAttachedRemovableStorage(); ASSERT_EQ(1U, devices.size()); EXPECT_EQ(kDeviceId2, devices[0].device_id); EXPECT_EQ(kDeviceName2, devices[0].name); EXPECT_EQ(kDevicePath2.value(), devices[0].location); system_monitor_->ProcessRemovableStorageDetached(kDeviceId2); message_loop_.RunUntilIdle(); devices = system_monitor_->GetAttachedRemovableStorage(); EXPECT_EQ(0U, devices.size()); } } // namespace } // namespace base