Skip to content

Commit

Permalink
[daemon][unit test] Add mount symlink resolution tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Sploder12 committed Sep 12, 2024
1 parent e5e2ec4 commit 4bb0fc1
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 3 deletions.
3 changes: 0 additions & 3 deletions src/utils/vm_mount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,6 @@ void mp::VMMount::resolve_source_path()
fs::path path{source_path};

auto status = MP_FILEOPS.symlink_status(path, err);
if (err)
throw std::runtime_error(
fmt::format("Mount source path \"{}\" is not accessible: {}.", source_path, err.message()));

if (status.type() == fs::file_type::symlink)
{
Expand Down
46 changes: 46 additions & 0 deletions tests/test_daemon_mount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "common.h"
#include "daemon_test_fixture.h"
#include "mock_file_ops.h"
#include "mock_logger.h"
#include "mock_mount_handler.h"
#include "mock_platform.h"
Expand Down Expand Up @@ -267,3 +268,48 @@ TEST_F(TestDaemonMount, performanceMountsNotImplementedHasErrorFails)
EXPECT_EQ(status.error_code(), grpc::StatusCode::FAILED_PRECONDITION);
EXPECT_THAT(status.error_message(), StrEq("The native mounts feature is not implemented on this backend."));
}

TEST_F(TestDaemonMount, symlinkSourceGetsResolved)
{
const auto [temp_dir, filename] = plant_instance_json(fake_json_contents(mac_addr, extra_interfaces));
config_builder.data_directory = temp_dir->path();

const auto [mock_file_ops, _] = mpt::MockFileOps::inject();
EXPECT_CALL(*mock_file_ops, symlink_status)
.WillOnce(Return(mp::fs::file_status{mp::fs::file_type::symlink}));
EXPECT_CALL(*mock_file_ops, read_symlink)
.WillOnce(Return(mp::fs::path{config_builder.data_directory.toStdString()}));


auto original_implementation_of_mkpath = [](const QDir& dir, const QString& dirName) -> bool {
return MP_FILEOPS.FileOps::mkpath(dir, dirName);
};
EXPECT_CALL(*mock_file_ops, mkpath)
.WillRepeatedly(original_implementation_of_mkpath);

auto original_implementation_of_open = [](QFileDevice& dev, QIODevice::OpenMode mode) -> bool {
return MP_FILEOPS.FileOps::open(dev, mode);
};
EXPECT_CALL(*mock_file_ops, open(A<QFileDevice&>(), A<QIODevice::OpenMode>()))
.WillRepeatedly(original_implementation_of_open);

auto original_implementation_of_commit = [](QSaveFile& file) -> bool {
return MP_FILEOPS.FileOps::commit(file);
};
EXPECT_CALL(*mock_file_ops, commit)
.WillRepeatedly(original_implementation_of_commit);

mp::Daemon daemon{config_builder.build()};

mp::MountRequest request;
request.set_source_path(mount_dir.path().toStdString());
request.set_mount_type(mp::MountRequest::NATIVE);
auto entry = request.add_target_paths();
entry->set_instance_name(mock_instance_name);
entry->set_target_path(fake_target_path);

auto status = call_daemon_slot(daemon, &mp::Daemon::mount, request,
StrictMock<mpt::MockServerReaderWriter<mp::MountReply, mp::MountRequest>>{});

EXPECT_TRUE(status.ok());
}
46 changes: 46 additions & 0 deletions tests/test_vm_mount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include "common.h"
#include "mock_file_ops.h"

#include <multipass/vm_mount.h>

Expand Down Expand Up @@ -139,4 +140,49 @@ TEST_F(TestVMMount, duplicateGidsThrowsWithDuplicateTargetID)
HasSubstr("1002:1001"),
HasSubstr("1000:1001"))));
}

TEST_F(TestVMMount, notSymlinkSourcePathUnchanged)
{
const auto [mock_file_ops, _] = mpt::MockFileOps::inject();
EXPECT_CALL(*mock_file_ops, symlink_status)
.WillOnce(Return(mp::fs::file_status{mp::fs::file_type::regular}));
EXPECT_CALL(*mock_file_ops, read_symlink).Times(0);

mp::VMMount mount{"src", {}, {}, mp::VMMount::MountType::Classic};

mount.resolve_source_path();

EXPECT_EQ(mount.get_source_path(), "src");
}

TEST_F(TestVMMount, absoluteSymlinkSourcePathResolved)
{
const auto [mock_file_ops, _] = mpt::MockFileOps::inject();
EXPECT_CALL(*mock_file_ops, symlink_status)
.WillOnce(Return(mp::fs::file_status{mp::fs::file_type::symlink}));
EXPECT_CALL(*mock_file_ops, read_symlink)
.WillOnce(Return(mp::fs::path{"/home/dest"}));

mp::VMMount mount{"/tmp/src", {}, {}, mp::VMMount::MountType::Classic};

mount.resolve_source_path();

EXPECT_EQ(mount.get_source_path(), "/home/dest");
}

TEST_F(TestVMMount, relativeSymlinkSourcePathResolved)
{
const auto [mock_file_ops, _] = mpt::MockFileOps::inject();
EXPECT_CALL(*mock_file_ops, symlink_status)
.WillOnce(Return(mp::fs::file_status{mp::fs::file_type::symlink}));
EXPECT_CALL(*mock_file_ops, read_symlink)
.WillOnce(Return(mp::fs::path{"./dest"}));

mp::VMMount mount{"/tmp/src", {}, {}, mp::VMMount::MountType::Classic};

mount.resolve_source_path();

EXPECT_EQ(mount.get_source_path(), "/tmp/dest");
}

} // namespace

0 comments on commit 4bb0fc1

Please sign in to comment.