blob: 8df169d9fb00a9ab73742623a9b0d941f66e0be8 [file] [log] [blame]
// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cros-disks/mount_point.h"
#include <limits>
#include <utility>
#include <base/test/bind.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "cros-disks/mock_platform.h"
#include "cros-disks/platform.h"
namespace cros_disks {
namespace {
using testing::_;
using testing::ElementsAre;
using testing::Return;
using testing::StrictMock;
class MountPointTest : public testing::Test {
protected:
const std::string kMountPath = "/mount/path";
const std::string kSource = "source";
const std::string kFSType = "fstype";
const std::string kOptions = "foo=bar";
StrictMock<MockPlatform> platform_;
const MountPointData data_ = {.mount_path = base::FilePath(kMountPath),
.source = kSource,
.filesystem_type = kFSType,
.flags = MS_DIRSYNC | MS_NODEV,
.data = kOptions};
};
} // namespace
TEST_F(MountPointTest, Unmount) {
auto mount_point = std::make_unique<MountPoint>(data_, &platform_);
EXPECT_CALL(platform_, Unmount(base::FilePath(kMountPath), kFSType))
.WillOnce(Return(MountError::kBusy));
EXPECT_EQ(MountError::kBusy, mount_point->Unmount());
EXPECT_CALL(platform_, Unmount(base::FilePath(kMountPath), kFSType))
.WillOnce(Return(MountError::kSuccess));
EXPECT_CALL(platform_, RemoveEmptyDirectory(kMountPath))
.WillOnce(Return(true));
EXPECT_EQ(MountError::kSuccess, mount_point->Unmount());
EXPECT_EQ(MountError::kPathNotMounted, mount_point->Unmount());
}
TEST_F(MountPointTest, UnmountOnDestroy) {
const std::unique_ptr<MountPoint> mount_point =
std::make_unique<MountPoint>(data_, &platform_);
EXPECT_TRUE(mount_point->is_mounted());
EXPECT_CALL(platform_, Unmount(base::FilePath(kMountPath), kFSType))
.WillOnce(Return(MountError::kSuccess));
EXPECT_CALL(platform_, RemoveEmptyDirectory(kMountPath))
.WillOnce(Return(false));
}
TEST_F(MountPointTest, UnmountError) {
const std::unique_ptr<MountPoint> mount_point =
std::make_unique<MountPoint>(data_, &platform_);
EXPECT_TRUE(mount_point->is_mounted());
EXPECT_CALL(platform_, Unmount(base::FilePath(kMountPath), kFSType))
.WillOnce(Return(MountError::kPathNotMounted));
EXPECT_CALL(platform_, RemoveEmptyDirectory(kMountPath))
.WillOnce(Return(true));
EXPECT_EQ(MountError::kPathNotMounted, mount_point->Unmount());
EXPECT_FALSE(mount_point->is_mounted());
}
TEST_F(MountPointTest, Remount) {
const std::unique_ptr<MountPoint> mount_point =
std::make_unique<MountPoint>(data_, &platform_);
EXPECT_TRUE(mount_point->is_mounted());
EXPECT_FALSE(mount_point->is_read_only());
EXPECT_CALL(platform_,
Mount(kSource, kMountPath, kFSType,
MS_DIRSYNC | MS_NODEV | MS_RDONLY | MS_REMOUNT, kOptions))
.WillOnce(Return(MountError::kSuccess));
EXPECT_EQ(MountError::kSuccess, mount_point->Remount(true));
EXPECT_TRUE(mount_point->is_read_only());
EXPECT_CALL(platform_, Mount(kSource, kMountPath, kFSType,
MS_DIRSYNC | MS_NODEV | MS_REMOUNT, kOptions))
.WillOnce(Return(MountError::kInternalError));
EXPECT_EQ(MountError::kInternalError, mount_point->Remount(false));
EXPECT_TRUE(mount_point->is_read_only());
EXPECT_CALL(platform_, Unmount(base::FilePath(kMountPath), kFSType))
.WillOnce(Return(MountError::kSuccess));
EXPECT_CALL(platform_, RemoveEmptyDirectory(kMountPath))
.WillOnce(Return(true));
}
TEST_F(MountPointTest, RemountUnmounted) {
const std::unique_ptr<MountPoint> mount_point =
MountPoint::CreateUnmounted(data_);
EXPECT_FALSE(mount_point->is_mounted());
EXPECT_FALSE(mount_point->is_read_only());
EXPECT_EQ(MountError::kPathNotMounted, mount_point->Remount(true));
EXPECT_FALSE(mount_point->is_read_only());
}
TEST_F(MountPointTest, MountError) {
EXPECT_CALL(platform_, Mount(kSource, kMountPath, kFSType,
MS_DIRSYNC | MS_NODEV, kOptions))
.WillOnce(Return(MountError::kInvalidArgument));
MountError error = MountError::kUnknownError;
const std::unique_ptr<MountPoint> mount_point =
MountPoint::Mount(data_, &platform_, &error);
EXPECT_FALSE(mount_point);
EXPECT_EQ(MountError::kInvalidArgument, error);
}
TEST_F(MountPointTest, MountSucceeds) {
MountError error = MountError::kUnknownError;
EXPECT_CALL(platform_, Mount(kSource, kMountPath, kFSType,
MS_DIRSYNC | MS_NODEV, kOptions))
.WillOnce(Return(MountError::kSuccess));
const std::unique_ptr<MountPoint> mount_point =
MountPoint::Mount(data_, &platform_, &error);
EXPECT_EQ(MountError::kSuccess, error);
EXPECT_TRUE(mount_point);
EXPECT_TRUE(mount_point->is_mounted());
EXPECT_EQ(data_.mount_path, mount_point->path());
EXPECT_EQ(data_.source, mount_point->source());
EXPECT_EQ(data_.filesystem_type, mount_point->fstype());
EXPECT_EQ(data_.flags, mount_point->flags());
EXPECT_CALL(platform_, Unmount(base::FilePath(kMountPath), kFSType))
.WillOnce(Return(MountError::kSuccess));
EXPECT_CALL(platform_, RemoveEmptyDirectory(kMountPath))
.WillOnce(Return(true));
}
TEST_F(MountPointTest, CreateUnmounted) {
const std::unique_ptr<MountPoint> mount_point =
MountPoint::CreateUnmounted(data_);
EXPECT_TRUE(mount_point);
EXPECT_FALSE(mount_point->is_mounted());
EXPECT_EQ(data_.mount_path, mount_point->path());
EXPECT_EQ(data_.source, mount_point->source());
EXPECT_EQ(data_.filesystem_type, mount_point->fstype());
EXPECT_EQ(data_.flags, mount_point->flags());
}
TEST_F(MountPointTest, ParseProgressMessage) {
int percent = -1;
EXPECT_FALSE(MountPoint::ParseProgressMessage("", &percent));
EXPECT_FALSE(MountPoint::ParseProgressMessage("x", &percent));
EXPECT_EQ(percent, -1);
EXPECT_FALSE(MountPoint::ParseProgressMessage("%", &percent));
EXPECT_FALSE(MountPoint::ParseProgressMessage(" %", &percent));
EXPECT_FALSE(MountPoint::ParseProgressMessage("x%", &percent));
percent = -1;
EXPECT_TRUE(MountPoint::ParseProgressMessage("0%", &percent));
EXPECT_EQ(percent, 0);
percent = -1;
EXPECT_TRUE(MountPoint::ParseProgressMessage("Whatever 1%", &percent));
EXPECT_EQ(percent, 1);
percent = -1;
EXPECT_TRUE(MountPoint::ParseProgressMessage("Whatever 99%", &percent));
EXPECT_EQ(percent, 99);
percent = -1;
EXPECT_TRUE(MountPoint::ParseProgressMessage("Whatever 100%", &percent));
EXPECT_EQ(percent, 100);
percent = -1;
EXPECT_FALSE(MountPoint::ParseProgressMessage("Whatever 101%", &percent));
EXPECT_EQ(percent, 101);
percent = -1;
EXPECT_FALSE(MountPoint::ParseProgressMessage("Whatever 9999999999999999999%",
&percent));
EXPECT_EQ(percent, std::numeric_limits<int>::max());
}
TEST_F(MountPointTest, ProgressCallback) {
const std::unique_ptr<MountPoint> mount_point =
MountPoint::CreateUnmounted(data_);
mount_point->OnProgress("Loading 1%");
mount_point->OnProgress("Loading 2%");
std::vector<int> progress_percents;
mount_point->SetProgressCallback(base::BindLambdaForTesting(
[&progress_percents, want_mount_point = mount_point.get()](
const MountPoint* const got_mount_point) {
EXPECT_EQ(want_mount_point, got_mount_point);
progress_percents.push_back(got_mount_point->progress_percent());
}));
mount_point->OnProgress("Loading 3%");
mount_point->OnProgress("Loading 99%");
mount_point->OnProgress("");
mount_point->OnProgress("%");
mount_point->OnProgress("xx%");
mount_point->OnProgress("Ignored 1");
mount_point->OnProgress("Loading 100%");
EXPECT_THAT(progress_percents, ElementsAre(3, 99, 100));
}
} // namespace cros_disks