Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / components / storage_monitor / storage_monitor_chromeos_unittest.cc
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.
4
5 #include "components/storage_monitor/storage_monitor_chromeos.h"
6
7 #include "base/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chromeos/disks/mock_disk_mount_manager.h"
14 #include "components/storage_monitor/mock_removable_storage_observer.h"
15 #include "components/storage_monitor/removable_device_constants.h"
16 #include "components/storage_monitor/storage_info.h"
17 #include "components/storage_monitor/test_media_transfer_protocol_manager_linux.h"
18 #include "components/storage_monitor/test_storage_monitor.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace storage_monitor {
24
25 namespace {
26
27 using content::BrowserThread;
28 using chromeos::disks::DiskMountManager;
29 using testing::_;
30
31 const char kDevice1[] = "/dev/d1";
32 const char kDevice1Name[] = "d1";
33 const char kDevice2[] = "/dev/disk/d2";
34 const char kDevice2Name[] = "d2";
35 const char kEmptyDeviceLabel[] = "";
36 const char kMountPointA[] = "mnt_a";
37 const char kMountPointB[] = "mnt_b";
38 const char kSDCardDeviceName1[] = "8.6 MB Amy_SD";
39 const char kSDCardDeviceName2[] = "8.6 MB SD Card";
40 const char kSDCardMountPoint1[] = "media/removable/Amy_SD";
41 const char kSDCardMountPoint2[] = "media/removable/SD Card";
42 const char kProductName[] = "Z101";
43 const char kUniqueId1[] = "FFFF-FFFF";
44 const char kUniqueId2[] = "FFFF-FF0F";
45 const char kVendorName[] = "CompanyA";
46
47 uint64 kDevice1SizeInBytes = 113048;
48 uint64 kDevice2SizeInBytes = 212312;
49 uint64 kSDCardSizeInBytes = 9000000;
50
51 std::string GetDCIMDeviceId(const std::string& unique_id) {
52   return StorageInfo::MakeDeviceId(
53       StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM,
54       kFSUniqueIdPrefix + unique_id);
55 }
56
57 // A test version of StorageMonitorCros that exposes protected methods to tests.
58 class TestStorageMonitorCros : public StorageMonitorCros {
59  public:
60   TestStorageMonitorCros() {}
61
62   virtual ~TestStorageMonitorCros() {}
63
64   virtual void Init() OVERRIDE {
65     SetMediaTransferProtocolManagerForTest(
66         new TestMediaTransferProtocolManagerLinux());
67     StorageMonitorCros::Init();
68   }
69
70   virtual void OnMountEvent(DiskMountManager::MountEvent event,
71       chromeos::MountError error_code,
72       const DiskMountManager::MountPointInfo& mount_info) OVERRIDE {
73     StorageMonitorCros::OnMountEvent(event, error_code, mount_info);
74   }
75
76   virtual bool GetStorageInfoForPath(const base::FilePath& path,
77                                      StorageInfo* device_info) const OVERRIDE {
78     return StorageMonitorCros::GetStorageInfoForPath(path, device_info);
79   }
80   virtual void EjectDevice(
81       const std::string& device_id,
82       base::Callback<void(EjectStatus)> callback) OVERRIDE {
83     StorageMonitorCros::EjectDevice(device_id, callback);
84   }
85
86  private:
87   DISALLOW_COPY_AND_ASSIGN(TestStorageMonitorCros);
88 };
89
90 // Wrapper class to test StorageMonitorCros.
91 class StorageMonitorCrosTest : public testing::Test {
92  public:
93   StorageMonitorCrosTest();
94   virtual ~StorageMonitorCrosTest();
95
96   void EjectNotify(StorageMonitor::EjectStatus status);
97
98  protected:
99   // testing::Test:
100   virtual void SetUp() OVERRIDE;
101   virtual void TearDown() OVERRIDE;
102
103   void MountDevice(chromeos::MountError error_code,
104                    const DiskMountManager::MountPointInfo& mount_info,
105                    const std::string& unique_id,
106                    const std::string& device_label,
107                    const std::string& vendor_name,
108                    const std::string& product_name,
109                    chromeos::DeviceType device_type,
110                    uint64 device_size_in_bytes);
111
112   void UnmountDevice(chromeos::MountError error_code,
113                      const DiskMountManager::MountPointInfo& mount_info);
114
115   uint64 GetDeviceStorageSize(const std::string& device_location);
116
117   // Create a directory named |dir| relative to the test directory.
118   // Set |with_dcim_dir| to true if the created directory will have a "DCIM"
119   // subdirectory.
120   // Returns the full path to the created directory on success, or an empty
121   // path on failure.
122   base::FilePath CreateMountPoint(const std::string& dir, bool with_dcim_dir);
123
124   static void PostQuitToUIThread();
125   static void WaitForFileThread();
126
127   MockRemovableStorageObserver& observer() {
128     return *mock_storage_observer_;
129   }
130
131   TestStorageMonitorCros* monitor_;
132
133   // Owned by DiskMountManager.
134   chromeos::disks::MockDiskMountManager* disk_mount_manager_mock_;
135
136   StorageMonitor::EjectStatus status_;
137
138  private:
139   content::TestBrowserThreadBundle thread_bundle_;
140
141   // Temporary directory for created test data.
142   base::ScopedTempDir scoped_temp_dir_;
143
144   // Objects that talks with StorageMonitorCros.
145   scoped_ptr<MockRemovableStorageObserver> mock_storage_observer_;
146
147   DISALLOW_COPY_AND_ASSIGN(StorageMonitorCrosTest);
148 };
149
150 StorageMonitorCrosTest::StorageMonitorCrosTest()
151     : monitor_(NULL),
152       disk_mount_manager_mock_(NULL),
153       status_(StorageMonitor::EJECT_FAILURE),
154       thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD) {
155 }
156
157 StorageMonitorCrosTest::~StorageMonitorCrosTest() {
158 }
159
160 void StorageMonitorCrosTest::SetUp() {
161   ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
162   ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
163   disk_mount_manager_mock_ = new chromeos::disks::MockDiskMountManager();
164   DiskMountManager::InitializeForTesting(disk_mount_manager_mock_);
165   disk_mount_manager_mock_->SetupDefaultReplies();
166
167   mock_storage_observer_.reset(new MockRemovableStorageObserver);
168
169   // Initialize the test subject.
170   TestStorageMonitor::Destroy();
171   monitor_ = new TestStorageMonitorCros();
172   scoped_ptr<StorageMonitor> pass_monitor(monitor_);
173   StorageMonitor::SetStorageMonitorForTesting(pass_monitor.Pass());
174
175   monitor_->Init();
176   monitor_->AddObserver(mock_storage_observer_.get());
177 }
178
179 void StorageMonitorCrosTest::TearDown() {
180   monitor_->RemoveObserver(mock_storage_observer_.get());
181   monitor_ = NULL;
182
183   disk_mount_manager_mock_ = NULL;
184   DiskMountManager::Shutdown();
185   WaitForFileThread();
186 }
187
188 void StorageMonitorCrosTest::MountDevice(
189     chromeos::MountError error_code,
190     const DiskMountManager::MountPointInfo& mount_info,
191     const std::string& unique_id,
192     const std::string& device_label,
193     const std::string& vendor_name,
194     const std::string& product_name,
195     chromeos::DeviceType device_type,
196     uint64 device_size_in_bytes) {
197   if (error_code == chromeos::MOUNT_ERROR_NONE) {
198     disk_mount_manager_mock_->CreateDiskEntryForMountDevice(
199         mount_info,
200         unique_id,
201         device_label,
202         vendor_name,
203         product_name,
204         device_type,
205         device_size_in_bytes,
206         false /* is_parent */,
207         true /* has_media */,
208         false /* on_boot_device */);
209   }
210   monitor_->OnMountEvent(DiskMountManager::MOUNTING, error_code, mount_info);
211   WaitForFileThread();
212 }
213
214 void StorageMonitorCrosTest::UnmountDevice(
215     chromeos::MountError error_code,
216     const DiskMountManager::MountPointInfo& mount_info) {
217   monitor_->OnMountEvent(DiskMountManager::UNMOUNTING, error_code, mount_info);
218   if (error_code == chromeos::MOUNT_ERROR_NONE)
219     disk_mount_manager_mock_->RemoveDiskEntryForMountDevice(mount_info);
220   WaitForFileThread();
221 }
222
223 uint64 StorageMonitorCrosTest::GetDeviceStorageSize(
224     const std::string& device_location) {
225   StorageInfo info;
226   if (!monitor_->GetStorageInfoForPath(base::FilePath(device_location), &info))
227     return 0;
228
229   return info.total_size_in_bytes();
230 }
231
232 base::FilePath StorageMonitorCrosTest::CreateMountPoint(
233     const std::string& dir, bool with_dcim_dir) {
234   base::FilePath return_path(scoped_temp_dir_.path());
235   return_path = return_path.AppendASCII(dir);
236   base::FilePath path(return_path);
237   if (with_dcim_dir)
238     path = path.Append(kDCIMDirectoryName);
239   if (!base::CreateDirectory(path))
240     return base::FilePath();
241   return return_path;
242 }
243
244 // static
245 void StorageMonitorCrosTest::PostQuitToUIThread() {
246   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
247                           base::MessageLoop::QuitClosure());
248 }
249
250 // static
251 void StorageMonitorCrosTest::WaitForFileThread() {
252   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
253                           base::Bind(&PostQuitToUIThread));
254   base::MessageLoop::current()->Run();
255 }
256
257 void StorageMonitorCrosTest::EjectNotify(StorageMonitor::EjectStatus status) {
258   status_ = status;
259 }
260
261 // Simple test case where we attach and detach a media device.
262 TEST_F(StorageMonitorCrosTest, BasicAttachDetach) {
263   base::FilePath mount_path1 = CreateMountPoint(kMountPointA, true);
264   ASSERT_FALSE(mount_path1.empty());
265   DiskMountManager::MountPointInfo mount_info(
266       kDevice1,
267       mount_path1.value(),
268       chromeos::MOUNT_TYPE_DEVICE,
269       chromeos::disks::MOUNT_CONDITION_NONE);
270   MountDevice(chromeos::MOUNT_ERROR_NONE,
271               mount_info,
272               kUniqueId1,
273               kDevice1Name,
274               kVendorName,
275               kProductName,
276               chromeos::DEVICE_TYPE_USB,
277               kDevice1SizeInBytes);
278   EXPECT_EQ(1, observer().attach_calls());
279   EXPECT_EQ(0, observer().detach_calls());
280   EXPECT_EQ(GetDCIMDeviceId(kUniqueId1),
281             observer().last_attached().device_id());
282   EXPECT_EQ(mount_path1.value(), observer().last_attached().location());
283
284   UnmountDevice(chromeos::MOUNT_ERROR_NONE, mount_info);
285   EXPECT_EQ(1, observer().attach_calls());
286   EXPECT_EQ(1, observer().detach_calls());
287   EXPECT_EQ(GetDCIMDeviceId(kUniqueId1),
288             observer().last_detached().device_id());
289
290   base::FilePath mount_path2 = CreateMountPoint(kMountPointB, true);
291   ASSERT_FALSE(mount_path2.empty());
292   DiskMountManager::MountPointInfo mount_info2(
293       kDevice2,
294       mount_path2.value(),
295       chromeos::MOUNT_TYPE_DEVICE,
296       chromeos::disks::MOUNT_CONDITION_NONE);
297   MountDevice(chromeos::MOUNT_ERROR_NONE,
298               mount_info2,
299               kUniqueId2,
300               kDevice2Name,
301               kVendorName,
302               kProductName,
303               chromeos::DEVICE_TYPE_USB,
304               kDevice2SizeInBytes);
305   EXPECT_EQ(2, observer().attach_calls());
306   EXPECT_EQ(1, observer().detach_calls());
307   EXPECT_EQ(GetDCIMDeviceId(kUniqueId2),
308             observer().last_attached().device_id());
309   EXPECT_EQ(mount_path2.value(), observer().last_attached().location());
310
311   UnmountDevice(chromeos::MOUNT_ERROR_NONE, mount_info2);
312   EXPECT_EQ(2, observer().attach_calls());
313   EXPECT_EQ(2, observer().detach_calls());
314   EXPECT_EQ(GetDCIMDeviceId(kUniqueId2),
315             observer().last_detached().device_id());
316 }
317
318 // Removable mass storage devices with no dcim folder are also recognized.
319 TEST_F(StorageMonitorCrosTest, NoDCIM) {
320   testing::Sequence mock_sequence;
321   base::FilePath mount_path = CreateMountPoint(kMountPointA, false);
322   const std::string kUniqueId = "FFFF-FFFF";
323   ASSERT_FALSE(mount_path.empty());
324   DiskMountManager::MountPointInfo mount_info(
325       kDevice1,
326       mount_path.value(),
327       chromeos::MOUNT_TYPE_DEVICE,
328       chromeos::disks::MOUNT_CONDITION_NONE);
329   const std::string device_id = StorageInfo::MakeDeviceId(
330       StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM,
331       kFSUniqueIdPrefix + kUniqueId);
332   MountDevice(chromeos::MOUNT_ERROR_NONE,
333               mount_info,
334               kUniqueId,
335               kDevice1Name,
336               kVendorName,
337               kProductName,
338               chromeos::DEVICE_TYPE_USB,
339               kDevice1SizeInBytes);
340   EXPECT_EQ(1, observer().attach_calls());
341   EXPECT_EQ(0, observer().detach_calls());
342   EXPECT_EQ(device_id, observer().last_attached().device_id());
343   EXPECT_EQ(mount_path.value(), observer().last_attached().location());
344 }
345
346 // Non device mounts and mount errors are ignored.
347 TEST_F(StorageMonitorCrosTest, Ignore) {
348   testing::Sequence mock_sequence;
349   base::FilePath mount_path = CreateMountPoint(kMountPointA, true);
350   const std::string kUniqueId = "FFFF-FFFF";
351   ASSERT_FALSE(mount_path.empty());
352
353   // Mount error.
354   DiskMountManager::MountPointInfo mount_info(
355       kDevice1,
356       mount_path.value(),
357       chromeos::MOUNT_TYPE_DEVICE,
358       chromeos::disks::MOUNT_CONDITION_NONE);
359   MountDevice(chromeos::MOUNT_ERROR_UNKNOWN,
360               mount_info,
361               kUniqueId,
362               kDevice1Name,
363               kVendorName,
364               kProductName,
365               chromeos::DEVICE_TYPE_USB,
366               kDevice1SizeInBytes);
367   EXPECT_EQ(0, observer().attach_calls());
368   EXPECT_EQ(0, observer().detach_calls());
369
370   // Not a device
371   mount_info.mount_type = chromeos::MOUNT_TYPE_ARCHIVE;
372   MountDevice(chromeos::MOUNT_ERROR_NONE,
373               mount_info,
374               kUniqueId,
375               kDevice1Name,
376               kVendorName,
377               kProductName,
378               chromeos::DEVICE_TYPE_USB,
379               kDevice1SizeInBytes);
380   EXPECT_EQ(0, observer().attach_calls());
381   EXPECT_EQ(0, observer().detach_calls());
382
383   // Unsupported file system.
384   mount_info.mount_type = chromeos::MOUNT_TYPE_DEVICE;
385   mount_info.mount_condition =
386       chromeos::disks::MOUNT_CONDITION_UNSUPPORTED_FILESYSTEM;
387   MountDevice(chromeos::MOUNT_ERROR_NONE,
388               mount_info,
389               kUniqueId,
390               kDevice1Name,
391               kVendorName,
392               kProductName,
393               chromeos::DEVICE_TYPE_USB,
394               kDevice1SizeInBytes);
395   EXPECT_EQ(0, observer().attach_calls());
396   EXPECT_EQ(0, observer().detach_calls());
397 }
398
399 TEST_F(StorageMonitorCrosTest, SDCardAttachDetach) {
400   base::FilePath mount_path1 = CreateMountPoint(kSDCardMountPoint1, true);
401   ASSERT_FALSE(mount_path1.empty());
402   DiskMountManager::MountPointInfo mount_info1(
403       kSDCardDeviceName1,
404       mount_path1.value(),
405       chromeos::MOUNT_TYPE_DEVICE,
406       chromeos::disks::MOUNT_CONDITION_NONE);
407   MountDevice(chromeos::MOUNT_ERROR_NONE,
408               mount_info1,
409               kUniqueId2,
410               kSDCardDeviceName1,
411               kVendorName,
412               kProductName,
413               chromeos::DEVICE_TYPE_SD,
414               kSDCardSizeInBytes);
415   EXPECT_EQ(1, observer().attach_calls());
416   EXPECT_EQ(0, observer().detach_calls());
417   EXPECT_EQ(GetDCIMDeviceId(kUniqueId2),
418             observer().last_attached().device_id());
419   EXPECT_EQ(mount_path1.value(), observer().last_attached().location());
420
421   UnmountDevice(chromeos::MOUNT_ERROR_NONE, mount_info1);
422   EXPECT_EQ(1, observer().attach_calls());
423   EXPECT_EQ(1, observer().detach_calls());
424   EXPECT_EQ(GetDCIMDeviceId(kUniqueId2),
425             observer().last_detached().device_id());
426
427   base::FilePath mount_path2 = CreateMountPoint(kSDCardMountPoint2, true);
428   ASSERT_FALSE(mount_path2.empty());
429   DiskMountManager::MountPointInfo mount_info2(
430       kSDCardDeviceName2,
431       mount_path2.value(),
432       chromeos::MOUNT_TYPE_DEVICE,
433       chromeos::disks::MOUNT_CONDITION_NONE);
434   MountDevice(chromeos::MOUNT_ERROR_NONE,
435               mount_info2,
436               kUniqueId2,
437               kSDCardDeviceName2,
438               kVendorName,
439               kProductName,
440               chromeos::DEVICE_TYPE_SD,
441               kSDCardSizeInBytes);
442   EXPECT_EQ(2, observer().attach_calls());
443   EXPECT_EQ(1, observer().detach_calls());
444   EXPECT_EQ(GetDCIMDeviceId(kUniqueId2),
445             observer().last_attached().device_id());
446   EXPECT_EQ(mount_path2.value(), observer().last_attached().location());
447
448   UnmountDevice(chromeos::MOUNT_ERROR_NONE, mount_info2);
449   EXPECT_EQ(2, observer().attach_calls());
450   EXPECT_EQ(2, observer().detach_calls());
451   EXPECT_EQ(GetDCIMDeviceId(kUniqueId2),
452             observer().last_detached().device_id());
453 }
454
455 TEST_F(StorageMonitorCrosTest, AttachDeviceWithEmptyLabel) {
456   base::FilePath mount_path1 = CreateMountPoint(kMountPointA, true);
457   ASSERT_FALSE(mount_path1.empty());
458   DiskMountManager::MountPointInfo mount_info(
459       kEmptyDeviceLabel,
460       mount_path1.value(),
461       chromeos::MOUNT_TYPE_DEVICE,
462       chromeos::disks::MOUNT_CONDITION_NONE);
463   MountDevice(chromeos::MOUNT_ERROR_NONE,
464               mount_info,
465               kUniqueId1,
466               kEmptyDeviceLabel,
467               kVendorName,
468               kProductName,
469               chromeos::DEVICE_TYPE_USB,
470               kDevice1SizeInBytes);
471   EXPECT_EQ(1, observer().attach_calls());
472   EXPECT_EQ(0, observer().detach_calls());
473   EXPECT_EQ(GetDCIMDeviceId(kUniqueId1),
474             observer().last_attached().device_id());
475   EXPECT_EQ(mount_path1.value(), observer().last_attached().location());
476
477   UnmountDevice(chromeos::MOUNT_ERROR_NONE, mount_info);
478   EXPECT_EQ(1, observer().attach_calls());
479   EXPECT_EQ(1, observer().detach_calls());
480   EXPECT_EQ(GetDCIMDeviceId(kUniqueId1),
481             observer().last_detached().device_id());
482 }
483
484 TEST_F(StorageMonitorCrosTest, GetStorageSize) {
485   base::FilePath mount_path1 = CreateMountPoint(kMountPointA, true);
486   ASSERT_FALSE(mount_path1.empty());
487   DiskMountManager::MountPointInfo mount_info(
488       kEmptyDeviceLabel,
489       mount_path1.value(),
490       chromeos::MOUNT_TYPE_DEVICE,
491       chromeos::disks::MOUNT_CONDITION_NONE);
492   MountDevice(chromeos::MOUNT_ERROR_NONE,
493               mount_info,
494               kUniqueId1,
495               kEmptyDeviceLabel,
496               kVendorName,
497               kProductName,
498               chromeos::DEVICE_TYPE_USB,
499               kDevice1SizeInBytes);
500   EXPECT_EQ(1, observer().attach_calls());
501   EXPECT_EQ(0, observer().detach_calls());
502   EXPECT_EQ(GetDCIMDeviceId(kUniqueId1),
503             observer().last_attached().device_id());
504   EXPECT_EQ(mount_path1.value(), observer().last_attached().location());
505
506   EXPECT_EQ(kDevice1SizeInBytes, GetDeviceStorageSize(mount_path1.value()));
507   UnmountDevice(chromeos::MOUNT_ERROR_NONE, mount_info);
508   EXPECT_EQ(1, observer().attach_calls());
509   EXPECT_EQ(1, observer().detach_calls());
510   EXPECT_EQ(GetDCIMDeviceId(kUniqueId1),
511             observer().last_detached().device_id());
512 }
513
514 void UnmountFake(const std::string& location,
515                  chromeos::UnmountOptions options,
516                  const DiskMountManager::UnmountPathCallback& cb) {
517   cb.Run(chromeos::MOUNT_ERROR_NONE);
518 }
519
520 TEST_F(StorageMonitorCrosTest, EjectTest) {
521   base::FilePath mount_path1 = CreateMountPoint(kMountPointA, true);
522   ASSERT_FALSE(mount_path1.empty());
523   DiskMountManager::MountPointInfo mount_info(
524       kEmptyDeviceLabel,
525       mount_path1.value(),
526       chromeos::MOUNT_TYPE_DEVICE,
527       chromeos::disks::MOUNT_CONDITION_NONE);
528   MountDevice(chromeos::MOUNT_ERROR_NONE,
529               mount_info,
530               kUniqueId1,
531               kEmptyDeviceLabel,
532               kVendorName,
533               kProductName,
534               chromeos::DEVICE_TYPE_USB,
535               kDevice1SizeInBytes);
536   EXPECT_EQ(1, observer().attach_calls());
537   EXPECT_EQ(0, observer().detach_calls());
538
539   ON_CALL(*disk_mount_manager_mock_, UnmountPath(_, _, _))
540       .WillByDefault(testing::Invoke(&UnmountFake));
541   EXPECT_CALL(*disk_mount_manager_mock_,
542               UnmountPath(observer().last_attached().location(), _, _));
543   monitor_->EjectDevice(observer().last_attached().device_id(),
544                         base::Bind(&StorageMonitorCrosTest::EjectNotify,
545                                    base::Unretained(this)));
546   base::RunLoop().RunUntilIdle();
547
548   EXPECT_EQ(StorageMonitor::EJECT_OK, status_);
549 }
550
551 }  // namespace
552
553 }  // namespace storage_monitor