- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / storage_monitor / storage_monitor_win_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <windows.h>
6 #include <dbt.h>
7
8 #include <string>
9 #include <vector>
10
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/run_loop.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "chrome/browser/storage_monitor/mock_removable_storage_observer.h"
17 #include "chrome/browser/storage_monitor/portable_device_watcher_win.h"
18 #include "chrome/browser/storage_monitor/removable_device_constants.h"
19 #include "chrome/browser/storage_monitor/storage_info.h"
20 #include "chrome/browser/storage_monitor/storage_monitor_win.h"
21 #include "chrome/browser/storage_monitor/test_portable_device_watcher_win.h"
22 #include "chrome/browser/storage_monitor/test_storage_monitor.h"
23 #include "chrome/browser/storage_monitor/test_storage_monitor_win.h"
24 #include "chrome/browser/storage_monitor/test_volume_mount_watcher_win.h"
25 #include "chrome/browser/storage_monitor/volume_mount_watcher_win.h"
26 #include "chrome/test/base/testing_browser_process.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/test/test_browser_thread_bundle.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30
31 using content::BrowserThread;
32
33 typedef std::vector<int> DeviceIndices;
34
35 // StorageMonitorWinTest -------------------------------------------------------
36
37 class StorageMonitorWinTest : public testing::Test {
38  public:
39   StorageMonitorWinTest();
40   virtual ~StorageMonitorWinTest();
41
42  protected:
43   // testing::Test:
44   virtual void SetUp() OVERRIDE;
45   virtual void TearDown() OVERRIDE;
46
47   void PreAttachDevices();
48
49   // Runs all the pending tasks on UI thread, FILE thread and blocking thread.
50   void RunUntilIdle();
51
52   void DoMassStorageDeviceAttachedTest(const DeviceIndices& device_indices);
53   void DoMassStorageDevicesDetachedTest(const DeviceIndices& device_indices);
54
55   // Injects a device attach or detach change (depending on the value of
56   // |test_attach|) and tests that the appropriate handler is called.
57   void DoMTPDeviceTest(const base::string16& pnp_device_id, bool test_attach);
58
59   // Gets the MTP details of the storage specified by the |storage_device_id|.
60   // On success, returns true and fills in |pnp_device_id| and
61   // |storage_object_id|.
62   bool GetMTPStorageInfo(const std::string& storage_device_id,
63                          base::string16* pnp_device_id,
64                          base::string16* storage_object_id);
65
66   TestStorageMonitorWin* monitor_;
67
68   // Weak pointer; owned by the device notifications class.
69   TestVolumeMountWatcherWin* volume_mount_watcher_;
70
71   MockRemovableStorageObserver observer_;
72
73  private:
74   content::TestBrowserThreadBundle thread_bundle_;
75
76   DISALLOW_COPY_AND_ASSIGN(StorageMonitorWinTest);
77 };
78
79 StorageMonitorWinTest::StorageMonitorWinTest() {
80 }
81
82 StorageMonitorWinTest::~StorageMonitorWinTest() {
83 }
84
85 void StorageMonitorWinTest::SetUp() {
86   TestStorageMonitor::RemoveSingleton();
87   volume_mount_watcher_ = new TestVolumeMountWatcherWin;
88   monitor_ = new TestStorageMonitorWin(volume_mount_watcher_,
89                                        new TestPortableDeviceWatcherWin);
90   scoped_ptr<StorageMonitor> pass_monitor(monitor_);
91   TestingBrowserProcess* browser_process = TestingBrowserProcess::GetGlobal();
92   DCHECK(browser_process);
93   browser_process->SetStorageMonitor(pass_monitor.Pass());
94
95   monitor_->Init();
96   RunUntilIdle();
97   monitor_->AddObserver(&observer_);
98 }
99
100 void StorageMonitorWinTest::TearDown() {
101   RunUntilIdle();
102   monitor_->RemoveObserver(&observer_);
103   volume_mount_watcher_->ShutdownWorkerPool();
104   monitor_ = NULL;
105
106   // Windows storage monitor must be destroyed on the same thread
107   // as construction.
108   TestStorageMonitor::RemoveSingleton();
109 }
110
111 void StorageMonitorWinTest::PreAttachDevices() {
112   TestStorageMonitor::RemoveSingleton();
113   monitor_ = NULL;
114   volume_mount_watcher_ = new TestVolumeMountWatcherWin;
115   volume_mount_watcher_->SetAttachedDevicesFake();
116
117   int expect_attach_calls = 0;
118   std::vector<base::FilePath> initial_devices =
119       volume_mount_watcher_->GetAttachedDevicesCallback().Run();
120   for (std::vector<base::FilePath>::const_iterator it = initial_devices.begin();
121        it != initial_devices.end(); ++it) {
122     bool removable;
123     ASSERT_TRUE(volume_mount_watcher_->GetDeviceRemovable(*it, &removable));
124     if (removable)
125       expect_attach_calls++;
126   }
127
128   monitor_ = new TestStorageMonitorWin(volume_mount_watcher_,
129                                        new TestPortableDeviceWatcherWin);
130   scoped_ptr<StorageMonitor> pass_monitor(monitor_);
131   TestingBrowserProcess* browser_process = TestingBrowserProcess::GetGlobal();
132   DCHECK(browser_process);
133   browser_process->SetStorageMonitor(pass_monitor.Pass());
134
135   monitor_->AddObserver(&observer_);
136   monitor_->Init();
137
138   EXPECT_EQ(0u, volume_mount_watcher_->devices_checked().size());
139
140   // This dance is because attachment bounces through a couple of
141   // closures, which need to be executed to finish the process.
142   RunUntilIdle();
143   volume_mount_watcher_->FlushWorkerPoolForTesting();
144   RunUntilIdle();
145
146   std::vector<base::FilePath> checked_devices =
147       volume_mount_watcher_->devices_checked();
148   sort(checked_devices.begin(), checked_devices.end());
149   EXPECT_EQ(initial_devices, checked_devices);
150   EXPECT_EQ(expect_attach_calls, observer_.attach_calls());
151   EXPECT_EQ(0, observer_.detach_calls());
152 }
153
154 void StorageMonitorWinTest::RunUntilIdle() {
155   volume_mount_watcher_->FlushWorkerPoolForTesting();
156   base::RunLoop().RunUntilIdle();
157 }
158
159 void StorageMonitorWinTest::DoMassStorageDeviceAttachedTest(
160     const DeviceIndices& device_indices) {
161   DEV_BROADCAST_VOLUME volume_broadcast;
162   volume_broadcast.dbcv_size = sizeof(volume_broadcast);
163   volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
164   volume_broadcast.dbcv_unitmask = 0x0;
165   volume_broadcast.dbcv_flags = 0x0;
166
167   int expect_attach_calls = observer_.attach_calls();
168   for (DeviceIndices::const_iterator it = device_indices.begin();
169        it != device_indices.end(); ++it) {
170     volume_broadcast.dbcv_unitmask |= 0x1 << *it;
171     bool removable;
172     ASSERT_TRUE(volume_mount_watcher_->GetDeviceRemovable(
173         VolumeMountWatcherWin::DriveNumberToFilePath(*it), &removable));
174     if (removable)
175       expect_attach_calls++;
176   }
177   monitor_->InjectDeviceChange(DBT_DEVICEARRIVAL,
178                                reinterpret_cast<DWORD>(&volume_broadcast));
179
180   RunUntilIdle();
181   volume_mount_watcher_->FlushWorkerPoolForTesting();
182   RunUntilIdle();
183
184   EXPECT_EQ(expect_attach_calls, observer_.attach_calls());
185   EXPECT_EQ(0, observer_.detach_calls());
186 }
187
188 void StorageMonitorWinTest::DoMassStorageDevicesDetachedTest(
189     const DeviceIndices& device_indices) {
190   DEV_BROADCAST_VOLUME volume_broadcast;
191   volume_broadcast.dbcv_size = sizeof(volume_broadcast);
192   volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
193   volume_broadcast.dbcv_unitmask = 0x0;
194   volume_broadcast.dbcv_flags = 0x0;
195
196   int pre_attach_calls = observer_.attach_calls();
197   int expect_detach_calls = 0;
198   for (DeviceIndices::const_iterator it = device_indices.begin();
199        it != device_indices.end(); ++it) {
200     volume_broadcast.dbcv_unitmask |= 0x1 << *it;
201     StorageInfo info;
202     ASSERT_TRUE(volume_mount_watcher_->GetDeviceInfo(
203         VolumeMountWatcherWin::DriveNumberToFilePath(*it), &info));
204     if (StorageInfo::IsRemovableDevice(info.device_id()))
205       ++expect_detach_calls;
206   }
207   monitor_->InjectDeviceChange(DBT_DEVICEREMOVECOMPLETE,
208                                reinterpret_cast<DWORD>(&volume_broadcast));
209   RunUntilIdle();
210   EXPECT_EQ(pre_attach_calls, observer_.attach_calls());
211   EXPECT_EQ(expect_detach_calls, observer_.detach_calls());
212 }
213
214 void StorageMonitorWinTest::DoMTPDeviceTest(const base::string16& pnp_device_id,
215                                             bool test_attach) {
216   GUID guidDevInterface = GUID_NULL;
217   HRESULT hr = CLSIDFromString(kWPDDevInterfaceGUID, &guidDevInterface);
218   if (FAILED(hr))
219     return;
220
221   size_t device_id_size = pnp_device_id.size() * sizeof(char16);
222   size_t size = sizeof(DEV_BROADCAST_DEVICEINTERFACE) + device_id_size;
223   scoped_ptr_malloc<DEV_BROADCAST_DEVICEINTERFACE> dev_interface_broadcast(
224       static_cast<DEV_BROADCAST_DEVICEINTERFACE*>(malloc(size)));
225   DCHECK(dev_interface_broadcast.get());
226   ZeroMemory(dev_interface_broadcast.get(), size);
227   dev_interface_broadcast->dbcc_size = size;
228   dev_interface_broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
229   dev_interface_broadcast->dbcc_classguid = guidDevInterface;
230   memcpy(dev_interface_broadcast->dbcc_name, pnp_device_id.data(),
231          device_id_size);
232
233   int expect_attach_calls = observer_.attach_calls();
234   int expect_detach_calls = observer_.detach_calls();
235   PortableDeviceWatcherWin::StorageObjectIDs storage_object_ids =
236       TestPortableDeviceWatcherWin::GetMTPStorageObjectIds(pnp_device_id);
237   for (PortableDeviceWatcherWin::StorageObjectIDs::const_iterator it =
238        storage_object_ids.begin(); it != storage_object_ids.end(); ++it) {
239     std::string unique_id;
240     base::string16 name;
241     base::string16 location;
242     TestPortableDeviceWatcherWin::GetMTPStorageDetails(pnp_device_id, *it,
243                                                        &location, &unique_id,
244                                                        &name);
245     if (test_attach && !name.empty() && !unique_id.empty())
246       expect_attach_calls++;
247     else if (!name.empty() && !unique_id.empty())
248       expect_detach_calls++;
249   }
250
251   monitor_->InjectDeviceChange(
252       test_attach ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE,
253       reinterpret_cast<DWORD>(dev_interface_broadcast.get()));
254
255   RunUntilIdle();
256   EXPECT_EQ(expect_attach_calls, observer_.attach_calls());
257   EXPECT_EQ(expect_detach_calls, observer_.detach_calls());
258 }
259
260 bool StorageMonitorWinTest::GetMTPStorageInfo(
261     const std::string& storage_device_id,
262     base::string16* pnp_device_id,
263     base::string16* storage_object_id) {
264   return monitor_->GetMTPStorageInfoFromDeviceId(storage_device_id,
265                                                  pnp_device_id,
266                                                  storage_object_id);
267 }
268
269 TEST_F(StorageMonitorWinTest, RandomMessage) {
270   monitor_->InjectDeviceChange(DBT_DEVICEQUERYREMOVE, NULL);
271   RunUntilIdle();
272 }
273
274 TEST_F(StorageMonitorWinTest, DevicesAttached) {
275   DeviceIndices device_indices;
276   device_indices.push_back(1);  // B
277   device_indices.push_back(5);  // F
278   device_indices.push_back(7);  // H
279   device_indices.push_back(13);  // N
280   DoMassStorageDeviceAttachedTest(device_indices);
281
282   StorageInfo info;
283   EXPECT_TRUE(monitor_->volume_mount_watcher()->GetDeviceInfo(
284       base::FilePath(ASCIIToUTF16("F:\\")), &info));
285   EXPECT_EQ(ASCIIToUTF16("F:\\"), info.location());
286   EXPECT_EQ("dcim:\\\\?\\Volume{F0000000-0000-0000-0000-000000000000}\\",
287             info.device_id());
288   EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info.storage_label());
289
290   EXPECT_FALSE(monitor_->GetStorageInfoForPath(
291       base::FilePath(ASCIIToUTF16("G:\\")), &info));
292   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
293       base::FilePath(ASCIIToUTF16("F:\\")), &info));
294   StorageInfo info1;
295   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
296       base::FilePath(ASCIIToUTF16("F:\\subdir")), &info1));
297   StorageInfo info2;
298   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
299       base::FilePath(ASCIIToUTF16("F:\\subdir\\sub")), &info2));
300   EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info.storage_label());
301   EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info1.storage_label());
302   EXPECT_EQ(ASCIIToUTF16("F:\\ Drive"), info2.storage_label());
303 }
304
305 TEST_F(StorageMonitorWinTest, PathMountDevices) {
306   PreAttachDevices();
307   int init_storages = monitor_->GetAllAvailableStorages().size();
308
309   volume_mount_watcher_->AddDeviceForTesting(
310       base::FilePath(FILE_PATH_LITERAL("F:\\mount1")),
311       "dcim:mount1", L"mount1", 100);
312   volume_mount_watcher_->AddDeviceForTesting(
313       base::FilePath(FILE_PATH_LITERAL("F:\\mount1\\subdir")),
314       "dcim:mount1subdir", L"mount1subdir", 100);
315   volume_mount_watcher_->AddDeviceForTesting(
316       base::FilePath(FILE_PATH_LITERAL("F:\\mount2")),
317       "dcim:mount2", L"mount2", 100);
318   RunUntilIdle();
319   EXPECT_EQ(init_storages + 3, monitor_->GetAllAvailableStorages().size());
320
321   StorageInfo info;
322   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
323       base::FilePath(ASCIIToUTF16("F:\\dir")), &info));
324   EXPECT_EQ(L"", info.name());
325   EXPECT_EQ(L"F:\\ Drive", info.storage_label());
326   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
327       base::FilePath(ASCIIToUTF16("F:\\mount1")), &info));
328   EXPECT_EQ(L"mount1", info.name());
329   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
330       base::FilePath(ASCIIToUTF16("F:\\mount1\\dir")), &info));
331   EXPECT_EQ(L"mount1", info.name());
332   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
333       base::FilePath(ASCIIToUTF16("F:\\mount2\\dir")), &info));
334   EXPECT_EQ(L"mount2", info.name());
335   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
336       base::FilePath(ASCIIToUTF16("F:\\mount1\\subdir")), &info));
337   EXPECT_EQ(L"mount1subdir", info.name());
338   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
339       base::FilePath(ASCIIToUTF16("F:\\mount1\\subdir\\dir")), &info));
340   EXPECT_EQ(L"mount1subdir", info.name());
341   EXPECT_TRUE(monitor_->GetStorageInfoForPath(
342       base::FilePath(ASCIIToUTF16("F:\\mount1\\subdir\\dir\\dir")), &info));
343   EXPECT_EQ(L"mount1subdir", info.name());
344 }
345
346 TEST_F(StorageMonitorWinTest, DevicesAttachedHighBoundary) {
347   DeviceIndices device_indices;
348   device_indices.push_back(25);
349
350   DoMassStorageDeviceAttachedTest(device_indices);
351 }
352
353 TEST_F(StorageMonitorWinTest, DevicesAttachedLowBoundary) {
354   DeviceIndices device_indices;
355   device_indices.push_back(0);
356
357   DoMassStorageDeviceAttachedTest(device_indices);
358 }
359
360 TEST_F(StorageMonitorWinTest, DevicesAttachedAdjacentBits) {
361   DeviceIndices device_indices;
362   device_indices.push_back(0);
363   device_indices.push_back(1);
364   device_indices.push_back(2);
365   device_indices.push_back(3);
366
367   DoMassStorageDeviceAttachedTest(device_indices);
368 }
369
370 TEST_F(StorageMonitorWinTest, DevicesDetached) {
371   PreAttachDevices();
372
373   DeviceIndices device_indices;
374   device_indices.push_back(1);
375   device_indices.push_back(5);
376   device_indices.push_back(7);
377   device_indices.push_back(13);
378
379   DoMassStorageDevicesDetachedTest(device_indices);
380 }
381
382 TEST_F(StorageMonitorWinTest, DevicesDetachedHighBoundary) {
383   PreAttachDevices();
384
385   DeviceIndices device_indices;
386   device_indices.push_back(25);
387
388   DoMassStorageDevicesDetachedTest(device_indices);
389 }
390
391 TEST_F(StorageMonitorWinTest, DevicesDetachedLowBoundary) {
392   PreAttachDevices();
393
394   DeviceIndices device_indices;
395   device_indices.push_back(0);
396
397   DoMassStorageDevicesDetachedTest(device_indices);
398 }
399
400 TEST_F(StorageMonitorWinTest, DevicesDetachedAdjacentBits) {
401   PreAttachDevices();
402
403   DeviceIndices device_indices;
404   device_indices.push_back(0);
405   device_indices.push_back(1);
406   device_indices.push_back(2);
407   device_indices.push_back(3);
408
409   DoMassStorageDevicesDetachedTest(device_indices);
410 }
411
412 TEST_F(StorageMonitorWinTest, DuplicateAttachCheckSuppressed) {
413   // Make sure the original C: mount notification makes it all the
414   // way through.
415   RunUntilIdle();
416   volume_mount_watcher_->FlushWorkerPoolForTesting();
417   RunUntilIdle();
418
419   volume_mount_watcher_->BlockDeviceCheckForTesting();
420   base::FilePath kAttachedDevicePath =
421       VolumeMountWatcherWin::DriveNumberToFilePath(8);  // I:
422
423   DEV_BROADCAST_VOLUME volume_broadcast;
424   volume_broadcast.dbcv_size = sizeof(volume_broadcast);
425   volume_broadcast.dbcv_devicetype = DBT_DEVTYP_VOLUME;
426   volume_broadcast.dbcv_flags = 0x0;
427   volume_broadcast.dbcv_unitmask = 0x100;  // I: drive
428   monitor_->InjectDeviceChange(DBT_DEVICEARRIVAL,
429                                reinterpret_cast<DWORD>(&volume_broadcast));
430
431   EXPECT_EQ(0u, volume_mount_watcher_->devices_checked().size());
432
433   // Re-attach the same volume. We haven't released the mock device check
434   // event, so there'll be pending calls in the UI thread to finish the
435   // device check notification, blocking the duplicate device injection.
436   monitor_->InjectDeviceChange(DBT_DEVICEARRIVAL,
437                                reinterpret_cast<DWORD>(&volume_broadcast));
438
439   EXPECT_EQ(0u, volume_mount_watcher_->devices_checked().size());
440   volume_mount_watcher_->ReleaseDeviceCheck();
441   RunUntilIdle();
442   volume_mount_watcher_->ReleaseDeviceCheck();
443
444   // Now let all attach notifications finish running. We'll only get one
445   // finish-attach call.
446   volume_mount_watcher_->FlushWorkerPoolForTesting();
447   RunUntilIdle();
448
449   const std::vector<base::FilePath>& checked_devices =
450       volume_mount_watcher_->devices_checked();
451   ASSERT_EQ(1u, checked_devices.size());
452   EXPECT_EQ(kAttachedDevicePath, checked_devices[0]);
453
454   // We'll receive a duplicate check now that the first check has fully cleared.
455   monitor_->InjectDeviceChange(DBT_DEVICEARRIVAL,
456                                reinterpret_cast<DWORD>(&volume_broadcast));
457   volume_mount_watcher_->FlushWorkerPoolForTesting();
458   volume_mount_watcher_->ReleaseDeviceCheck();
459   RunUntilIdle();
460
461   ASSERT_EQ(2u, checked_devices.size());
462   EXPECT_EQ(kAttachedDevicePath, checked_devices[0]);
463   EXPECT_EQ(kAttachedDevicePath, checked_devices[1]);
464 }
465
466 TEST_F(StorageMonitorWinTest, DeviceInfoForPath) {
467   PreAttachDevices();
468
469   StorageInfo device_info;
470   // An invalid path.
471   EXPECT_FALSE(monitor_->GetStorageInfoForPath(base::FilePath(L"COM1:\\"),
472                                                &device_info));
473
474   // An unconnected removable device.
475   EXPECT_FALSE(monitor_->GetStorageInfoForPath(base::FilePath(L"E:\\"),
476                                                &device_info));
477
478   // A connected removable device.
479   base::FilePath removable_device(L"F:\\");
480   EXPECT_TRUE(monitor_->GetStorageInfoForPath(removable_device, &device_info));
481
482   StorageInfo info;
483   ASSERT_TRUE(volume_mount_watcher_->GetDeviceInfo(removable_device, &info));
484   EXPECT_TRUE(StorageInfo::IsRemovableDevice(info.device_id()));
485   EXPECT_EQ(info.device_id(), device_info.device_id());
486   EXPECT_EQ(info.name(), device_info.name());
487   EXPECT_EQ(info.location(), device_info.location());
488   EXPECT_EQ(1000000, info.total_size_in_bytes());
489
490   // A fixed device.
491   base::FilePath fixed_device(L"N:\\");
492   EXPECT_TRUE(monitor_->GetStorageInfoForPath(fixed_device, &device_info));
493
494   ASSERT_TRUE(volume_mount_watcher_->GetDeviceInfo(
495       fixed_device, &info));
496   EXPECT_FALSE(StorageInfo::IsRemovableDevice(info.device_id()));
497   EXPECT_EQ(info.device_id(), device_info.device_id());
498   EXPECT_EQ(info.name(), device_info.name());
499   EXPECT_EQ(info.location(), device_info.location());
500 }
501
502 // Test to verify basic MTP storage attach and detach notifications.
503 TEST_F(StorageMonitorWinTest, MTPDeviceBasicAttachDetach) {
504   DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, true);
505   DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, false);
506 }
507
508 // When a MTP storage device with invalid storage label and id is
509 // attached/detached, there should not be any device attach/detach
510 // notifications.
511 TEST_F(StorageMonitorWinTest, MTPDeviceWithInvalidInfo) {
512   DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithInvalidInfo,
513                   true);
514   DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithInvalidInfo,
515                   false);
516 }
517
518 // Attach a device with two data partitions. Verify that attach/detach
519 // notifications are sent out for each removable storage.
520 TEST_F(StorageMonitorWinTest, MTPDeviceWithMultipleStorageObjects) {
521   DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithMultipleStorages,
522                   true);
523   DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithMultipleStorages,
524                   false);
525 }
526
527 TEST_F(StorageMonitorWinTest, DriveNumberToFilePath) {
528   EXPECT_EQ(L"A:\\", VolumeMountWatcherWin::DriveNumberToFilePath(0).value());
529   EXPECT_EQ(L"Y:\\", VolumeMountWatcherWin::DriveNumberToFilePath(24).value());
530   EXPECT_EQ(L"", VolumeMountWatcherWin::DriveNumberToFilePath(-1).value());
531   EXPECT_EQ(L"", VolumeMountWatcherWin::DriveNumberToFilePath(199).value());
532 }
533
534 // Given a MTP storage persistent id, GetMTPStorageInfo() should fetch the
535 // device interface path and local storage object identifier.
536 TEST_F(StorageMonitorWinTest, GetMTPStorageInfoFromDeviceId) {
537   DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, true);
538   PortableDeviceWatcherWin::StorageObjects storage_objects =
539       TestPortableDeviceWatcherWin::GetDeviceStorageObjects(
540           TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo);
541   for (PortableDeviceWatcherWin::StorageObjects::const_iterator it =
542            storage_objects.begin();
543        it != storage_objects.end(); ++it) {
544     base::string16 pnp_device_id;
545     base::string16 storage_object_id;
546     ASSERT_TRUE(GetMTPStorageInfo(it->object_persistent_id, &pnp_device_id,
547                                   &storage_object_id));
548     base::string16 expected(
549         TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo);
550     EXPECT_EQ(expected, pnp_device_id);
551     EXPECT_EQ(it->object_persistent_id,
552               TestPortableDeviceWatcherWin::GetMTPStorageUniqueId(
553                   pnp_device_id, storage_object_id));
554   }
555   DoMTPDeviceTest(TestPortableDeviceWatcherWin::kMTPDeviceWithValidInfo, false);
556 }