blob: 6f51900be29e7ce2625af4df4ff76bd01e8f7165 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Unit tests for cros_disks::MountManager. See mount-manager.h for details
// on MountManager.
#include "cros-disks/mount_manager.h"
#include <sys/mount.h>
#include <sys/unistd.h>
#include <algorithm>
#include <string>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "cros-disks/metrics.h"
#include "cros-disks/mount_entry.h"
#include "cros-disks/mount_options.h"
#include "cros-disks/platform.h"
using std::set;
using std::string;
using std::vector;
using testing::ElementsAre;
using testing::Invoke;
using testing::Return;
using testing::_;
namespace {
const char kMountRootDirectory[] = "/media/removable";
const char kTestSourcePath[] = "source";
const char kTestMountPath[] = "/media/removable/test";
const char kInvalidMountPath[] = "/media/removable/../test/doc";
} // namespace
namespace cros_disks {
// A mock platform class for testing the mount manager base class.
class MockPlatform : public Platform {
public:
MockPlatform() {}
MOCK_CONST_METHOD1(CreateDirectory, bool(const string& path));
MOCK_CONST_METHOD1(CreateOrReuseEmptyDirectory, bool(const string& path));
MOCK_CONST_METHOD3(CreateOrReuseEmptyDirectoryWithFallback,
bool(string* path, unsigned max_suffix_to_retry,
const set<string>& reserved_paths));
MOCK_CONST_METHOD1(RemoveEmptyDirectory, bool(const string& path));
MOCK_CONST_METHOD3(SetOwnership, bool(const string& path,
uid_t user_id, gid_t group_id));
MOCK_CONST_METHOD2(SetPermissions, bool(const string& path, mode_t mode));
};
// A mock mount manager class for testing the mount manager base class.
class MountManagerUnderTest : public MountManager {
public:
MountManagerUnderTest(Platform* platform, Metrics* metrics)
: MountManager(kMountRootDirectory, platform, metrics) {
}
MOCK_CONST_METHOD1(CanMount, bool(const string& source_path));
MOCK_CONST_METHOD0(GetMountSourceType, MountSourceType());
MOCK_METHOD5(DoMount, MountErrorType(const string& source_path,
const string& filesystem_type,
const vector<string>& options,
const string& mount_path,
MountOptions* applied_options));
MOCK_METHOD2(DoUnmount, MountErrorType(const string& path,
const vector<string>& options));
MOCK_CONST_METHOD1(ShouldReserveMountPathOnError,
bool(MountErrorType error_type));
MOCK_CONST_METHOD1(SuggestMountPath, string(const string& source_path));
};
class MountManagerTest : public ::testing::Test {
public:
MountManagerTest() : manager_(&platform_, &metrics_) {}
protected:
Metrics metrics_;
MockPlatform platform_;
MountManagerUnderTest manager_;
string filesystem_type_;
string mount_path_;
string source_path_;
vector<string> options_;
};
// Verifies that MountManager::Initialize() returns false when it fails to
// create the mount root directory.
TEST_F(MountManagerTest, InitializeFailedInCreateDirectory) {
EXPECT_CALL(platform_, CreateDirectory(kMountRootDirectory))
.WillOnce(Return(false));
EXPECT_CALL(platform_,
SetOwnership(kMountRootDirectory, getuid(), getgid()))
.Times(0);
EXPECT_CALL(platform_, SetPermissions(kMountRootDirectory, _))
.Times(0);
EXPECT_FALSE(manager_.Initialize());
}
// Verifies that MountManager::Initialize() returns false when it fails to
// set the ownership of the created mount root directory.
TEST_F(MountManagerTest, InitializeFailedInSetOwnership) {
EXPECT_CALL(platform_, CreateDirectory(kMountRootDirectory))
.WillOnce(Return(true));
EXPECT_CALL(platform_,
SetOwnership(kMountRootDirectory, getuid(), getgid()))
.WillOnce(Return(false));
EXPECT_CALL(platform_, SetPermissions(kMountRootDirectory, _))
.Times(0);
EXPECT_FALSE(manager_.Initialize());
}
// Verifies that MountManager::Initialize() returns false when it fails to
// set the permissions of the created mount root directory.
TEST_F(MountManagerTest, InitializeFailedInSetPermissions) {
EXPECT_CALL(platform_, CreateDirectory(kMountRootDirectory))
.WillOnce(Return(true));
EXPECT_CALL(platform_,
SetOwnership(kMountRootDirectory, getuid(), getgid()))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(kMountRootDirectory, _))
.WillOnce(Return(false));
EXPECT_FALSE(manager_.Initialize());
}
// Verifies that MountManager::Initialize() returns true when it creates
// the mount root directory with the specified ownership and permissions.
TEST_F(MountManagerTest, InitializeSucceeded) {
EXPECT_CALL(platform_, CreateDirectory(kMountRootDirectory))
.WillOnce(Return(true));
EXPECT_CALL(platform_,
SetOwnership(kMountRootDirectory, getuid(), getgid()))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(kMountRootDirectory, _))
.WillOnce(Return(true));
EXPECT_TRUE(manager_.Initialize());
}
// Verifies that MountManager::Mount() returns an error when it is invoked
// to mount an empty source path.
TEST_F(MountManagerTest, MountFailedWithEmptySourcePath) {
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_INVALID_ARGUMENT,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
}
// Verifies that MountManager::Mount() returns an error when it is invoked
// with a nullptr mount path.
TEST_F(MountManagerTest, MountFailedWithNullMountPath) {
source_path_ = kTestSourcePath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_INVALID_ARGUMENT,
manager_.Mount(source_path_, filesystem_type_, options_, nullptr));
}
// Verifies that MountManager::Mount() returns an error when it is invoked
// with an invalid mount path.
TEST_F(MountManagerTest, MountFailedWithInvalidMountPath) {
source_path_ = kTestSourcePath;
mount_path_ = kInvalidMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_INVALID_PATH,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
}
// Verifies that MountManager::Mount() returns an error when it is invoked
// without a given mount path and the suggested mount path is invalid.
TEST_F(MountManagerTest, MountFailedWithInvalidSuggestedMountPath) {
source_path_ = kTestSourcePath;
string suggested_mount_path = kInvalidMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_))
.WillRepeatedly(Return(suggested_mount_path));
EXPECT_EQ(MOUNT_ERROR_INVALID_PATH,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
options_.push_back("mountlabel=custom_label");
EXPECT_EQ(MOUNT_ERROR_INVALID_PATH,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
}
// Verifies that MountManager::Mount() returns an error when it is invoked
// with an mount label that yields an invalid mount path.
TEST_F(MountManagerTest, MountFailedWithInvalidMountLabel) {
source_path_ = kTestSourcePath;
string suggested_mount_path = kTestSourcePath;
options_.push_back("mountlabel=../custom_label");
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_))
.WillOnce(Return(suggested_mount_path));
EXPECT_EQ(MOUNT_ERROR_INVALID_PATH,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
}
// Verifies that MountManager::Mount() returns an error when it fails to
// create the specified mount directory.
TEST_F(MountManagerTest, MountFailedInCreateOrReuseEmptyDirectory) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(false));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_DIRECTORY_CREATION_FAILED,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
}
// Verifies that MountManager::Mount() returns an error when it fails to
// create a specified but already reserved mount directory.
TEST_F(MountManagerTest, MountFailedInCreateDirectoryDueToReservedMountPath) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
manager_.ReserveMountPath(mount_path_, MOUNT_ERROR_UNKNOWN_FILESYSTEM);
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.GetMountErrorOfReservedMountPath(mount_path_));
EXPECT_EQ(MOUNT_ERROR_DIRECTORY_CREATION_FAILED,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.GetMountErrorOfReservedMountPath(mount_path_));
}
// Verifies that MountManager::Mount() returns an error when it fails to
// create a mount directory after a number of trials.
TEST_F(MountManagerTest, MountFailedInCreateOrReuseEmptyDirectoryWithFallback) {
source_path_ = kTestSourcePath;
string suggested_mount_path = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.WillOnce(Return(false));
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(source_path_))
.WillOnce(Return(suggested_mount_path));
EXPECT_EQ(MOUNT_ERROR_DIRECTORY_CREATION_FAILED,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ("", mount_path_);
EXPECT_FALSE(manager_.IsMountPathInCache(suggested_mount_path));
}
// Verifies that MountManager::Mount() returns an error when it fails to
// set the ownership of the created mount directory.
TEST_F(MountManagerTest, MountFailedInSetOwnership) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(false));
EXPECT_CALL(platform_, SetPermissions(_, _)).Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_DIRECTORY_CREATION_FAILED,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
}
// Verifies that MountManager::Mount() returns an error when it fails to
// set the permissions of the created mount directory.
TEST_F(MountManagerTest, MountFailedInSetPermissions) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(false));
EXPECT_CALL(platform_, RemoveEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_DIRECTORY_CREATION_FAILED,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
}
// Verifies that MountManager::Mount() returns no error when it successfully
// mounts a source path to a specified mount path.
TEST_F(MountManagerTest, MountSucceededWithGivenMountPath) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, DoUnmount(mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
MountManager::MountState mount_state;
EXPECT_TRUE(manager_.GetMountStateFromCache(source_path_, &mount_state));
EXPECT_TRUE(mount_state.is_read_only);
EXPECT_TRUE(manager_.UnmountAll());
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Mock action to emulate DoMount with fallback to read-only mode.
MountErrorType DoMountSuccessReadOnly(
const std::string& source_path,
const std::string& filesystem_type,
const std::vector<std::string>& options,
const std::string& mount_path,
MountOptions* applied_options) {
applied_options->SetReadOnlyOption();
return MOUNT_ERROR_NONE;
}
// Verifies that MountManager::Mount() stores corret mount status in cache when
// read-only option is specified.
TEST_F(MountManagerTest, MountCachesStatusWithReadOnlyOption) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(true));
// Add read-only mount option.
options_.push_back("ro");
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
MountManager::MountState mount_state;
EXPECT_TRUE(manager_.GetMountStateFromCache(source_path_, &mount_state));
EXPECT_TRUE(mount_state.is_read_only);
}
// Verifies that MountManager::Mount() stores corret mount status in cache when
// the mounter successfully mounted a device but only in its read-only mode.
TEST_F(MountManagerTest, MountSuccededWithReadOnlyFallback) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(true));
// Emulate Mounter added read-only option as a fallback.
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
mount_path_, _))
.WillOnce(Invoke(DoMountSuccessReadOnly));
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
MountManager::MountState mount_state;
EXPECT_TRUE(manager_.GetMountStateFromCache(source_path_, &mount_state));
EXPECT_TRUE(mount_state.is_read_only);
}
// Verifies that MountManager::Mount() returns no error when it successfully
// mounts a source path with no mount path specified.
TEST_F(MountManagerTest, MountSucceededWithEmptyMountPath) {
source_path_ = kTestSourcePath;
string suggested_mount_path = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetOwnership(suggested_mount_path, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(suggested_mount_path, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(suggested_mount_path))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
suggested_mount_path, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, DoUnmount(suggested_mount_path, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, SuggestMountPath(source_path_))
.WillOnce(Return(suggested_mount_path));
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(suggested_mount_path, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.UnmountAll());
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Verifies that MountManager::Mount() returns no error when it successfully
// mounts a source path with a given mount label in options.
TEST_F(MountManagerTest, MountSucceededWithGivenMountLabel) {
source_path_ = kTestSourcePath;
string suggested_mount_path = kTestMountPath;
string final_mount_path = string(kMountRootDirectory) + "/custom_label";
options_.push_back("mountlabel=custom_label");
vector<string> updated_options;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetOwnership(final_mount_path, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(final_mount_path, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(final_mount_path))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, updated_options,
final_mount_path, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, DoUnmount(final_mount_path, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, SuggestMountPath(source_path_))
.WillOnce(Return(suggested_mount_path));
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(final_mount_path, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.UnmountAll());
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Verifies that MountManager::Mount() handles the mounting of an already
// mounted source path properly.
TEST_F(MountManagerTest, MountWithAlreadyMountedSourcePath) {
source_path_ = kTestSourcePath;
string suggested_mount_path = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetOwnership(suggested_mount_path, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(suggested_mount_path, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(suggested_mount_path))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
suggested_mount_path, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, DoUnmount(suggested_mount_path, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, SuggestMountPath(source_path_))
.WillOnce(Return(suggested_mount_path));
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(suggested_mount_path, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
// Mount an already-mounted source path without specifying a mount path
mount_path_.clear();
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(suggested_mount_path, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
// Mount an already-mounted source path to the same mount path
mount_path_ = suggested_mount_path;
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(suggested_mount_path, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
// Mount an already-mounted source path to a different mount path
mount_path_ = "another-path";
EXPECT_EQ(MOUNT_ERROR_PATH_ALREADY_MOUNTED,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.IsMountPathInCache(suggested_mount_path));
EXPECT_TRUE(manager_.UnmountAll());
EXPECT_FALSE(manager_.IsMountPathReserved(suggested_mount_path));
}
// Verifies that MountManager::Mount() successfully reserves a path for a given
// type of error. A specific mount path is given in this case.
TEST_F(MountManagerTest, MountSucceededWithGivenMountPathInReservedCase) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_UNKNOWN_FILESYSTEM));
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_,
ShouldReserveMountPathOnError(MOUNT_ERROR_UNKNOWN_FILESYSTEM))
.WillOnce(Return(true));
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_TRUE(manager_.UnmountAll());
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Verifies that MountManager::Mount() successfully reserves a path for a given
// type of error. No specific mount path is given in this case.
TEST_F(MountManagerTest, MountSucceededWithEmptyMountPathInReservedCase) {
source_path_ = kTestSourcePath;
string suggested_mount_path = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetOwnership(suggested_mount_path, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(suggested_mount_path, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(suggested_mount_path))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
suggested_mount_path, _))
.WillOnce(Return(MOUNT_ERROR_UNKNOWN_FILESYSTEM));
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_,
ShouldReserveMountPathOnError(MOUNT_ERROR_UNKNOWN_FILESYSTEM))
.WillOnce(Return(true));
EXPECT_CALL(manager_, SuggestMountPath(source_path_))
.WillOnce(Return(suggested_mount_path));
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(suggested_mount_path, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_TRUE(manager_.UnmountAll());
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Verifies that MountManager::Mount() successfully reserves a path for a given
// type of error and returns the same error when it tries to mount the same path
// again.
TEST_F(MountManagerTest, MountSucceededWithAlreadyReservedMountPath) {
source_path_ = kTestSourcePath;
string suggested_mount_path = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetOwnership(suggested_mount_path, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(suggested_mount_path, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(suggested_mount_path))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
suggested_mount_path, _))
.WillOnce(Return(MOUNT_ERROR_UNKNOWN_FILESYSTEM));
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_,
ShouldReserveMountPathOnError(MOUNT_ERROR_UNKNOWN_FILESYSTEM))
.WillOnce(Return(true));
EXPECT_CALL(manager_, SuggestMountPath(source_path_))
.WillOnce(Return(suggested_mount_path));
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(suggested_mount_path, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
mount_path_ = "";
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(suggested_mount_path, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_TRUE(manager_.UnmountAll());
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Verifies that MountManager::Mount() successfully reserves a path for a given
// type of error and returns the same error when it tries to mount the same path
// again.
TEST_F(MountManagerTest, MountFailedWithGivenMountPathInReservedCase) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_UNKNOWN_FILESYSTEM));
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_,
ShouldReserveMountPathOnError(MOUNT_ERROR_UNKNOWN_FILESYSTEM))
.WillOnce(Return(false));
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Verifies that MountManager::Mount() fails to mount or reserve a path for
// a type of error that is not enabled for reservation.
TEST_F(MountManagerTest, MountFailedWithEmptyMountPathInReservedCase) {
source_path_ = kTestSourcePath;
string suggested_mount_path = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetOwnership(suggested_mount_path, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(suggested_mount_path, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(suggested_mount_path))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
suggested_mount_path, _))
.WillOnce(Return(MOUNT_ERROR_UNKNOWN_FILESYSTEM));
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_,
ShouldReserveMountPathOnError(MOUNT_ERROR_UNKNOWN_FILESYSTEM))
.WillOnce(Return(false));
EXPECT_CALL(manager_, SuggestMountPath(source_path_))
.WillOnce(Return(suggested_mount_path));
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ("", mount_path_);
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Verifies that MountManager::Unmount() returns an error when it is invoked
// to unmount an empty path.
TEST_F(MountManagerTest, UnmountFailedWithEmptyPath) {
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_INVALID_ARGUMENT,
manager_.Unmount(mount_path_, options_));
}
// Verifies that MountManager::Unmount() returns an error when it fails to
// unmount a path that is not mounted.
TEST_F(MountManagerTest, UnmountFailedWithPathNotMounted) {
mount_path_ = "nonexistent-path";
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(_)).Times(0);
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, RemoveEmptyDirectory(_)).Times(0);
EXPECT_CALL(manager_, DoMount(_, _, _, _, _)).Times(0);
EXPECT_CALL(manager_, DoUnmount(_, _)).Times(0);
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_PATH_NOT_MOUNTED,
manager_.Unmount(mount_path_, options_));
}
// Verifies that MountManager::Unmount() returns no error when it successfully
// unmounts a source path.
TEST_F(MountManagerTest, UnmountSucceededWithGivenSourcePath) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, DoUnmount(mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_EQ(MOUNT_ERROR_NONE, manager_.Unmount(source_path_, options_));
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
}
// Verifies that MountManager::Unmount() returns no error when it successfully
// unmounts a mount path.
TEST_F(MountManagerTest, UnmountSucceededWithGivenMountPath) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, DoUnmount(mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_NONE));
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_EQ(MOUNT_ERROR_NONE, manager_.Unmount(mount_path_, options_));
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
}
// Verifies that MountManager::Unmount() returns no error when it is invoked
// to unmount the source path of a reserved mount path.
TEST_F(MountManagerTest, UnmountSucceededWithGivenSourcePathInReservedCase) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_UNKNOWN_FILESYSTEM));
EXPECT_CALL(manager_, DoUnmount(mount_path_, _)).Times(0);
EXPECT_CALL(manager_,
ShouldReserveMountPathOnError(MOUNT_ERROR_UNKNOWN_FILESYSTEM))
.WillOnce(Return(true));
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_NONE, manager_.Unmount(source_path_, options_));
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Verifies that MountManager::Unmount() returns no error when it is invoked
// to unmount a reserved mount path.
TEST_F(MountManagerTest, UnmountSucceededWithGivenMountPathInReservedCase) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(platform_, CreateOrReuseEmptyDirectoryWithFallback(_, _, _))
.Times(0);
EXPECT_CALL(platform_, SetOwnership(mount_path_, _, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, SetPermissions(mount_path_, _))
.WillOnce(Return(true));
EXPECT_CALL(platform_, RemoveEmptyDirectory(mount_path_))
.WillOnce(Return(true));
EXPECT_CALL(manager_, DoMount(source_path_, filesystem_type_, options_,
mount_path_, _))
.WillOnce(Return(MOUNT_ERROR_UNKNOWN_FILESYSTEM));
EXPECT_CALL(manager_, DoUnmount(mount_path_, _)).Times(0);
EXPECT_CALL(manager_,
ShouldReserveMountPathOnError(MOUNT_ERROR_UNKNOWN_FILESYSTEM))
.WillOnce(Return(true));
EXPECT_CALL(manager_, SuggestMountPath(_)).Times(0);
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.Mount(source_path_, filesystem_type_, options_,
&mount_path_));
EXPECT_EQ(kTestMountPath, mount_path_);
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_NONE, manager_.Unmount(mount_path_, options_));
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
}
// Verifies that MountManager::AddMountPathToCache() works as expected.
TEST_F(MountManagerTest, AddMountPathToCache) {
string result;
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
bool is_read_only = true;
EXPECT_TRUE(manager_.AddMountPathToCache(source_path_, mount_path_,
is_read_only));
EXPECT_TRUE(manager_.GetMountPathFromCache(source_path_, &result));
EXPECT_EQ(mount_path_, result);
MountManager::MountState result_state;
EXPECT_TRUE(manager_.GetMountStateFromCache(source_path_, &result_state));
EXPECT_EQ(kTestMountPath, result_state.mount_path);
EXPECT_EQ(is_read_only, result_state.is_read_only);
EXPECT_FALSE(manager_.AddMountPathToCache(source_path_, "target1", false));
EXPECT_TRUE(manager_.GetMountPathFromCache(source_path_, &result));
EXPECT_EQ(mount_path_, result);
EXPECT_TRUE(manager_.RemoveMountPathFromCache(mount_path_));
}
// Verifies that MountManager::GetSourcePathFromCache() works as expected.
TEST_F(MountManagerTest, GetSourcePathFromCache) {
string result;
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_FALSE(manager_.GetSourcePathFromCache(mount_path_, &result));
EXPECT_TRUE(manager_.AddMountPathToCache(source_path_, mount_path_, false));
EXPECT_TRUE(manager_.GetSourcePathFromCache(mount_path_, &result));
EXPECT_EQ(source_path_, result);
EXPECT_TRUE(manager_.RemoveMountPathFromCache(mount_path_));
EXPECT_FALSE(manager_.GetSourcePathFromCache(mount_path_, &result));
}
// Verifies that MountManager::GetMountPathFromCache() works as expected.
TEST_F(MountManagerTest, GetMountPathFromCache) {
string result;
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_FALSE(manager_.GetMountPathFromCache(source_path_, &result));
EXPECT_TRUE(manager_.AddMountPathToCache(source_path_, mount_path_, false));
EXPECT_TRUE(manager_.GetMountPathFromCache(source_path_, &result));
EXPECT_EQ(mount_path_, result);
EXPECT_TRUE(manager_.RemoveMountPathFromCache(mount_path_));
EXPECT_FALSE(manager_.GetMountPathFromCache(source_path_, &result));
}
// Verifies that MountManager::IsMountPathInCache() works as expected.
TEST_F(MountManagerTest, IsMountPathInCache) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.AddMountPathToCache(source_path_, mount_path_, false));
EXPECT_TRUE(manager_.IsMountPathInCache(mount_path_));
EXPECT_TRUE(manager_.RemoveMountPathFromCache(mount_path_));
EXPECT_FALSE(manager_.IsMountPathInCache(mount_path_));
}
// Verifies that MountManager::RemoveMountPathFromCache() works as expected.
TEST_F(MountManagerTest, RemoveMountPathFromCache) {
source_path_ = kTestSourcePath;
mount_path_ = kTestMountPath;
EXPECT_FALSE(manager_.RemoveMountPathFromCache(mount_path_));
EXPECT_TRUE(manager_.AddMountPathToCache(source_path_, mount_path_, false));
EXPECT_TRUE(manager_.RemoveMountPathFromCache(mount_path_));
EXPECT_FALSE(manager_.RemoveMountPathFromCache(mount_path_));
}
// Verifies that MountManager::GetReservedMountPaths() works as expected.
TEST_F(MountManagerTest, GetReservedMountPaths) {
set<string> reserved_paths;
set<string> expected_paths;
string path1 = "path1";
string path2 = "path2";
reserved_paths = manager_.GetReservedMountPaths();
EXPECT_TRUE(expected_paths == reserved_paths);
manager_.ReserveMountPath(path1, MOUNT_ERROR_UNKNOWN_FILESYSTEM);
reserved_paths = manager_.GetReservedMountPaths();
expected_paths.insert(path1);
EXPECT_TRUE(expected_paths == reserved_paths);
manager_.ReserveMountPath(path2, MOUNT_ERROR_UNKNOWN_FILESYSTEM);
reserved_paths = manager_.GetReservedMountPaths();
expected_paths.insert(path2);
EXPECT_TRUE(expected_paths == reserved_paths);
manager_.UnreserveMountPath(path1);
reserved_paths = manager_.GetReservedMountPaths();
expected_paths.erase(path1);
EXPECT_TRUE(expected_paths == reserved_paths);
manager_.UnreserveMountPath(path2);
reserved_paths = manager_.GetReservedMountPaths();
expected_paths.erase(path2);
EXPECT_TRUE(expected_paths == reserved_paths);
}
// Verifies that MountManager::ReserveMountPath() and
// MountManager::UnreserveMountPath() work as expected.
TEST_F(MountManagerTest, ReserveAndUnreserveMountPath) {
mount_path_ = kTestMountPath;
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.GetMountErrorOfReservedMountPath(mount_path_));
manager_.ReserveMountPath(mount_path_, MOUNT_ERROR_UNKNOWN_FILESYSTEM);
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM,
manager_.GetMountErrorOfReservedMountPath(mount_path_));
manager_.UnreserveMountPath(mount_path_);
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.GetMountErrorOfReservedMountPath(mount_path_));
// Removing a nonexistent mount path should be ok
manager_.UnreserveMountPath(mount_path_);
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
// Adding an existent mount path should be ok
manager_.ReserveMountPath(mount_path_, MOUNT_ERROR_UNSUPPORTED_FILESYSTEM);
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_UNSUPPORTED_FILESYSTEM,
manager_.GetMountErrorOfReservedMountPath(mount_path_));
manager_.ReserveMountPath(mount_path_, MOUNT_ERROR_UNKNOWN_FILESYSTEM);
EXPECT_TRUE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_UNSUPPORTED_FILESYSTEM,
manager_.GetMountErrorOfReservedMountPath(mount_path_));
manager_.UnreserveMountPath(mount_path_);
EXPECT_FALSE(manager_.IsMountPathReserved(mount_path_));
EXPECT_EQ(MOUNT_ERROR_NONE,
manager_.GetMountErrorOfReservedMountPath(mount_path_));
}
// Verifies that MountManager::GetMountEntries() returns the expected list of
// mount entries under different scenarios.
TEST_F(MountManagerTest, GetMountEntries) {
EXPECT_CALL(manager_, GetMountSourceType())
.WillRepeatedly(Return(MOUNT_SOURCE_REMOVABLE_DEVICE));
vector<MountEntry> mount_entries;
// No mount entries is returned.
manager_.GetMountEntries(&mount_entries);
EXPECT_TRUE(mount_entries.empty());
// Verify that |mount_entries| is overwritten.
mount_entries.push_back(
MountEntry(MOUNT_ERROR_NONE, "", MOUNT_SOURCE_ARCHIVE, "", false));
manager_.GetMountEntries(&mount_entries);
EXPECT_TRUE(mount_entries.empty());
// A normal mount entry is returned.
EXPECT_TRUE(manager_.AddMountPathToCache(kTestSourcePath, kTestMountPath,
false));
manager_.GetMountEntries(&mount_entries);
ASSERT_EQ(1, mount_entries.size());
EXPECT_EQ(MOUNT_ERROR_NONE, mount_entries[0].error_type());
EXPECT_EQ(kTestSourcePath, mount_entries[0].source_path());
EXPECT_EQ(MOUNT_SOURCE_REMOVABLE_DEVICE, mount_entries[0].source_type());
EXPECT_EQ(kTestMountPath, mount_entries[0].mount_path());
// A reserved mount entry is returned.
manager_.ReserveMountPath(kTestMountPath, MOUNT_ERROR_UNKNOWN_FILESYSTEM);
manager_.GetMountEntries(&mount_entries);
ASSERT_EQ(1, mount_entries.size());
EXPECT_EQ(MOUNT_ERROR_UNKNOWN_FILESYSTEM, mount_entries[0].error_type());
EXPECT_EQ(kTestSourcePath, mount_entries[0].source_path());
EXPECT_EQ(MOUNT_SOURCE_REMOVABLE_DEVICE, mount_entries[0].source_type());
EXPECT_EQ(kTestMountPath, mount_entries[0].mount_path());
}
// Verifies that MountManager::ExtractMountLabelFromOptions() extracts a mount
// label from the given options and returns true.
TEST_F(MountManagerTest, ExtractMountLabelFromOptions) {
vector<string> options = {"ro", "mountlabel=My USB Drive", "noexec"};
string mount_label;
EXPECT_TRUE(manager_.ExtractMountLabelFromOptions(&options, &mount_label));
EXPECT_THAT(options, ElementsAre("ro", "noexec"));
EXPECT_EQ("My USB Drive", mount_label);
}
// Verifies that MountManager::ExtractMountLabelFromOptions() returns false
// when no mount label is found in the given options.
TEST_F(MountManagerTest, ExtractMountLabelFromOptionsWithNoMountLabel) {
vector<string> options;
string mount_label;
EXPECT_FALSE(manager_.ExtractMountLabelFromOptions(&options, &mount_label));
EXPECT_THAT(options, ElementsAre());
EXPECT_EQ("", mount_label);
options.push_back("ro");
EXPECT_FALSE(manager_.ExtractMountLabelFromOptions(&options, &mount_label));
EXPECT_THAT(options, ElementsAre("ro"));
EXPECT_EQ("", mount_label);
options.push_back("mountlabel");
EXPECT_FALSE(manager_.ExtractMountLabelFromOptions(&options, &mount_label));
EXPECT_THAT(options, ElementsAre("ro", "mountlabel"));
EXPECT_EQ("", mount_label);
}
// Verifies that MountManager::ExtractMountLabelFromOptions() extracts the last
// mount label from the given options with two mount labels.
TEST_F(MountManagerTest, ExtractMountLabelFromOptionsWithTwoMountLabels) {
vector<string> options = {"ro", "mountlabel=My USB Drive", "noexec",
"mountlabel=Another Label"};
string mount_label;
EXPECT_TRUE(manager_.ExtractMountLabelFromOptions(&options, &mount_label));
EXPECT_THAT(options, ElementsAre("ro", "noexec"));
EXPECT_EQ("Another Label", mount_label);
}
// Verifies that MountManager::ExtractUnmountOptions() extracts supported
// unmount options and returns true.
TEST_F(MountManagerTest, ExtractSupportedUnmountOptions) {
int unmount_flags = 0;
int expected_unmount_flags = MNT_FORCE;
options_.push_back("force");
EXPECT_TRUE(manager_.ExtractUnmountOptions(options_, &unmount_flags));
EXPECT_EQ(expected_unmount_flags, unmount_flags);
unmount_flags = 0;
expected_unmount_flags = MNT_DETACH;
options_.clear();
options_.push_back("lazy");
EXPECT_TRUE(manager_.ExtractUnmountOptions(options_, &unmount_flags));
EXPECT_EQ(expected_unmount_flags, unmount_flags);
unmount_flags = 0;
expected_unmount_flags = MNT_FORCE | MNT_DETACH;
options_.clear();
options_.push_back("force");
options_.push_back("lazy");
EXPECT_TRUE(manager_.ExtractUnmountOptions(options_, &unmount_flags));
EXPECT_EQ(expected_unmount_flags, unmount_flags);
}
// Verifies that MountManager::ExtractUnmountOptions() returns false when
// unsupported unmount options are given.
TEST_F(MountManagerTest, ExtractUnsupportedUnmountOptions) {
int unmount_flags = 0;
options_.push_back("foo");
EXPECT_FALSE(manager_.ExtractUnmountOptions(options_, &unmount_flags));
EXPECT_EQ(0, unmount_flags);
}
// Verifies that MountManager::IsPathImmediateChildOfParent() correctly
// determines if a path is an immediate child of another path.
TEST_F(MountManagerTest, IsPathImmediateChildOfParent) {
EXPECT_TRUE(manager_.IsPathImmediateChildOfParent(
"/media/archive/test.zip", "/media/archive"));
EXPECT_TRUE(manager_.IsPathImmediateChildOfParent(
"/media/archive/test.zip/", "/media/archive"));
EXPECT_TRUE(manager_.IsPathImmediateChildOfParent(
"/media/archive/test.zip", "/media/archive/"));
EXPECT_TRUE(manager_.IsPathImmediateChildOfParent(
"/media/archive/test.zip/", "/media/archive/"));
EXPECT_FALSE(manager_.IsPathImmediateChildOfParent(
"/media/archive/test.zip/doc.zip", "/media/archive/"));
EXPECT_FALSE(manager_.IsPathImmediateChildOfParent(
"/media/archive/test.zip", "/media/removable"));
EXPECT_FALSE(manager_.IsPathImmediateChildOfParent(
"/tmp/archive/test.zip", "/media/removable"));
EXPECT_FALSE(manager_.IsPathImmediateChildOfParent(
"/media", "/media/removable"));
}
// Verifies that MountManager::IsValidMountPath() correctly determines if a
// mount path is an immediate child of the mount root.
TEST_F(MountManagerTest, IsValidMountPath) {
manager_.mount_root_ = "/media/removable";
EXPECT_TRUE(manager_.IsValidMountPath("/media/removable/test"));
EXPECT_TRUE(manager_.IsValidMountPath("/media/removable/test/"));
EXPECT_TRUE(manager_.IsValidMountPath("/media/removable/test/"));
EXPECT_TRUE(manager_.IsValidMountPath("/media/removable//test"));
EXPECT_FALSE(manager_.IsValidMountPath("/media/archive/test"));
EXPECT_FALSE(manager_.IsValidMountPath("/media/removable/test/doc"));
EXPECT_FALSE(manager_.IsValidMountPath("/media/removable/../test"));
EXPECT_FALSE(manager_.IsValidMountPath("/media/removable/../test/"));
EXPECT_FALSE(manager_.IsValidMountPath("/media/removable/test/.."));
EXPECT_FALSE(manager_.IsValidMountPath("/media/removable/test/../"));
manager_.mount_root_ = "/media/archive";
EXPECT_TRUE(manager_.IsValidMountPath("/media/archive/test"));
EXPECT_FALSE(manager_.IsValidMountPath("/media/removable/test"));
}
} // namespace cros_disks