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 // StorageMonitorLinux unit tests.
7 #include "components/storage_monitor/storage_monitor_linux.h"
14 #include "base/files/file_util.h"
15 #include "base/files/scoped_temp_dir.h"
16 #include "base/logging.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/run_loop.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "components/storage_monitor/mock_removable_storage_observer.h"
21 #include "components/storage_monitor/removable_device_constants.h"
22 #include "components/storage_monitor/storage_info.h"
23 #include "components/storage_monitor/storage_monitor.h"
24 #include "components/storage_monitor/test_media_transfer_protocol_manager_linux.h"
25 #include "components/storage_monitor/test_storage_monitor.h"
26 #include "content/public/test/test_browser_thread_bundle.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 namespace storage_monitor
{
33 const char kValidFS
[] = "vfat";
34 const char kInvalidFS
[] = "invalidfs";
36 const char kInvalidPath
[] = "invalid path does not exist";
38 const char kDeviceDCIM1
[] = "d1";
39 const char kDeviceDCIM2
[] = "d2";
40 const char kDeviceDCIM3
[] = "d3";
41 const char kDeviceNoDCIM
[] = "d4";
42 const char kDeviceFixed
[] = "d5";
44 const char kInvalidDevice
[] = "invalid_device";
46 const char kMountPointA
[] = "mnt_a";
47 const char kMountPointB
[] = "mnt_b";
48 const char kMountPointC
[] = "mnt_c";
50 struct TestDeviceData
{
51 const char* device_path
;
52 const char* unique_id
;
53 StorageInfo::Type type
;
54 uint64 partition_size_in_bytes
;
57 const TestDeviceData kTestDeviceData
[] = {
58 { kDeviceDCIM1
, "UUID:FFF0-000F",
59 StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM
, 88788 },
60 { kDeviceDCIM2
, "VendorModelSerial:ComName:Model2010:8989",
61 StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM
,
63 { kDeviceDCIM3
, "VendorModelSerial:::WEM319X792",
64 StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM
, 22837 },
65 { kDeviceNoDCIM
, "UUID:ABCD-1234",
66 StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM
, 512 },
67 { kDeviceFixed
, "UUID:743A-2349",
68 StorageInfo::FIXED_MASS_STORAGE
, 17282 },
71 scoped_ptr
<StorageInfo
> GetDeviceInfo(const base::FilePath
& device_path
,
72 const base::FilePath
& mount_point
) {
73 bool device_found
= false;
75 for (; i
< arraysize(kTestDeviceData
); i
++) {
76 if (device_path
.value() == kTestDeviceData
[i
].device_path
) {
82 scoped_ptr
<StorageInfo
> storage_info
;
85 return storage_info
.Pass();
88 StorageInfo::Type type
= kTestDeviceData
[i
].type
;
89 storage_info
.reset(new StorageInfo(
90 StorageInfo::MakeDeviceId(type
, kTestDeviceData
[i
].unique_id
),
92 base::ASCIIToUTF16("volume label"),
93 base::ASCIIToUTF16("vendor name"),
94 base::ASCIIToUTF16("model name"),
95 kTestDeviceData
[i
].partition_size_in_bytes
));
96 return storage_info
.Pass();
99 uint64
GetDevicePartitionSize(const std::string
& device
) {
100 for (size_t i
= 0; i
< arraysize(kTestDeviceData
); ++i
) {
101 if (device
== kTestDeviceData
[i
].device_path
)
102 return kTestDeviceData
[i
].partition_size_in_bytes
;
107 std::string
GetDeviceId(const std::string
& device
) {
108 for (size_t i
= 0; i
< arraysize(kTestDeviceData
); ++i
) {
109 if (device
== kTestDeviceData
[i
].device_path
) {
110 return StorageInfo::MakeDeviceId(kTestDeviceData
[i
].type
,
111 kTestDeviceData
[i
].unique_id
);
114 if (device
== kInvalidDevice
) {
115 return StorageInfo::MakeDeviceId(StorageInfo::FIXED_MASS_STORAGE
,
118 return std::string();
121 class TestStorageMonitorLinux
: public StorageMonitorLinux
{
123 explicit TestStorageMonitorLinux(const base::FilePath
& path
)
124 : StorageMonitorLinux(path
) {
125 SetMediaTransferProtocolManagerForTest(
126 new TestMediaTransferProtocolManagerLinux());
127 SetGetDeviceInfoCallbackForTest(base::Bind(&GetDeviceInfo
));
129 virtual ~TestStorageMonitorLinux() {}
132 virtual void UpdateMtab(
133 const MtabWatcherLinux::MountPointDeviceMap
& new_mtab
) OVERRIDE
{
134 StorageMonitorLinux::UpdateMtab(new_mtab
);
135 base::MessageLoopProxy::current()->PostTask(
136 FROM_HERE
, base::MessageLoop::QuitClosure());
139 DISALLOW_COPY_AND_ASSIGN(TestStorageMonitorLinux
);
142 class StorageMonitorLinuxTest
: public testing::Test
{
144 struct MtabTestData
{
145 MtabTestData(const std::string
& mount_device
,
146 const std::string
& mount_point
,
147 const std::string
& mount_type
)
148 : mount_device(mount_device
),
149 mount_point(mount_point
),
150 mount_type(mount_type
) {
153 const std::string mount_device
;
154 const std::string mount_point
;
155 const std::string mount_type
;
158 StorageMonitorLinuxTest()
159 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
) {}
160 virtual ~StorageMonitorLinuxTest() {}
163 virtual void SetUp() OVERRIDE
{
164 // Create and set up a temp dir with files for the test.
165 ASSERT_TRUE(scoped_temp_dir_
.CreateUniqueTempDir());
166 base::FilePath test_dir
= scoped_temp_dir_
.path().AppendASCII("test_etc");
167 ASSERT_TRUE(base::CreateDirectory(test_dir
));
168 mtab_file_
= test_dir
.AppendASCII("test_mtab");
169 MtabTestData initial_test_data
[] = {
170 MtabTestData("dummydevice", "dummydir", kInvalidFS
),
172 WriteToMtab(initial_test_data
,
173 arraysize(initial_test_data
),
174 true /* overwrite */);
176 monitor_
.reset(new TestStorageMonitorLinux(mtab_file_
));
178 mock_storage_observer_
.reset(new MockRemovableStorageObserver
);
179 monitor_
->AddObserver(mock_storage_observer_
.get());
182 base::RunLoop().RunUntilIdle();
185 virtual void TearDown() OVERRIDE
{
186 base::RunLoop().RunUntilIdle();
187 monitor_
->RemoveObserver(mock_storage_observer_
.get());
188 base::RunLoop().RunUntilIdle();
190 // Linux storage monitor must be destroyed on the UI thread, so do it here.
194 // Append mtab entries from the |data| array of size |data_size| to the mtab
195 // file, and run the message loop.
196 void AppendToMtabAndRunLoop(const MtabTestData
* data
, size_t data_size
) {
197 WriteToMtab(data
, data_size
, false /* do not overwrite */);
198 base::RunLoop().Run();
201 // Overwrite the mtab file with mtab entries from the |data| array of size
202 // |data_size|, and run the message loop.
203 void OverwriteMtabAndRunLoop(const MtabTestData
* data
, size_t data_size
) {
204 WriteToMtab(data
, data_size
, true /* overwrite */);
205 base::RunLoop().Run();
208 // Simplied version of OverwriteMtabAndRunLoop() that just deletes all the
209 // entries in the mtab file.
210 void WriteEmptyMtabAndRunLoop() {
211 OverwriteMtabAndRunLoop(NULL
, // No data.
212 0); // No data length.
215 // Create a directory named |dir| relative to the test directory.
216 // It has a DCIM directory, so StorageMonitorLinux recognizes it as a media
218 base::FilePath
CreateMountPointWithDCIMDir(const std::string
& dir
) {
219 return CreateMountPoint(dir
, true /* create DCIM dir */);
222 // Create a directory named |dir| relative to the test directory.
223 // It does not have a DCIM directory, so StorageMonitorLinux does not
224 // recognize it as a media directory.
225 base::FilePath
CreateMountPointWithoutDCIMDir(const std::string
& dir
) {
226 return CreateMountPoint(dir
, false /* do not create DCIM dir */);
229 void RemoveDCIMDirFromMountPoint(const std::string
& dir
) {
230 base::FilePath dcim
=
231 scoped_temp_dir_
.path().AppendASCII(dir
).Append(kDCIMDirectoryName
);
232 base::DeleteFile(dcim
, false);
235 MockRemovableStorageObserver
& observer() {
236 return *mock_storage_observer_
;
239 StorageMonitor
* notifier() {
240 return monitor_
.get();
243 uint64
GetStorageSize(const base::FilePath
& path
) {
245 if (!notifier()->GetStorageInfoForPath(path
, &info
))
248 return info
.total_size_in_bytes();
252 // Create a directory named |dir| relative to the test directory.
253 // Set |with_dcim_dir| to true if the created directory will have a "DCIM"
255 // Returns the full path to the created directory on success, or an empty
257 base::FilePath
CreateMountPoint(const std::string
& dir
, bool with_dcim_dir
) {
258 base::FilePath
return_path(scoped_temp_dir_
.path());
259 return_path
= return_path
.AppendASCII(dir
);
260 base::FilePath
path(return_path
);
262 path
= path
.Append(kDCIMDirectoryName
);
263 if (!base::CreateDirectory(path
))
264 return base::FilePath();
268 // Write the test mtab data to |mtab_file_|.
269 // |data| is an array of mtab entries.
270 // |data_size| is the array size of |data|.
271 // |overwrite| specifies whether to overwrite |mtab_file_|.
272 void WriteToMtab(const MtabTestData
* data
,
275 FILE* file
= setmntent(mtab_file_
.value().c_str(), overwrite
? "w" : "a");
278 // Due to the glibc *mntent() interface design, which is out of our
279 // control, the mtnent struct has several char* fields, even though
280 // addmntent() does not write to them in the calls below. To make the
281 // compiler happy while avoiding making additional copies of strings,
282 // we just const_cast() the strings' c_str()s.
283 // Assuming addmntent() does not write to the char* fields, this is safe.
284 // It is unlikely the platforms this test suite runs on will have an
285 // addmntent() implementation that does change the char* fields. If that
286 // was ever the case, the test suite will start crashing or failing.
288 static const char kMountOpts
[] = "rw";
289 entry
.mnt_opts
= const_cast<char*>(kMountOpts
);
291 entry
.mnt_passno
= 0;
292 for (size_t i
= 0; i
< data_size
; ++i
) {
293 entry
.mnt_fsname
= const_cast<char*>(data
[i
].mount_device
.c_str());
294 entry
.mnt_dir
= const_cast<char*>(data
[i
].mount_point
.c_str());
295 entry
.mnt_type
= const_cast<char*>(data
[i
].mount_type
.c_str());
296 ASSERT_EQ(0, addmntent(file
, &entry
));
298 ASSERT_EQ(1, endmntent(file
));
301 content::TestBrowserThreadBundle thread_bundle_
;
303 scoped_ptr
<MockRemovableStorageObserver
> mock_storage_observer_
;
305 // Temporary directory for created test data.
306 base::ScopedTempDir scoped_temp_dir_
;
307 // Path to the test mtab file.
308 base::FilePath mtab_file_
;
310 scoped_ptr
<TestStorageMonitorLinux
> monitor_
;
312 DISALLOW_COPY_AND_ASSIGN(StorageMonitorLinuxTest
);
315 // Simple test case where we attach and detach a media device.
316 TEST_F(StorageMonitorLinuxTest
, BasicAttachDetach
) {
317 base::FilePath test_path
= CreateMountPointWithDCIMDir(kMountPointA
);
318 ASSERT_FALSE(test_path
.empty());
319 MtabTestData test_data
[] = {
320 MtabTestData(kDeviceDCIM2
, test_path
.value(), kValidFS
),
321 MtabTestData(kDeviceFixed
, kInvalidPath
, kValidFS
),
323 // Only |kDeviceDCIM2| should be attached, since |kDeviceFixed| has a bad
325 AppendToMtabAndRunLoop(test_data
, arraysize(test_data
));
327 EXPECT_EQ(1, observer().attach_calls());
328 EXPECT_EQ(0, observer().detach_calls());
329 EXPECT_EQ(GetDeviceId(kDeviceDCIM2
), observer().last_attached().device_id());
330 EXPECT_EQ(test_path
.value(), observer().last_attached().location());
332 // |kDeviceDCIM2| should be detached here.
333 WriteEmptyMtabAndRunLoop();
334 EXPECT_EQ(1, observer().attach_calls());
335 EXPECT_EQ(1, observer().detach_calls());
336 EXPECT_EQ(GetDeviceId(kDeviceDCIM2
), observer().last_detached().device_id());
339 // Only removable devices are recognized.
340 TEST_F(StorageMonitorLinuxTest
, Removable
) {
341 base::FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
342 ASSERT_FALSE(test_path_a
.empty());
343 MtabTestData test_data1
[] = {
344 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
346 // |kDeviceDCIM1| should be attached as expected.
347 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
349 EXPECT_EQ(1, observer().attach_calls());
350 EXPECT_EQ(0, observer().detach_calls());
351 EXPECT_EQ(GetDeviceId(kDeviceDCIM1
), observer().last_attached().device_id());
352 EXPECT_EQ(test_path_a
.value(), observer().last_attached().location());
354 // This should do nothing, since |kDeviceFixed| is not removable.
355 base::FilePath test_path_b
= CreateMountPointWithoutDCIMDir(kMountPointB
);
356 ASSERT_FALSE(test_path_b
.empty());
357 MtabTestData test_data2
[] = {
358 MtabTestData(kDeviceFixed
, test_path_b
.value(), kValidFS
),
360 AppendToMtabAndRunLoop(test_data2
, arraysize(test_data2
));
361 EXPECT_EQ(1, observer().attach_calls());
362 EXPECT_EQ(0, observer().detach_calls());
364 // |kDeviceDCIM1| should be detached as expected.
365 WriteEmptyMtabAndRunLoop();
366 EXPECT_EQ(1, observer().attach_calls());
367 EXPECT_EQ(1, observer().detach_calls());
368 EXPECT_EQ(GetDeviceId(kDeviceDCIM1
), observer().last_detached().device_id());
370 // |kDeviceNoDCIM| should be attached as expected.
371 MtabTestData test_data3
[] = {
372 MtabTestData(kDeviceNoDCIM
, test_path_b
.value(), kValidFS
),
374 AppendToMtabAndRunLoop(test_data3
, arraysize(test_data3
));
375 EXPECT_EQ(2, observer().attach_calls());
376 EXPECT_EQ(1, observer().detach_calls());
377 EXPECT_EQ(GetDeviceId(kDeviceNoDCIM
), observer().last_attached().device_id());
378 EXPECT_EQ(test_path_b
.value(), observer().last_attached().location());
380 // |kDeviceNoDCIM| should be detached as expected.
381 WriteEmptyMtabAndRunLoop();
382 EXPECT_EQ(2, observer().attach_calls());
383 EXPECT_EQ(2, observer().detach_calls());
384 EXPECT_EQ(GetDeviceId(kDeviceNoDCIM
), observer().last_detached().device_id());
387 // More complicated test case with multiple devices on multiple mount points.
388 TEST_F(StorageMonitorLinuxTest
, SwapMountPoints
) {
389 base::FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
390 base::FilePath test_path_b
= CreateMountPointWithDCIMDir(kMountPointB
);
391 ASSERT_FALSE(test_path_a
.empty());
392 ASSERT_FALSE(test_path_b
.empty());
394 // Attach two devices.
395 // (*'d mounts are those StorageMonitor knows about.)
396 // kDeviceDCIM1 -> kMountPointA *
397 // kDeviceDCIM2 -> kMountPointB *
398 MtabTestData test_data1
[] = {
399 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
400 MtabTestData(kDeviceDCIM2
, test_path_b
.value(), kValidFS
),
402 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
403 EXPECT_EQ(2, observer().attach_calls());
404 EXPECT_EQ(0, observer().detach_calls());
406 // Detach two devices from old mount points and attach the devices at new
408 // kDeviceDCIM1 -> kMountPointB *
409 // kDeviceDCIM2 -> kMountPointA *
410 MtabTestData test_data2
[] = {
411 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
412 MtabTestData(kDeviceDCIM2
, test_path_a
.value(), kValidFS
),
414 OverwriteMtabAndRunLoop(test_data2
, arraysize(test_data2
));
415 EXPECT_EQ(4, observer().attach_calls());
416 EXPECT_EQ(2, observer().detach_calls());
418 // Detach all devices.
419 WriteEmptyMtabAndRunLoop();
420 EXPECT_EQ(4, observer().attach_calls());
421 EXPECT_EQ(4, observer().detach_calls());
424 // More complicated test case with multiple devices on multiple mount points.
425 TEST_F(StorageMonitorLinuxTest
, MultiDevicesMultiMountPoints
) {
426 base::FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
427 base::FilePath test_path_b
= CreateMountPointWithDCIMDir(kMountPointB
);
428 ASSERT_FALSE(test_path_a
.empty());
429 ASSERT_FALSE(test_path_b
.empty());
431 // Attach two devices.
432 // (*'d mounts are those StorageMonitor knows about.)
433 // kDeviceDCIM1 -> kMountPointA *
434 // kDeviceDCIM2 -> kMountPointB *
435 MtabTestData test_data1
[] = {
436 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
437 MtabTestData(kDeviceDCIM2
, test_path_b
.value(), kValidFS
),
439 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
440 EXPECT_EQ(2, observer().attach_calls());
441 EXPECT_EQ(0, observer().detach_calls());
443 // Attach |kDeviceDCIM1| to |kMountPointB|.
444 // |kDeviceDCIM2| is inaccessible, so it is detached. |kDeviceDCIM1| has been
445 // attached at |kMountPointB|, but is still accessible from |kMountPointA|.
446 // kDeviceDCIM1 -> kMountPointA *
447 // kDeviceDCIM2 -> kMountPointB
448 // kDeviceDCIM1 -> kMountPointB
449 MtabTestData test_data2
[] = {
450 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
452 AppendToMtabAndRunLoop(test_data2
, arraysize(test_data2
));
453 EXPECT_EQ(2, observer().attach_calls());
454 EXPECT_EQ(1, observer().detach_calls());
456 // Detach |kDeviceDCIM1| from |kMountPointA|, causing a detach and attach
458 // kDeviceDCIM2 -> kMountPointB
459 // kDeviceDCIM1 -> kMountPointB *
460 MtabTestData test_data3
[] = {
461 MtabTestData(kDeviceDCIM2
, test_path_b
.value(), kValidFS
),
462 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
464 OverwriteMtabAndRunLoop(test_data3
, arraysize(test_data3
));
465 EXPECT_EQ(3, observer().attach_calls());
466 EXPECT_EQ(2, observer().detach_calls());
468 // Attach |kDeviceDCIM1| to |kMountPointA|.
469 // kDeviceDCIM2 -> kMountPointB
470 // kDeviceDCIM1 -> kMountPointB *
471 // kDeviceDCIM1 -> kMountPointA
472 MtabTestData test_data4
[] = {
473 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
475 AppendToMtabAndRunLoop(test_data4
, arraysize(test_data4
));
476 EXPECT_EQ(3, observer().attach_calls());
477 EXPECT_EQ(2, observer().detach_calls());
479 // Detach |kDeviceDCIM1| from |kMountPointB|.
480 // kDeviceDCIM1 -> kMountPointA *
481 // kDeviceDCIM2 -> kMountPointB *
482 OverwriteMtabAndRunLoop(test_data1
, arraysize(test_data1
));
483 EXPECT_EQ(5, observer().attach_calls());
484 EXPECT_EQ(3, observer().detach_calls());
486 // Detach all devices.
487 WriteEmptyMtabAndRunLoop();
488 EXPECT_EQ(5, observer().attach_calls());
489 EXPECT_EQ(5, observer().detach_calls());
492 TEST_F(StorageMonitorLinuxTest
, MultipleMountPointsWithNonDCIMDevices
) {
493 base::FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
494 base::FilePath test_path_b
= CreateMountPointWithDCIMDir(kMountPointB
);
495 ASSERT_FALSE(test_path_a
.empty());
496 ASSERT_FALSE(test_path_b
.empty());
498 // Attach to one first.
499 // (*'d mounts are those StorageMonitor knows about.)
500 // kDeviceDCIM1 -> kMountPointA *
501 MtabTestData test_data1
[] = {
502 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
504 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
505 EXPECT_EQ(1, observer().attach_calls());
506 EXPECT_EQ(0, observer().detach_calls());
508 // Attach |kDeviceDCIM1| to |kMountPointB|.
509 // kDeviceDCIM1 -> kMountPointA *
510 // kDeviceDCIM1 -> kMountPointB
511 MtabTestData test_data2
[] = {
512 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
514 AppendToMtabAndRunLoop(test_data2
, arraysize(test_data2
));
515 EXPECT_EQ(1, observer().attach_calls());
516 EXPECT_EQ(0, observer().detach_calls());
518 // Attach |kDeviceFixed| (a non-removable device) to |kMountPointA|.
519 // kDeviceDCIM1 -> kMountPointA
520 // kDeviceDCIM1 -> kMountPointB *
521 // kDeviceFixed -> kMountPointA
522 MtabTestData test_data3
[] = {
523 MtabTestData(kDeviceFixed
, test_path_a
.value(), kValidFS
),
525 RemoveDCIMDirFromMountPoint(kMountPointA
);
526 AppendToMtabAndRunLoop(test_data3
, arraysize(test_data3
));
527 EXPECT_EQ(2, observer().attach_calls());
528 EXPECT_EQ(1, observer().detach_calls());
530 // Detach |kDeviceFixed|.
531 // kDeviceDCIM1 -> kMountPointA
532 // kDeviceDCIM1 -> kMountPointB *
533 MtabTestData test_data4
[] = {
534 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
535 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
537 CreateMountPointWithDCIMDir(kMountPointA
);
538 OverwriteMtabAndRunLoop(test_data4
, arraysize(test_data4
));
539 EXPECT_EQ(2, observer().attach_calls());
540 EXPECT_EQ(1, observer().detach_calls());
542 // Attach |kDeviceNoDCIM| (a non-DCIM device) to |kMountPointB|.
543 // kDeviceDCIM1 -> kMountPointA *
544 // kDeviceDCIM1 -> kMountPointB
545 // kDeviceNoDCIM -> kMountPointB *
546 MtabTestData test_data5
[] = {
547 MtabTestData(kDeviceNoDCIM
, test_path_b
.value(), kValidFS
),
549 base::DeleteFile(test_path_b
.Append(kDCIMDirectoryName
), false);
550 AppendToMtabAndRunLoop(test_data5
, arraysize(test_data5
));
551 EXPECT_EQ(4, observer().attach_calls());
552 EXPECT_EQ(2, observer().detach_calls());
554 // Detach |kDeviceNoDCIM|.
555 // kDeviceDCIM1 -> kMountPointA *
556 // kDeviceDCIM1 -> kMountPointB
557 MtabTestData test_data6
[] = {
558 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
559 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
561 CreateMountPointWithDCIMDir(kMountPointB
);
562 OverwriteMtabAndRunLoop(test_data6
, arraysize(test_data6
));
563 EXPECT_EQ(4, observer().attach_calls());
564 EXPECT_EQ(3, observer().detach_calls());
566 // Detach |kDeviceDCIM1| from |kMountPointB|.
567 // kDeviceDCIM1 -> kMountPointA *
568 OverwriteMtabAndRunLoop(test_data1
, arraysize(test_data1
));
569 EXPECT_EQ(4, observer().attach_calls());
570 EXPECT_EQ(3, observer().detach_calls());
572 // Detach all devices.
573 WriteEmptyMtabAndRunLoop();
574 EXPECT_EQ(4, observer().attach_calls());
575 EXPECT_EQ(4, observer().detach_calls());
578 TEST_F(StorageMonitorLinuxTest
, DeviceLookUp
) {
579 base::FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
580 base::FilePath test_path_b
= CreateMountPointWithoutDCIMDir(kMountPointB
);
581 base::FilePath test_path_c
= CreateMountPointWithoutDCIMDir(kMountPointC
);
582 ASSERT_FALSE(test_path_a
.empty());
583 ASSERT_FALSE(test_path_b
.empty());
584 ASSERT_FALSE(test_path_c
.empty());
586 // Attach to one first.
587 // (starred mounts are those StorageMonitor knows about.)
588 // kDeviceDCIM1 -> kMountPointA *
589 // kDeviceNoDCIM -> kMountPointB *
590 // kDeviceFixed -> kMountPointC
591 MtabTestData test_data1
[] = {
592 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
593 MtabTestData(kDeviceNoDCIM
, test_path_b
.value(), kValidFS
),
594 MtabTestData(kDeviceFixed
, test_path_c
.value(), kValidFS
),
596 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
597 EXPECT_EQ(2, observer().attach_calls());
598 EXPECT_EQ(0, observer().detach_calls());
600 StorageInfo device_info
;
601 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_a
, &device_info
));
602 EXPECT_EQ(GetDeviceId(kDeviceDCIM1
), device_info
.device_id());
603 EXPECT_EQ(test_path_a
.value(), device_info
.location());
604 EXPECT_EQ(88788ULL, device_info
.total_size_in_bytes());
605 EXPECT_EQ(base::ASCIIToUTF16("volume label"), device_info
.storage_label());
606 EXPECT_EQ(base::ASCIIToUTF16("vendor name"), device_info
.vendor_name());
607 EXPECT_EQ(base::ASCIIToUTF16("model name"), device_info
.model_name());
609 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_b
, &device_info
));
610 EXPECT_EQ(GetDeviceId(kDeviceNoDCIM
), device_info
.device_id());
611 EXPECT_EQ(test_path_b
.value(), device_info
.location());
613 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_c
, &device_info
));
614 EXPECT_EQ(GetDeviceId(kDeviceFixed
), device_info
.device_id());
615 EXPECT_EQ(test_path_c
.value(), device_info
.location());
618 EXPECT_FALSE(notifier()->GetStorageInfoForPath(base::FilePath(kInvalidPath
),
621 // Test filling in of the mount point.
623 notifier()->GetStorageInfoForPath(test_path_a
.Append("some/other/path"),
625 EXPECT_EQ(GetDeviceId(kDeviceDCIM1
), device_info
.device_id());
626 EXPECT_EQ(test_path_a
.value(), device_info
.location());
628 // One device attached at multiple points.
629 // kDeviceDCIM1 -> kMountPointA *
630 // kDeviceFixed -> kMountPointB
631 // kDeviceFixed -> kMountPointC
632 MtabTestData test_data2
[] = {
633 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
634 MtabTestData(kDeviceFixed
, test_path_b
.value(), kValidFS
),
635 MtabTestData(kDeviceFixed
, test_path_c
.value(), kValidFS
),
637 AppendToMtabAndRunLoop(test_data2
, arraysize(test_data2
));
639 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_a
, &device_info
));
640 EXPECT_EQ(GetDeviceId(kDeviceDCIM1
), device_info
.device_id());
642 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_b
, &device_info
));
643 EXPECT_EQ(GetDeviceId(kDeviceFixed
), device_info
.device_id());
645 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_c
, &device_info
));
646 EXPECT_EQ(GetDeviceId(kDeviceFixed
), device_info
.device_id());
648 EXPECT_EQ(2, observer().attach_calls());
649 EXPECT_EQ(1, observer().detach_calls());
652 TEST_F(StorageMonitorLinuxTest
, DevicePartitionSize
) {
653 base::FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
654 base::FilePath test_path_b
= CreateMountPointWithoutDCIMDir(kMountPointB
);
655 ASSERT_FALSE(test_path_a
.empty());
656 ASSERT_FALSE(test_path_b
.empty());
658 MtabTestData test_data1
[] = {
659 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
660 MtabTestData(kDeviceNoDCIM
, test_path_b
.value(), kValidFS
),
661 MtabTestData(kDeviceFixed
, kInvalidPath
, kInvalidFS
),
663 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
664 EXPECT_EQ(2, observer().attach_calls());
665 EXPECT_EQ(0, observer().detach_calls());
667 EXPECT_EQ(GetDevicePartitionSize(kDeviceDCIM1
),
668 GetStorageSize(test_path_a
));
669 EXPECT_EQ(GetDevicePartitionSize(kDeviceNoDCIM
),
670 GetStorageSize(test_path_b
));
671 EXPECT_EQ(GetDevicePartitionSize(kInvalidPath
),
672 GetStorageSize(base::FilePath(kInvalidPath
)));
677 } // namespace storage_monitor