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