Home | History | Annotate | Download | only in disks
      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 #include "base/bind.h"
      6 #include "base/message_loop/message_loop.h"
      7 #include "chromeos/dbus/fake_cros_disks_client.h"
      8 #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.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"
     12 
     13 using chromeos::disks::DiskMountManager;
     14 using chromeos::CrosDisksClient;
     15 using chromeos::DBusThreadManager;
     16 using chromeos::FakeCrosDisksClient;
     17 using chromeos::MockDBusThreadManagerWithoutGMock;
     18 using testing::_;
     19 using testing::Field;
     20 using testing::InSequence;
     21 
     22 namespace {
     23 
     24 // Holds information needed to create a DiskMountManager::Disk instance.
     25 struct TestDiskInfo {
     26   const char* source_path;
     27   const char* mount_path;
     28   const char* system_path;
     29   const char* file_path;
     30   const char* device_label;
     31   const char* drive_label;
     32   const char* vendor_id;
     33   const char* vendor_name;
     34   const char* product_id;
     35   const char* product_name;
     36   const char* fs_uuid;
     37   const char* system_path_prefix;
     38   chromeos::DeviceType device_type;
     39   uint64 size_in_bytes;
     40   bool is_parent;
     41   bool is_read_only;
     42   bool has_media;
     43   bool on_boot_device;
     44   bool is_hidden;
     45 };
     46 
     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;
     53 };
     54 
     55 // List of disks held in DiskMountManager at the begining of the test.
     56 const TestDiskInfo kTestDisks[] = {
     57   {
     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     false  // is hidden
     77   },
     78 };
     79 
     80 // List of mount points  held in DiskMountManager at the begining of the test.
     81 const TestMountPointInfo kTestMountPoints[] = {
     82   {
     83     "/archive/source_path",
     84     "/archive/mount_path",
     85     chromeos::MOUNT_TYPE_ARCHIVE,
     86     chromeos::disks::MOUNT_CONDITION_NONE
     87   },
     88   {
     89     "/device/source_path",
     90     "/device/mount_path",
     91     chromeos::MOUNT_TYPE_DEVICE,
     92     chromeos::disks::MOUNT_CONDITION_NONE
     93   },
     94 };
     95 
     96 // Mocks DiskMountManager observer.
     97 class MockDiskMountManagerObserver : public DiskMountManager::Observer {
     98  public:
     99   virtual ~MockDiskMountManagerObserver() {}
    100 
    101   MOCK_METHOD2(OnDiskEvent, void(DiskMountManager::DiskEvent event,
    102                                  const DiskMountManager::Disk* disk));
    103   MOCK_METHOD2(OnDeviceEvent, void(DiskMountManager::DeviceEvent event,
    104                                    const std::string& device_path));
    105   MOCK_METHOD3(OnMountEvent,
    106       void(DiskMountManager::MountEvent event,
    107            chromeos::MountError error_code,
    108            const DiskMountManager::MountPointInfo& mount_point));
    109   MOCK_METHOD3(OnFormatEvent,
    110       void(DiskMountManager::FormatEvent event,
    111            chromeos::FormatError error_code,
    112            const std::string& device_path));
    113 };
    114 
    115 class DiskMountManagerTest : public testing::Test {
    116  public:
    117   DiskMountManagerTest() {}
    118   virtual ~DiskMountManagerTest() {}
    119 
    120   // Sets up test dbus tread manager and disks mount manager.
    121   // Initializes disk mount manager disks and mount points.
    122   // Adds a test observer to the disk mount manager.
    123   virtual void SetUp() {
    124     MockDBusThreadManagerWithoutGMock* mock_thread_manager =
    125         new MockDBusThreadManagerWithoutGMock();
    126     DBusThreadManager::InitializeForTesting(mock_thread_manager);
    127 
    128     fake_cros_disks_client_ = mock_thread_manager->fake_cros_disks_client();
    129 
    130     DiskMountManager::Initialize();
    131 
    132     InitDisksAndMountPoints();
    133 
    134     DiskMountManager::GetInstance()->AddObserver(&observer_);
    135   }
    136 
    137   // Shuts down dbus thread manager and disk moutn manager used in the test.
    138   virtual void TearDown() {
    139     DiskMountManager::GetInstance()->RemoveObserver(&observer_);
    140     DiskMountManager::Shutdown();
    141     DBusThreadManager::Shutdown();
    142   }
    143 
    144  protected:
    145   // Checks if disk mount manager contains a mount point with specified moutn
    146   // path.
    147   bool HasMountPoint(const std::string& mount_path) {
    148     const DiskMountManager::MountPointMap& mount_points =
    149         DiskMountManager::GetInstance()->mount_points();
    150     return mount_points.find(mount_path) != mount_points.end();
    151   }
    152 
    153  private:
    154   // Adds a new disk to the disk mount manager.
    155   void AddTestDisk(const TestDiskInfo& disk) {
    156     EXPECT_TRUE(DiskMountManager::GetInstance()->AddDiskForTest(
    157         new DiskMountManager::Disk(disk.source_path,
    158                                    disk.mount_path,
    159                                    disk.system_path,
    160                                    disk.file_path,
    161                                    disk.device_label,
    162                                    disk.drive_label,
    163                                    disk.vendor_id,
    164                                    disk.vendor_name,
    165                                    disk.product_id,
    166                                    disk.product_name,
    167                                    disk.fs_uuid,
    168                                    disk.system_path_prefix,
    169                                    disk.device_type,
    170                                    disk.size_in_bytes,
    171                                    disk.is_parent,
    172                                    disk.is_read_only,
    173                                    disk.has_media,
    174                                    disk.on_boot_device,
    175                                    disk.is_hidden)));
    176   }
    177 
    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)));
    187   }
    188 
    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]);
    195 
    196     for (size_t i = 0; i < arraysize(kTestMountPoints); i++)
    197       AddTestMountPoint(kTestMountPoints[i]);
    198   }
    199 
    200  protected:
    201   chromeos::FakeCrosDisksClient* fake_cros_disks_client_;
    202   MockDiskMountManagerObserver observer_;
    203   base::MessageLoopForUI message_loop_;
    204 };
    205 
    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_STARTED,
    210                                        chromeos::FORMAT_ERROR_UNKNOWN,
    211                                        "/mount/non_existent"))
    212       .Times(1);
    213   DiskMountManager::GetInstance()->FormatMountedDevice("/mount/non_existent");
    214 }
    215 
    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_STARTED,
    219                                        chromeos::FORMAT_ERROR_UNKNOWN,
    220                                        "/archive/source_path"))
    221       .Times(1);
    222 
    223   DiskMountManager::GetInstance()->FormatMountedDevice("/archive/mount_path");
    224 }
    225 
    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.
    231 
    232   // Set up expectations for observer mock.
    233   // Observer should be notified that unmount attempt fails and format task
    234   // failed to start.
    235   {
    236     InSequence s;
    237 
    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);
    244 
    245     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    246                                          chromeos::FORMAT_ERROR_UNKNOWN,
    247                                          "/device/source_path"))
    248         .Times(1);
    249   }
    250 
    251   fake_cros_disks_client_->MakeUnmountFail();
    252   // Start test.
    253   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    254 
    255   // Cros disks will respond asynchronoulsy, so let's drain the message loop.
    256   message_loop_.RunUntilIdle();
    257 
    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_device_call_count());
    264 
    265   // The device mount should still be here.
    266   EXPECT_TRUE(HasMountPoint("/device/mount_path"));
    267 }
    268 
    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 FormatDevice method will
    274   // fail.
    275 
    276   // Set up expectations for observer mock.
    277   // Observer should be notified that the device was unmounted and format task
    278   // failed to start.
    279   {
    280     InSequence s;
    281 
    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);
    288 
    289     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    290                                          chromeos::FORMAT_ERROR_UNKNOWN,
    291                                          "/device/source_path"))
    292         .Times(1);
    293   }
    294 
    295   fake_cros_disks_client_->MakeFormatDeviceFail();
    296   // Start the test.
    297   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    298 
    299   // Cros disks will respond asynchronoulsy, so let's drain the message loop.
    300   message_loop_.RunUntilIdle();
    301 
    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_device_call_count());
    308   EXPECT_EQ("/device/source_path",
    309             fake_cros_disks_client_->last_format_device_device_path());
    310   EXPECT_EQ("vfat",
    311             fake_cros_disks_client_->last_format_device_filesystem());
    312 
    313   // The device mount should be gone.
    314   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    315 }
    316 
    317 // Tests the case where there are two format requests for the same device.
    318 TEST_F(DiskMountManagerTest, Format_ConcurrentFormatCalls) {
    319   // Only the first format request should be processed (the second unmount
    320   // request fails because the device is already unmounted at that point).
    321   // CrosDisksClient will report that the format process for the first request
    322   // is successfully started.
    323 
    324   // Set up expectations for observer mock.
    325   // The observer should get two FORMAT_STARTED events, one for each format
    326   // request, but with different error codes (the formatting will be started
    327   // only for the first request).
    328   // There should be only one UNMOUNTING event. The result of the second one
    329   // should not be reported as the mount point will go away after the first
    330   // request.
    331   //
    332   // Note that in this test the format completion signal will not be simulated,
    333   // so the observer should not get FORMAT_COMPLETED signal.
    334   {
    335     InSequence s;
    336 
    337     EXPECT_CALL(observer_,
    338         OnMountEvent(DiskMountManager::UNMOUNTING,
    339                      chromeos::MOUNT_ERROR_NONE,
    340                      Field(&DiskMountManager::MountPointInfo::mount_path,
    341                            "/device/mount_path")))
    342         .Times(1);
    343 
    344     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    345                                          chromeos::FORMAT_ERROR_UNKNOWN,
    346                                          "/device/source_path"))
    347         .Times(1);
    348 
    349     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    350                                          chromeos::FORMAT_ERROR_NONE,
    351                                          "/device/source_path"))
    352         .Times(1);
    353   }
    354 
    355   fake_cros_disks_client_->set_unmount_listener(
    356       base::Bind(&FakeCrosDisksClient::MakeUnmountFail,
    357                  base::Unretained(fake_cros_disks_client_)));
    358   // Start the test.
    359   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    360   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    361 
    362   // Cros disks will respond asynchronoulsy, so let's drain the message loop.
    363   message_loop_.RunUntilIdle();
    364 
    365   EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
    366   EXPECT_EQ("/device/mount_path",
    367             fake_cros_disks_client_->last_unmount_device_path());
    368   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    369             fake_cros_disks_client_->last_unmount_options());
    370   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    371   EXPECT_EQ("/device/source_path",
    372             fake_cros_disks_client_->last_format_device_device_path());
    373   EXPECT_EQ("vfat",
    374             fake_cros_disks_client_->last_format_device_filesystem());
    375 
    376   // The device mount should be gone.
    377   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    378 }
    379 
    380 // Tests the case when the format process actually starts and fails.
    381 TEST_F(DiskMountManagerTest, Format_FormatFails) {
    382   // Both unmount and format device cals are successfull in this test.
    383 
    384   // Set up expectations for observer mock.
    385   // The observer should get notified that the device was unmounted and that
    386   // formatting has started.
    387   // After the formatting starts, the test will simulate failing
    388   // FORMATTING_FINISHED signal, so the observer should also be notified the
    389   // formatting has failed (FORMAT_COMPLETED event).
    390   {
    391     InSequence s;
    392 
    393     EXPECT_CALL(observer_,
    394         OnMountEvent(DiskMountManager::UNMOUNTING,
    395                      chromeos::MOUNT_ERROR_NONE,
    396                      Field(&DiskMountManager::MountPointInfo::mount_path,
    397                            "/device/mount_path")))
    398         .Times(1);
    399 
    400     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    401                                          chromeos::FORMAT_ERROR_NONE,
    402                                          "/device/source_path"))
    403         .Times(1);
    404 
    405     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
    406                                          chromeos::FORMAT_ERROR_UNKNOWN,
    407                                          "/device/source_path"))
    408         .Times(1);
    409   }
    410 
    411   // Start the test.
    412   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    413 
    414   // Wait for Unmount and FormatDevice calls to end.
    415   message_loop_.RunUntilIdle();
    416 
    417   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    418   EXPECT_EQ("/device/mount_path",
    419             fake_cros_disks_client_->last_unmount_device_path());
    420   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    421             fake_cros_disks_client_->last_unmount_options());
    422   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    423   EXPECT_EQ("/device/source_path",
    424             fake_cros_disks_client_->last_format_device_device_path());
    425   EXPECT_EQ("vfat",
    426             fake_cros_disks_client_->last_format_device_filesystem());
    427 
    428   // The device should be unmounted by now.
    429   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    430 
    431   // Send failing FORMATTING_FINISHED signal.
    432   // The failure is marked by ! in fromt of the path (but this should change
    433   // soon).
    434   fake_cros_disks_client_->SendMountEvent(
    435       chromeos::CROS_DISKS_FORMATTING_FINISHED, "!/device/source_path");
    436 }
    437 
    438 // Tests the same case as Format_FormatFails, but the FORMATTING_FINISHED event
    439 // is sent with file_path of the formatted device (instead of its device path).
    440 TEST_F(DiskMountManagerTest, Format_FormatFailsAndReturnFilePath) {
    441   // Set up expectations for observer mock.
    442   {
    443     InSequence s;
    444 
    445     EXPECT_CALL(observer_,
    446         OnMountEvent(DiskMountManager::UNMOUNTING,
    447                      chromeos::MOUNT_ERROR_NONE,
    448                      Field(&DiskMountManager::MountPointInfo::mount_path,
    449                            "/device/mount_path")))
    450         .Times(1);
    451 
    452     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    453                                          chromeos::FORMAT_ERROR_NONE,
    454                                          "/device/source_path"))
    455         .Times(1);
    456 
    457     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
    458                                          chromeos::FORMAT_ERROR_UNKNOWN,
    459                                          "/device/source_path"))
    460         .Times(1);
    461   }
    462 
    463   // Start test.
    464   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    465 
    466   // Wait for Unmount and FormatDevice calls to end.
    467   message_loop_.RunUntilIdle();
    468 
    469   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    470   EXPECT_EQ("/device/mount_path",
    471             fake_cros_disks_client_->last_unmount_device_path());
    472   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    473             fake_cros_disks_client_->last_unmount_options());
    474   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    475   EXPECT_EQ("/device/source_path",
    476             fake_cros_disks_client_->last_format_device_device_path());
    477   EXPECT_EQ("vfat",
    478             fake_cros_disks_client_->last_format_device_filesystem());
    479 
    480   // The device should be unmounted by now.
    481   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    482 
    483   // Send failing FORMATTING_FINISHED signal with the device's file path.
    484   fake_cros_disks_client_->SendMountEvent(
    485       chromeos::CROS_DISKS_FORMATTING_FINISHED, "!/device/file_path");
    486 }
    487 
    488 // Tests the case when formatting completes successfully.
    489 TEST_F(DiskMountManagerTest, Format_FormatSuccess) {
    490   // Set up cros disks client mocks.
    491   // Both unmount and format device cals are successfull in this test.
    492 
    493   // Set up expectations for observer mock.
    494   // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED
    495   // events (all of them without an error set).
    496   {
    497     InSequence s;
    498 
    499     EXPECT_CALL(observer_,
    500         OnMountEvent(DiskMountManager::UNMOUNTING,
    501                      chromeos::MOUNT_ERROR_NONE,
    502                      Field(&DiskMountManager::MountPointInfo::mount_path,
    503                            "/device/mount_path")))
    504         .Times(1);
    505 
    506     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    507                                          chromeos::FORMAT_ERROR_NONE,
    508                                          "/device/source_path"))
    509         .Times(1);
    510 
    511     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
    512                                          chromeos::FORMAT_ERROR_NONE,
    513                                          "/device/source_path"))
    514         .Times(1);
    515   }
    516 
    517   // Start the test.
    518   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    519 
    520   // Wait for Unmount and FormatDevice calls to end.
    521   message_loop_.RunUntilIdle();
    522 
    523   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    524   EXPECT_EQ("/device/mount_path",
    525             fake_cros_disks_client_->last_unmount_device_path());
    526   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    527             fake_cros_disks_client_->last_unmount_options());
    528   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    529   EXPECT_EQ("/device/source_path",
    530             fake_cros_disks_client_->last_format_device_device_path());
    531   EXPECT_EQ("vfat",
    532             fake_cros_disks_client_->last_format_device_filesystem());
    533 
    534   // The device should be unmounted by now.
    535   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    536 
    537   // Simulate cros_disks reporting success.
    538   fake_cros_disks_client_->SendMountEvent(
    539       chromeos::CROS_DISKS_FORMATTING_FINISHED, "/device/source_path");
    540 }
    541 
    542 // Tests that it's possible to format the device twice in a row (this may not be
    543 // true if the list of pending formats is not properly cleared).
    544 TEST_F(DiskMountManagerTest, Format_ConsecutiveFormatCalls) {
    545   // All unmount and format device cals are successfull in this test.
    546   // Each of the should be made twice (once for each formatting task).
    547 
    548   // Set up expectations for observer mock.
    549   // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED
    550   // events (all of them without an error set) twice (once for each formatting
    551   // task).
    552   // Also, there should be a MOUNTING event when the device remounting is
    553   // simulated.
    554   EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
    555                                        chromeos::FORMAT_ERROR_NONE,
    556                                        "/device/source_path"))
    557       .Times(2);
    558 
    559   EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    560                                        chromeos::FORMAT_ERROR_NONE,
    561                                        "/device/source_path"))
    562       .Times(2);
    563 
    564   EXPECT_CALL(observer_,
    565       OnMountEvent(DiskMountManager::UNMOUNTING,
    566                    chromeos::MOUNT_ERROR_NONE,
    567                    Field(&DiskMountManager::MountPointInfo::mount_path,
    568                          "/device/mount_path")))
    569       .Times(2);
    570 
    571   EXPECT_CALL(observer_,
    572       OnMountEvent(DiskMountManager::MOUNTING,
    573                    chromeos::MOUNT_ERROR_NONE,
    574                    Field(&DiskMountManager::MountPointInfo::mount_path,
    575                          "/device/mount_path")))
    576       .Times(1);
    577 
    578   // Start the test.
    579   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    580 
    581   // Wait for Unmount and FormatDevice calls to end.
    582   message_loop_.RunUntilIdle();
    583 
    584   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    585   EXPECT_EQ("/device/mount_path",
    586             fake_cros_disks_client_->last_unmount_device_path());
    587   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    588             fake_cros_disks_client_->last_unmount_options());
    589   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    590   EXPECT_EQ("/device/source_path",
    591             fake_cros_disks_client_->last_format_device_device_path());
    592   EXPECT_EQ("vfat",
    593             fake_cros_disks_client_->last_format_device_filesystem());
    594 
    595   // The device should be unmounted by now.
    596   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    597 
    598   // Simulate cros_disks reporting success.
    599   fake_cros_disks_client_->SendMountEvent(
    600       chromeos::CROS_DISKS_FORMATTING_FINISHED, "/device/source_path");
    601 
    602   // Simulate the device remounting.
    603   fake_cros_disks_client_->SendMountCompletedEvent(
    604       chromeos::MOUNT_ERROR_NONE,
    605       "/device/source_path",
    606       chromeos::MOUNT_TYPE_DEVICE,
    607       "/device/mount_path");
    608 
    609   EXPECT_TRUE(HasMountPoint("/device/mount_path"));
    610 
    611   // Try formatting again.
    612   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    613 
    614   // Wait for Unmount and FormatDevice calls to end.
    615   message_loop_.RunUntilIdle();
    616 
    617   EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
    618   EXPECT_EQ("/device/mount_path",
    619             fake_cros_disks_client_->last_unmount_device_path());
    620   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    621             fake_cros_disks_client_->last_unmount_options());
    622   EXPECT_EQ(2, fake_cros_disks_client_->format_device_call_count());
    623   EXPECT_EQ("/device/source_path",
    624             fake_cros_disks_client_->last_format_device_device_path());
    625   EXPECT_EQ("vfat",
    626             fake_cros_disks_client_->last_format_device_filesystem());
    627 
    628   // Simulate cros_disks reporting success.
    629   fake_cros_disks_client_->SendMountEvent(
    630       chromeos::CROS_DISKS_FORMATTING_FINISHED, "/device/source_path");
    631 }
    632 
    633 }  // namespace
    634 
    635