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