Added unit test for base/hash.
[chromium-blink-merge.git] / components / storage_monitor / storage_monitor_linux_unittest.cc
blob7949ae0495ef2c5f9c89f9dddf717fdd20fa6c37
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"
9 #include <mntent.h>
10 #include <stdio.h>
12 #include <string>
14 #include "base/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 {
31 namespace {
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,
62 8773 },
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;
74 size_t i = 0;
75 for (; i < arraysize(kTestDeviceData); i++) {
76 if (device_path.value() == kTestDeviceData[i].device_path) {
77 device_found = true;
78 break;
82 scoped_ptr<StorageInfo> storage_info;
83 if (!device_found) {
84 NOTREACHED();
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),
91 base::string16(),
92 mount_point.value(),
93 base::ASCIIToUTF16("volume label"),
94 base::ASCIIToUTF16("vendor name"),
95 base::ASCIIToUTF16("model name"),
96 kTestDeviceData[i].partition_size_in_bytes));
97 return storage_info.Pass();
100 uint64 GetDevicePartitionSize(const std::string& device) {
101 for (size_t i = 0; i < arraysize(kTestDeviceData); ++i) {
102 if (device == kTestDeviceData[i].device_path)
103 return kTestDeviceData[i].partition_size_in_bytes;
105 return 0;
108 std::string GetDeviceId(const std::string& device) {
109 for (size_t i = 0; i < arraysize(kTestDeviceData); ++i) {
110 if (device == kTestDeviceData[i].device_path) {
111 return StorageInfo::MakeDeviceId(kTestDeviceData[i].type,
112 kTestDeviceData[i].unique_id);
115 if (device == kInvalidDevice) {
116 return StorageInfo::MakeDeviceId(StorageInfo::FIXED_MASS_STORAGE,
117 kInvalidDevice);
119 return std::string();
122 class TestStorageMonitorLinux : public StorageMonitorLinux {
123 public:
124 explicit TestStorageMonitorLinux(const base::FilePath& path)
125 : StorageMonitorLinux(path) {
126 SetMediaTransferProtocolManagerForTest(
127 new TestMediaTransferProtocolManagerLinux());
128 SetGetDeviceInfoCallbackForTest(base::Bind(&GetDeviceInfo));
130 virtual ~TestStorageMonitorLinux() {}
132 private:
133 virtual void UpdateMtab(
134 const MtabWatcherLinux::MountPointDeviceMap& new_mtab) OVERRIDE {
135 StorageMonitorLinux::UpdateMtab(new_mtab);
136 base::MessageLoopProxy::current()->PostTask(
137 FROM_HERE, base::MessageLoop::QuitClosure());
140 DISALLOW_COPY_AND_ASSIGN(TestStorageMonitorLinux);
143 class StorageMonitorLinuxTest : public testing::Test {
144 public:
145 struct MtabTestData {
146 MtabTestData(const std::string& mount_device,
147 const std::string& mount_point,
148 const std::string& mount_type)
149 : mount_device(mount_device),
150 mount_point(mount_point),
151 mount_type(mount_type) {
154 const std::string mount_device;
155 const std::string mount_point;
156 const std::string mount_type;
159 StorageMonitorLinuxTest()
160 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
161 virtual ~StorageMonitorLinuxTest() {}
163 protected:
164 virtual void SetUp() OVERRIDE {
165 // Create and set up a temp dir with files for the test.
166 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
167 base::FilePath test_dir = scoped_temp_dir_.path().AppendASCII("test_etc");
168 ASSERT_TRUE(base::CreateDirectory(test_dir));
169 mtab_file_ = test_dir.AppendASCII("test_mtab");
170 MtabTestData initial_test_data[] = {
171 MtabTestData("dummydevice", "dummydir", kInvalidFS),
173 WriteToMtab(initial_test_data,
174 arraysize(initial_test_data),
175 true /* overwrite */);
177 monitor_.reset(new TestStorageMonitorLinux(mtab_file_));
179 mock_storage_observer_.reset(new MockRemovableStorageObserver);
180 monitor_->AddObserver(mock_storage_observer_.get());
182 monitor_->Init();
183 base::RunLoop().RunUntilIdle();
186 virtual void TearDown() OVERRIDE {
187 base::RunLoop().RunUntilIdle();
188 monitor_->RemoveObserver(mock_storage_observer_.get());
189 base::RunLoop().RunUntilIdle();
191 // Linux storage monitor must be destroyed on the UI thread, so do it here.
192 monitor_.reset();
195 // Append mtab entries from the |data| array of size |data_size| to the mtab
196 // file, and run the message loop.
197 void AppendToMtabAndRunLoop(const MtabTestData* data, size_t data_size) {
198 WriteToMtab(data, data_size, false /* do not overwrite */);
199 base::RunLoop().Run();
202 // Overwrite the mtab file with mtab entries from the |data| array of size
203 // |data_size|, and run the message loop.
204 void OverwriteMtabAndRunLoop(const MtabTestData* data, size_t data_size) {
205 WriteToMtab(data, data_size, true /* overwrite */);
206 base::RunLoop().Run();
209 // Simplied version of OverwriteMtabAndRunLoop() that just deletes all the
210 // entries in the mtab file.
211 void WriteEmptyMtabAndRunLoop() {
212 OverwriteMtabAndRunLoop(NULL, // No data.
213 0); // No data length.
216 // Create a directory named |dir| relative to the test directory.
217 // It has a DCIM directory, so StorageMonitorLinux recognizes it as a media
218 // directory.
219 base::FilePath CreateMountPointWithDCIMDir(const std::string& dir) {
220 return CreateMountPoint(dir, true /* create DCIM dir */);
223 // Create a directory named |dir| relative to the test directory.
224 // It does not have a DCIM directory, so StorageMonitorLinux does not
225 // recognize it as a media directory.
226 base::FilePath CreateMountPointWithoutDCIMDir(const std::string& dir) {
227 return CreateMountPoint(dir, false /* do not create DCIM dir */);
230 void RemoveDCIMDirFromMountPoint(const std::string& dir) {
231 base::FilePath dcim =
232 scoped_temp_dir_.path().AppendASCII(dir).Append(kDCIMDirectoryName);
233 base::DeleteFile(dcim, false);
236 MockRemovableStorageObserver& observer() {
237 return *mock_storage_observer_;
240 StorageMonitor* notifier() {
241 return monitor_.get();
244 uint64 GetStorageSize(const base::FilePath& path) {
245 StorageInfo info;
246 if (!notifier()->GetStorageInfoForPath(path, &info))
247 return 0;
249 return info.total_size_in_bytes();
252 private:
253 // Create a directory named |dir| relative to the test directory.
254 // Set |with_dcim_dir| to true if the created directory will have a "DCIM"
255 // subdirectory.
256 // Returns the full path to the created directory on success, or an empty
257 // path on failure.
258 base::FilePath CreateMountPoint(const std::string& dir, bool with_dcim_dir) {
259 base::FilePath return_path(scoped_temp_dir_.path());
260 return_path = return_path.AppendASCII(dir);
261 base::FilePath path(return_path);
262 if (with_dcim_dir)
263 path = path.Append(kDCIMDirectoryName);
264 if (!base::CreateDirectory(path))
265 return base::FilePath();
266 return return_path;
269 // Write the test mtab data to |mtab_file_|.
270 // |data| is an array of mtab entries.
271 // |data_size| is the array size of |data|.
272 // |overwrite| specifies whether to overwrite |mtab_file_|.
273 void WriteToMtab(const MtabTestData* data,
274 size_t data_size,
275 bool overwrite) {
276 FILE* file = setmntent(mtab_file_.value().c_str(), overwrite ? "w" : "a");
277 ASSERT_TRUE(file);
279 // Due to the glibc *mntent() interface design, which is out of our
280 // control, the mtnent struct has several char* fields, even though
281 // addmntent() does not write to them in the calls below. To make the
282 // compiler happy while avoiding making additional copies of strings,
283 // we just const_cast() the strings' c_str()s.
284 // Assuming addmntent() does not write to the char* fields, this is safe.
285 // It is unlikely the platforms this test suite runs on will have an
286 // addmntent() implementation that does change the char* fields. If that
287 // was ever the case, the test suite will start crashing or failing.
288 mntent entry;
289 static const char kMountOpts[] = "rw";
290 entry.mnt_opts = const_cast<char*>(kMountOpts);
291 entry.mnt_freq = 0;
292 entry.mnt_passno = 0;
293 for (size_t i = 0; i < data_size; ++i) {
294 entry.mnt_fsname = const_cast<char*>(data[i].mount_device.c_str());
295 entry.mnt_dir = const_cast<char*>(data[i].mount_point.c_str());
296 entry.mnt_type = const_cast<char*>(data[i].mount_type.c_str());
297 ASSERT_EQ(0, addmntent(file, &entry));
299 ASSERT_EQ(1, endmntent(file));
302 content::TestBrowserThreadBundle thread_bundle_;
304 scoped_ptr<MockRemovableStorageObserver> mock_storage_observer_;
306 // Temporary directory for created test data.
307 base::ScopedTempDir scoped_temp_dir_;
308 // Path to the test mtab file.
309 base::FilePath mtab_file_;
311 scoped_ptr<TestStorageMonitorLinux> monitor_;
313 DISALLOW_COPY_AND_ASSIGN(StorageMonitorLinuxTest);
316 // Simple test case where we attach and detach a media device.
317 TEST_F(StorageMonitorLinuxTest, BasicAttachDetach) {
318 base::FilePath test_path = CreateMountPointWithDCIMDir(kMountPointA);
319 ASSERT_FALSE(test_path.empty());
320 MtabTestData test_data[] = {
321 MtabTestData(kDeviceDCIM2, test_path.value(), kValidFS),
322 MtabTestData(kDeviceFixed, kInvalidPath, kValidFS),
324 // Only |kDeviceDCIM2| should be attached, since |kDeviceFixed| has a bad
325 // path.
326 AppendToMtabAndRunLoop(test_data, arraysize(test_data));
328 EXPECT_EQ(1, observer().attach_calls());
329 EXPECT_EQ(0, observer().detach_calls());
330 EXPECT_EQ(GetDeviceId(kDeviceDCIM2), observer().last_attached().device_id());
331 EXPECT_EQ(base::string16(), observer().last_attached().name());
332 EXPECT_EQ(test_path.value(), observer().last_attached().location());
334 // |kDeviceDCIM2| should be detached here.
335 WriteEmptyMtabAndRunLoop();
336 EXPECT_EQ(1, observer().attach_calls());
337 EXPECT_EQ(1, observer().detach_calls());
338 EXPECT_EQ(GetDeviceId(kDeviceDCIM2), observer().last_detached().device_id());
341 // Only removable devices are recognized.
342 TEST_F(StorageMonitorLinuxTest, Removable) {
343 base::FilePath test_path_a = CreateMountPointWithDCIMDir(kMountPointA);
344 ASSERT_FALSE(test_path_a.empty());
345 MtabTestData test_data1[] = {
346 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
348 // |kDeviceDCIM1| should be attached as expected.
349 AppendToMtabAndRunLoop(test_data1, arraysize(test_data1));
351 EXPECT_EQ(1, observer().attach_calls());
352 EXPECT_EQ(0, observer().detach_calls());
353 EXPECT_EQ(GetDeviceId(kDeviceDCIM1), observer().last_attached().device_id());
354 EXPECT_EQ(base::string16(), observer().last_attached().name());
355 EXPECT_EQ(test_path_a.value(), observer().last_attached().location());
357 // This should do nothing, since |kDeviceFixed| is not removable.
358 base::FilePath test_path_b = CreateMountPointWithoutDCIMDir(kMountPointB);
359 ASSERT_FALSE(test_path_b.empty());
360 MtabTestData test_data2[] = {
361 MtabTestData(kDeviceFixed, test_path_b.value(), kValidFS),
363 AppendToMtabAndRunLoop(test_data2, arraysize(test_data2));
364 EXPECT_EQ(1, observer().attach_calls());
365 EXPECT_EQ(0, observer().detach_calls());
367 // |kDeviceDCIM1| should be detached as expected.
368 WriteEmptyMtabAndRunLoop();
369 EXPECT_EQ(1, observer().attach_calls());
370 EXPECT_EQ(1, observer().detach_calls());
371 EXPECT_EQ(GetDeviceId(kDeviceDCIM1), observer().last_detached().device_id());
373 // |kDeviceNoDCIM| should be attached as expected.
374 MtabTestData test_data3[] = {
375 MtabTestData(kDeviceNoDCIM, test_path_b.value(), kValidFS),
377 AppendToMtabAndRunLoop(test_data3, arraysize(test_data3));
378 EXPECT_EQ(2, observer().attach_calls());
379 EXPECT_EQ(1, observer().detach_calls());
380 EXPECT_EQ(GetDeviceId(kDeviceNoDCIM), observer().last_attached().device_id());
381 EXPECT_EQ(base::string16(), observer().last_attached().name());
382 EXPECT_EQ(test_path_b.value(), observer().last_attached().location());
384 // |kDeviceNoDCIM| should be detached as expected.
385 WriteEmptyMtabAndRunLoop();
386 EXPECT_EQ(2, observer().attach_calls());
387 EXPECT_EQ(2, observer().detach_calls());
388 EXPECT_EQ(GetDeviceId(kDeviceNoDCIM), observer().last_detached().device_id());
391 // More complicated test case with multiple devices on multiple mount points.
392 TEST_F(StorageMonitorLinuxTest, SwapMountPoints) {
393 base::FilePath test_path_a = CreateMountPointWithDCIMDir(kMountPointA);
394 base::FilePath test_path_b = CreateMountPointWithDCIMDir(kMountPointB);
395 ASSERT_FALSE(test_path_a.empty());
396 ASSERT_FALSE(test_path_b.empty());
398 // Attach two devices.
399 // (*'d mounts are those StorageMonitor knows about.)
400 // kDeviceDCIM1 -> kMountPointA *
401 // kDeviceDCIM2 -> kMountPointB *
402 MtabTestData test_data1[] = {
403 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
404 MtabTestData(kDeviceDCIM2, test_path_b.value(), kValidFS),
406 AppendToMtabAndRunLoop(test_data1, arraysize(test_data1));
407 EXPECT_EQ(2, observer().attach_calls());
408 EXPECT_EQ(0, observer().detach_calls());
410 // Detach two devices from old mount points and attach the devices at new
411 // mount points.
412 // kDeviceDCIM1 -> kMountPointB *
413 // kDeviceDCIM2 -> kMountPointA *
414 MtabTestData test_data2[] = {
415 MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS),
416 MtabTestData(kDeviceDCIM2, test_path_a.value(), kValidFS),
418 OverwriteMtabAndRunLoop(test_data2, arraysize(test_data2));
419 EXPECT_EQ(4, observer().attach_calls());
420 EXPECT_EQ(2, observer().detach_calls());
422 // Detach all devices.
423 WriteEmptyMtabAndRunLoop();
424 EXPECT_EQ(4, observer().attach_calls());
425 EXPECT_EQ(4, observer().detach_calls());
428 // More complicated test case with multiple devices on multiple mount points.
429 TEST_F(StorageMonitorLinuxTest, MultiDevicesMultiMountPoints) {
430 base::FilePath test_path_a = CreateMountPointWithDCIMDir(kMountPointA);
431 base::FilePath test_path_b = CreateMountPointWithDCIMDir(kMountPointB);
432 ASSERT_FALSE(test_path_a.empty());
433 ASSERT_FALSE(test_path_b.empty());
435 // Attach two devices.
436 // (*'d mounts are those StorageMonitor knows about.)
437 // kDeviceDCIM1 -> kMountPointA *
438 // kDeviceDCIM2 -> kMountPointB *
439 MtabTestData test_data1[] = {
440 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
441 MtabTestData(kDeviceDCIM2, test_path_b.value(), kValidFS),
443 AppendToMtabAndRunLoop(test_data1, arraysize(test_data1));
444 EXPECT_EQ(2, observer().attach_calls());
445 EXPECT_EQ(0, observer().detach_calls());
447 // Attach |kDeviceDCIM1| to |kMountPointB|.
448 // |kDeviceDCIM2| is inaccessible, so it is detached. |kDeviceDCIM1| has been
449 // attached at |kMountPointB|, but is still accessible from |kMountPointA|.
450 // kDeviceDCIM1 -> kMountPointA *
451 // kDeviceDCIM2 -> kMountPointB
452 // kDeviceDCIM1 -> kMountPointB
453 MtabTestData test_data2[] = {
454 MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS),
456 AppendToMtabAndRunLoop(test_data2, arraysize(test_data2));
457 EXPECT_EQ(2, observer().attach_calls());
458 EXPECT_EQ(1, observer().detach_calls());
460 // Detach |kDeviceDCIM1| from |kMountPointA|, causing a detach and attach
461 // event.
462 // kDeviceDCIM2 -> kMountPointB
463 // kDeviceDCIM1 -> kMountPointB *
464 MtabTestData test_data3[] = {
465 MtabTestData(kDeviceDCIM2, test_path_b.value(), kValidFS),
466 MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS),
468 OverwriteMtabAndRunLoop(test_data3, arraysize(test_data3));
469 EXPECT_EQ(3, observer().attach_calls());
470 EXPECT_EQ(2, observer().detach_calls());
472 // Attach |kDeviceDCIM1| to |kMountPointA|.
473 // kDeviceDCIM2 -> kMountPointB
474 // kDeviceDCIM1 -> kMountPointB *
475 // kDeviceDCIM1 -> kMountPointA
476 MtabTestData test_data4[] = {
477 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
479 AppendToMtabAndRunLoop(test_data4, arraysize(test_data4));
480 EXPECT_EQ(3, observer().attach_calls());
481 EXPECT_EQ(2, observer().detach_calls());
483 // Detach |kDeviceDCIM1| from |kMountPointB|.
484 // kDeviceDCIM1 -> kMountPointA *
485 // kDeviceDCIM2 -> kMountPointB *
486 OverwriteMtabAndRunLoop(test_data1, arraysize(test_data1));
487 EXPECT_EQ(5, observer().attach_calls());
488 EXPECT_EQ(3, observer().detach_calls());
490 // Detach all devices.
491 WriteEmptyMtabAndRunLoop();
492 EXPECT_EQ(5, observer().attach_calls());
493 EXPECT_EQ(5, observer().detach_calls());
496 TEST_F(StorageMonitorLinuxTest, MultipleMountPointsWithNonDCIMDevices) {
497 base::FilePath test_path_a = CreateMountPointWithDCIMDir(kMountPointA);
498 base::FilePath test_path_b = CreateMountPointWithDCIMDir(kMountPointB);
499 ASSERT_FALSE(test_path_a.empty());
500 ASSERT_FALSE(test_path_b.empty());
502 // Attach to one first.
503 // (*'d mounts are those StorageMonitor knows about.)
504 // kDeviceDCIM1 -> kMountPointA *
505 MtabTestData test_data1[] = {
506 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
508 AppendToMtabAndRunLoop(test_data1, arraysize(test_data1));
509 EXPECT_EQ(1, observer().attach_calls());
510 EXPECT_EQ(0, observer().detach_calls());
512 // Attach |kDeviceDCIM1| to |kMountPointB|.
513 // kDeviceDCIM1 -> kMountPointA *
514 // kDeviceDCIM1 -> kMountPointB
515 MtabTestData test_data2[] = {
516 MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS),
518 AppendToMtabAndRunLoop(test_data2, arraysize(test_data2));
519 EXPECT_EQ(1, observer().attach_calls());
520 EXPECT_EQ(0, observer().detach_calls());
522 // Attach |kDeviceFixed| (a non-removable device) to |kMountPointA|.
523 // kDeviceDCIM1 -> kMountPointA
524 // kDeviceDCIM1 -> kMountPointB *
525 // kDeviceFixed -> kMountPointA
526 MtabTestData test_data3[] = {
527 MtabTestData(kDeviceFixed, test_path_a.value(), kValidFS),
529 RemoveDCIMDirFromMountPoint(kMountPointA);
530 AppendToMtabAndRunLoop(test_data3, arraysize(test_data3));
531 EXPECT_EQ(2, observer().attach_calls());
532 EXPECT_EQ(1, observer().detach_calls());
534 // Detach |kDeviceFixed|.
535 // kDeviceDCIM1 -> kMountPointA
536 // kDeviceDCIM1 -> kMountPointB *
537 MtabTestData test_data4[] = {
538 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
539 MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS),
541 CreateMountPointWithDCIMDir(kMountPointA);
542 OverwriteMtabAndRunLoop(test_data4, arraysize(test_data4));
543 EXPECT_EQ(2, observer().attach_calls());
544 EXPECT_EQ(1, observer().detach_calls());
546 // Attach |kDeviceNoDCIM| (a non-DCIM device) to |kMountPointB|.
547 // kDeviceDCIM1 -> kMountPointA *
548 // kDeviceDCIM1 -> kMountPointB
549 // kDeviceNoDCIM -> kMountPointB *
550 MtabTestData test_data5[] = {
551 MtabTestData(kDeviceNoDCIM, test_path_b.value(), kValidFS),
553 base::DeleteFile(test_path_b.Append(kDCIMDirectoryName), false);
554 AppendToMtabAndRunLoop(test_data5, arraysize(test_data5));
555 EXPECT_EQ(4, observer().attach_calls());
556 EXPECT_EQ(2, observer().detach_calls());
558 // Detach |kDeviceNoDCIM|.
559 // kDeviceDCIM1 -> kMountPointA *
560 // kDeviceDCIM1 -> kMountPointB
561 MtabTestData test_data6[] = {
562 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
563 MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS),
565 CreateMountPointWithDCIMDir(kMountPointB);
566 OverwriteMtabAndRunLoop(test_data6, arraysize(test_data6));
567 EXPECT_EQ(4, observer().attach_calls());
568 EXPECT_EQ(3, observer().detach_calls());
570 // Detach |kDeviceDCIM1| from |kMountPointB|.
571 // kDeviceDCIM1 -> kMountPointA *
572 OverwriteMtabAndRunLoop(test_data1, arraysize(test_data1));
573 EXPECT_EQ(4, observer().attach_calls());
574 EXPECT_EQ(3, observer().detach_calls());
576 // Detach all devices.
577 WriteEmptyMtabAndRunLoop();
578 EXPECT_EQ(4, observer().attach_calls());
579 EXPECT_EQ(4, observer().detach_calls());
582 TEST_F(StorageMonitorLinuxTest, DeviceLookUp) {
583 base::FilePath test_path_a = CreateMountPointWithDCIMDir(kMountPointA);
584 base::FilePath test_path_b = CreateMountPointWithoutDCIMDir(kMountPointB);
585 base::FilePath test_path_c = CreateMountPointWithoutDCIMDir(kMountPointC);
586 ASSERT_FALSE(test_path_a.empty());
587 ASSERT_FALSE(test_path_b.empty());
588 ASSERT_FALSE(test_path_c.empty());
590 // Attach to one first.
591 // (starred mounts are those StorageMonitor knows about.)
592 // kDeviceDCIM1 -> kMountPointA *
593 // kDeviceNoDCIM -> kMountPointB *
594 // kDeviceFixed -> kMountPointC
595 MtabTestData test_data1[] = {
596 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
597 MtabTestData(kDeviceNoDCIM, test_path_b.value(), kValidFS),
598 MtabTestData(kDeviceFixed, test_path_c.value(), kValidFS),
600 AppendToMtabAndRunLoop(test_data1, arraysize(test_data1));
601 EXPECT_EQ(2, observer().attach_calls());
602 EXPECT_EQ(0, observer().detach_calls());
604 StorageInfo device_info;
605 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_a, &device_info));
606 EXPECT_EQ(GetDeviceId(kDeviceDCIM1), device_info.device_id());
607 EXPECT_EQ(test_path_a.value(), device_info.location());
608 EXPECT_EQ(base::string16(), device_info.name());
609 EXPECT_EQ(88788ULL, device_info.total_size_in_bytes());
610 EXPECT_EQ(base::ASCIIToUTF16("volume label"), device_info.storage_label());
611 EXPECT_EQ(base::ASCIIToUTF16("vendor name"), device_info.vendor_name());
612 EXPECT_EQ(base::ASCIIToUTF16("model name"), device_info.model_name());
614 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_b, &device_info));
615 EXPECT_EQ(GetDeviceId(kDeviceNoDCIM), device_info.device_id());
616 EXPECT_EQ(test_path_b.value(), device_info.location());
617 EXPECT_EQ(base::string16(), device_info.name());
619 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_c, &device_info));
620 EXPECT_EQ(GetDeviceId(kDeviceFixed), device_info.device_id());
621 EXPECT_EQ(test_path_c.value(), device_info.location());
622 EXPECT_EQ(base::string16(), device_info.name());
624 // An invalid path.
625 EXPECT_FALSE(notifier()->GetStorageInfoForPath(base::FilePath(kInvalidPath),
626 &device_info));
628 // Test filling in of the mount point.
629 EXPECT_TRUE(
630 notifier()->GetStorageInfoForPath(test_path_a.Append("some/other/path"),
631 &device_info));
632 EXPECT_EQ(GetDeviceId(kDeviceDCIM1), device_info.device_id());
633 EXPECT_EQ(test_path_a.value(), device_info.location());
634 EXPECT_EQ(base::string16(), device_info.name());
636 // One device attached at multiple points.
637 // kDeviceDCIM1 -> kMountPointA *
638 // kDeviceFixed -> kMountPointB
639 // kDeviceFixed -> kMountPointC
640 MtabTestData test_data2[] = {
641 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
642 MtabTestData(kDeviceFixed, test_path_b.value(), kValidFS),
643 MtabTestData(kDeviceFixed, test_path_c.value(), kValidFS),
645 AppendToMtabAndRunLoop(test_data2, arraysize(test_data2));
647 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_a, &device_info));
648 EXPECT_EQ(GetDeviceId(kDeviceDCIM1), device_info.device_id());
650 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_b, &device_info));
651 EXPECT_EQ(GetDeviceId(kDeviceFixed), device_info.device_id());
653 EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_c, &device_info));
654 EXPECT_EQ(GetDeviceId(kDeviceFixed), device_info.device_id());
656 EXPECT_EQ(2, observer().attach_calls());
657 EXPECT_EQ(1, observer().detach_calls());
660 TEST_F(StorageMonitorLinuxTest, DevicePartitionSize) {
661 base::FilePath test_path_a = CreateMountPointWithDCIMDir(kMountPointA);
662 base::FilePath test_path_b = CreateMountPointWithoutDCIMDir(kMountPointB);
663 ASSERT_FALSE(test_path_a.empty());
664 ASSERT_FALSE(test_path_b.empty());
666 MtabTestData test_data1[] = {
667 MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS),
668 MtabTestData(kDeviceNoDCIM, test_path_b.value(), kValidFS),
669 MtabTestData(kDeviceFixed, kInvalidPath, kInvalidFS),
671 AppendToMtabAndRunLoop(test_data1, arraysize(test_data1));
672 EXPECT_EQ(2, observer().attach_calls());
673 EXPECT_EQ(0, observer().detach_calls());
675 EXPECT_EQ(GetDevicePartitionSize(kDeviceDCIM1),
676 GetStorageSize(test_path_a));
677 EXPECT_EQ(GetDevicePartitionSize(kDeviceNoDCIM),
678 GetStorageSize(test_path_b));
679 EXPECT_EQ(GetDevicePartitionSize(kInvalidPath),
680 GetStorageSize(base::FilePath(kInvalidPath)));
683 } // namespace
685 } // namespace storage_monitor