// Copyright 2014 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. // // MediaTransferProtocolDeviceObserverLinux unit tests. #include "components/storage_monitor/media_transfer_protocol_device_observer_linux.h" #include #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "components/storage_monitor/mock_removable_storage_observer.h" #include "components/storage_monitor/storage_info.h" #include "components/storage_monitor/storage_monitor.h" #include "components/storage_monitor/test_storage_monitor.h" #include "content/public/test/test_browser_thread_bundle.h" #include "device/media_transfer_protocol/media_transfer_protocol_manager.h" #include "testing/gtest/include/gtest/gtest.h" namespace storage_monitor { namespace { // Sample mtp device storage information. const char kStorageLabel[] = "Camera V1.0"; const char kStorageLocation[] = "/usb:2,2,88888"; const char kStorageUniqueId[] = "VendorModelSerial:COM:MOD2012:283"; const char kStorageWithInvalidInfo[] = "usb:2,3,11111"; const char kStorageWithValidInfo[] = "usb:2,2,88888"; const char kStorageVendor[] = "ExampleVendor"; const char kStorageProductName[] = "ExampleCamera"; // Returns the mtp device id given the |unique_id|. std::string GetMtpDeviceId(const std::string& unique_id) { return StorageInfo::MakeDeviceId(StorageInfo::MTP_OR_PTP, unique_id); } // Helper function to get the device storage details such as device id, label // and location. On success, fills in |id|, |label|, |location|, |vendor_name|, // and |product_name|. void GetStorageInfo(const std::string& storage_name, device::MediaTransferProtocolManager* mtp_manager, std::string* id, base::string16* label, std::string* location, base::string16* vendor_name, base::string16* product_name) { if (storage_name == kStorageWithInvalidInfo) return; // Do not set any storage details. ASSERT_EQ(kStorageWithValidInfo, storage_name); *id = GetMtpDeviceId(kStorageUniqueId); *label = base::ASCIIToUTF16(kStorageLabel); *location = kStorageLocation; *vendor_name = base::ASCIIToUTF16(kStorageVendor); *product_name = base::ASCIIToUTF16(kStorageProductName); } class TestMediaTransferProtocolDeviceObserverLinux : public MediaTransferProtocolDeviceObserverLinux { public: TestMediaTransferProtocolDeviceObserverLinux( StorageMonitor::Receiver* receiver, device::MediaTransferProtocolManager* mtp_manager) : MediaTransferProtocolDeviceObserverLinux(receiver, mtp_manager, &GetStorageInfo) { } // Notifies MediaTransferProtocolDeviceObserverLinux about the attachment of // mtp storage device given the |storage_name|. void MtpStorageAttached(const std::string& storage_name) { StorageChanged(true, storage_name); base::RunLoop().RunUntilIdle(); } // Notifies MediaTransferProtocolDeviceObserverLinux about the detachment of // mtp storage device given the |storage_name|. void MtpStorageDetached(const std::string& storage_name) { StorageChanged(false, storage_name); base::RunLoop().RunUntilIdle(); } private: DISALLOW_COPY_AND_ASSIGN(TestMediaTransferProtocolDeviceObserverLinux); }; } // namespace // A class to test the functionality of MediaTransferProtocolDeviceObserverLinux // member functions. class MediaTransferProtocolDeviceObserverLinuxTest : public testing::Test { public: MediaTransferProtocolDeviceObserverLinuxTest() : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} ~MediaTransferProtocolDeviceObserverLinuxTest() override {} protected: void SetUp() override { mock_storage_observer_.reset(new MockRemovableStorageObserver); TestStorageMonitor* monitor = TestStorageMonitor::CreateAndInstall(); mtp_device_observer_.reset( new TestMediaTransferProtocolDeviceObserverLinux( monitor->receiver(), monitor->media_transfer_protocol_manager())); monitor->AddObserver(mock_storage_observer_.get()); } void TearDown() override { StorageMonitor* monitor = StorageMonitor::GetInstance(); monitor->RemoveObserver(mock_storage_observer_.get()); mtp_device_observer_.reset(); TestStorageMonitor::Destroy(); } // Returns the device changed observer object. MockRemovableStorageObserver& observer() { return *mock_storage_observer_; } TestMediaTransferProtocolDeviceObserverLinux* mtp_device_observer() { return mtp_device_observer_.get(); } private: content::TestBrowserThreadBundle thread_bundle_; scoped_ptr mtp_device_observer_; scoped_ptr mock_storage_observer_; DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDeviceObserverLinuxTest); }; // Test to verify basic mtp storage attach and detach notifications. TEST_F(MediaTransferProtocolDeviceObserverLinuxTest, BasicAttachDetach) { std::string device_id = GetMtpDeviceId(kStorageUniqueId); // Attach a mtp storage. mtp_device_observer()->MtpStorageAttached(kStorageWithValidInfo); EXPECT_EQ(1, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); EXPECT_EQ(device_id, observer().last_attached().device_id()); EXPECT_EQ(kStorageLocation, observer().last_attached().location()); EXPECT_EQ(base::ASCIIToUTF16(kStorageVendor), observer().last_attached().vendor_name()); EXPECT_EQ(base::ASCIIToUTF16(kStorageProductName), observer().last_attached().model_name()); // Detach the attached storage. mtp_device_observer()->MtpStorageDetached(kStorageWithValidInfo); EXPECT_EQ(1, observer().attach_calls()); EXPECT_EQ(1, observer().detach_calls()); EXPECT_EQ(device_id, observer().last_detached().device_id()); } // When a mtp storage device with invalid storage label and id is // attached/detached, there should not be any device attach/detach // notifications. TEST_F(MediaTransferProtocolDeviceObserverLinuxTest, StorageWithInvalidInfo) { // Attach the mtp storage with invalid storage info. mtp_device_observer()->MtpStorageAttached(kStorageWithInvalidInfo); // Detach the attached storage. mtp_device_observer()->MtpStorageDetached(kStorageWithInvalidInfo); EXPECT_EQ(0, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); } } // namespace storage_monitor