Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / system_monitor / removable_device_notifications_linux_unittest.cc
bloba598f62aa905bd1bc1e7fb125ceb70028fd005b7
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"
9 #include <mntent.h>
10 #include <stdio.h>
12 #include <string>
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"
28 namespace chrome {
30 namespace {
32 using testing::_;
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,
64 8773 },
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,
74 std::string* id,
75 string16* name,
76 bool* removable,
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) {
80 if (id)
81 *id = kTestDeviceData[i].unique_id;
82 if (name)
83 *name = ASCIIToUTF16(kTestDeviceData[i].device_name);
84 if (removable) {
85 MediaStorageUtil::Type type = kTestDeviceData[i].type;
86 *removable =
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;
92 return;
95 NOTREACHED();
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;
103 return 0;
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,
115 kInvalidDevice);
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));
128 return string16();
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);
136 return string16();
139 class RemovableDeviceNotificationsLinuxTestWrapper
140 : public RemovableDeviceNotificationsLinux {
141 public:
142 RemovableDeviceNotificationsLinuxTestWrapper(const FilePath& path,
143 MessageLoop* message_loop)
144 : RemovableDeviceNotificationsLinux(path, &GetDeviceInfo),
145 message_loop_(message_loop) {
148 private:
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 {
165 public:
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() {}
186 protected:
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 */);
222 message_loop_.Run();
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 */);
229 message_loop_.Run();
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) {
254 FilePath dcim =
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();
267 private:
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"
270 // subdirectory.
271 // Returns the full path to the created directory on success, or an empty
272 // path on failure.
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);
277 if (with_dcim_dir)
278 path = path.Append(kDCIMDirectoryName);
279 if (!file_util::CreateDirectory(path))
280 return FilePath();
281 return return_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,
289 size_t data_size,
290 bool overwrite) {
291 FILE* file = setmntent(mtab_file_.value().c_str(), overwrite ? "w" : "a");
292 ASSERT_TRUE(file);
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.
303 mntent entry;
304 static const char kMountOpts[] = "rw";
305 entry.mnt_opts = const_cast<char*>(kMountOpts);
306 entry.mnt_freq = 0;
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.
328 FilePath 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
345 // path.
346 EXPECT_CALL(observer(),
347 OnRemovableStorageAttached(
348 GetDeviceId(kDeviceDCIM2),
349 GetDeviceNameWithSizeDetails(kDeviceDCIM2),
350 test_path.value()))
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
428 // mount points.
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
477 // event.
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);
635 // An invalid path.
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));
691 } // namespace
693 } // namespace chrome