| // 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. |
| // |
| // MtpManagerClientChromeOS unit tests. |
| |
| #include "components/storage_monitor/mtp_manager_client_chromeos.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "base/lazy_instance.h" |
| #include "base/macros.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_info_utils.h" |
| #include "components/storage_monitor/storage_monitor.h" |
| #include "components/storage_monitor/test_storage_monitor.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "services/device/public/mojom/mtp_manager.mojom.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace storage_monitor { |
| |
| namespace { |
| |
| // Sample MTP device storage information. |
| const char kStorageWithInvalidInfo[] = "usb:2,3:11111"; |
| const char kStorageWithValidInfo[] = "usb:2,2:88888"; |
| const char kStorageVendor[] = "ExampleVendor"; |
| const uint32_t kStorageVendorId = 0x040a; |
| const char kStorageProduct[] = "ExampleCamera"; |
| const uint32_t kStorageProductId = 0x0160; |
| const uint32_t kStorageDeviceFlags = 0x0004000; |
| const uint32_t kStorageType = 3; // Fixed RAM |
| const uint32_t kStorageFilesystemType = 2; // Generic Hierarchical |
| const uint32_t kStorageAccessCapability = 0; // Read-Write |
| const uint64_t kStorageMaxCapacity = 0x40000000; // 1G in total |
| const uint64_t kStorageFreeSpaceInBytes = 0x20000000; // 512M bytes left |
| const uint64_t kStorageFreeSpaceInObjects = 0x04000000; // 64M Objects left |
| const char kStorageDescription[] = "ExampleDescription"; |
| const char kStorageVolumeIdentifier[] = "ExampleVolumeId"; |
| |
| base::LazyInstance<std::map<std::string, device::mojom::MtpStorageInfo>>::Leaky |
| g_fake_storage_info_map = LAZY_INSTANCE_INITIALIZER; |
| |
| const device::mojom::MtpStorageInfo* GetFakeMtpStorageInfoSync( |
| const std::string& storage_name) { |
| // Fill the map out if it is empty. |
| if (g_fake_storage_info_map.Get().empty()) { |
| // Add the invalid MTP storage info. |
| auto storage_info = device::mojom::MtpStorageInfo(); |
| storage_info.storage_name = kStorageWithInvalidInfo; |
| g_fake_storage_info_map.Get().insert( |
| std::make_pair(kStorageWithInvalidInfo, storage_info)); |
| // Add the valid MTP storage info. |
| g_fake_storage_info_map.Get().insert(std::make_pair( |
| kStorageWithValidInfo, |
| device::mojom::MtpStorageInfo( |
| kStorageWithValidInfo, kStorageVendor, kStorageVendorId, |
| kStorageProduct, kStorageProductId, kStorageDeviceFlags, |
| kStorageType, kStorageFilesystemType, kStorageAccessCapability, |
| kStorageMaxCapacity, kStorageFreeSpaceInBytes, |
| kStorageFreeSpaceInObjects, kStorageDescription, |
| kStorageVolumeIdentifier))); |
| } |
| |
| const auto it = g_fake_storage_info_map.Get().find(storage_name); |
| return it != g_fake_storage_info_map.Get().end() ? &it->second : nullptr; |
| } |
| |
| class FakeMtpManagerClientChromeOS : public MtpManagerClientChromeOS { |
| public: |
| FakeMtpManagerClientChromeOS(StorageMonitor::Receiver* receiver, |
| device::mojom::MtpManager* mtp_manager) |
| : MtpManagerClientChromeOS(receiver, mtp_manager) {} |
| |
| // Notifies MtpManagerClientChromeOS about the attachment of MTP storage |
| // device given the |storage_name|. |
| void MtpStorageAttached(const std::string& storage_name) { |
| auto* storage_info = GetFakeMtpStorageInfoSync(storage_name); |
| DCHECK(storage_info); |
| |
| StorageAttached(storage_info->Clone()); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| // Notifies MtpManagerClientChromeOS about the detachment of MTP storage |
| // device given the |storage_name|. |
| void MtpStorageDetached(const std::string& storage_name) { |
| StorageDetached(storage_name); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(FakeMtpManagerClientChromeOS); |
| }; |
| |
| } // namespace |
| |
| // A class to test the functionality of MtpManagerClientChromeOS member |
| // functions. |
| class MtpManagerClientChromeOSTest : public testing::Test { |
| public: |
| MtpManagerClientChromeOSTest() |
| : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {} |
| |
| ~MtpManagerClientChromeOSTest() override {} |
| |
| protected: |
| void SetUp() override { |
| mock_storage_observer_.reset(new MockRemovableStorageObserver); |
| TestStorageMonitor* monitor = TestStorageMonitor::CreateAndInstall(); |
| mtp_device_observer_ = std::make_unique<FakeMtpManagerClientChromeOS>( |
| 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_; } |
| |
| FakeMtpManagerClientChromeOS* mtp_device_observer() { |
| return mtp_device_observer_.get(); |
| } |
| |
| private: |
| content::BrowserTaskEnvironment task_environment_; |
| |
| std::unique_ptr<FakeMtpManagerClientChromeOS> mtp_device_observer_; |
| std::unique_ptr<MockRemovableStorageObserver> mock_storage_observer_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MtpManagerClientChromeOSTest); |
| }; |
| |
| // Test to verify basic MTP storage attach and detach notifications. |
| TEST_F(MtpManagerClientChromeOSTest, BasicAttachDetach) { |
| auto* mtpStorageInfo = GetFakeMtpStorageInfoSync(kStorageWithValidInfo); |
| std::string device_id = GetDeviceIdFromStorageInfo(*mtpStorageInfo); |
| |
| // 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(GetDeviceLocationFromStorageName(kStorageWithValidInfo), |
| observer().last_attached().location()); |
| EXPECT_EQ(base::ASCIIToUTF16(kStorageVendor), |
| observer().last_attached().vendor_name()); |
| EXPECT_EQ(base::ASCIIToUTF16(kStorageProduct), |
| 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(MtpManagerClientChromeOSTest, 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 |