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