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