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.
5 // RemovableDeviceNotificationsLinux unit tests.
7 #include "chrome/browser/system_monitor/removable_device_notifications_linux.h"
14 #include "base/file_util.h"
15 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/message_loop.h"
18 #include "base/scoped_temp_dir.h"
19 #include "base/system_monitor/system_monitor.h"
20 #include "base/test/mock_devices_changed_observer.h"
21 #include "base/utf_string_conversions.h"
22 #include "chrome/browser/system_monitor/media_device_notifications_utils.h"
23 #include "chrome/browser/system_monitor/media_storage_util.h"
24 #include "chrome/browser/system_monitor/removable_device_constants.h"
25 #include "content/public/test/test_browser_thread.h"
26 #include "testing/gtest/include/gtest/gtest.h"
34 const char kValidFS
[] = "vfat";
35 const char kInvalidFS
[] = "invalidfs";
37 const char kInvalidPath
[] = "invalid path does not exist";
39 const char kDeviceDCIM1
[] = "d1";
40 const char kDeviceDCIM2
[] = "d2";
41 const char kDeviceDCIM3
[] = "d3";
42 const char kDeviceNoDCIM
[] = "d4";
43 const char kDeviceFixed
[] = "d5";
45 const char kInvalidDevice
[] = "invalid_device";
47 const char kMountPointA
[] = "mnt_a";
48 const char kMountPointB
[] = "mnt_b";
49 const char kMountPointC
[] = "mnt_c";
51 struct TestDeviceData
{
52 const char* device_path
;
53 const char* unique_id
;
54 const char* device_name
;
55 MediaStorageUtil::Type type
;
56 uint64 partition_size_in_bytes
;
59 const TestDeviceData kTestDeviceData
[] = {
60 { kDeviceDCIM1
, "UUID:FFF0-000F", "TEST_USB_MODEL_1",
61 MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM
, 88788 },
62 { kDeviceDCIM2
, "VendorModelSerial:ComName:Model2010:8989",
63 "TEST_USB_MODEL_2", MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM
,
65 { kDeviceDCIM3
, "VendorModelSerial:::WEM319X792", "TEST_USB_MODEL_3",
66 MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM
, 22837 },
67 { kDeviceNoDCIM
, "UUID:ABCD-1234", "TEST_USB_MODEL_4",
68 MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM
, 512 },
69 { kDeviceFixed
, "UUID:743A-2349", "743A-2349",
70 MediaStorageUtil::FIXED_MASS_STORAGE
, 17282 },
73 void GetDeviceInfo(const FilePath
& device_path
,
77 uint64
* partition_size_in_bytes
) {
78 for (size_t i
= 0; i
< arraysize(kTestDeviceData
); i
++) {
79 if (device_path
.value() == kTestDeviceData
[i
].device_path
) {
81 *id
= kTestDeviceData
[i
].unique_id
;
83 *name
= ASCIIToUTF16(kTestDeviceData
[i
].device_name
);
85 MediaStorageUtil::Type type
= kTestDeviceData
[i
].type
;
87 (type
== MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM
) ||
88 (type
== MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM
);
90 if (partition_size_in_bytes
)
91 *partition_size_in_bytes
= kTestDeviceData
[i
].partition_size_in_bytes
;
98 uint64
GetDevicePartitionSize(const std::string
& device
) {
99 for (size_t i
= 0; i
< arraysize(kTestDeviceData
); ++i
) {
100 if (device
== kTestDeviceData
[i
].device_path
)
101 return kTestDeviceData
[i
].partition_size_in_bytes
;
106 std::string
GetDeviceId(const std::string
& device
) {
107 for (size_t i
= 0; i
< arraysize(kTestDeviceData
); ++i
) {
108 if (device
== kTestDeviceData
[i
].device_path
) {
109 return MediaStorageUtil::MakeDeviceId(kTestDeviceData
[i
].type
,
110 kTestDeviceData
[i
].unique_id
);
113 if (device
== kInvalidDevice
) {
114 return MediaStorageUtil::MakeDeviceId(MediaStorageUtil::FIXED_MASS_STORAGE
,
117 return std::string();
120 string16
GetDeviceNameWithSizeDetails(const std::string
& device
) {
121 for (size_t i
= 0; i
< arraysize(kTestDeviceData
); ++i
) {
122 if (device
== kTestDeviceData
[i
].device_path
) {
123 return GetDisplayNameForDevice(
124 kTestDeviceData
[i
].partition_size_in_bytes
,
125 ASCIIToUTF16(kTestDeviceData
[i
].device_name
));
131 string16
GetDeviceName(const std::string
& device
) {
132 for (size_t i
= 0; i
< arraysize(kTestDeviceData
); i
++) {
133 if (device
== kTestDeviceData
[i
].device_path
)
134 return ASCIIToUTF16(kTestDeviceData
[i
].device_name
);
139 class RemovableDeviceNotificationsLinuxTestWrapper
140 : public RemovableDeviceNotificationsLinux
{
142 RemovableDeviceNotificationsLinuxTestWrapper(const FilePath
& path
,
143 MessageLoop
* message_loop
)
144 : RemovableDeviceNotificationsLinux(path
, &GetDeviceInfo
),
145 message_loop_(message_loop
) {
149 // Avoids code deleting the object while there are references to it.
150 // Aside from the base::RefCountedThreadSafe friend class, any attempts to
151 // call this dtor will result in a compile-time error.
152 ~RemovableDeviceNotificationsLinuxTestWrapper() {}
154 virtual void OnFilePathChanged(const FilePath
& path
, bool error
) OVERRIDE
{
155 RemovableDeviceNotificationsLinux::OnFilePathChanged(path
, error
);
156 message_loop_
->PostTask(FROM_HERE
, MessageLoop::QuitClosure());
159 MessageLoop
* message_loop_
;
161 DISALLOW_COPY_AND_ASSIGN(RemovableDeviceNotificationsLinuxTestWrapper
);
164 class RemovableDeviceNotificationLinuxTest
: public testing::Test
{
166 struct MtabTestData
{
167 MtabTestData(const std::string
& mount_device
,
168 const std::string
& mount_point
,
169 const std::string
& mount_type
)
170 : mount_device(mount_device
),
171 mount_point(mount_point
),
172 mount_type(mount_type
) {
175 const std::string mount_device
;
176 const std::string mount_point
;
177 const std::string mount_type
;
180 RemovableDeviceNotificationLinuxTest()
181 : message_loop_(MessageLoop::TYPE_IO
),
182 file_thread_(content::BrowserThread::FILE, &message_loop_
) {
184 virtual ~RemovableDeviceNotificationLinuxTest() {}
187 virtual void SetUp() OVERRIDE
{
188 mock_devices_changed_observer_
.reset(new base::MockDevicesChangedObserver
);
189 system_monitor_
.AddDevicesChangedObserver(
190 mock_devices_changed_observer_
.get());
192 // Create and set up a temp dir with files for the test.
193 ASSERT_TRUE(scoped_temp_dir_
.CreateUniqueTempDir());
194 FilePath test_dir
= scoped_temp_dir_
.path().AppendASCII("test_etc");
195 ASSERT_TRUE(file_util::CreateDirectory(test_dir
));
196 mtab_file_
= test_dir
.AppendASCII("test_mtab");
197 MtabTestData initial_test_data
[] = {
198 MtabTestData("dummydevice", "dummydir", kInvalidFS
),
200 WriteToMtab(initial_test_data
,
201 arraysize(initial_test_data
),
202 true /* overwrite */);
204 // Initialize the test subject.
205 notifications_
= new RemovableDeviceNotificationsLinuxTestWrapper(
206 mtab_file_
, &message_loop_
);
207 notifications_
->Init();
208 message_loop_
.RunAllPending();
211 virtual void TearDown() OVERRIDE
{
212 message_loop_
.RunAllPending();
213 notifications_
= NULL
;
214 system_monitor_
.RemoveDevicesChangedObserver(
215 mock_devices_changed_observer_
.get());
218 // Append mtab entries from the |data| array of size |data_size| to the mtab
219 // file, and run the message loop.
220 void AppendToMtabAndRunLoop(const MtabTestData
* data
, size_t data_size
) {
221 WriteToMtab(data
, data_size
, false /* do not overwrite */);
225 // Overwrite the mtab file with mtab entries from the |data| array of size
226 // |data_size|, and run the message loop.
227 void OverwriteMtabAndRunLoop(const MtabTestData
* data
, size_t data_size
) {
228 WriteToMtab(data
, data_size
, true /* overwrite */);
232 // Simplied version of OverwriteMtabAndRunLoop() that just deletes all the
233 // entries in the mtab file.
234 void WriteEmptyMtabAndRunLoop() {
235 OverwriteMtabAndRunLoop(NULL
, // No data.
236 0); // No data length.
239 // Create a directory named |dir| relative to the test directory.
240 // It has a DCIM directory, so RemovableDeviceNotificationsLinux recognizes it
241 // as a media directory.
242 FilePath
CreateMountPointWithDCIMDir(const std::string
& dir
) {
243 return CreateMountPoint(dir
, true /* create DCIM dir */);
246 // Create a directory named |dir| relative to the test directory.
247 // It does not have a DCIM directory, so RemovableDeviceNotificationsLinux
248 // does not recognizes it as a media directory.
249 FilePath
CreateMountPointWithoutDCIMDir(const std::string
& dir
) {
250 return CreateMountPoint(dir
, false /* do not create DCIM dir */);
253 void RemoveDCIMDirFromMountPoint(const std::string
& dir
) {
255 scoped_temp_dir_
.path().AppendASCII(dir
).Append(kDCIMDirectoryName
);
256 file_util::Delete(dcim
, false);
259 base::MockDevicesChangedObserver
& observer() {
260 return *mock_devices_changed_observer_
;
263 RemovableDeviceNotificationsLinux
* notifier() {
264 return notifications_
.get();
268 // Create a directory named |dir| relative to the test directory.
269 // Set |with_dcim_dir| to true if the created directory will have a "DCIM"
271 // Returns the full path to the created directory on success, or an empty
273 FilePath
CreateMountPoint(const std::string
& dir
, bool with_dcim_dir
) {
274 FilePath
return_path(scoped_temp_dir_
.path());
275 return_path
= return_path
.AppendASCII(dir
);
276 FilePath
path(return_path
);
278 path
= path
.Append(kDCIMDirectoryName
);
279 if (!file_util::CreateDirectory(path
))
284 // Write the test mtab data to |mtab_file_|.
285 // |data| is an array of mtab entries.
286 // |data_size| is the array size of |data|.
287 // |overwrite| specifies whether to overwrite |mtab_file_|.
288 void WriteToMtab(const MtabTestData
* data
,
291 FILE* file
= setmntent(mtab_file_
.value().c_str(), overwrite
? "w" : "a");
294 // Due to the glibc *mntent() interface design, which is out of our
295 // control, the mtnent struct has several char* fields, even though
296 // addmntent() does not write to them in the calls below. To make the
297 // compiler happy while avoiding making additional copies of strings,
298 // we just const_cast() the strings' c_str()s.
299 // Assuming addmntent() does not write to the char* fields, this is safe.
300 // It is unlikely the platforms this test suite runs on will have an
301 // addmntent() implementation that does change the char* fields. If that
302 // was ever the case, the test suite will start crashing or failing.
304 static const char kMountOpts
[] = "rw";
305 entry
.mnt_opts
= const_cast<char*>(kMountOpts
);
307 entry
.mnt_passno
= 0;
308 for (size_t i
= 0; i
< data_size
; ++i
) {
309 entry
.mnt_fsname
= const_cast<char*>(data
[i
].mount_device
.c_str());
310 entry
.mnt_dir
= const_cast<char*>(data
[i
].mount_point
.c_str());
311 entry
.mnt_type
= const_cast<char*>(data
[i
].mount_type
.c_str());
312 ASSERT_EQ(0, addmntent(file
, &entry
));
314 ASSERT_EQ(1, endmntent(file
));
317 // The message loop and file thread to run tests on.
318 MessageLoop message_loop_
;
319 content::TestBrowserThread file_thread_
;
321 // SystemMonitor and DevicesChangedObserver to hook together to test.
322 base::SystemMonitor system_monitor_
;
323 scoped_ptr
<base::MockDevicesChangedObserver
> mock_devices_changed_observer_
;
325 // Temporary directory for created test data.
326 ScopedTempDir scoped_temp_dir_
;
327 // Path to the test mtab file.
330 scoped_refptr
<RemovableDeviceNotificationsLinuxTestWrapper
> notifications_
;
332 DISALLOW_COPY_AND_ASSIGN(RemovableDeviceNotificationLinuxTest
);
335 // Simple test case where we attach and detach a media device.
336 TEST_F(RemovableDeviceNotificationLinuxTest
, BasicAttachDetach
) {
337 testing::Sequence mock_sequence
;
338 FilePath test_path
= CreateMountPointWithDCIMDir(kMountPointA
);
339 ASSERT_FALSE(test_path
.empty());
340 MtabTestData test_data
[] = {
341 MtabTestData(kDeviceDCIM2
, test_path
.value(), kValidFS
),
342 MtabTestData(kDeviceFixed
, kInvalidPath
, kValidFS
),
344 // Only |kDeviceDCIM2| should be attached, since |kDeviceFixed| has a bad
346 EXPECT_CALL(observer(),
347 OnRemovableStorageAttached(
348 GetDeviceId(kDeviceDCIM2
),
349 GetDeviceNameWithSizeDetails(kDeviceDCIM2
),
351 .InSequence(mock_sequence
);
352 AppendToMtabAndRunLoop(test_data
, arraysize(test_data
));
354 // |kDeviceDCIM2| should be detached here.
355 EXPECT_CALL(observer(), OnRemovableStorageDetached(GetDeviceId(kDeviceDCIM2
)))
356 .InSequence(mock_sequence
);
357 WriteEmptyMtabAndRunLoop();
360 // Only removable devices are recognized.
361 TEST_F(RemovableDeviceNotificationLinuxTest
, Removable
) {
362 testing::Sequence mock_sequence
;
363 FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
364 ASSERT_FALSE(test_path_a
.empty());
365 MtabTestData test_data1
[] = {
366 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
368 // |kDeviceDCIM1| should be attached as expected.
369 EXPECT_CALL(observer(),
370 OnRemovableStorageAttached(
371 GetDeviceId(kDeviceDCIM1
),
372 GetDeviceNameWithSizeDetails(kDeviceDCIM1
),
373 test_path_a
.value()))
374 .InSequence(mock_sequence
);
375 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
377 // This should do nothing, since |kDeviceFixed| is not removable.
378 FilePath test_path_b
= CreateMountPointWithoutDCIMDir(kMountPointB
);
379 ASSERT_FALSE(test_path_b
.empty());
380 MtabTestData test_data2
[] = {
381 MtabTestData(kDeviceFixed
, test_path_b
.value(), kValidFS
),
383 AppendToMtabAndRunLoop(test_data2
, arraysize(test_data2
));
385 // |kDeviceDCIM1| should be detached as expected.
386 EXPECT_CALL(observer(), OnRemovableStorageDetached(GetDeviceId(kDeviceDCIM1
)))
387 .InSequence(mock_sequence
);
388 WriteEmptyMtabAndRunLoop();
390 // |kDeviceNoDCIM| should be attached as expected.
391 EXPECT_CALL(observer(),
392 OnRemovableStorageAttached(
393 GetDeviceId(kDeviceNoDCIM
),
394 GetDeviceNameWithSizeDetails(kDeviceNoDCIM
),
395 test_path_b
.value()))
396 .InSequence(mock_sequence
);
397 MtabTestData test_data3
[] = {
398 MtabTestData(kDeviceNoDCIM
, test_path_b
.value(), kValidFS
),
400 AppendToMtabAndRunLoop(test_data3
, arraysize(test_data3
));
402 // |kDeviceNoDCIM| should be detached as expected.
403 EXPECT_CALL(observer(),
404 OnRemovableStorageDetached(GetDeviceId(kDeviceNoDCIM
)))
405 .InSequence(mock_sequence
);
406 WriteEmptyMtabAndRunLoop();
409 // More complicated test case with multiple devices on multiple mount points.
410 TEST_F(RemovableDeviceNotificationLinuxTest
, SwapMountPoints
) {
411 FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
412 FilePath test_path_b
= CreateMountPointWithDCIMDir(kMountPointB
);
413 ASSERT_FALSE(test_path_a
.empty());
414 ASSERT_FALSE(test_path_b
.empty());
416 // Attach two devices. (*'d mounts are those SystemMonitor knows about.)
417 // kDeviceDCIM1 -> kMountPointA *
418 // kDeviceDCIM2 -> kMountPointB *
419 MtabTestData test_data1
[] = {
420 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
421 MtabTestData(kDeviceDCIM2
, test_path_b
.value(), kValidFS
),
423 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(2);
424 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(0);
425 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
427 // Detach two devices from old mount points and attach the devices at new
429 // kDeviceDCIM1 -> kMountPointB *
430 // kDeviceDCIM2 -> kMountPointA *
431 MtabTestData test_data2
[] = {
432 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
433 MtabTestData(kDeviceDCIM2
, test_path_a
.value(), kValidFS
),
435 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(2);
436 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(2);
437 OverwriteMtabAndRunLoop(test_data2
, arraysize(test_data2
));
439 // Detach all devices.
440 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
441 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(2);
442 WriteEmptyMtabAndRunLoop();
445 // More complicated test case with multiple devices on multiple mount points.
446 TEST_F(RemovableDeviceNotificationLinuxTest
, MultiDevicesMultiMountPoints
) {
447 FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
448 FilePath test_path_b
= CreateMountPointWithDCIMDir(kMountPointB
);
449 ASSERT_FALSE(test_path_a
.empty());
450 ASSERT_FALSE(test_path_b
.empty());
452 // Attach two devices. (*'d mounts are those SystemMonitor knows about.)
453 // kDeviceDCIM1 -> kMountPointA *
454 // kDeviceDCIM2 -> kMountPointB *
455 MtabTestData test_data1
[] = {
456 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
457 MtabTestData(kDeviceDCIM2
, test_path_b
.value(), kValidFS
),
459 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(2);
460 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(0);
461 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
463 // Attach |kDeviceDCIM1| to |kMountPointB|.
464 // |kDeviceDCIM2| is inaccessible, so it is detached. |kDeviceDCIM1| has been
465 // attached at |kMountPointB|, but is still accessible from |kMountPointA|.
466 // kDeviceDCIM1 -> kMountPointA *
467 // kDeviceDCIM2 -> kMountPointB
468 // kDeviceDCIM1 -> kMountPointB
469 MtabTestData test_data2
[] = {
470 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
472 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
473 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(1);
474 AppendToMtabAndRunLoop(test_data2
, arraysize(test_data2
));
476 // Detach |kDeviceDCIM1| from |kMountPointA|, causing a detach and attach
478 // kDeviceDCIM2 -> kMountPointB
479 // kDeviceDCIM1 -> kMountPointB *
480 MtabTestData test_data3
[] = {
481 MtabTestData(kDeviceDCIM2
, test_path_b
.value(), kValidFS
),
482 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
484 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(1);
485 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(1);
486 OverwriteMtabAndRunLoop(test_data3
, arraysize(test_data3
));
488 // Attach |kDeviceDCIM1| to |kMountPointA|.
489 // kDeviceDCIM2 -> kMountPointB
490 // kDeviceDCIM1 -> kMountPointB *
491 // kDeviceDCIM1 -> kMountPointA
492 MtabTestData test_data4
[] = {
493 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
495 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
496 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(0);
497 AppendToMtabAndRunLoop(test_data4
, arraysize(test_data4
));
499 // Detach |kDeviceDCIM1| from |kMountPointB|.
500 // kDeviceDCIM1 -> kMountPointA *
501 // kDeviceDCIM2 -> kMountPointB *
502 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(2);
503 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(1);
504 OverwriteMtabAndRunLoop(test_data1
, arraysize(test_data1
));
506 // Detach all devices.
507 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
508 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(2);
509 WriteEmptyMtabAndRunLoop();
512 TEST_F(RemovableDeviceNotificationLinuxTest
,
513 MultipleMountPointsWithNonDCIMDevices
) {
514 FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
515 FilePath test_path_b
= CreateMountPointWithDCIMDir(kMountPointB
);
516 ASSERT_FALSE(test_path_a
.empty());
517 ASSERT_FALSE(test_path_b
.empty());
519 // Attach to one first. (*'d mounts are those SystemMonitor knows about.)
520 // kDeviceDCIM1 -> kMountPointA *
521 MtabTestData test_data1
[] = {
522 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
524 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(1);
525 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(0);
526 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
528 // Attach |kDeviceDCIM1| to |kMountPointB|.
529 // kDeviceDCIM1 -> kMountPointA *
530 // kDeviceDCIM1 -> kMountPointB
531 MtabTestData test_data2
[] = {
532 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
534 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
535 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(0);
536 AppendToMtabAndRunLoop(test_data2
, arraysize(test_data2
));
538 // Attach |kDeviceFixed| (a non-removable device) to |kMountPointA|.
539 // kDeviceDCIM1 -> kMountPointA
540 // kDeviceDCIM1 -> kMountPointB *
541 // kDeviceFixed -> kMountPointA
542 MtabTestData test_data3
[] = {
543 MtabTestData(kDeviceFixed
, test_path_a
.value(), kValidFS
),
545 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(1);
546 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(1);
547 RemoveDCIMDirFromMountPoint(kMountPointA
);
548 AppendToMtabAndRunLoop(test_data3
, arraysize(test_data3
));
550 // Detach |kDeviceFixed|.
551 // kDeviceDCIM1 -> kMountPointA
552 // kDeviceDCIM1 -> kMountPointB *
553 MtabTestData test_data4
[] = {
554 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
555 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
557 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
558 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(0);
559 CreateMountPointWithDCIMDir(kMountPointA
);
560 OverwriteMtabAndRunLoop(test_data4
, arraysize(test_data4
));
562 // Attach |kDeviceNoDCIM| (a non-DCIM device) to |kMountPointB|.
563 // kDeviceDCIM1 -> kMountPointA *
564 // kDeviceDCIM1 -> kMountPointB
565 // kDeviceNoDCIM -> kMountPointB *
566 MtabTestData test_data5
[] = {
567 MtabTestData(kDeviceNoDCIM
, test_path_b
.value(), kValidFS
),
569 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(2);
570 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(1);
571 file_util::Delete(test_path_b
.Append(kDCIMDirectoryName
), false);
572 AppendToMtabAndRunLoop(test_data5
, arraysize(test_data5
));
574 // Detach |kDeviceNoDCIM|.
575 // kDeviceDCIM1 -> kMountPointA *
576 // kDeviceDCIM1 -> kMountPointB
577 MtabTestData test_data6
[] = {
578 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
579 MtabTestData(kDeviceDCIM1
, test_path_b
.value(), kValidFS
),
581 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
582 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(1);
583 CreateMountPointWithDCIMDir(kMountPointB
);
584 OverwriteMtabAndRunLoop(test_data6
, arraysize(test_data6
));
586 // Detach |kDeviceDCIM1| from |kMountPointB|.
587 // kDeviceDCIM1 -> kMountPointA *
588 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
589 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(0);
590 OverwriteMtabAndRunLoop(test_data1
, arraysize(test_data1
));
592 // Detach all devices.
593 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
594 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(1);
595 WriteEmptyMtabAndRunLoop();
598 TEST_F(RemovableDeviceNotificationLinuxTest
, DeviceLookUp
) {
599 FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
600 FilePath test_path_b
= CreateMountPointWithoutDCIMDir(kMountPointB
);
601 FilePath test_path_c
= CreateMountPointWithoutDCIMDir(kMountPointC
);
602 ASSERT_FALSE(test_path_a
.empty());
603 ASSERT_FALSE(test_path_b
.empty());
604 ASSERT_FALSE(test_path_c
.empty());
606 // Attach to one first. (*'d mounts are those SystemMonitor knows about.)
607 // kDeviceDCIM1 -> kMountPointA *
608 // kDeviceNoDCIM -> kMountPointB *
609 // kDeviceFixed -> kMountPointC
610 MtabTestData test_data1
[] = {
611 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
612 MtabTestData(kDeviceNoDCIM
, test_path_b
.value(), kValidFS
),
613 MtabTestData(kDeviceFixed
, test_path_c
.value(), kValidFS
),
615 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(2);
616 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(0);
617 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
619 base::SystemMonitor::RemovableStorageInfo device_info
;
620 EXPECT_TRUE(notifier()->GetDeviceInfoForPath(test_path_a
, &device_info
));
621 EXPECT_EQ(GetDeviceId(kDeviceDCIM1
), device_info
.device_id
);
622 EXPECT_EQ(test_path_a
.value(), device_info
.location
);
623 EXPECT_EQ(GetDeviceName(kDeviceDCIM1
), device_info
.name
);
625 EXPECT_TRUE(notifier()->GetDeviceInfoForPath(test_path_b
, &device_info
));
626 EXPECT_EQ(GetDeviceId(kDeviceNoDCIM
), device_info
.device_id
);
627 EXPECT_EQ(test_path_b
.value(), device_info
.location
);
628 EXPECT_EQ(GetDeviceName(kDeviceNoDCIM
), device_info
.name
);
630 EXPECT_TRUE(notifier()->GetDeviceInfoForPath(test_path_c
, &device_info
));
631 EXPECT_EQ(GetDeviceId(kDeviceFixed
), device_info
.device_id
);
632 EXPECT_EQ(test_path_c
.value(), device_info
.location
);
633 EXPECT_EQ(GetDeviceName(kDeviceFixed
), device_info
.name
);
636 EXPECT_FALSE(notifier()->GetDeviceInfoForPath(FilePath(kInvalidPath
), NULL
));
638 // Test filling in of the mount point.
639 EXPECT_TRUE(notifier()->GetDeviceInfoForPath(
640 test_path_a
.Append("some/other/path"), &device_info
));
641 EXPECT_EQ(GetDeviceId(kDeviceDCIM1
), device_info
.device_id
);
642 EXPECT_EQ(test_path_a
.value(), device_info
.location
);
643 EXPECT_EQ(GetDeviceName(kDeviceDCIM1
), device_info
.name
);
645 // One device attached at multiple points.
646 // kDeviceDCIM1 -> kMountPointA *
647 // kDeviceFixed -> kMountPointB
648 // kDeviceFixed -> kMountPointC
649 MtabTestData test_data2
[] = {
650 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
651 MtabTestData(kDeviceFixed
, test_path_b
.value(), kValidFS
),
652 MtabTestData(kDeviceFixed
, test_path_c
.value(), kValidFS
),
654 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(0);
655 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(1);
656 AppendToMtabAndRunLoop(test_data2
, arraysize(test_data2
));
658 EXPECT_TRUE(notifier()->GetDeviceInfoForPath(test_path_a
, &device_info
));
659 EXPECT_EQ(GetDeviceId(kDeviceDCIM1
), device_info
.device_id
);
661 EXPECT_TRUE(notifier()->GetDeviceInfoForPath(test_path_b
, &device_info
));
662 EXPECT_EQ(GetDeviceId(kDeviceFixed
), device_info
.device_id
);
664 EXPECT_TRUE(notifier()->GetDeviceInfoForPath(test_path_c
, &device_info
));
665 EXPECT_EQ(GetDeviceId(kDeviceFixed
), device_info
.device_id
);
668 TEST_F(RemovableDeviceNotificationLinuxTest
, DevicePartitionSize
) {
669 FilePath test_path_a
= CreateMountPointWithDCIMDir(kMountPointA
);
670 FilePath test_path_b
= CreateMountPointWithoutDCIMDir(kMountPointB
);
671 ASSERT_FALSE(test_path_a
.empty());
672 ASSERT_FALSE(test_path_b
.empty());
674 MtabTestData test_data1
[] = {
675 MtabTestData(kDeviceDCIM1
, test_path_a
.value(), kValidFS
),
676 MtabTestData(kDeviceNoDCIM
, test_path_b
.value(), kValidFS
),
677 MtabTestData(kDeviceFixed
, kInvalidPath
, kInvalidFS
),
679 EXPECT_CALL(observer(), OnRemovableStorageAttached(_
, _
, _
)).Times(2);
680 EXPECT_CALL(observer(), OnRemovableStorageDetached(_
)).Times(0);
681 AppendToMtabAndRunLoop(test_data1
, arraysize(test_data1
));
683 EXPECT_EQ(GetDevicePartitionSize(kDeviceDCIM1
),
684 notifier()->GetStorageSize(test_path_a
.value()));
685 EXPECT_EQ(GetDevicePartitionSize(kDeviceNoDCIM
),
686 notifier()->GetStorageSize(test_path_b
.value()));
687 EXPECT_EQ(GetDevicePartitionSize(kInvalidPath
),
688 notifier()->GetStorageSize(kInvalidPath
));
693 } // namespace chrome