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/fake_dbus_thread_manager.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::FakeDBusThreadManager;
     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     FakeDBusThreadManager* fake_thread_manager = new FakeDBusThreadManager();
    125     fake_cros_disks_client_ = new FakeCrosDisksClient;
    126     fake_thread_manager->SetCrosDisksClient(
    127         scoped_ptr<CrosDisksClient>(fake_cros_disks_client_));
    128 
    129     DBusThreadManager::InitializeForTesting(fake_thread_manager);
    130 
    131     DiskMountManager::Initialize();
    132 
    133     InitDisksAndMountPoints();
    134 
    135     DiskMountManager::GetInstance()->AddObserver(&observer_);
    136   }
    137 
    138   // Shuts down dbus thread manager and disk moutn manager used in the test.
    139   virtual void TearDown() {
    140     DiskMountManager::GetInstance()->RemoveObserver(&observer_);
    141     DiskMountManager::Shutdown();
    142     DBusThreadManager::Shutdown();
    143   }
    144 
    145  protected:
    146   // Checks if disk mount manager contains a mount point with specified moutn
    147   // path.
    148   bool HasMountPoint(const std::string& mount_path) {
    149     const DiskMountManager::MountPointMap& mount_points =
    150         DiskMountManager::GetInstance()->mount_points();
    151     return mount_points.find(mount_path) != mount_points.end();
    152   }
    153 
    154  private:
    155   // Adds a new disk to the disk mount manager.
    156   void AddTestDisk(const TestDiskInfo& disk) {
    157     EXPECT_TRUE(DiskMountManager::GetInstance()->AddDiskForTest(
    158         new DiskMountManager::Disk(disk.source_path,
    159                                    disk.mount_path,
    160                                    disk.system_path,
    161                                    disk.file_path,
    162                                    disk.device_label,
    163                                    disk.drive_label,
    164                                    disk.vendor_id,
    165                                    disk.vendor_name,
    166                                    disk.product_id,
    167                                    disk.product_name,
    168                                    disk.fs_uuid,
    169                                    disk.system_path_prefix,
    170                                    disk.device_type,
    171                                    disk.size_in_bytes,
    172                                    disk.is_parent,
    173                                    disk.is_read_only,
    174                                    disk.has_media,
    175                                    disk.on_boot_device,
    176                                    disk.is_hidden)));
    177   }
    178 
    179   // Adds a new mount point to the disk mount manager.
    180   // If the moutn point is a device mount point, disk with its source path
    181   // should already be added to the disk mount manager.
    182   void AddTestMountPoint(const TestMountPointInfo& mount_point) {
    183     EXPECT_TRUE(DiskMountManager::GetInstance()->AddMountPointForTest(
    184         DiskMountManager::MountPointInfo(mount_point.source_path,
    185                                          mount_point.mount_path,
    186                                          mount_point.mount_type,
    187                                          mount_point.mount_condition)));
    188   }
    189 
    190   // Adds disks and mount points to disk mount manager.
    191   void InitDisksAndMountPoints() {
    192     // Disks should be  added first (when adding device mount points it is
    193     // expected that the corresponding disk is already added).
    194     for (size_t i = 0; i < arraysize(kTestDisks); i++)
    195       AddTestDisk(kTestDisks[i]);
    196 
    197     for (size_t i = 0; i < arraysize(kTestMountPoints); i++)
    198       AddTestMountPoint(kTestMountPoints[i]);
    199   }
    200 
    201  protected:
    202   chromeos::FakeCrosDisksClient* fake_cros_disks_client_;
    203   MockDiskMountManagerObserver observer_;
    204   base::MessageLoopForUI message_loop_;
    205 };
    206 
    207 // Tests that the observer gets notified on attempt to format non existent mount
    208 // point.
    209 TEST_F(DiskMountManagerTest, Format_NotMounted) {
    210   EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    211                                        chromeos::FORMAT_ERROR_UNKNOWN,
    212                                        "/mount/non_existent"))
    213       .Times(1);
    214   DiskMountManager::GetInstance()->FormatMountedDevice("/mount/non_existent");
    215 }
    216 
    217 // Tests that it is not possible to format archive mount point.
    218 TEST_F(DiskMountManagerTest, Format_Archive) {
    219   EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    220                                        chromeos::FORMAT_ERROR_UNKNOWN,
    221                                        "/archive/source_path"))
    222       .Times(1);
    223 
    224   DiskMountManager::GetInstance()->FormatMountedDevice("/archive/mount_path");
    225 }
    226 
    227 // Tests that format fails if the device cannot be unmounted.
    228 TEST_F(DiskMountManagerTest, Format_FailToUnmount) {
    229   // Before formatting mounted device, the device should be unmounted.
    230   // In this test unmount will fail, and there should be no attempt to
    231   // format the device.
    232 
    233   // Set up expectations for observer mock.
    234   // Observer should be notified that unmount attempt fails and format task
    235   // failed to start.
    236   {
    237     InSequence s;
    238 
    239     EXPECT_CALL(observer_,
    240         OnMountEvent(DiskMountManager::UNMOUNTING,
    241                      chromeos::MOUNT_ERROR_INTERNAL,
    242                      Field(&DiskMountManager::MountPointInfo::mount_path,
    243                            "/device/mount_path")))
    244         .Times(1);
    245 
    246     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    247                                          chromeos::FORMAT_ERROR_UNKNOWN,
    248                                          "/device/source_path"))
    249         .Times(1);
    250   }
    251 
    252   fake_cros_disks_client_->MakeUnmountFail();
    253   // Start test.
    254   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    255 
    256   // Cros disks will respond asynchronoulsy, so let's drain the message loop.
    257   message_loop_.RunUntilIdle();
    258 
    259   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    260   EXPECT_EQ("/device/mount_path",
    261             fake_cros_disks_client_->last_unmount_device_path());
    262   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    263             fake_cros_disks_client_->last_unmount_options());
    264   EXPECT_EQ(0, fake_cros_disks_client_->format_device_call_count());
    265 
    266   // The device mount should still be here.
    267   EXPECT_TRUE(HasMountPoint("/device/mount_path"));
    268 }
    269 
    270 // Tests that observer is notified when cros disks fails to start format
    271 // process.
    272 TEST_F(DiskMountManagerTest, Format_FormatFailsToStart) {
    273   // Before formatting mounted device, the device should be unmounted.
    274   // In this test, unmount will succeed, but call to FormatDevice method will
    275   // fail.
    276 
    277   // Set up expectations for observer mock.
    278   // Observer should be notified that the device was unmounted and format task
    279   // failed to start.
    280   {
    281     InSequence s;
    282 
    283     EXPECT_CALL(observer_,
    284         OnMountEvent(DiskMountManager::UNMOUNTING,
    285                      chromeos::MOUNT_ERROR_NONE,
    286                      Field(&DiskMountManager::MountPointInfo::mount_path,
    287                            "/device/mount_path")))
    288         .Times(1);
    289 
    290     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    291                                          chromeos::FORMAT_ERROR_UNKNOWN,
    292                                          "/device/source_path"))
    293         .Times(1);
    294   }
    295 
    296   fake_cros_disks_client_->MakeFormatDeviceFail();
    297   // Start the test.
    298   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    299 
    300   // Cros disks will respond asynchronoulsy, so let's drain the message loop.
    301   message_loop_.RunUntilIdle();
    302 
    303   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    304   EXPECT_EQ("/device/mount_path",
    305             fake_cros_disks_client_->last_unmount_device_path());
    306   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    307             fake_cros_disks_client_->last_unmount_options());
    308   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    309   EXPECT_EQ("/device/source_path",
    310             fake_cros_disks_client_->last_format_device_device_path());
    311   EXPECT_EQ("vfat",
    312             fake_cros_disks_client_->last_format_device_filesystem());
    313 
    314   // The device mount should be gone.
    315   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    316 }
    317 
    318 // Tests the case where there are two format requests for the same device.
    319 TEST_F(DiskMountManagerTest, Format_ConcurrentFormatCalls) {
    320   // Only the first format request should be processed (the second unmount
    321   // request fails because the device is already unmounted at that point).
    322   // CrosDisksClient will report that the format process for the first request
    323   // is successfully started.
    324 
    325   // Set up expectations for observer mock.
    326   // The observer should get two FORMAT_STARTED events, one for each format
    327   // request, but with different error codes (the formatting will be started
    328   // only for the first request).
    329   // There should be only one UNMOUNTING event. The result of the second one
    330   // should not be reported as the mount point will go away after the first
    331   // request.
    332   //
    333   // Note that in this test the format completion signal will not be simulated,
    334   // so the observer should not get FORMAT_COMPLETED signal.
    335   {
    336     InSequence s;
    337 
    338     EXPECT_CALL(observer_,
    339         OnMountEvent(DiskMountManager::UNMOUNTING,
    340                      chromeos::MOUNT_ERROR_NONE,
    341                      Field(&DiskMountManager::MountPointInfo::mount_path,
    342                            "/device/mount_path")))
    343         .Times(1);
    344 
    345     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    346                                          chromeos::FORMAT_ERROR_UNKNOWN,
    347                                          "/device/source_path"))
    348         .Times(1);
    349 
    350     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    351                                          chromeos::FORMAT_ERROR_NONE,
    352                                          "/device/source_path"))
    353         .Times(1);
    354   }
    355 
    356   fake_cros_disks_client_->set_unmount_listener(
    357       base::Bind(&FakeCrosDisksClient::MakeUnmountFail,
    358                  base::Unretained(fake_cros_disks_client_)));
    359   // Start the test.
    360   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    361   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    362 
    363   // Cros disks will respond asynchronoulsy, so let's drain the message loop.
    364   message_loop_.RunUntilIdle();
    365 
    366   EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
    367   EXPECT_EQ("/device/mount_path",
    368             fake_cros_disks_client_->last_unmount_device_path());
    369   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    370             fake_cros_disks_client_->last_unmount_options());
    371   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    372   EXPECT_EQ("/device/source_path",
    373             fake_cros_disks_client_->last_format_device_device_path());
    374   EXPECT_EQ("vfat",
    375             fake_cros_disks_client_->last_format_device_filesystem());
    376 
    377   // The device mount should be gone.
    378   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    379 }
    380 
    381 // Tests the case when the format process actually starts and fails.
    382 TEST_F(DiskMountManagerTest, Format_FormatFails) {
    383   // Both unmount and format device cals are successfull in this test.
    384 
    385   // Set up expectations for observer mock.
    386   // The observer should get notified that the device was unmounted and that
    387   // formatting has started.
    388   // After the formatting starts, the test will simulate failing
    389   // FORMATTING_FINISHED signal, so the observer should also be notified the
    390   // formatting has failed (FORMAT_COMPLETED event).
    391   {
    392     InSequence s;
    393 
    394     EXPECT_CALL(observer_,
    395         OnMountEvent(DiskMountManager::UNMOUNTING,
    396                      chromeos::MOUNT_ERROR_NONE,
    397                      Field(&DiskMountManager::MountPointInfo::mount_path,
    398                            "/device/mount_path")))
    399         .Times(1);
    400 
    401     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    402                                          chromeos::FORMAT_ERROR_NONE,
    403                                          "/device/source_path"))
    404         .Times(1);
    405 
    406     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
    407                                          chromeos::FORMAT_ERROR_UNKNOWN,
    408                                          "/device/source_path"))
    409         .Times(1);
    410   }
    411 
    412   // Start the test.
    413   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    414 
    415   // Wait for Unmount and FormatDevice calls to end.
    416   message_loop_.RunUntilIdle();
    417 
    418   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    419   EXPECT_EQ("/device/mount_path",
    420             fake_cros_disks_client_->last_unmount_device_path());
    421   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    422             fake_cros_disks_client_->last_unmount_options());
    423   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    424   EXPECT_EQ("/device/source_path",
    425             fake_cros_disks_client_->last_format_device_device_path());
    426   EXPECT_EQ("vfat",
    427             fake_cros_disks_client_->last_format_device_filesystem());
    428 
    429   // The device should be unmounted by now.
    430   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    431 
    432   // Send failing FORMATTING_FINISHED signal.
    433   // The failure is marked by ! in fromt of the path (but this should change
    434   // soon).
    435   fake_cros_disks_client_->SendMountEvent(
    436       chromeos::CROS_DISKS_FORMATTING_FINISHED, "!/device/source_path");
    437 }
    438 
    439 // Tests the same case as Format_FormatFails, but the FORMATTING_FINISHED event
    440 // is sent with file_path of the formatted device (instead of its device path).
    441 TEST_F(DiskMountManagerTest, Format_FormatFailsAndReturnFilePath) {
    442   // Set up expectations for observer mock.
    443   {
    444     InSequence s;
    445 
    446     EXPECT_CALL(observer_,
    447         OnMountEvent(DiskMountManager::UNMOUNTING,
    448                      chromeos::MOUNT_ERROR_NONE,
    449                      Field(&DiskMountManager::MountPointInfo::mount_path,
    450                            "/device/mount_path")))
    451         .Times(1);
    452 
    453     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    454                                          chromeos::FORMAT_ERROR_NONE,
    455                                          "/device/source_path"))
    456         .Times(1);
    457 
    458     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
    459                                          chromeos::FORMAT_ERROR_UNKNOWN,
    460                                          "/device/source_path"))
    461         .Times(1);
    462   }
    463 
    464   // Start test.
    465   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    466 
    467   // Wait for Unmount and FormatDevice calls to end.
    468   message_loop_.RunUntilIdle();
    469 
    470   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    471   EXPECT_EQ("/device/mount_path",
    472             fake_cros_disks_client_->last_unmount_device_path());
    473   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    474             fake_cros_disks_client_->last_unmount_options());
    475   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    476   EXPECT_EQ("/device/source_path",
    477             fake_cros_disks_client_->last_format_device_device_path());
    478   EXPECT_EQ("vfat",
    479             fake_cros_disks_client_->last_format_device_filesystem());
    480 
    481   // The device should be unmounted by now.
    482   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    483 
    484   // Send failing FORMATTING_FINISHED signal with the device's file path.
    485   fake_cros_disks_client_->SendMountEvent(
    486       chromeos::CROS_DISKS_FORMATTING_FINISHED, "!/device/file_path");
    487 }
    488 
    489 // Tests the case when formatting completes successfully.
    490 TEST_F(DiskMountManagerTest, Format_FormatSuccess) {
    491   // Set up cros disks client mocks.
    492   // Both unmount and format device cals are successfull in this test.
    493 
    494   // Set up expectations for observer mock.
    495   // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED
    496   // events (all of them without an error set).
    497   {
    498     InSequence s;
    499 
    500     EXPECT_CALL(observer_,
    501         OnMountEvent(DiskMountManager::UNMOUNTING,
    502                      chromeos::MOUNT_ERROR_NONE,
    503                      Field(&DiskMountManager::MountPointInfo::mount_path,
    504                            "/device/mount_path")))
    505         .Times(1);
    506 
    507     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    508                                          chromeos::FORMAT_ERROR_NONE,
    509                                          "/device/source_path"))
    510         .Times(1);
    511 
    512     EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
    513                                          chromeos::FORMAT_ERROR_NONE,
    514                                          "/device/source_path"))
    515         .Times(1);
    516   }
    517 
    518   // Start the test.
    519   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    520 
    521   // Wait for Unmount and FormatDevice calls to end.
    522   message_loop_.RunUntilIdle();
    523 
    524   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    525   EXPECT_EQ("/device/mount_path",
    526             fake_cros_disks_client_->last_unmount_device_path());
    527   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    528             fake_cros_disks_client_->last_unmount_options());
    529   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    530   EXPECT_EQ("/device/source_path",
    531             fake_cros_disks_client_->last_format_device_device_path());
    532   EXPECT_EQ("vfat",
    533             fake_cros_disks_client_->last_format_device_filesystem());
    534 
    535   // The device should be unmounted by now.
    536   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    537 
    538   // Simulate cros_disks reporting success.
    539   fake_cros_disks_client_->SendMountEvent(
    540       chromeos::CROS_DISKS_FORMATTING_FINISHED, "/device/source_path");
    541 }
    542 
    543 // Tests that it's possible to format the device twice in a row (this may not be
    544 // true if the list of pending formats is not properly cleared).
    545 TEST_F(DiskMountManagerTest, Format_ConsecutiveFormatCalls) {
    546   // All unmount and format device cals are successfull in this test.
    547   // Each of the should be made twice (once for each formatting task).
    548 
    549   // Set up expectations for observer mock.
    550   // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED
    551   // events (all of them without an error set) twice (once for each formatting
    552   // task).
    553   // Also, there should be a MOUNTING event when the device remounting is
    554   // simulated.
    555   EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED,
    556                                        chromeos::FORMAT_ERROR_NONE,
    557                                        "/device/source_path"))
    558       .Times(2);
    559 
    560   EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED,
    561                                        chromeos::FORMAT_ERROR_NONE,
    562                                        "/device/source_path"))
    563       .Times(2);
    564 
    565   EXPECT_CALL(observer_,
    566       OnMountEvent(DiskMountManager::UNMOUNTING,
    567                    chromeos::MOUNT_ERROR_NONE,
    568                    Field(&DiskMountManager::MountPointInfo::mount_path,
    569                          "/device/mount_path")))
    570       .Times(2);
    571 
    572   EXPECT_CALL(observer_,
    573       OnMountEvent(DiskMountManager::MOUNTING,
    574                    chromeos::MOUNT_ERROR_NONE,
    575                    Field(&DiskMountManager::MountPointInfo::mount_path,
    576                          "/device/mount_path")))
    577       .Times(1);
    578 
    579   // Start the test.
    580   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    581 
    582   // Wait for Unmount and FormatDevice calls to end.
    583   message_loop_.RunUntilIdle();
    584 
    585   EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
    586   EXPECT_EQ("/device/mount_path",
    587             fake_cros_disks_client_->last_unmount_device_path());
    588   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    589             fake_cros_disks_client_->last_unmount_options());
    590   EXPECT_EQ(1, fake_cros_disks_client_->format_device_call_count());
    591   EXPECT_EQ("/device/source_path",
    592             fake_cros_disks_client_->last_format_device_device_path());
    593   EXPECT_EQ("vfat",
    594             fake_cros_disks_client_->last_format_device_filesystem());
    595 
    596   // The device should be unmounted by now.
    597   EXPECT_FALSE(HasMountPoint("/device/mount_path"));
    598 
    599   // Simulate cros_disks reporting success.
    600   fake_cros_disks_client_->SendMountEvent(
    601       chromeos::CROS_DISKS_FORMATTING_FINISHED, "/device/source_path");
    602 
    603   // Simulate the device remounting.
    604   fake_cros_disks_client_->SendMountCompletedEvent(
    605       chromeos::MOUNT_ERROR_NONE,
    606       "/device/source_path",
    607       chromeos::MOUNT_TYPE_DEVICE,
    608       "/device/mount_path");
    609 
    610   EXPECT_TRUE(HasMountPoint("/device/mount_path"));
    611 
    612   // Try formatting again.
    613   DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path");
    614 
    615   // Wait for Unmount and FormatDevice calls to end.
    616   message_loop_.RunUntilIdle();
    617 
    618   EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
    619   EXPECT_EQ("/device/mount_path",
    620             fake_cros_disks_client_->last_unmount_device_path());
    621   EXPECT_EQ(chromeos::UNMOUNT_OPTIONS_NONE,
    622             fake_cros_disks_client_->last_unmount_options());
    623   EXPECT_EQ(2, fake_cros_disks_client_->format_device_call_count());
    624   EXPECT_EQ("/device/source_path",
    625             fake_cros_disks_client_->last_format_device_device_path());
    626   EXPECT_EQ("vfat",
    627             fake_cros_disks_client_->last_format_device_filesystem());
    628 
    629   // Simulate cros_disks reporting success.
    630   fake_cros_disks_client_->SendMountEvent(
    631       chromeos::CROS_DISKS_FORMATTING_FINISHED, "/device/source_path");
    632 }
    633 
    634 }  // namespace
    635