Roll src/third_party/skia ce86687:b880d7f
[chromium-blink-merge.git] / chromeos / disks / disk_mount_manager_unittest.cc
blobbecb950800e349adbcdf694afb4789777555802e
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 #include "base/bind.h"
6 #include "base/message_loop/message_loop.h"
7 #include "chromeos/dbus/dbus_thread_manager.h"
8 #include "chromeos/dbus/fake_cros_disks_client.h"
9 #include "chromeos/disks/disk_mount_manager.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 using chromeos::disks::DiskMountManager;
14 using chromeos::CrosDisksClient;
15 using chromeos::DBusThreadManager;
16 using chromeos::FakeCrosDisksClient;
17 using testing::_;
18 using testing::Field;
19 using testing::InSequence;
21 namespace {
23 // Holds information needed to create a DiskMountManager::Disk instance.
24 struct TestDiskInfo {
25 const char* source_path;
26 const char* mount_path;
27 const char* system_path;
28 const char* file_path;
29 const char* device_label;
30 const char* drive_label;
31 const char* vendor_id;
32 const char* vendor_name;
33 const char* product_id;
34 const char* product_name;
35 const char* fs_uuid;
36 const char* system_path_prefix;
37 chromeos::DeviceType device_type;
38 uint64 size_in_bytes;
39 bool is_parent;
40 bool is_read_only;
41 bool has_media;
42 bool on_boot_device;
43 bool on_removable_device;
44 bool is_hidden;
47 // Holds information to create a DiskMOuntManager::MountPointInfo instance.
48 struct TestMountPointInfo {
49 const char* source_path;
50 const char* mount_path;
51 chromeos::MountType mount_type;
52 chromeos::disks::MountCondition mount_condition;
55 // List of disks held in DiskMountManager at the begining of the test.
56 const TestDiskInfo kTestDisks[] = {
58 "/device/source_path",
59 "/device/mount_path",
60 "/device/prefix/system_path",
61 "/device/file_path",
62 "/device/device_label",
63 "/device/drive_label",
64 "/device/vendor_id",
65 "/device/vendor_name",
66 "/device/product_id",
67 "/device/product_name",
68 "/device/fs_uuid",
69 "/device/prefix",
70 chromeos::DEVICE_TYPE_USB,
71 1073741824, // size in bytes
72 false, // is parent
73 false, // is read only
74 true, // has media
75 false, // is on boot device
76 true, // is on removable device
77 false // is hidden
81 // List of mount points held in DiskMountManager at the begining of the test.
82 const TestMountPointInfo kTestMountPoints[] = {
84 "/archive/source_path",
85 "/archive/mount_path",
86 chromeos::MOUNT_TYPE_ARCHIVE,
87 chromeos::disks::MOUNT_CONDITION_NONE
90 "/device/source_path",
91 "/device/mount_path",
92 chromeos::MOUNT_TYPE_DEVICE,
93 chromeos::disks::MOUNT_CONDITION_NONE
97 // Mocks DiskMountManager observer.
98 class MockDiskMountManagerObserver : public DiskMountManager::Observer {
99 public:
100 virtual ~MockDiskMountManagerObserver() {}
102 MOCK_METHOD2(OnDiskEvent, void(DiskMountManager::DiskEvent event,
103 const DiskMountManager::Disk* disk));
104 MOCK_METHOD2(OnDeviceEvent, void(DiskMountManager::DeviceEvent event,
105 const std::string& device_path));
106 MOCK_METHOD3(OnMountEvent,
107 void(DiskMountManager::MountEvent event,
108 chromeos::MountError error_code,
109 const DiskMountManager::MountPointInfo& mount_point));
110 MOCK_METHOD3(OnFormatEvent,
111 void(DiskMountManager::FormatEvent event,
112 chromeos::FormatError error_code,
113 const std::string& device_path));
116 class DiskMountManagerTest : public testing::Test {
117 public:
118 DiskMountManagerTest() {}
119 ~DiskMountManagerTest() override {}
121 // Sets up test dbus tread manager and disks mount manager.
122 // Initializes disk mount manager disks and mount points.
123 // Adds a test observer to the disk mount manager.
124 void SetUp() override {
125 fake_cros_disks_client_ = new FakeCrosDisksClient;
126 DBusThreadManager::GetSetterForTesting()->SetCrosDisksClient(
127 scoped_ptr<CrosDisksClient>(fake_cros_disks_client_));
129 DiskMountManager::Initialize();
131 InitDisksAndMountPoints();
133 DiskMountManager::GetInstance()->AddObserver(&observer_);
136 // Shuts down dbus thread manager and disk moutn manager used in the test.
137 void TearDown() override {
138 DiskMountManager::GetInstance()->RemoveObserver(&observer_);
139 DiskMountManager::Shutdown();
140 DBusThreadManager::Shutdown();
143 protected:
144 // Checks if disk mount manager contains a mount point with specified moutn
145 // path.
146 bool HasMountPoint(const std::string& mount_path) {
147 const DiskMountManager::MountPointMap& mount_points =
148 DiskMountManager::GetInstance()->mount_points();
149 return mount_points.find(mount_path) != mount_points.end();
152 private:
153 // Adds a new disk to the disk mount manager.
154 void AddTestDisk(const TestDiskInfo& disk) {
155 EXPECT_TRUE(DiskMountManager::GetInstance()->AddDiskForTest(
156 new DiskMountManager::Disk(disk.source_path,
157 disk.mount_path,
158 disk.system_path,
159 disk.file_path,
160 disk.device_label,
161 disk.drive_label,
162 disk.vendor_id,
163 disk.vendor_name,
164 disk.product_id,
165 disk.product_name,
166 disk.fs_uuid,
167 disk.system_path_prefix,
168 disk.device_type,
169 disk.size_in_bytes,
170 disk.is_parent,
171 disk.is_read_only,
172 disk.has_media,
173 disk.on_boot_device,
174 disk.on_removable_device,
175 disk.is_hidden)));
178 // Adds a new mount point to the disk mount manager.
179 // If the moutn point is a device mount point, disk with its source path
180 // should already be added to the disk mount manager.
181 void AddTestMountPoint(const TestMountPointInfo& mount_point) {
182 EXPECT_TRUE(DiskMountManager::GetInstance()->AddMountPointForTest(
183 DiskMountManager::MountPointInfo(mount_point.source_path,
184 mount_point.mount_path,
185 mount_point.mount_type,
186 mount_point.mount_condition)));
189 // Adds disks and mount points to disk mount manager.
190 void InitDisksAndMountPoints() {
191 // Disks should be added first (when adding device mount points it is
192 // expected that the corresponding disk is already added).
193 for (size_t i = 0; i < arraysize(kTestDisks); i++)
194 AddTestDisk(kTestDisks[i]);
196 for (size_t i = 0; i < arraysize(kTestMountPoints); i++)
197 AddTestMountPoint(kTestMountPoints[i]);
200 protected:
201 chromeos::FakeCrosDisksClient* fake_cros_disks_client_;
202 MockDiskMountManagerObserver observer_;
203 base::MessageLoopForUI message_loop_;
206 // Tests that the observer gets notified on attempt to format non existent mount
207 // point.
208 TEST_F(DiskMountManagerTest, Format_NotMounted) {
209 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
210 chromeos::FORMAT_ERROR_UNKNOWN,
211 "/mount/non_existent"))
212 .Times(1);
213 DiskMountManager::GetInstance()->FormatMountedDevice("/mount/non_existent");
216 // Tests that it is not possible to format archive mount point.
217 TEST_F(DiskMountManagerTest, Format_Archive) {
218 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
219 chromeos::FORMAT_ERROR_UNKNOWN,
220 "/archive/source_path"))
221 .Times(1);
223 DiskMountManager::GetInstance()->FormatMountedDevice("/archive/mount_path");
226 // Tests that format fails if the device cannot be unmounted.
227 TEST_F(DiskMountManagerTest, Format_FailToUnmount) {
228 // Before formatting mounted device, the device should be unmounted.
229 // In this test unmount will fail, and there should be no attempt to
230 // format the device.
232 // Set up expectations for observer mock.
233 // Observer should be notified that unmount attempt fails and format task
234 // failed to start.
236 InSequence s;
238 EXPECT_CALL(observer_,
239 OnMountEvent(DiskMountManager::UNMOUNTING,
240 chromeos::MOUNT_ERROR_INTERNAL,
241 Field(&DiskMountManager::MountPointInfo::mount_path,
242 "/device/mount_path")))
243 .Times(1);
245 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
246 chromeos::FORMAT_ERROR_UNKNOWN,
247 "/device/source_path"))
248 .Times(1);
251 fake_cros_disks_client_->MakeUnmountFail();
252 // Start test.
253 DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
255 // Cros disks will respond asynchronoulsy, so let's drain the message loop.
256 message_loop_.RunUntilIdle();
258 EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
259 EXPECT_EQ("/device/mount_path",
260 fake_cros_disks_client_->last_unmount_device_path());
261 EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
262 fake_cros_disks_client_->last_unmount_options());
263 EXPECT_EQ(0, fake_cros_disks_client_->format_call_count());
265 // The device mount should still be here.
266 EXPECT_TRUE(HasMountPoint("/device/mount_path"));
269 // Tests that observer is notified when cros disks fails to start format
270 // process.
271 TEST_F(DiskMountManagerTest, Format_FormatFailsToStart) {
272 // Before formatting mounted device, the device should be unmounted.
273 // In this test, unmount will succeed, but call to Format method will
274 // fail.
276 // Set up expectations for observer mock.
277 // Observer should be notified that the device was unmounted and format task
278 // failed to start.
280 InSequence s;
282 EXPECT_CALL(observer_,
283 OnMountEvent(DiskMountManager::UNMOUNTING,
284 chromeos::MOUNT_ERROR_NONE,
285 Field(&DiskMountManager::MountPointInfo::mount_path,
286 "/device/mount_path")))
287 .Times(1);
289 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
290 chromeos::FORMAT_ERROR_UNKNOWN,
291 "/device/source_path"))
292 .Times(1);
295 fake_cros_disks_client_->MakeFormatFail();
296 // Start the test.
297 DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
299 // Cros disks will respond asynchronoulsy, so let's drain the message loop.
300 message_loop_.RunUntilIdle();
302 EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
303 EXPECT_EQ("/device/mount_path",
304 fake_cros_disks_client_->last_unmount_device_path());
305 EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
306 fake_cros_disks_client_->last_unmount_options());
307 EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
308 EXPECT_EQ("/device/source_path",
309 fake_cros_disks_client_->last_format_device_path());
310 EXPECT_EQ("vfat", fake_cros_disks_client_->last_format_filesystem());
312 // The device mount should be gone.
313 EXPECT_FALSE(HasMountPoint("/device/mount_path"));
316 // Tests the case where there are two format requests for the same device.
317 TEST_F(DiskMountManagerTest, Format_ConcurrentFormatCalls) {
318 // Only the first format request should be processed (the second unmount
319 // request fails because the device is already unmounted at that point).
320 // CrosDisksClient will report that the format process for the first request
321 // is successfully started.
323 // Set up expectations for observer mock.
324 // The observer should get a FORMAT_STARTED event for one format request and a
325 // FORMAT_COMPLETED with an error code for the other format request. The
326 // formatting will be started only for the first request.
327 // There should be only one UNMOUNTING event. The result of the second one
328 // should not be reported as the mount point will go away after the first
329 // request.
331 // Note that in this test the format completion signal will not be simulated,
332 // so the observer should not get FORMAT_COMPLETED signal.
334 InSequence s;
336 EXPECT_CALL(observer_,
337 OnMountEvent(DiskMountManager::UNMOUNTING,
338 chromeos::MOUNT_ERROR_NONE,
339 Field(&DiskMountManager::MountPointInfo::mount_path,
340 "/device/mount_path")))
341 .Times(1);
343 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
344 chromeos::FORMAT_ERROR_UNKNOWN,
345 "/device/source_path"))
346 .Times(1);
348 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
349 chromeos::FORMAT_ERROR_NONE,
350 "/device/source_path"))
351 .Times(1);
354 fake_cros_disks_client_->set_unmount_listener(
355 base::Bind(&FakeCrosDisksClient::MakeUnmountFail,
356 base::Unretained(fake_cros_disks_client_)));
357 // Start the test.
358 DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
359 DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
361 // Cros disks will respond asynchronoulsy, so let's drain the message loop.
362 message_loop_.RunUntilIdle();
364 EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
365 EXPECT_EQ("/device/mount_path",
366 fake_cros_disks_client_->last_unmount_device_path());
367 EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
368 fake_cros_disks_client_->last_unmount_options());
369 EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
370 EXPECT_EQ("/device/source_path",
371 fake_cros_disks_client_->last_format_device_path());
372 EXPECT_EQ("vfat",
373 fake_cros_disks_client_->last_format_filesystem());
375 // The device mount should be gone.
376 EXPECT_FALSE(HasMountPoint("/device/mount_path"));
379 // Tests the case when the format process actually starts and fails.
380 TEST_F(DiskMountManagerTest, Format_FormatFails) {
381 // Both unmount and format device cals are successful in this test.
383 // Set up expectations for observer mock.
384 // The observer should get notified that the device was unmounted and that
385 // formatting has started.
386 // After the formatting starts, the test will simulate failing
387 // FORMAT_COMPLETED signal, so the observer should also be notified the
388 // formatting has failed (FORMAT_COMPLETED event).
390 InSequence s;
392 EXPECT_CALL(observer_,
393 OnMountEvent(DiskMountManager::UNMOUNTING,
394 chromeos::MOUNT_ERROR_NONE,
395 Field(&DiskMountManager::MountPointInfo::mount_path,
396 "/device/mount_path")))
397 .Times(1);
399 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
400 chromeos::FORMAT_ERROR_NONE,
401 "/device/source_path"))
402 .Times(1);
404 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
405 chromeos::FORMAT_ERROR_UNKNOWN,
406 "/device/source_path"))
407 .Times(1);
410 // Start the test.
411 DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
413 // Wait for Unmount and Format calls to end.
414 message_loop_.RunUntilIdle();
416 EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
417 EXPECT_EQ("/device/mount_path",
418 fake_cros_disks_client_->last_unmount_device_path());
419 EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
420 fake_cros_disks_client_->last_unmount_options());
421 EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
422 EXPECT_EQ("/device/source_path",
423 fake_cros_disks_client_->last_format_device_path());
424 EXPECT_EQ("vfat", fake_cros_disks_client_->last_format_filesystem());
426 // The device should be unmounted by now.
427 EXPECT_FALSE(HasMountPoint("/device/mount_path"));
429 // Send failing FORMAT_COMPLETED signal.
430 // The failure is marked by ! in fromt of the path (but this should change
431 // soon).
432 fake_cros_disks_client_->SendFormatCompletedEvent(
433 chromeos::FORMAT_ERROR_UNKNOWN, "/device/source_path");
436 // Tests the case when formatting completes successfully.
437 TEST_F(DiskMountManagerTest, Format_FormatSuccess) {
438 // Set up cros disks client mocks.
439 // Both unmount and format device cals are successful in this test.
441 // Set up expectations for observer mock.
442 // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED
443 // events (all of them without an error set).
445 InSequence s;
447 EXPECT_CALL(observer_,
448 OnMountEvent(DiskMountManager::UNMOUNTING,
449 chromeos::MOUNT_ERROR_NONE,
450 Field(&DiskMountManager::MountPointInfo::mount_path,
451 "/device/mount_path")))
452 .Times(1);
454 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
455 chromeos::FORMAT_ERROR_NONE,
456 "/device/source_path"))
457 .Times(1);
459 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
460 chromeos::FORMAT_ERROR_NONE,
461 "/device/source_path"))
462 .Times(1);
465 // Start the test.
466 DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
468 // Wait for Unmount and Format calls to end.
469 message_loop_.RunUntilIdle();
471 EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
472 EXPECT_EQ("/device/mount_path",
473 fake_cros_disks_client_->last_unmount_device_path());
474 EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
475 fake_cros_disks_client_->last_unmount_options());
476 EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
477 EXPECT_EQ("/device/source_path",
478 fake_cros_disks_client_->last_format_device_path());
479 EXPECT_EQ("vfat", fake_cros_disks_client_->last_format_filesystem());
481 // The device should be unmounted by now.
482 EXPECT_FALSE(HasMountPoint("/device/mount_path"));
484 // Simulate cros_disks reporting success.
485 fake_cros_disks_client_->SendFormatCompletedEvent(
486 chromeos::FORMAT_ERROR_NONE, "/device/source_path");
489 // Tests that it's possible to format the device twice in a row (this may not be
490 // true if the list of pending formats is not properly cleared).
491 TEST_F(DiskMountManagerTest, Format_ConsecutiveFormatCalls) {
492 // All unmount and format device cals are successful in this test.
493 // Each of the should be made twice (once for each formatting task).
495 // Set up expectations for observer mock.
496 // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED
497 // events (all of them without an error set) twice (once for each formatting
498 // task).
499 // Also, there should be a MOUNTING event when the device remounting is
500 // simulated.
501 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
502 chromeos::FORMAT_ERROR_NONE,
503 "/device/source_path"))
504 .Times(2);
506 EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
507 chromeos::FORMAT_ERROR_NONE,
508 "/device/source_path"))
509 .Times(2);
511 EXPECT_CALL(observer_,
512 OnMountEvent(DiskMountManager::UNMOUNTING,
513 chromeos::MOUNT_ERROR_NONE,
514 Field(&DiskMountManager::MountPointInfo::mount_path,
515 "/device/mount_path")))
516 .Times(2);
518 EXPECT_CALL(observer_,
519 OnMountEvent(DiskMountManager::MOUNTING,
520 chromeos::MOUNT_ERROR_NONE,
521 Field(&DiskMountManager::MountPointInfo::mount_path,
522 "/device/mount_path")))
523 .Times(1);
525 // Start the test.
526 DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
528 // Wait for Unmount and Format calls to end.
529 message_loop_.RunUntilIdle();
531 EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
532 EXPECT_EQ("/device/mount_path",
533 fake_cros_disks_client_->last_unmount_device_path());
534 EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
535 fake_cros_disks_client_->last_unmount_options());
536 EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
537 EXPECT_EQ("/device/source_path",
538 fake_cros_disks_client_->last_format_device_path());
539 EXPECT_EQ("vfat", fake_cros_disks_client_->last_format_filesystem());
541 // The device should be unmounted by now.
542 EXPECT_FALSE(HasMountPoint("/device/mount_path"));
544 // Simulate cros_disks reporting success.
545 fake_cros_disks_client_->SendFormatCompletedEvent(
546 chromeos::FORMAT_ERROR_NONE, "/device/source_path");
548 // Simulate the device remounting.
549 fake_cros_disks_client_->SendMountCompletedEvent(
550 chromeos::MOUNT_ERROR_NONE,
551 "/device/source_path",
552 chromeos::MOUNT_TYPE_DEVICE,
553 "/device/mount_path");
555 EXPECT_TRUE(HasMountPoint("/device/mount_path"));
557 // Try formatting again.
558 DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
560 // Wait for Unmount and Format calls to end.
561 message_loop_.RunUntilIdle();
563 EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
564 EXPECT_EQ("/device/mount_path",
565 fake_cros_disks_client_->last_unmount_device_path());
566 EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
567 fake_cros_disks_client_->last_unmount_options());
568 EXPECT_EQ(2, fake_cros_disks_client_->format_call_count());
569 EXPECT_EQ("/device/source_path",
570 fake_cros_disks_client_->last_format_device_path());
571 EXPECT_EQ("vfat", fake_cros_disks_client_->last_format_filesystem());
573 // Simulate cros_disks reporting success.
574 fake_cros_disks_client_->SendFormatCompletedEvent(
575 chromeos::FORMAT_ERROR_NONE, "/device/source_path");
578 } // namespace