12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/components/disks/disk_mount_manager.h"
- #include <stddef.h>
- #include <stdint.h>
- #include <memory>
- #include <string>
- #include <utility>
- #include <vector>
- #include "ash/components/disks/disk.h"
- #include "base/bind.h"
- #include "base/run_loop.h"
- #include "base/strings/stringprintf.h"
- #include "base/test/bind.h"
- #include "base/test/mock_callback.h"
- #include "base/test/task_environment.h"
- #include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
- #include "chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.h"
- #include "chromeos/dbus/power/power_manager_client.h"
- #include "dbus/message.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using base::StringPrintf;
- using testing::_;
- using testing::Field;
- namespace ash {
- namespace disks {
- namespace {
- const char kDevice1SourcePath[] = "/device/source_path";
- const char kDevice1MountPath[] = "/device/mount_path";
- const char kDevice2SourcePath[] = "/device/source_path2";
- const char kReadOnlyDeviceMountPath[] = "/device/read_only_mount_path";
- const char kReadOnlyDeviceSourcePath[] = "/device/read_only_source_path";
- const char kFileSystemType1[] = "ntfs";
- const char kFileSystemType2[] = "exfat";
- const FormatFileSystemType kFormatFileSystemType1 = FormatFileSystemType::kVfat;
- const FormatFileSystemType kFormatFileSystemType2 =
- FormatFileSystemType::kExfat;
- const char kFormatFileSystemType1String[] = "vfat";
- const char kFormatFileSystemType2String[] = "exfat";
- const char kFormatLabel1[] = "UNTITLED";
- const char kFormatLabel2[] = "TESTUSB";
- // Holds information needed to create a Disk instance.
- struct TestDiskInfo {
- const char* source_path;
- const char* mount_path;
- const char* file_path;
- const char* device_label;
- const char* drive_label;
- const char* vendor_id;
- const char* vendor_name;
- const char* product_id;
- const char* product_name;
- const char* fs_uuid;
- const char* storage_device_path;
- DeviceType device_type;
- uint64_t size_in_bytes;
- bool is_read_only;
- const char* file_system_type;
- bool is_mounted;
- };
- // List of disks held in DiskMountManager at the beginning of the test.
- const TestDiskInfo kTestDisks[] = {
- {
- kDevice1SourcePath,
- kDevice1MountPath,
- "/device/file_path",
- "/device/device_label",
- "/device/drive_label",
- "/device/vendor_id",
- "/device/vendor_name",
- "/device/product_id",
- "/device/product_name",
- "/device/fs_uuid",
- "/device/prefix",
- DeviceType::kUSB,
- 1073741824, // size in bytes
- false, // is read only
- kFileSystemType1,
- true, // is_mounted
- },
- {
- kDevice2SourcePath,
- "", // not mounted initially
- "/device/file_path2",
- "/device/device_label2",
- "/device/drive_label2",
- "/device/vendor_id2",
- "/device/vendor_name2",
- "/device/product_id2",
- "/device/product_name2",
- "/device/fs_uuid2",
- "/device/prefix2",
- DeviceType::kSD,
- 1073741824, // size in bytes
- false, // is read only
- kFileSystemType2,
- false, // is_mounted
- },
- {
- kReadOnlyDeviceSourcePath,
- kReadOnlyDeviceMountPath,
- "/device/file_path_3",
- "/device/device_label_3",
- "/device/drive_label_3",
- "/device/vendor_id_3",
- "/device/vendor_name_3",
- "/device/product_id_3",
- "/device/product_name_3",
- "/device/fs_uuid_3",
- "/device/prefix",
- DeviceType::kUSB,
- 1073741824, // size in bytes
- true, // is read only
- kFileSystemType2,
- true, // is_mounted
- },
- };
- // Represents which function in |DiskMountManager::Observer| was invoked.
- enum ObserverEventType {
- DEVICE_EVENT, // OnDeviceEvent()
- AUTO_MOUNTABLE_DISK_EVENT, // OnAutoMountableDiskEvent()
- BOOT_DEVICE_DISK_EVENT, // OnBootDeviceDiskEvent()
- FORMAT_EVENT, // OnFormatEvent()
- MOUNT_EVENT, // OnMountEvent()
- RENAME_EVENT // OnRenameEvent()
- };
- // Represents every event notified to |DiskMountManager::Observer|.
- struct ObserverEvent {
- public:
- virtual ObserverEventType type() const = 0;
- virtual ~ObserverEvent() = default;
- };
- // Represents an invocation of |DiskMountManager::Observer::OnDeviceEvent()|.
- struct DeviceEvent : public ObserverEvent {
- DiskMountManager::DeviceEvent event;
- std::string device_path;
- DeviceEvent() = default;
- 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::OnAutoMountableDiskEvent().
- struct AutoMountableDiskEvent : public ObserverEvent {
- DiskMountManager::DiskEvent event;
- std::unique_ptr<Disk> disk;
- AutoMountableDiskEvent(DiskMountManager::DiskEvent event, const Disk& disk)
- : event(event), disk(std::make_unique<Disk>(disk)) {}
- AutoMountableDiskEvent(AutoMountableDiskEvent&& other)
- : event(other.event), disk(std::move(other.disk)) {}
- ObserverEventType type() const override { return AUTO_MOUNTABLE_DISK_EVENT; }
- bool operator==(const AutoMountableDiskEvent& other) const {
- return event == other.event && disk == other.disk;
- }
- std::string DebugString() const {
- return StringPrintf(
- "OnAutoMountableDiskEvent(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::OnBootDeviceDiskEvent().
- // TODO(agawronska): Add tests for disks events.
- struct BootDeviceDiskEvent : public ObserverEvent {
- DiskMountManager::DiskEvent event;
- std::unique_ptr<Disk> disk;
- BootDeviceDiskEvent(DiskMountManager::DiskEvent event, const Disk& disk)
- : event(event), disk(std::make_unique<Disk>(disk)) {}
- BootDeviceDiskEvent(BootDeviceDiskEvent&& other)
- : event(other.event), disk(std::move(other.disk)) {}
- ObserverEventType type() const override { return BOOT_DEVICE_DISK_EVENT; }
- bool operator==(const BootDeviceDiskEvent& other) const {
- return event == other.event && disk == other.disk;
- }
- std::string DebugString() const {
- return StringPrintf(
- "OnBootDeviceDiskEvent(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;
- FormatError error_code;
- std::string device_path;
- std::string device_label;
- FormatEvent() = default;
- FormatEvent(DiskMountManager::FormatEvent event,
- FormatError error_code,
- const std::string& device_path,
- const std::string& device_label)
- : event(event),
- error_code(error_code),
- device_path(device_path),
- device_label(device_label) {}
- 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 &&
- device_label == other.device_label;
- }
- std::string DebugString() const {
- return StringPrintf("OnFormatEvent(%d, %d, %s, %s)", event, error_code,
- device_path.c_str(), device_label.c_str());
- }
- };
- // Represents an invocation of |DiskMountManager::Observer::OnRenameEvent()|.
- struct RenameEvent : public ObserverEvent {
- DiskMountManager::RenameEvent event;
- RenameError error_code;
- std::string device_path;
- std::string device_label;
- RenameEvent(DiskMountManager::RenameEvent event,
- RenameError error_code,
- const std::string& device_path,
- const std::string& device_label)
- : event(event),
- error_code(error_code),
- device_path(device_path),
- device_label(device_label) {}
- ObserverEventType type() const override { return RENAME_EVENT; }
- bool operator==(const RenameEvent& other) const {
- return event == other.event && error_code == other.error_code &&
- device_path == other.device_path &&
- device_label == other.device_label;
- }
- std::string DebugString() const {
- return StringPrintf("OnRenameEvent(%d, %d, %s, %s)", event, error_code,
- device_path.c_str(), device_label.c_str());
- }
- };
- // Represents an invocation of |DiskMountManager::Observer::OnMountEvent()|.
- struct MountEvent : public ObserverEvent {
- DiskMountManager::MountEvent event;
- MountError error_code;
- DiskMountManager::MountPoint mount_point;
- // Not passed to callback, but read by handlers. So it's captured upon
- // callback.
- std::unique_ptr<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,
- MountError error_code,
- const DiskMountManager::MountPoint& mount_point,
- const Disk& disk)
- : event(event),
- error_code(error_code),
- mount_point(mount_point),
- disk(std::make_unique<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:
- explicit MockDiskMountManagerObserver(const DiskMountManager* manager)
- : manager_(manager) {}
- ~MockDiskMountManagerObserver() override = default;
- // Mock notify methods.
- void OnDeviceEvent(DiskMountManager::DeviceEvent event,
- const std::string& device_path) override {
- events_.push_back(std::make_unique<DeviceEvent>(event, device_path));
- }
- void OnBootDeviceDiskEvent(DiskMountManager::DiskEvent event,
- const Disk& disk) override {
- // Take a snapshot (copy) of the Disk object at the time of invocation for
- // later verification.
- events_.push_back(std::make_unique<BootDeviceDiskEvent>(event, disk));
- }
- void OnAutoMountableDiskEvent(DiskMountManager::DiskEvent event,
- const Disk& disk) override {
- // Take a snapshot (copy) of the Disk object at the time of invocation for
- // later verification.
- events_.push_back(std::make_unique<AutoMountableDiskEvent>(event, disk));
- }
- void OnFormatEvent(DiskMountManager::FormatEvent event,
- FormatError error_code,
- const std::string& device_path,
- const std::string& device_label) override {
- events_.push_back(std::make_unique<FormatEvent>(event, error_code,
- device_path, device_label));
- }
- void OnRenameEvent(DiskMountManager::RenameEvent event,
- RenameError error_code,
- const std::string& device_path,
- const std::string& device_label) override {
- events_.push_back(std::make_unique<RenameEvent>(event, error_code,
- device_path, device_label));
- }
- void OnMountEvent(DiskMountManager::MountEvent event,
- MountError error_code,
- const DiskMountManager::MountPoint& 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(std::make_unique<MountEvent>(
- event, error_code, mount_point,
- *manager_->disks().find(mount_point.source_path)->get()));
- }
- // 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 OnAutoMountableDiskEvent() and
- // returns details.
- const AutoMountableDiskEvent& GetAutoMountableDiskEvent(size_t index) {
- DCHECK_GT(events_.size(), index);
- DCHECK_EQ(AUTO_MOUNTABLE_DISK_EVENT, events_[index]->type());
- return static_cast<const AutoMountableDiskEvent&>(*events_[index]);
- }
- // Verifies if the |index|th invocation is OnBootDeviceDiskEvent() and returns
- // details.
- const BootDeviceDiskEvent& GetBootDeviceDiskEvent(size_t index) {
- DCHECK_GT(events_.size(), index);
- DCHECK_EQ(BOOT_DEVICE_DISK_EVENT, events_[index]->type());
- return static_cast<const BootDeviceDiskEvent&>(*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 OnRenameEvent() and returns
- // details.
- const RenameEvent& GetRenameEvent(size_t index) {
- DCHECK_GT(events_.size(), index);
- DCHECK_EQ(RENAME_EVENT, events_[index]->type());
- return static_cast<const RenameEvent&>(*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,
- 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;
- }
- // Counts the number of |RenameEvent| recorded so far that matches with
- // |rename_event|.
- size_t CountRenameEvents(const RenameEvent& exptected_rename_event) {
- size_t num_matched = 0;
- for (const auto& event : events_) {
- if (event->type() != RENAME_EVENT)
- continue;
- if (static_cast<const RenameEvent&>(*event) == exptected_rename_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_;
- };
- // Shift operators of ostream.
- // Needed to print values in case of EXPECT_* failure in gtest.
- std::ostream& operator<<(std::ostream& stream,
- const FormatEvent& format_event) {
- return stream << format_event.DebugString();
- }
- std::ostream& operator<<(std::ostream& stream,
- const RenameEvent& rename_event) {
- return stream << rename_event.DebugString();
- }
- class DiskMountManagerTest : public testing::Test {
- public:
- DiskMountManagerTest()
- : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
- ~DiskMountManagerTest() override = default;
- // Sets up test disks mount manager.
- // Initializes disk mount manager disks and mount points.
- // Adds a test observer to the disk mount manager.
- void SetUp() override {
- CrosDisksClient::InitializeFake();
- fake_cros_disks_client_ =
- static_cast<FakeCrosDisksClient*>(CrosDisksClient::Get());
- PowerManagerClient::InitializeFake();
- DiskMountManager::Initialize();
- InitDisksAndMountPoints();
- observer_ = std::make_unique<MockDiskMountManagerObserver>(
- DiskMountManager::GetInstance());
- DiskMountManager::GetInstance()->AddObserver(observer_.get());
- }
- // Shuts down dbus thread manager and disk mount manager used in the test.
- void TearDown() override {
- DiskMountManager::GetInstance()->RemoveObserver(observer_.get());
- DiskMountManager::Shutdown();
- PowerManagerClient::Shutdown();
- CrosDisksClient::Shutdown();
- }
- protected:
- // Checks if disk mount manager contains a mount point with specified mount
- // path.
- bool HasMountPoint(const std::string& mount_path) {
- return DiskMountManager::GetInstance()->mount_points().count(mount_path) !=
- 0;
- }
- private:
- // Adds a new disk to the disk mount manager.
- void AddTestDisk(const TestDiskInfo& disk) {
- std::unique_ptr<Disk> test_disk =
- Disk::Builder()
- .SetDevicePath(disk.source_path)
- .SetMountPath(disk.mount_path)
- .SetFilePath(disk.file_path)
- .SetDeviceLabel(disk.device_label)
- .SetDriveLabel(disk.drive_label)
- .SetVendorId(disk.vendor_id)
- .SetVendorName(disk.vendor_name)
- .SetProductId(disk.product_id)
- .SetProductName(disk.product_name)
- .SetFileSystemUUID(disk.fs_uuid)
- .SetStorageDevicePath(disk.storage_device_path)
- .SetDeviceType(disk.device_type)
- .SetSizeInBytes(disk.size_in_bytes)
- .SetIsReadOnlyHardware(disk.is_read_only)
- .SetHasMedia(true)
- .SetOnRemovableDevice(true)
- .SetFileSystemType(disk.file_system_type)
- .SetIsMounted(disk.is_mounted)
- .Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(test_disk)));
- }
- // Adds a new mount point to the disk mount manager.
- // If the mount point is a device mount point, disk with its source path
- // should already be added to the disk mount manager.
- void AddTestMountPoint(const DiskMountManager::MountPoint& mount_point) {
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddMountPointForTest(mount_point));
- }
- // Adds disks and mount points to disk mount manager.
- void InitDisksAndMountPoints() {
- // Disks should be added first (when adding device mount points it is
- // expected that the corresponding disk is already added).
- for (const TestDiskInfo& disk : kTestDisks)
- AddTestDisk(disk);
- AddTestMountPoint(
- {"/archive/source_path", "/archive/mount_path", MountType::kArchive});
- AddTestMountPoint(
- {kDevice1SourcePath, kDevice1MountPath, MountType::kDevice});
- AddTestMountPoint({kReadOnlyDeviceSourcePath, kReadOnlyDeviceMountPath,
- MountType::kDevice});
- }
- protected:
- FakeCrosDisksClient* fake_cros_disks_client_;
- std::unique_ptr<MockDiskMountManagerObserver> observer_;
- private:
- base::test::TaskEnvironment task_environment_;
- };
- // Tests that the observer gets notified on attempt to format non existent mount
- // point.
- TEST_F(DiskMountManagerTest, Format_NotMounted) {
- DiskMountManager::GetInstance()->FormatMountedDevice(
- "/mount/non_existent", kFormatFileSystemType1, kFormatLabel1);
- ASSERT_EQ(1U, observer_->GetEventCount());
- EXPECT_EQ(
- FormatEvent(DiskMountManager::FORMAT_COMPLETED, FormatError::kUnknown,
- "/mount/non_existent", kFormatLabel1),
- observer_->GetFormatEvent(0));
- }
- // Tests that the observer gets notified on attempt to format read-only mount
- // point.
- TEST_F(DiskMountManagerTest, Format_ReadOnly) {
- DiskMountManager::GetInstance()->FormatMountedDevice(
- kReadOnlyDeviceMountPath, kFormatFileSystemType1, kFormatLabel1);
- ASSERT_EQ(1U, observer_->GetEventCount());
- EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED,
- FormatError::kDeviceNotAllowed,
- kReadOnlyDeviceSourcePath, kFormatLabel1),
- observer_->GetFormatEvent(0));
- }
- // Tests that it is not possible to format archive mount point.
- TEST_F(DiskMountManagerTest, Format_Archive) {
- DiskMountManager::GetInstance()->FormatMountedDevice(
- "/archive/mount_path", kFormatFileSystemType1, kFormatLabel1);
- ASSERT_EQ(1U, observer_->GetEventCount());
- EXPECT_EQ(
- FormatEvent(DiskMountManager::FORMAT_COMPLETED, FormatError::kUnknown,
- "/archive/source_path", kFormatLabel1),
- observer_->GetFormatEvent(0));
- }
- // Tests that format fails if the device cannot be unmounted.
- TEST_F(DiskMountManagerTest, Format_FailToUnmount) {
- // Before formatting mounted device, the device should be unmounted.
- // In this test unmount will fail, and there should be no attempt to
- // format the device.
- fake_cros_disks_client_->MakeUnmountFail(
- MountError::kInsufficientPermissions);
- // Start test.
- DiskMountManager::GetInstance()->FormatMountedDevice(
- kDevice1MountPath, kFormatFileSystemType1, kFormatLabel1);
- // 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(MountError::kInsufficientPermissions, mount_event.error_code);
- EXPECT_EQ(kDevice1MountPath, mount_event.mount_point.mount_path);
- EXPECT_EQ(
- FormatEvent(DiskMountManager::FORMAT_COMPLETED, FormatError::kUnknown,
- kDevice1SourcePath, kFormatLabel1),
- observer_->GetFormatEvent(1));
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(0, fake_cros_disks_client_->format_call_count());
- // The device mount should still be here.
- EXPECT_TRUE(HasMountPoint(kDevice1MountPath));
- }
- // Tests that observer is notified when cros disks fails to start format
- // process.
- TEST_F(DiskMountManagerTest, Format_FormatFailsToStart) {
- // Before formatting mounted device, the device should be unmounted.
- // In this test, unmount will succeed, but call to Format method will
- // fail.
- fake_cros_disks_client_->MakeFormatFail();
- // Start the test.
- DiskMountManager::GetInstance()->FormatMountedDevice(
- kDevice1MountPath, kFormatFileSystemType1, kFormatLabel1);
- // 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(MountError::kNone, mount_event.error_code);
- EXPECT_EQ(kDevice1MountPath, mount_event.mount_point.mount_path);
- EXPECT_EQ(
- FormatEvent(DiskMountManager::FORMAT_COMPLETED, FormatError::kUnknown,
- kDevice1SourcePath, kFormatLabel1),
- observer_->GetFormatEvent(1));
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_format_device_path());
- EXPECT_EQ(kFormatFileSystemType1String,
- fake_cros_disks_client_->last_format_filesystem());
- EXPECT_EQ(kFormatLabel1, fake_cros_disks_client_->last_format_label());
- // The device mount should be gone.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- }
- // Tests the case where there are two format requests for the same device.
- TEST_F(DiskMountManagerTest, Format_ConcurrentFormatCalls) {
- // Only the first format request should be processed (the second unmount
- // request fails because the device is already unmounted at that point).
- // CrosDisksClient will report that the format process for the first request
- // is successfully started.
- fake_cros_disks_client_->set_unmount_listener(
- base::BindRepeating(&FakeCrosDisksClient::MakeUnmountFail,
- base::Unretained(fake_cros_disks_client_),
- MountError::kInvalidUnmountOptions));
- // Start the test.
- DiskMountManager::GetInstance()->FormatMountedDevice(
- kDevice1MountPath, kFormatFileSystemType1, kFormatLabel1);
- DiskMountManager::GetInstance()->FormatMountedDevice(
- kDevice1MountPath, kFormatFileSystemType2, kFormatLabel2);
- // 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.
- // There should be only one UNMOUNTING event. The result of the second one
- // should not be reported as the mount point will go away after the first
- // request.
- //
- // Note that in this test the format completion signal will not be simulated,
- // so the observer should not get FORMAT_COMPLETED signal.
- ASSERT_EQ(3U, observer_->GetEventCount());
- const MountEvent& mount_event = observer_->GetMountEvent(0);
- EXPECT_EQ(DiskMountManager::UNMOUNTING, mount_event.event);
- EXPECT_EQ(MountError::kNone, mount_event.error_code);
- EXPECT_EQ(kDevice1MountPath, mount_event.mount_point.mount_path);
- EXPECT_EQ(
- FormatEvent(DiskMountManager::FORMAT_COMPLETED, FormatError::kUnknown,
- kDevice1SourcePath, kFormatLabel2),
- observer_->GetFormatEvent(1));
- EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_STARTED, FormatError::kNone,
- kDevice1SourcePath, kFormatLabel1),
- observer_->GetFormatEvent(2));
- EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_format_device_path());
- EXPECT_EQ(kFormatFileSystemType1String,
- fake_cros_disks_client_->last_format_filesystem());
- EXPECT_EQ(kFormatLabel1, fake_cros_disks_client_->last_format_label());
- // The device mount should be gone.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- }
- // 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,
- 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.
- // Start the test.
- DiskMountManager::GetInstance()->FormatMountedDevice(
- kDevice1MountPath, kFormatFileSystemType1, kFormatLabel1);
- // Wait for Unmount and Format calls to end.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_format_device_path());
- EXPECT_EQ(kFormatFileSystemType1String,
- fake_cros_disks_client_->last_format_filesystem());
- EXPECT_EQ(kFormatLabel1, fake_cros_disks_client_->last_format_label());
- // The device should be unmounted by now.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- // Send failing FORMAT_COMPLETED signal.
- // The failure is marked by ! in fromt of the path (but this should change
- // soon).
- fake_cros_disks_client_->NotifyFormatCompleted(FormatError::kUnknown,
- kDevice1SourcePath);
- // 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,
- MountError::kNone, kDevice1MountPath);
- EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_STARTED, FormatError::kNone,
- kDevice1SourcePath, kFormatLabel1),
- observer_->GetFormatEvent(1));
- EXPECT_EQ(
- FormatEvent(DiskMountManager::FORMAT_COMPLETED, FormatError::kUnknown,
- kDevice1SourcePath, kFormatLabel1),
- observer_->GetFormatEvent(2));
- }
- // Tests the case when formatting completes successfully.
- TEST_F(DiskMountManagerTest, Format_FormatSuccess) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- const DiskMountManager::Disks& disks = manager->disks();
- // Set up cros disks client mocks.
- // Both unmount and format device cals are successful in this test.
- // Start the test.
- DiskMountManager::GetInstance()->FormatMountedDevice(
- kDevice1MountPath, kFormatFileSystemType1, kFormatLabel1);
- // Wait for Unmount and Format calls to end.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_format_device_path());
- EXPECT_EQ(kFormatFileSystemType1String,
- fake_cros_disks_client_->last_format_filesystem());
- EXPECT_EQ(kFormatLabel1, fake_cros_disks_client_->last_format_label());
- // The device should be unmounted by now.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- // Simulate cros_disks reporting success.
- fake_cros_disks_client_->NotifyFormatCompleted(FormatError::kNone,
- kDevice1SourcePath);
- // 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,
- MountError::kNone, kDevice1MountPath);
- EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_STARTED, FormatError::kNone,
- kDevice1SourcePath, kFormatLabel1),
- observer_->GetFormatEvent(1));
- EXPECT_EQ(FormatEvent(DiskMountManager::FORMAT_COMPLETED, FormatError::kNone,
- kDevice1SourcePath, kFormatLabel1),
- observer_->GetFormatEvent(2));
- // Disk should have new values for file system type and device label name
- EXPECT_EQ(kFormatFileSystemType1String,
- disks.find(kDevice1SourcePath)->get()->file_system_type());
- EXPECT_EQ(kFormatLabel1,
- disks.find(kDevice1SourcePath)->get()->device_label());
- }
- // Tests that it's possible to format the device twice in a row (this may not be
- // true if the list of pending formats is not properly cleared).
- 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).
- // Start the test.
- DiskMountManager::GetInstance()->FormatMountedDevice(
- kDevice1MountPath, kFormatFileSystemType1, kFormatLabel1);
- // Wait for Unmount and Format calls to end.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->format_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_format_device_path());
- EXPECT_EQ(kFormatFileSystemType1String,
- fake_cros_disks_client_->last_format_filesystem());
- EXPECT_EQ(kFormatLabel1, fake_cros_disks_client_->last_format_label());
- // The device should be unmounted by now.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- // Simulate cros_disks reporting success.
- fake_cros_disks_client_->NotifyFormatCompleted(FormatError::kNone,
- kDevice1SourcePath);
- // Simulate the device remounting.
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice1SourcePath, MountType::kDevice,
- kDevice1MountPath);
- EXPECT_TRUE(HasMountPoint(kDevice1MountPath));
- // Try formatting again.
- DiskMountManager::GetInstance()->FormatMountedDevice(
- kDevice1MountPath, kFormatFileSystemType2, kFormatLabel2);
- // Wait for Unmount and Format calls to end.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(2, fake_cros_disks_client_->format_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_format_device_path());
- EXPECT_EQ(kFormatFileSystemType2String,
- fake_cros_disks_client_->last_format_filesystem());
- EXPECT_EQ(kFormatLabel2, fake_cros_disks_client_->last_format_label());
- // Simulate cros_disks reporting success.
- fake_cros_disks_client_->NotifyFormatCompleted(FormatError::kNone,
- kDevice1SourcePath);
- // 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(1U, observer_->CountFormatEvents(FormatEvent(
- DiskMountManager::FORMAT_COMPLETED, FormatError::kNone,
- kDevice1SourcePath, kFormatLabel1)));
- EXPECT_EQ(1U, observer_->CountFormatEvents(FormatEvent(
- DiskMountManager::FORMAT_COMPLETED, FormatError::kNone,
- kDevice1SourcePath, kFormatLabel2)));
- EXPECT_EQ(1U, observer_->CountFormatEvents(FormatEvent(
- DiskMountManager::FORMAT_STARTED, FormatError::kNone,
- kDevice1SourcePath, kFormatLabel1)));
- EXPECT_EQ(1U, observer_->CountFormatEvents(FormatEvent(
- DiskMountManager::FORMAT_STARTED, FormatError::kNone,
- kDevice1SourcePath, kFormatLabel2)));
- EXPECT_EQ(2U,
- observer_->CountMountEvents(DiskMountManager::UNMOUNTING,
- MountError::kNone, kDevice1MountPath));
- EXPECT_EQ(1U,
- observer_->CountMountEvents(DiskMountManager::MOUNTING,
- MountError::kNone, kDevice1MountPath));
- }
- TEST_F(DiskMountManagerTest, MountPath_RecordAccessMode) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- const std::string kSourcePath1 = kDevice1SourcePath;
- const std::string kSourcePath2 = kDevice2SourcePath;
- const std::string kSourceFormat = std::string();
- const std::string kMountLabel = std::string(); // N/A for MountType::kDevice
- // For MountCompleted. Must be non-empty strings.
- const std::string kMountPath1 = "/media/foo";
- const std::string kMountPath2 = "/media/bar";
- // MountPath should call the given callback when the mount completes.
- base::MockCallback<DiskMountManager::MountPathCallback> mock_callback1;
- EXPECT_CALL(
- mock_callback1,
- Run(MountError::kNone,
- Field(&DiskMountManager::MountPoint::mount_path, kMountPath1)));
- base::MockCallback<DiskMountManager::MountPathCallback> mock_callback2;
- EXPECT_CALL(
- mock_callback2,
- Run(MountError::kNone,
- Field(&DiskMountManager::MountPoint::mount_path, kMountPath2)))
- .WillOnce([&](MountError,
- const DiskMountManager::MountPoint& mount_point) {
- // Verify the disk appears read-only when the callback is invoked. See
- // below comment about the 2nd source.
- EXPECT_TRUE(manager->disks()
- .find(mount_point.source_path)
- ->get()
- ->is_read_only());
- });
- manager->MountPath(kSourcePath1, kSourceFormat, std::string(), {},
- MountType::kDevice, MountAccessMode::kReadWrite,
- mock_callback1.Get());
- manager->MountPath(kSourcePath2, kSourceFormat, std::string(), {},
- MountType::kDevice, MountAccessMode::kReadOnly,
- mock_callback2.Get());
- // Simulate cros_disks reporting mount completed.
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kSourcePath1, MountType::kDevice, kMountPath1);
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kSourcePath2, MountType::kDevice, kMountPath2);
- // Event handlers of observers should be called.
- ASSERT_EQ(2U, observer_->GetEventCount());
- VerifyMountEvent(observer_->GetMountEvent(0), DiskMountManager::MOUNTING,
- MountError::kNone, 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(MountError::kNone, 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::Disks& disks = manager->disks();
- ASSERT_GT(disks.count(kSourcePath1), 0U);
- EXPECT_FALSE(disks.find(kSourcePath1)->get()->is_read_only());
- ASSERT_GT(disks.count(kSourcePath2), 0U);
- EXPECT_TRUE(disks.find(kSourcePath2)->get()->is_read_only());
- }
- TEST_F(DiskMountManagerTest, MountPath_ReadOnlyDevice) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- const std::string kSourceFormat = std::string();
- const std::string kMountLabel = std::string(); // N/A for MountType::kDevice
- base::MockCallback<DiskMountManager::MountPathCallback> mock_callback;
- EXPECT_CALL(
- mock_callback,
- Run(MountError::kNone, Field(&DiskMountManager::MountPoint::mount_path,
- kReadOnlyDeviceMountPath)));
- // Attempt to mount a read-only device in read-write mode.
- manager->MountPath(kReadOnlyDeviceSourcePath, kSourceFormat, std::string(),
- {}, MountType::kDevice, MountAccessMode::kReadWrite,
- mock_callback.Get());
- // Simulate cros_disks reporting mount completed.
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kReadOnlyDeviceSourcePath, MountType::kDevice,
- kReadOnlyDeviceMountPath);
- // Event handlers of observers should be called.
- ASSERT_EQ(1U, observer_->GetEventCount());
- VerifyMountEvent(observer_->GetMountEvent(0), DiskMountManager::MOUNTING,
- MountError::kNone, kReadOnlyDeviceMountPath);
- const DiskMountManager::Disks& disks = manager->disks();
- ASSERT_GT(disks.count(kReadOnlyDeviceSourcePath), 0U);
- // The mounted disk should preserve the read-only flag of the block device.
- EXPECT_TRUE(disks.find(kReadOnlyDeviceSourcePath)->get()->is_read_only());
- }
- TEST_F(DiskMountManagerTest, MountPath_DoubleCall) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- const std::string kMountPath1 = "/media/foo";
- base::MockCallback<DiskMountManager::MountPathCallback> mock_callback1;
- manager->MountPath(kDevice1SourcePath, "", "", {}, MountType::kDevice,
- MountAccessMode::kReadWrite, mock_callback1.Get());
- {
- // While the first mount is occurring, queue up a second mount for the same
- // source. It should immediately fail.
- base::MockCallback<DiskMountManager::MountPathCallback> mock_callback2;
- EXPECT_CALL(mock_callback2, Run(MountError::kPathAlreadyMounted, _));
- manager->MountPath(kDevice1SourcePath, "", "", {}, MountType::kDevice,
- MountAccessMode::kReadWrite, mock_callback2.Get());
- }
- // Verify the first mount can complete as expected.
- EXPECT_CALL(
- mock_callback1,
- Run(MountError::kNone,
- Field(&DiskMountManager::MountPoint::mount_path, kMountPath1)));
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice1SourcePath, MountType::kDevice, kMountPath1);
- }
- TEST_F(DiskMountManagerTest, MountPath_CallbackCallsMount) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- const std::string kMountPath1 = "/media/foo";
- const std::string kMountPath2 = "/media/bar";
- base::MockCallback<DiskMountManager::MountPathCallback> mock_callback1;
- // Try call MountPath() again in the complete callback of a MountPath() call.
- EXPECT_CALL(
- mock_callback1,
- Run(MountError::kNone,
- Field(&DiskMountManager::MountPoint::mount_path, kMountPath1)))
- .WillOnce([=](MountError error,
- const DiskMountManager::MountPoint& mount_info) {
- // Try remount the same path and verify it fails.
- base::MockCallback<DiskMountManager::MountPathCallback> mock_callback2;
- EXPECT_CALL(mock_callback2, Run(MountError::kPathAlreadyMounted, _));
- manager->MountPath(kDevice1SourcePath, "", "", {}, MountType::kDevice,
- MountAccessMode::kReadWrite, mock_callback2.Get());
- // Try mount a different path and verify it succeeds.
- base::MockCallback<DiskMountManager::MountPathCallback> mock_callback3;
- EXPECT_CALL(
- mock_callback3,
- Run(MountError::kNone,
- Field(&DiskMountManager::MountPoint::mount_path, kMountPath2)));
- manager->MountPath(kDevice2SourcePath, "", "", {}, MountType::kDevice,
- MountAccessMode::kReadWrite, mock_callback3.Get());
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice2SourcePath, MountType::kDevice,
- kMountPath2);
- });
- manager->MountPath(kDevice1SourcePath, "", "", {}, MountType::kDevice,
- MountAccessMode::kReadWrite, mock_callback1.Get());
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice1SourcePath, MountType::kDevice, kMountPath1);
- }
- TEST_F(DiskMountManagerTest, RemountRemovableDrives) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- // Initially we have 2 mounted devices.
- // kDevice1MountPath --- read-write device, mounted in read-write mode.
- // kReadOnlyDeviceMountPath --- read-only device, mounted in read-only mode.
- manager->RemountAllRemovableDrives(MountAccessMode::kReadOnly);
- // Simulate cros_disks reporting mount completed.
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice1SourcePath, MountType::kDevice,
- kDevice1MountPath);
- // Should remount disks that are not read-only by its hardware device.
- ASSERT_EQ(1U, observer_->GetEventCount());
- VerifyMountEvent(observer_->GetMountEvent(0), DiskMountManager::MOUNTING,
- MountError::kNone, kDevice1MountPath);
- // The disk is remounted in read-only mode.
- EXPECT_TRUE(
- manager->FindDiskBySourcePath(kDevice1SourcePath)->is_read_only());
- // Remounted disk should also appear as read-only to observers.
- EXPECT_TRUE(observer_->GetMountEvent(0).disk->is_read_only());
- // Remount in read-write mode again.
- manager->RemountAllRemovableDrives(MountAccessMode::kReadWrite);
- // Simulate cros_disks reporting mount completed.
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice1SourcePath, MountType::kDevice,
- kDevice1MountPath);
- // Event handlers of observers should be called.
- ASSERT_EQ(2U, observer_->GetEventCount());
- VerifyMountEvent(observer_->GetMountEvent(1), DiskMountManager::MOUNTING,
- MountError::kNone, kDevice1MountPath);
- // The read-write device should be remounted in read-write mode.
- EXPECT_FALSE(
- manager->FindDiskBySourcePath(kDevice1SourcePath)->is_read_only());
- // Remounted disk should also appear as writable to observers.
- EXPECT_FALSE(observer_->GetMountEvent(1).disk->is_read_only());
- }
- // Tests that the observer gets notified on attempt to rename non existent mount
- // point.
- TEST_F(DiskMountManagerTest, Rename_NotMounted) {
- DiskMountManager::GetInstance()->RenameMountedDevice("/mount/non_existent",
- "MYUSB");
- ASSERT_EQ(1U, observer_->GetEventCount());
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_COMPLETED,
- RenameError::kUnknown, "/mount/non_existent", "MYUSB"),
- observer_->GetRenameEvent(0));
- }
- // Tests that the observer gets notified on attempt to rename read-only mount
- // point.
- TEST_F(DiskMountManagerTest, Rename_ReadOnly) {
- DiskMountManager::GetInstance()->RenameMountedDevice(kReadOnlyDeviceMountPath,
- "MYUSB");
- ASSERT_EQ(1U, observer_->GetEventCount());
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_COMPLETED,
- RenameError::kDeviceNotAllowed,
- kReadOnlyDeviceSourcePath, "MYUSB"),
- observer_->GetRenameEvent(0));
- }
- // Tests that it is not possible to rename archive mount point.
- TEST_F(DiskMountManagerTest, Rename_Archive) {
- DiskMountManager::GetInstance()->RenameMountedDevice("/archive/mount_path",
- "MYUSB");
- ASSERT_EQ(1U, observer_->GetEventCount());
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_COMPLETED,
- RenameError::kUnknown, "/archive/source_path", "MYUSB"),
- observer_->GetRenameEvent(0));
- }
- // Tests that rename fails if the device cannot be unmounted.
- TEST_F(DiskMountManagerTest, Rename_FailToUnmount) {
- // Before renaming mounted device, the device should be unmounted.
- // In this test unmount will fail, and there should be no attempt to
- // rename the device.
- fake_cros_disks_client_->MakeUnmountFail(MountError::kUnknown);
- // Start test.
- DiskMountManager::GetInstance()->RenameMountedDevice(kDevice1MountPath,
- "MYUSB");
- // Cros disks will respond asynchronoulsy, so let's drain the message loop.
- base::RunLoop().RunUntilIdle();
- // Observer should be notified that unmount attempt fails and rename 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(MountError::kUnknown, mount_event.error_code);
- EXPECT_EQ(kDevice1MountPath, mount_event.mount_point.mount_path);
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_COMPLETED,
- RenameError::kUnknown, kDevice1SourcePath, "MYUSB"),
- observer_->GetRenameEvent(1));
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(0, fake_cros_disks_client_->rename_call_count());
- // The device mount should still be here.
- EXPECT_TRUE(HasMountPoint(kDevice1MountPath));
- }
- // Tests that observer is notified when cros disks fails to start rename
- // process.
- TEST_F(DiskMountManagerTest, Rename_RenameFailsToStart) {
- // Before renaming mounted device, the device should be unmounted.
- // In this test, unmount will succeed, but call to Rename method will
- // fail.
- fake_cros_disks_client_->MakeRenameFail();
- // Start the test.
- DiskMountManager::GetInstance()->RenameMountedDevice(kDevice1MountPath,
- "MYUSB");
- // 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 rename 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(MountError::kNone, mount_event.error_code);
- EXPECT_EQ(kDevice1MountPath, mount_event.mount_point.mount_path);
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_COMPLETED,
- RenameError::kUnknown, kDevice1SourcePath, "MYUSB"),
- observer_->GetRenameEvent(1));
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->rename_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_rename_device_path());
- EXPECT_EQ("MYUSB", fake_cros_disks_client_->last_rename_volume_name());
- // The device mount should be gone.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- }
- // Tests the case where there are two rename requests for the same device.
- TEST_F(DiskMountManagerTest, Rename_ConcurrentRenameCalls) {
- // Only the first rename request should be processed (the second unmount
- // request fails because the device is already unmounted at that point).
- // CrosDisksClient will report that the rename process for the first request
- // is successfully started.
- fake_cros_disks_client_->set_unmount_listener(base::BindRepeating(
- &FakeCrosDisksClient::MakeUnmountFail,
- base::Unretained(fake_cros_disks_client_), MountError::kInternal));
- // Start the test.
- DiskMountManager::GetInstance()->RenameMountedDevice(kDevice1MountPath,
- "MYUSB1");
- DiskMountManager::GetInstance()->RenameMountedDevice(kDevice1MountPath,
- "MYUSB2");
- // Cros disks will respond asynchronoulsy, so let's drain the message loop.
- base::RunLoop().RunUntilIdle();
- // The observer should get a RENAME_STARTED event for one rename request and a
- // RENAME_COMPLETED with an error code for the other rename request. The
- // renaming will be started only for the first request.
- // There should be only one UNMOUNTING event. The result of the second one
- // should not be reported as the mount point will go away after the first
- // request.
- //
- // Note that in this test the rename completion signal will not be simulated,
- // so the observer should not get RENAME_COMPLETED signal.
- ASSERT_EQ(3U, observer_->GetEventCount());
- const MountEvent& mount_event = observer_->GetMountEvent(0);
- EXPECT_EQ(DiskMountManager::UNMOUNTING, mount_event.event);
- EXPECT_EQ(MountError::kNone, mount_event.error_code);
- EXPECT_EQ(kDevice1MountPath, mount_event.mount_point.mount_path);
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_COMPLETED,
- RenameError::kUnknown, kDevice1SourcePath, "MYUSB2"),
- observer_->GetRenameEvent(1));
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_STARTED, RenameError::kNone,
- kDevice1SourcePath, "MYUSB1"),
- observer_->GetRenameEvent(2));
- EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->rename_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_rename_device_path());
- EXPECT_EQ("MYUSB1", fake_cros_disks_client_->last_rename_volume_name());
- // The device mount should be gone.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- }
- // Tests the case when the rename process actually starts and fails.
- TEST_F(DiskMountManagerTest, Rename_RenameFails) {
- // Both unmount and rename device calls are successful in this test.
- // Start the test.
- DiskMountManager::GetInstance()->RenameMountedDevice(kDevice1MountPath,
- "MYUSB");
- // Wait for Unmount and Rename calls to end.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->rename_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_rename_device_path());
- EXPECT_EQ("MYUSB", fake_cros_disks_client_->last_rename_volume_name());
- // The device should be unmounted by now.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- // Send failing RENAME_COMPLETED signal.
- // The failure is marked by ! in fromt of the path (but this should change
- // soon).
- fake_cros_disks_client_->NotifyRenameCompleted(RenameError::kUnknown,
- kDevice1SourcePath);
- // The observer should get notified that the device was unmounted and that
- // renaming has started.
- // After the renaming starts, the test will simulate failing
- // RENAME_COMPLETED signal, so the observer should also be notified the
- // renaming has failed (RENAME_COMPLETED event).
- ASSERT_EQ(3U, observer_->GetEventCount());
- VerifyMountEvent(observer_->GetMountEvent(0), DiskMountManager::UNMOUNTING,
- MountError::kNone, kDevice1MountPath);
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_STARTED, RenameError::kNone,
- kDevice1SourcePath, "MYUSB"),
- observer_->GetRenameEvent(1));
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_COMPLETED,
- RenameError::kUnknown, kDevice1SourcePath, "MYUSB"),
- observer_->GetRenameEvent(2));
- }
- // Tests the case when renaming completes successfully.
- TEST_F(DiskMountManagerTest, Rename_RenameSuccess) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- const DiskMountManager::Disks& disks = manager->disks();
- // Set up cros disks client mocks.
- // Both unmount and rename device calls are successful in this test.
- // Start the test.
- DiskMountManager::GetInstance()->RenameMountedDevice(kDevice1MountPath,
- "MYUSB1");
- // Wait for Unmount and Rename calls to end.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->rename_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_rename_device_path());
- EXPECT_EQ("MYUSB1", fake_cros_disks_client_->last_rename_volume_name());
- // The device should be unmounted by now.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- // Simulate cros_disks reporting success.
- fake_cros_disks_client_->NotifyRenameCompleted(RenameError::kNone,
- kDevice1SourcePath);
- // The observer should receive UNMOUNTING, RENAME_STARTED and RENAME_COMPLETED
- // events (all of them without an error set).
- ASSERT_EQ(3U, observer_->GetEventCount());
- VerifyMountEvent(observer_->GetMountEvent(0), DiskMountManager::UNMOUNTING,
- MountError::kNone, kDevice1MountPath);
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_STARTED, RenameError::kNone,
- kDevice1SourcePath, "MYUSB1"),
- observer_->GetRenameEvent(1));
- EXPECT_EQ(RenameEvent(DiskMountManager::RENAME_COMPLETED, RenameError::kNone,
- kDevice1SourcePath, "MYUSB1"),
- observer_->GetRenameEvent(2));
- // Disk should have new value for device label name
- EXPECT_EQ("MYUSB1", disks.find(kDevice1SourcePath)->get()->device_label());
- }
- // Tests that it's possible to rename the device twice in a row (this may not be
- // true if the list of pending renames is not properly cleared).
- TEST_F(DiskMountManagerTest, Rename_ConsecutiveRenameCalls) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- const DiskMountManager::Disks& disks = manager->disks();
- // All unmount and rename device calls are successful in this test.
- // Each of the should be made twice (once for each renaming task).
- // Start the test.
- DiskMountManager::GetInstance()->RenameMountedDevice(kDevice1MountPath,
- "MYUSB");
- // Wait for Unmount and Rename calls to end.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(1, fake_cros_disks_client_->rename_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_rename_device_path());
- EXPECT_EQ("MYUSB", fake_cros_disks_client_->last_rename_volume_name());
- EXPECT_EQ("", disks.find(kDevice1SourcePath)->get()->base_mount_path());
- // The device should be unmounted by now.
- EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
- // Simulate cros_disks reporting success.
- fake_cros_disks_client_->NotifyRenameCompleted(RenameError::kNone,
- kDevice1SourcePath);
- // Simulate the device remounting.
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice1SourcePath, MountType::kDevice,
- kDevice1MountPath);
- EXPECT_TRUE(HasMountPoint(kDevice1MountPath));
- auto previousMountPath = disks.find(kDevice1SourcePath)->get()->mount_path();
- // Try renaming again.
- DiskMountManager::GetInstance()->RenameMountedDevice(kDevice1MountPath,
- "MYUSB2");
- // Wait for Unmount and Rename calls to end.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(kDevice1MountPath,
- fake_cros_disks_client_->last_unmount_device_path());
- EXPECT_EQ(2, fake_cros_disks_client_->rename_call_count());
- EXPECT_EQ(kDevice1SourcePath,
- fake_cros_disks_client_->last_rename_device_path());
- EXPECT_EQ("MYUSB2", fake_cros_disks_client_->last_rename_volume_name());
- // Base mount path should be set to previous mount path.
- EXPECT_EQ(previousMountPath,
- disks.find(kDevice1SourcePath)->get()->base_mount_path());
- // Simulate cros_disks reporting success.
- fake_cros_disks_client_->NotifyRenameCompleted(RenameError::kNone,
- kDevice1SourcePath);
- // The observer should receive UNMOUNTING, RENAME_STARTED and RENAME_COMPLETED
- // events (all of them without an error set) twice (once for each renaming
- // task).
- // Also, there should be a MOUNTING event when the device remounting is
- // simulated.
- EXPECT_EQ(7U, observer_->GetEventCount());
- EXPECT_EQ(1U, observer_->CountRenameEvents(RenameEvent(
- DiskMountManager::RENAME_COMPLETED, RenameError::kNone,
- kDevice1SourcePath, "MYUSB2")));
- EXPECT_EQ(1U, observer_->CountRenameEvents(RenameEvent(
- DiskMountManager::RENAME_COMPLETED, RenameError::kNone,
- kDevice1SourcePath, "MYUSB")));
- EXPECT_EQ(1U, observer_->CountRenameEvents(RenameEvent(
- DiskMountManager::RENAME_STARTED, RenameError::kNone,
- kDevice1SourcePath, "MYUSB")));
- EXPECT_EQ(1U, observer_->CountRenameEvents(RenameEvent(
- DiskMountManager::RENAME_STARTED, RenameError::kNone,
- kDevice1SourcePath, "MYUSB2")));
- EXPECT_EQ(2U,
- observer_->CountMountEvents(DiskMountManager::UNMOUNTING,
- MountError::kNone, kDevice1MountPath));
- EXPECT_EQ(1U,
- observer_->CountMountEvents(DiskMountManager::MOUNTING,
- MountError::kNone, kDevice1MountPath));
- }
- void SaveUnmountResult(MountError* save_error,
- base::OnceClosure done_callback,
- MountError error_code) {
- *save_error = error_code;
- std::move(done_callback).Run();
- }
- TEST_F(DiskMountManagerTest, UnmountDeviceRecursively) {
- base::RunLoop run_loop;
- auto disk_sda =
- Disk::Builder().SetDevicePath("/dev/sda").SetIsParent(true).Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda)));
- auto disk_sda1 = Disk::Builder()
- .SetDevicePath("/dev/sda1")
- .SetMountPath("/mount/path1")
- .Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda1)));
- auto disk_sda2 = Disk::Builder()
- .SetDevicePath("/dev/sda2")
- .SetMountPath("/mount/path2")
- .Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda2)));
- MountError error_code = MountError::kUnknown;
- DiskMountManager::GetInstance()->UnmountDeviceRecursively(
- "/dev/sda",
- base::BindOnce(&SaveUnmountResult, base::Unretained(&error_code),
- run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(MountError::kNone, error_code);
- }
- TEST_F(DiskMountManagerTest, UnmountDeviceRecursively_NoMounted) {
- base::RunLoop run_loop;
- auto disk_sda =
- Disk::Builder().SetDevicePath("/dev/sda").SetIsParent(true).Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda)));
- auto disk_sda1 = Disk::Builder().SetDevicePath("/dev/sda1").Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda1)));
- MountError error_code = MountError::kUnknown;
- DiskMountManager::GetInstance()->UnmountDeviceRecursively(
- "/dev/sda",
- base::BindOnce(&SaveUnmountResult, base::Unretained(&error_code),
- run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(0, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(MountError::kNone, error_code);
- }
- TEST_F(DiskMountManagerTest, UnmountDeviceRecursively_NoDisk) {
- base::RunLoop run_loop;
- auto disk_sda =
- Disk::Builder().SetDevicePath("/dev/sda").SetIsParent(true).Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda)));
- auto disk_sda1 = Disk::Builder().SetDevicePath("/dev/sda1").Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda1)));
- MountError error_code = MountError::kUnknown;
- // Unmount sdB instead of sdA.
- DiskMountManager::GetInstance()->UnmountDeviceRecursively(
- "/dev/sdb",
- base::BindOnce(&SaveUnmountResult, base::Unretained(&error_code),
- run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(0, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(MountError::kInvalidDevicePath, error_code);
- }
- void SetUnmountError(FakeCrosDisksClient* client, MountError error_code) {
- client->MakeUnmountFail(error_code);
- }
- TEST_F(DiskMountManagerTest, UnmountDeviceRecursively_FailFirst) {
- base::RunLoop run_loop;
- auto disk_sda =
- Disk::Builder().SetDevicePath("/dev/sda").SetIsParent(true).Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda)));
- auto disk_sda1 = Disk::Builder()
- .SetDevicePath("/dev/sda1")
- .SetMountPath("/mount/path1")
- .Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda1)));
- auto disk_sda2 = Disk::Builder()
- .SetDevicePath("/dev/sda2")
- .SetMountPath("/mount/path2")
- .Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda2)));
- // Fail the first unmount, but make the second succeed.
- fake_cros_disks_client_->MakeUnmountFail(MountError::kInvalidUnmountOptions);
- fake_cros_disks_client_->set_unmount_listener(base::BindRepeating(
- &SetUnmountError, base::Unretained(fake_cros_disks_client_),
- MountError::kNone));
- MountError error_code = MountError::kUnknown;
- DiskMountManager::GetInstance()->UnmountDeviceRecursively(
- "/dev/sda",
- base::BindOnce(&SaveUnmountResult, base::Unretained(&error_code),
- run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(2, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(MountError::kInvalidUnmountOptions, error_code);
- }
- TEST_F(DiskMountManagerTest, UnmountDeviceRecursively_AlreadyUnmounted) {
- base::RunLoop run_loop;
- auto disk_sda =
- Disk::Builder().SetDevicePath("/dev/sda").SetIsParent(true).Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda)));
- auto disk_sda1 = Disk::Builder()
- .SetDevicePath("/dev/sda1")
- .SetMountPath("/mount/path1")
- .Build();
- EXPECT_TRUE(
- DiskMountManager::GetInstance()->AddDiskForTest(std::move(disk_sda1)));
- // Fail the unmount with "not mounted".
- fake_cros_disks_client_->MakeUnmountFail(MountError::kPathNotMounted);
- MountError error_code = MountError::kUnknown;
- DiskMountManager::GetInstance()->UnmountDeviceRecursively(
- "/dev/sda",
- base::BindOnce(&SaveUnmountResult, base::Unretained(&error_code),
- run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(1, fake_cros_disks_client_->unmount_call_count());
- EXPECT_EQ(MountError::kNone, error_code);
- }
- TEST_F(DiskMountManagerTest, Mount_MountUnsetsFirstMount) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- const Disk* device1 = manager->FindDiskBySourcePath(kDevice1SourcePath);
- EXPECT_TRUE(device1->is_first_mount());
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice1SourcePath, MountType::kDevice,
- kDevice1MountPath);
- EXPECT_FALSE(device1->is_first_mount());
- }
- TEST_F(DiskMountManagerTest, Mount_RemountPreservesFirstMount) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- EXPECT_TRUE(
- manager->FindDiskBySourcePath(kDevice1SourcePath)->is_first_mount());
- std::unique_ptr<dbus::Response> response = dbus::Response::CreateEmpty();
- DiskInfo disk_info(kDevice1SourcePath, response.get());
- fake_cros_disks_client_->set_next_get_device_properties_disk_info(&disk_info);
- fake_cros_disks_client_->NotifyMountEvent(MountEventType::kDiskAdded,
- kDevice1SourcePath);
- // NotifyMountEvent indirectly invokes CrosDisksClient::GetDeviceProperties,
- // which responds asynchronously.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, fake_cros_disks_client_->get_device_properties_success_count());
- EXPECT_TRUE(
- manager->FindDiskBySourcePath(kDevice1SourcePath)->is_first_mount());
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice1SourcePath, MountType::kDevice,
- kDevice1MountPath);
- EXPECT_FALSE(
- manager->FindDiskBySourcePath(kDevice1SourcePath)->is_first_mount());
- fake_cros_disks_client_->NotifyMountEvent(MountEventType::kDiskAdded,
- kDevice1SourcePath);
- // NotifyMountEvent indirectly invokes CrosDisksClient::GetDeviceProperties,
- // which responds asynchronously.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, fake_cros_disks_client_->get_device_properties_success_count());
- EXPECT_FALSE(
- manager->FindDiskBySourcePath(kDevice1SourcePath)->is_first_mount());
- }
- TEST_F(DiskMountManagerTest, Mount_DefersDuringGetDeviceProperties) {
- DiskMountManager* manager = DiskMountManager::GetInstance();
- // When a disk is added, we call GetDeviceProperties() before updating our
- // DiskMap. If the disk is mounted before this asynchronous call returns, we
- // defer sending the mount event so that clients are able to access the disk
- // information immediately.
- fake_cros_disks_client_->NotifyMountEvent(MountEventType::kDiskRemoved,
- kDevice1SourcePath);
- EXPECT_EQ(nullptr, manager->FindDiskBySourcePath(kDevice1SourcePath));
- std::unique_ptr<dbus::Response> response = dbus::Response::CreateEmpty();
- DiskInfo disk_info(kDevice1SourcePath, response.get());
- fake_cros_disks_client_->set_next_get_device_properties_disk_info(&disk_info);
- fake_cros_disks_client_->NotifyMountEvent(MountEventType::kDiskAdded,
- kDevice1SourcePath);
- fake_cros_disks_client_->NotifyMountCompleted(
- MountError::kNone, kDevice1SourcePath, MountType::kDevice,
- kDevice1MountPath);
- // The mount event will not have fired yet as we are still waiting for
- // GetDeviceProperties() to return.
- EXPECT_EQ(0u,
- observer_->CountMountEvents(DiskMountManager::MOUNTING,
- MountError::kNone, kDevice1MountPath));
- base::RunLoop().RunUntilIdle();
- // We have fired 3 events: disk removed -> disk added -> mounting
- const MountEvent& mount_event = observer_->GetMountEvent(2);
- EXPECT_EQ(DiskMountManager::MOUNTING, mount_event.event);
- EXPECT_EQ(kDevice1MountPath, mount_event.mount_point.mount_path);
- // The test OnMountEvent() finds the matching disk when it is called.
- EXPECT_NE(nullptr, mount_event.disk);
- }
- } // namespace
- } // namespace disks
- } // namespace ash
|