Chromium Code Reviews| Index: chromeos/disks/disk_mount_manager_unittest.cc |
| diff --git a/chromeos/disks/disk_mount_manager_unittest.cc b/chromeos/disks/disk_mount_manager_unittest.cc |
| index 314f9d2ba960da25d1cfa88672eaefebfb2dc5f3..3bb583e0180d22f85934cb0101debd909e57dfc1 100644 |
| --- a/chromeos/disks/disk_mount_manager_unittest.cc |
| +++ b/chromeos/disks/disk_mount_manager_unittest.cc |
| @@ -6,22 +6,23 @@ |
| #include <stdint.h> |
| #include "base/bind.h" |
| +#include "base/memory/ptr_util.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| +#include "base/strings/stringprintf.h" |
| #include "chromeos/dbus/dbus_thread_manager.h" |
| #include "chromeos/dbus/fake_cros_disks_client.h" |
| #include "chromeos/disks/disk_mount_manager.h" |
| -#include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| +using base::MakeUnique; |
| +using base::StringPrintf; |
| using chromeos::disks::DiskMountManager; |
| using chromeos::CrosDisksClient; |
| using chromeos::DBusThreadManager; |
| using chromeos::FakeCrosDisksClient; |
| -using testing::_; |
| -using testing::Field; |
| -using testing::InSequence; |
| -using testing::InvokeWithoutArgs; |
| +using chromeos::MountType; |
| +using chromeos::disks::MountCondition; |
| namespace { |
| @@ -152,31 +153,259 @@ const TestMountPointInfo kTestMountPoints[] = { |
| }, |
| }; |
| -// Mocks DiskMountManager observer. |
| +// Represents which function in |DiskMountManager::Observer| was invoked. |
| +enum ObserverEventType { |
| + DEVICE_EVENT, // OnDeviceEvent() |
| + DISK_EVENT, // OnDiskEvent() |
| + FORMAT_EVENT, // OnFormatEvent() |
| + MOUNT_EVENT // OnMountEvent() |
| +}; |
| + |
| +// Represents every event notified to |DiskMountManager::Observer|. |
| +struct ObserverEvent { |
|
fukino
2016/09/15 03:15:00
Virtual destructor should be required in this base
|
| + public: |
| + virtual ObserverEventType type() const = 0; |
| +}; |
| + |
| +// Represents an invocation of |DiskMountManager::Observer::OnDeviceEvent()|. |
| +struct DeviceEvent : public ObserverEvent { |
| + DiskMountManager::DeviceEvent event; |
| + std::string device_path; |
| + |
| + DeviceEvent() {} |
| + |
| + DeviceEvent(DiskMountManager::DeviceEvent event, |
| + const std::string& device_path) |
| + : event(event), device_path(device_path) {} |
| + |
| + ObserverEventType type() const override { return DEVICE_EVENT; } |
| + |
| + bool operator==(const DeviceEvent& other) const { |
| + return event == other.event && device_path == other.device_path; |
| + } |
| + |
| + std::string DebugString() const { |
| + return StringPrintf("OnDeviceEvent(%d, %s)", event, device_path.c_str()); |
| + } |
| +}; |
| + |
| +// Represents an invocation of |DiskMountManager::Observer::OnDiskEvent()|. |
| +struct DiskEvent : public ObserverEvent { |
| + DiskMountManager::DiskEvent event; |
| + std::unique_ptr<DiskMountManager::Disk> disk; |
| + |
| + DiskEvent(DiskMountManager::DiskEvent event, |
| + const DiskMountManager::Disk& disk) |
| + : event(event), |
| + disk(std::unique_ptr<DiskMountManager::Disk>( |
| + new DiskMountManager::Disk(disk))) {} |
| + |
| + DiskEvent(DiskEvent&& other) |
| + : event(other.event), disk(std::move(other.disk)) {} |
| + |
| + ObserverEventType type() const override { return DISK_EVENT; } |
| + |
| + bool operator==(const DiskEvent& other) const { |
| + return event == other.event && disk == other.disk; |
| + } |
| + |
| + std::string DebugString() const { |
| + return StringPrintf("OnDiskEvent(event=%d, device_path=%s, mount_path=%s", |
| + event, disk->device_path().c_str(), |
| + disk->mount_path().c_str()); |
| + } |
| +}; |
| + |
| +// Represents an invocation of |DiskMountManager::Observer::OnFormatEvent()|. |
| +struct FormatEvent : public ObserverEvent { |
| + DiskMountManager::FormatEvent event; |
| + chromeos::FormatError error_code; |
| + std::string device_path; |
| + |
| + FormatEvent() {} |
| + FormatEvent(DiskMountManager::FormatEvent event, |
| + chromeos::FormatError error_code, |
| + const std::string& device_path) |
| + : event(event), error_code(error_code), device_path(device_path) {} |
| + |
| + ObserverEventType type() const override { return FORMAT_EVENT; } |
| + |
| + bool operator==(const FormatEvent& other) const { |
| + return event == other.event && error_code == other.error_code && |
| + device_path == other.device_path; |
| + } |
| + |
| + std::string DebugString() const { |
| + return StringPrintf("OnFormatEvent(%d, %d, %s)", event, error_code, |
| + device_path.c_str()); |
| + } |
| +}; |
| + |
| +// Represents an invocation of |DiskMountManager::Observer::OnMountEvent()|. |
| +struct MountEvent : public ObserverEvent { |
| + DiskMountManager::MountEvent event; |
| + chromeos::MountError error_code; |
| + DiskMountManager::MountPointInfo mount_point; |
| + |
| + // Not passed to callback, but read by handlers. So it's captured upon |
| + // callback. |
| + std::unique_ptr<DiskMountManager::Disk> disk; |
| + |
| + MountEvent(MountEvent&& other) |
| + : event(other.event), |
| + error_code(other.error_code), |
| + mount_point(other.mount_point), |
| + disk(std::move(other.disk)) {} |
| + MountEvent(DiskMountManager::MountEvent event, |
| + chromeos::MountError error_code, |
| + const DiskMountManager::MountPointInfo& mount_point, |
| + const DiskMountManager::Disk& disk) |
| + : event(event), |
| + error_code(error_code), |
| + mount_point(mount_point), |
| + disk(new DiskMountManager::Disk(disk)) {} |
| + |
| + ObserverEventType type() const override { return MOUNT_EVENT; } |
| + |
| + bool operator==(const MountEvent& other) const; |
| + |
| + std::string DebugString() const { |
| + return StringPrintf("OnMountEvent(%d, %d, %s, %s, %d, %d)", event, |
| + error_code, mount_point.source_path.c_str(), |
| + mount_point.mount_path.c_str(), mount_point.mount_type, |
| + mount_point.mount_condition); |
| + } |
| +}; |
| + |
| +// A mock |Observer| class which records all invocation of the methods invoked |
| +// from DiskMountManager and all the arguments passed to them. |
| class MockDiskMountManagerObserver : public DiskMountManager::Observer { |
| public: |
| - virtual ~MockDiskMountManagerObserver() {} |
| - |
| - MOCK_METHOD2(OnDiskEvent, void(DiskMountManager::DiskEvent event, |
| - const DiskMountManager::Disk* disk)); |
| - MOCK_METHOD2(OnDeviceEvent, void(DiskMountManager::DeviceEvent event, |
| - const std::string& device_path)); |
| - MOCK_METHOD3(OnMountEvent, |
| - void(DiskMountManager::MountEvent event, |
| - chromeos::MountError error_code, |
| - const DiskMountManager::MountPointInfo& mount_point)); |
| - MOCK_METHOD3(OnFormatEvent, |
| - void(DiskMountManager::FormatEvent event, |
| - chromeos::FormatError error_code, |
| - const std::string& device_path)); |
| + MockDiskMountManagerObserver(const DiskMountManager* manager) |
| + : manager_(manager) {} |
| + ~MockDiskMountManagerObserver() override {} |
| + |
| + // Mock notify methods. |
| + void OnDeviceEvent(DiskMountManager::DeviceEvent event, |
| + const std::string& device_path) override { |
| + events_.push_back(MakeUnique<DeviceEvent>(event, device_path)); |
| + } |
| + |
| + void OnDiskEvent(DiskMountManager::DiskEvent event, |
| + const DiskMountManager::Disk* disk) override { |
| + // Take a snapshot (copy) of the Disk object at the time of invocation for |
| + // later verification. |
| + events_.push_back(MakeUnique<DiskEvent>(event, *disk)); |
| + } |
| + |
| + void OnFormatEvent(DiskMountManager::FormatEvent event, |
| + chromeos::FormatError error_code, |
| + const std::string& device_path) override { |
| + events_.push_back(MakeUnique<FormatEvent>(event, error_code, device_path)); |
| + } |
| + |
| + void OnMountEvent( |
| + DiskMountManager::MountEvent event, |
| + chromeos::MountError error_code, |
| + const DiskMountManager::MountPointInfo& mount_point) override { |
| + // Take a snapshot (copy) of a Disk object at the time of invocation. |
| + // It can be verified later besides the arguments. |
| + events_.push_back(MakeUnique<MountEvent>( |
| + event, error_code, mount_point, |
| + *manager_->disks().find(mount_point.source_path)->second)); |
| + } |
| + |
| + // Gets invocation history to be verified by testcases. |
| + // Verifies if the |index|th invocation is OnDeviceEvent() and returns |
| + // details. |
| + const DeviceEvent& GetDeviceEvent(size_t index) { |
| + DCHECK_GT(events_.size(), index); |
| + DCHECK_EQ(DEVICE_EVENT, events_[index]->type()); |
| + return static_cast<const DeviceEvent&>(*events_[index]); |
| + } |
| + |
| + // Verifies if the |index|th invocation is OnDiskEvent() and returns details. |
| + const DiskEvent& GetDiskEvent(size_t index) { |
| + DCHECK_GT(events_.size(), index); |
| + DCHECK_EQ(DISK_EVENT, events_[index]->type()); |
| + return static_cast<const DiskEvent&>(*events_[index]); |
| + } |
| + |
| + // Verifies if the |index|th invocation is OnFormatEvent() and returns |
| + // details. |
| + const FormatEvent& GetFormatEvent(size_t index) { |
| + DCHECK_GT(events_.size(), index); |
| + DCHECK_EQ(FORMAT_EVENT, events_[index]->type()); |
| + return static_cast<const FormatEvent&>(*events_[index]); |
| + } |
| + |
| + // Verifies if the |index|th invocation is OnMountEvent() and returns details. |
| + const MountEvent& GetMountEvent(size_t index) { |
| + DCHECK_GT(events_.size(), index); |
| + DCHECK_EQ(MOUNT_EVENT, events_[index]->type()); |
| + return static_cast<const MountEvent&>(*events_[index]); |
| + } |
| + |
| + // Returns number of callback invocations happened so far. |
| + size_t GetEventCount() { return events_.size(); } |
| + |
| + // Counts the number of |MountEvent| recorded so far that matches the given |
| + // condition. |
| + size_t CountMountEvents(DiskMountManager::MountEvent mount_event_type, |
| + chromeos::MountError error_code, |
| + const std::string& mount_path) { |
| + size_t num_matched = 0; |
| + for (const auto& it : events_) { |
| + if (it->type() != MOUNT_EVENT) |
| + continue; |
| + const MountEvent& mount_event = static_cast<const MountEvent&>(*it); |
| + if (mount_event.event == mount_event_type && |
| + mount_event.error_code == error_code && |
| + mount_event.mount_point.mount_path == mount_path) |
| + num_matched++; |
| + } |
| + return num_matched; |
| + } |
| + |
| + // Counts the number of |FormatEvent| recorded so far that matches with |
| + // |format_event|. |
| + size_t CountFormatEvents(const FormatEvent& exptected_format_event) { |
| + size_t num_matched = 0; |
| + for (const auto& it : events_) { |
| + if (it->type() != FORMAT_EVENT) |
| + continue; |
| + if (static_cast<const FormatEvent&>(*it) == exptected_format_event) |
| + num_matched++; |
| + } |
| + return num_matched; |
| + } |
| + |
| + private: |
| + // Pointer to the manager object to which this |Observer| is registered. |
| + const DiskMountManager* manager_; |
| + |
| + // Records all invocations. |
| + std::vector<std::unique_ptr<ObserverEvent>> events_; |
| }; |
| -// Expect |is_read_only| value of a disk object keyed by |source_path|. |
| -void ExpectDiskReadOnly(const DiskMountManager* manager, |
| - const std::string& source_path, |
| - bool expected) { |
| - EXPECT_EQ(expected, |
| - manager->disks().find(source_path)->second->is_read_only()); |
| +// Shift operators of ostream. |
| +// Needed to print values in case of EXPECT_* failure in gtest. |
| +std::ostream& operator<<(std::ostream& stream, |
| + const DeviceEvent& device_event) { |
| + return stream << device_event.DebugString(); |
| +} |
| + |
| +std::ostream& operator<<(std::ostream& stream, const DiskEvent& disk_event) { |
| + return stream << disk_event.DebugString(); |
| +} |
| + |
| +std::ostream& operator<<(std::ostream& stream, |
| + const FormatEvent& format_event) { |
| + return stream << format_event.DebugString(); |
| +} |
| + |
| +std::ostream& operator<<(std::ostream& stream, const MountEvent& mount_event) { |
| + return stream << mount_event.DebugString(); |
| } |
| class DiskMountManagerTest : public testing::Test { |
| @@ -196,12 +425,14 @@ class DiskMountManagerTest : public testing::Test { |
| InitDisksAndMountPoints(); |
| - DiskMountManager::GetInstance()->AddObserver(&observer_); |
| + observer_.reset( |
| + new MockDiskMountManagerObserver(DiskMountManager::GetInstance())); |
| + DiskMountManager::GetInstance()->AddObserver(observer_.get()); |
| } |
| // Shuts down dbus thread manager and disk moutn manager used in the test. |
| void TearDown() override { |
| - DiskMountManager::GetInstance()->RemoveObserver(&observer_); |
| + DiskMountManager::GetInstance()->RemoveObserver(observer_.get()); |
| DiskMountManager::Shutdown(); |
| DBusThreadManager::Shutdown(); |
| } |
| @@ -265,39 +496,38 @@ class DiskMountManagerTest : public testing::Test { |
| protected: |
| chromeos::FakeCrosDisksClient* fake_cros_disks_client_; |
| - MockDiskMountManagerObserver observer_; |
| + std::unique_ptr<MockDiskMountManagerObserver> observer_; |
| base::MessageLoopForUI message_loop_; |
| }; |
| // Tests that the observer gets notified on attempt to format non existent mount |
| // point. |
| TEST_F(DiskMountManagerTest, Format_NotMounted) { |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| - chromeos::FORMAT_ERROR_UNKNOWN, |
| - "/mount/non_existent")) |
| - .Times(1); |
| DiskMountManager::GetInstance()->FormatMountedDevice("/mount/non_existent"); |
| + ASSERT_EQ(1U, observer_->GetEventCount()); |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| + chromeos::FORMAT_ERROR_UNKNOWN, "/mount/non_existent"), |
| + observer_->GetFormatEvent(0)); |
| } |
| // Tests that the observer gets notified on attempt to format read-only mount |
| // point. |
| TEST_F(DiskMountManagerTest, Format_ReadOnly) { |
| - EXPECT_CALL(observer_, |
| - OnFormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| - chromeos::FORMAT_ERROR_DEVICE_NOT_ALLOWED, |
| - kReadOnlyMountpath)) |
| - .Times(1); |
| DiskMountManager::GetInstance()->FormatMountedDevice(kReadOnlyMountpath); |
| + ASSERT_EQ(1U, observer_->GetEventCount()); |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| + chromeos::FORMAT_ERROR_DEVICE_NOT_ALLOWED, |
| + kReadOnlyMountpath), |
| + observer_->GetFormatEvent(0)); |
| } |
| // Tests that it is not possible to format archive mount point. |
| TEST_F(DiskMountManagerTest, Format_Archive) { |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| - chromeos::FORMAT_ERROR_UNKNOWN, |
| - "/archive/source_path")) |
| - .Times(1); |
| - |
| DiskMountManager::GetInstance()->FormatMountedDevice("/archive/mount_path"); |
| + ASSERT_EQ(1U, observer_->GetEventCount()); |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| + chromeos::FORMAT_ERROR_UNKNOWN, "/archive/source_path"), |
| + observer_->GetFormatEvent(0)); |
| } |
| // Tests that format fails if the device cannot be unmounted. |
| @@ -306,25 +536,6 @@ TEST_F(DiskMountManagerTest, Format_FailToUnmount) { |
| // In this test unmount will fail, and there should be no attempt to |
| // format the device. |
| - // Set up expectations for observer mock. |
| - // Observer should be notified that unmount attempt fails and format task |
| - // failed to start. |
| - { |
| - InSequence s; |
| - |
| - EXPECT_CALL(observer_, |
| - OnMountEvent(DiskMountManager::UNMOUNTING, |
| - chromeos::MOUNT_ERROR_INTERNAL, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, |
| - "/device/mount_path"))) |
| - .Times(1); |
| - |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| - chromeos::FORMAT_ERROR_UNKNOWN, |
| - "/device/source_path")) |
| - .Times(1); |
| - } |
| - |
| fake_cros_disks_client_->MakeUnmountFail(); |
| // Start test. |
| DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path"); |
| @@ -332,6 +543,17 @@ TEST_F(DiskMountManagerTest, Format_FailToUnmount) { |
| // Cros disks will respond asynchronoulsy, so let's drain the message loop. |
| base::RunLoop().RunUntilIdle(); |
| + // Observer should be notified that unmount attempt fails and format task |
| + // failed to start. |
| + ASSERT_EQ(2U, observer_->GetEventCount()); |
| + const MountEvent& mount_event = observer_->GetMountEvent(0); |
| + EXPECT_EQ(DiskMountManager::UNMOUNTING, mount_event.event); |
| + EXPECT_EQ(chromeos::MOUNT_ERROR_INTERNAL, mount_event.error_code); |
| + EXPECT_EQ("/device/mount_path", mount_event.mount_point.mount_path); |
| + |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| + chromeos::FORMAT_ERROR_UNKNOWN, "/device/source_path"), |
| + observer_->GetFormatEvent(1)); |
| EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count()); |
| EXPECT_EQ("/device/mount_path", |
| fake_cros_disks_client_->last_unmount_device_path()); |
| @@ -350,25 +572,6 @@ TEST_F(DiskMountManagerTest, Format_FormatFailsToStart) { |
| // In this test, unmount will succeed, but call to Format method will |
| // fail. |
| - // Set up expectations for observer mock. |
| - // Observer should be notified that the device was unmounted and format task |
| - // failed to start. |
| - { |
| - InSequence s; |
| - |
| - EXPECT_CALL(observer_, |
| - OnMountEvent(DiskMountManager::UNMOUNTING, |
| - chromeos::MOUNT_ERROR_NONE, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, |
| - "/device/mount_path"))) |
| - .Times(1); |
| - |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| - chromeos::FORMAT_ERROR_UNKNOWN, |
| - "/device/source_path")) |
| - .Times(1); |
| - } |
| - |
| fake_cros_disks_client_->MakeFormatFail(); |
| // Start the test. |
| DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path"); |
| @@ -376,6 +579,18 @@ TEST_F(DiskMountManagerTest, Format_FormatFailsToStart) { |
| // Cros disks will respond asynchronoulsy, so let's drain the message loop. |
| base::RunLoop().RunUntilIdle(); |
| + // Observer should be notified that the device was unmounted and format task |
| + // failed to start. |
| + ASSERT_EQ(2U, observer_->GetEventCount()); |
| + const MountEvent& mount_event = observer_->GetMountEvent(0); |
| + EXPECT_EQ(DiskMountManager::UNMOUNTING, mount_event.event); |
| + EXPECT_EQ(chromeos::MOUNT_ERROR_NONE, mount_event.error_code); |
| + EXPECT_EQ("/device/mount_path", mount_event.mount_point.mount_path); |
| + |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| + chromeos::FORMAT_ERROR_UNKNOWN, "/device/source_path"), |
| + observer_->GetFormatEvent(1)); |
| + |
| EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count()); |
| EXPECT_EQ("/device/mount_path", |
| fake_cros_disks_client_->last_unmount_device_path()); |
| @@ -397,7 +612,16 @@ TEST_F(DiskMountManagerTest, Format_ConcurrentFormatCalls) { |
| // CrosDisksClient will report that the format process for the first request |
| // is successfully started. |
| - // Set up expectations for observer mock. |
| + fake_cros_disks_client_->set_unmount_listener( |
| + base::Bind(&FakeCrosDisksClient::MakeUnmountFail, |
| + base::Unretained(fake_cros_disks_client_))); |
| + // Start the test. |
| + DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path"); |
| + DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path"); |
| + |
| + // Cros disks will respond asynchronoulsy, so let's drain the message loop. |
| + base::RunLoop().RunUntilIdle(); |
| + |
| // The observer should get a FORMAT_STARTED event for one format request and a |
| // FORMAT_COMPLETED with an error code for the other format request. The |
| // formatting will be started only for the first request. |
| @@ -407,36 +631,18 @@ TEST_F(DiskMountManagerTest, Format_ConcurrentFormatCalls) { |
| // |
| // Note that in this test the format completion signal will not be simulated, |
| // so the observer should not get FORMAT_COMPLETED signal. |
| - { |
| - InSequence s; |
| - |
| - EXPECT_CALL(observer_, |
| - OnMountEvent(DiskMountManager::UNMOUNTING, |
| - chromeos::MOUNT_ERROR_NONE, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, |
| - "/device/mount_path"))) |
| - .Times(1); |
| - |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| - chromeos::FORMAT_ERROR_UNKNOWN, |
| - "/device/source_path")) |
| - .Times(1); |
| - |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED, |
| - chromeos::FORMAT_ERROR_NONE, |
| - "/device/source_path")) |
| - .Times(1); |
| - } |
| - fake_cros_disks_client_->set_unmount_listener( |
| - base::Bind(&FakeCrosDisksClient::MakeUnmountFail, |
| - base::Unretained(fake_cros_disks_client_))); |
| - // Start the test. |
| - DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path"); |
| - DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path"); |
| - |
| - // Cros disks will respond asynchronoulsy, so let's drain the message loop. |
| - base::RunLoop().RunUntilIdle(); |
| + ASSERT_EQ(3U, observer_->GetEventCount()); |
| + const MountEvent& mount_event = observer_->GetMountEvent(0); |
| + EXPECT_EQ(DiskMountManager::UNMOUNTING, mount_event.event); |
| + EXPECT_EQ(chromeos::MOUNT_ERROR_NONE, mount_event.error_code); |
| + EXPECT_EQ("/device/mount_path", mount_event.mount_point.mount_path); |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| + chromeos::FORMAT_ERROR_UNKNOWN, "/device/source_path"), |
| + observer_->GetFormatEvent(1)); |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_STARTED, |
| + chromeos::FORMAT_ERROR_NONE, "/device/source_path"), |
| + observer_->GetFormatEvent(2)); |
| EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count()); |
| EXPECT_EQ("/device/mount_path", |
| @@ -453,37 +659,22 @@ TEST_F(DiskMountManagerTest, Format_ConcurrentFormatCalls) { |
| EXPECT_FALSE(HasMountPoint("/device/mount_path")); |
| } |
| +// Verifies a |MountEvent| with the given condition. This function only checks |
| +// the |mount_path| in |MountPointInfo| to make sure to match the event with |
| +// preceding mount invocations. |
| +void VerifyMountEvent(const MountEvent& mount_event, |
| + DiskMountManager::MountEvent mount_event_type, |
| + chromeos::MountError error_code, |
| + const std::string& mount_path) { |
| + EXPECT_EQ(mount_event_type, mount_event.event); |
| + EXPECT_EQ(error_code, mount_event.error_code); |
| + EXPECT_EQ(mount_path, mount_event.mount_point.mount_path); |
| +} |
| + |
| // Tests the case when the format process actually starts and fails. |
| TEST_F(DiskMountManagerTest, Format_FormatFails) { |
| // Both unmount and format device cals are successful in this test. |
| - // Set up expectations for observer mock. |
| - // The observer should get notified that the device was unmounted and that |
| - // formatting has started. |
| - // After the formatting starts, the test will simulate failing |
| - // FORMAT_COMPLETED signal, so the observer should also be notified the |
| - // formatting has failed (FORMAT_COMPLETED event). |
| - { |
| - InSequence s; |
| - |
| - EXPECT_CALL(observer_, |
| - OnMountEvent(DiskMountManager::UNMOUNTING, |
| - chromeos::MOUNT_ERROR_NONE, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, |
| - "/device/mount_path"))) |
| - .Times(1); |
| - |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED, |
| - chromeos::FORMAT_ERROR_NONE, |
| - "/device/source_path")) |
| - .Times(1); |
| - |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| - chromeos::FORMAT_ERROR_UNKNOWN, |
| - "/device/source_path")) |
| - .Times(1); |
| - } |
| - |
| // Start the test. |
| DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path"); |
| @@ -508,6 +699,21 @@ TEST_F(DiskMountManagerTest, Format_FormatFails) { |
| // soon). |
| fake_cros_disks_client_->SendFormatCompletedEvent( |
| chromeos::FORMAT_ERROR_UNKNOWN, "/device/source_path"); |
| + |
| + // The observer should get notified that the device was unmounted and that |
| + // formatting has started. |
| + // After the formatting starts, the test will simulate failing |
| + // FORMAT_COMPLETED signal, so the observer should also be notified the |
| + // formatting has failed (FORMAT_COMPLETED event). |
| + ASSERT_EQ(3U, observer_->GetEventCount()); |
| + VerifyMountEvent(observer_->GetMountEvent(0), DiskMountManager::UNMOUNTING, |
| + chromeos::MOUNT_ERROR_NONE, "/device/mount_path"); |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_STARTED, |
| + chromeos::FORMAT_ERROR_NONE, "/device/source_path"), |
| + observer_->GetFormatEvent(1)); |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| + chromeos::FORMAT_ERROR_UNKNOWN, "/device/source_path"), |
| + observer_->GetFormatEvent(2)); |
| } |
| // Tests the case when formatting completes successfully. |
| @@ -515,30 +721,6 @@ TEST_F(DiskMountManagerTest, Format_FormatSuccess) { |
| // Set up cros disks client mocks. |
| // Both unmount and format device cals are successful in this test. |
| - // Set up expectations for observer mock. |
| - // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED |
| - // events (all of them without an error set). |
| - { |
| - InSequence s; |
| - |
| - EXPECT_CALL(observer_, |
| - OnMountEvent(DiskMountManager::UNMOUNTING, |
| - chromeos::MOUNT_ERROR_NONE, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, |
| - "/device/mount_path"))) |
| - .Times(1); |
| - |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED, |
| - chromeos::FORMAT_ERROR_NONE, |
| - "/device/source_path")) |
| - .Times(1); |
| - |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| - chromeos::FORMAT_ERROR_NONE, |
| - "/device/source_path")) |
| - .Times(1); |
| - } |
| - |
| // Start the test. |
| DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path"); |
| @@ -561,6 +743,18 @@ TEST_F(DiskMountManagerTest, Format_FormatSuccess) { |
| // Simulate cros_disks reporting success. |
| fake_cros_disks_client_->SendFormatCompletedEvent( |
| chromeos::FORMAT_ERROR_NONE, "/device/source_path"); |
| + |
| + // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED |
| + // events (all of them without an error set). |
| + ASSERT_EQ(3U, observer_->GetEventCount()); |
| + VerifyMountEvent(observer_->GetMountEvent(0), DiskMountManager::UNMOUNTING, |
| + chromeos::MOUNT_ERROR_NONE, "/device/mount_path"); |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_STARTED, |
| + chromeos::FORMAT_ERROR_NONE, "/device/source_path"), |
| + observer_->GetFormatEvent(1)); |
| + EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| + chromeos::FORMAT_ERROR_NONE, "/device/source_path"), |
| + observer_->GetFormatEvent(2)); |
| } |
| // Tests that it's possible to format the device twice in a row (this may not be |
| @@ -569,36 +763,6 @@ TEST_F(DiskMountManagerTest, Format_ConsecutiveFormatCalls) { |
| // All unmount and format device cals are successful in this test. |
| // Each of the should be made twice (once for each formatting task). |
| - // Set up expectations for observer mock. |
| - // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED |
| - // events (all of them without an error set) twice (once for each formatting |
| - // task). |
| - // Also, there should be a MOUNTING event when the device remounting is |
| - // simulated. |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_COMPLETED, |
| - chromeos::FORMAT_ERROR_NONE, |
| - "/device/source_path")) |
| - .Times(2); |
| - |
| - EXPECT_CALL(observer_, OnFormatEvent(DiskMountManager::FORMAT_STARTED, |
| - chromeos::FORMAT_ERROR_NONE, |
| - "/device/source_path")) |
| - .Times(2); |
| - |
| - EXPECT_CALL(observer_, |
| - OnMountEvent(DiskMountManager::UNMOUNTING, |
| - chromeos::MOUNT_ERROR_NONE, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, |
| - "/device/mount_path"))) |
| - .Times(2); |
| - |
| - EXPECT_CALL(observer_, |
| - OnMountEvent(DiskMountManager::MOUNTING, |
| - chromeos::MOUNT_ERROR_NONE, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, |
| - "/device/mount_path"))) |
| - .Times(1); |
| - |
| // Start the test. |
| DiskMountManager::GetInstance()->FormatMountedDevice("/device/mount_path"); |
| @@ -650,6 +814,29 @@ TEST_F(DiskMountManagerTest, Format_ConsecutiveFormatCalls) { |
| // Simulate cros_disks reporting success. |
| fake_cros_disks_client_->SendFormatCompletedEvent( |
| chromeos::FORMAT_ERROR_NONE, "/device/source_path"); |
| + |
| + // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED |
| + // events (all of them without an error set) twice (once for each formatting |
| + // task). |
| + // Also, there should be a MOUNTING event when the device remounting is |
| + // simulated. |
| + EXPECT_EQ(7U, observer_->GetEventCount()); |
| + |
| + EXPECT_EQ(2U, observer_->CountFormatEvents(FormatEvent( |
| + DiskMountManager::FORMAT_COMPLETED, |
| + chromeos::FORMAT_ERROR_NONE, "/device/source_path"))); |
| + |
| + EXPECT_EQ(2U, observer_->CountFormatEvents(FormatEvent( |
| + DiskMountManager::FORMAT_STARTED, |
| + chromeos::FORMAT_ERROR_NONE, "/device/source_path"))); |
| + |
| + EXPECT_EQ(2U, observer_->CountMountEvents(DiskMountManager::UNMOUNTING, |
| + chromeos::MOUNT_ERROR_NONE, |
| + "/device/mount_path")); |
| + |
| + EXPECT_EQ(1U, observer_->CountMountEvents(DiskMountManager::MOUNTING, |
| + chromeos::MOUNT_ERROR_NONE, |
| + "/device/mount_path")); |
| } |
| TEST_F(DiskMountManagerTest, MountPath_RecordAccessMode) { |
| @@ -662,27 +849,6 @@ TEST_F(DiskMountManagerTest, MountPath_RecordAccessMode) { |
| const std::string kMountPath1 = "/media/foo"; |
| const std::string kMountPath2 = "/media/bar"; |
| - // Event handlers of observers should be called. |
| - EXPECT_CALL( |
| - observer_, |
| - OnMountEvent( |
| - DiskMountManager::MOUNTING, chromeos::MOUNT_ERROR_NONE, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, kMountPath1))); |
| - // For the 2nd source, the disk (block device) is not read-only but the |
| - // test will mount it in read-only mode. |
| - // Observers query |disks_| from |DiskMountManager| in its event handler for |
| - // a mount completion event. Therefore |disks_| must be updated with correct |
| - // |read_only| value before notifying to observers. |
| - EXPECT_CALL( |
| - observer_, |
| - OnMountEvent( |
| - DiskMountManager::MOUNTING, chromeos::MOUNT_ERROR_NONE, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, kMountPath2))) |
| - .WillOnce(InvokeWithoutArgs( |
| - // Verify if the disk appears read-only at the time of notification |
| - // to observers. |
| - [&]() { ExpectDiskReadOnly(manager, kSourcePath2, true); })); |
| - |
| manager->MountPath(kSourcePath1, kSourceFormat, std::string(), |
| chromeos::MOUNT_TYPE_DEVICE, |
| chromeos::MOUNT_ACCESS_MODE_READ_WRITE); |
| @@ -697,6 +863,24 @@ TEST_F(DiskMountManagerTest, MountPath_RecordAccessMode) { |
| chromeos::MOUNT_ERROR_NONE, kSourcePath2, chromeos::MOUNT_TYPE_DEVICE, |
| kMountPath2); |
| + // Event handlers of observers should be called. |
| + ASSERT_EQ(2U, observer_->GetEventCount()); |
| + VerifyMountEvent(observer_->GetMountEvent(0), DiskMountManager::MOUNTING, |
| + chromeos::MOUNT_ERROR_NONE, kMountPath1); |
| + // For the 2nd source, the disk (block device) is not read-only but the |
| + // test will mount it in read-only mode. |
| + // Observers query |disks_| from |DiskMountManager| in its event handler for |
| + // a mount completion event. Therefore |disks_| must be updated with correct |
| + // |read_only| value before notifying to observers. |
| + const MountEvent& secondMountEvent = observer_->GetMountEvent(1); |
| + EXPECT_EQ(DiskMountManager::MOUNTING, secondMountEvent.event); |
| + EXPECT_EQ(chromeos::MOUNT_ERROR_NONE, secondMountEvent.error_code); |
| + EXPECT_EQ(kMountPath2, secondMountEvent.mount_point.mount_path); |
| + // Verify if the disk appears read-only at the time of notification to |
| + // observers. |
| + EXPECT_TRUE(secondMountEvent.disk->is_read_only()); |
| + |
| + // Verify the final state of manager->disks. |
| const DiskMountManager::DiskMap& disks = manager->disks(); |
| ASSERT_GT(disks.count(kSourcePath1), 0U); |
| EXPECT_FALSE(disks.find(kSourcePath1)->second->is_read_only()); |
| @@ -709,13 +893,6 @@ TEST_F(DiskMountManagerTest, MountPath_ReadOnlyDevice) { |
| const std::string kSourceFormat = std::string(); |
| const std::string kMountLabel = std::string(); // N/A for MOUNT_TYPE_DEVICE |
| - // Event handlers of observers should be called. |
| - EXPECT_CALL( |
| - observer_, |
| - OnMountEvent(DiskMountManager::MOUNTING, chromeos::MOUNT_ERROR_NONE, |
| - Field(&DiskMountManager::MountPointInfo::mount_path, |
| - kReadOnlyMountpath))); |
| - |
| // Attempt to mount a read-only device in read-write mode. |
| manager->MountPath(kReadOnlyDeviceSource, kSourceFormat, std::string(), |
| chromeos::MOUNT_TYPE_DEVICE, |
| @@ -725,6 +902,10 @@ TEST_F(DiskMountManagerTest, MountPath_ReadOnlyDevice) { |
| chromeos::MOUNT_ERROR_NONE, kReadOnlyDeviceSource, |
| chromeos::MOUNT_TYPE_DEVICE, kReadOnlyMountpath); |
| + // Event handlers of observers should be called. |
| + ASSERT_EQ(1U, observer_->GetEventCount()); |
| + VerifyMountEvent(observer_->GetMountEvent(0), DiskMountManager::MOUNTING, |
| + chromeos::MOUNT_ERROR_NONE, kReadOnlyMountpath); |
| const DiskMountManager::DiskMap& disks = manager->disks(); |
| ASSERT_GT(disks.count(kReadOnlyDeviceSource), 0U); |
| // The mounted disk should preserve the read-only flag of the block device. |