// 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.

#include "cros-disks/system_mounter.h"

#include <sys/mount.h>

#include <base/files/scoped_temp_dir.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "cros-disks/mount_options.h"
#include "cros-disks/mount_point.h"
#include "cros-disks/platform.h"

namespace cros_disks {

using testing::_;
using testing::Return;

namespace {

constexpr uint64_t kDefaultMountFlags =
    MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC | MS_NOSYMFOLLOW;

class PlatformForTest : public Platform {
 public:
  // Tests are being run on devices that don't support nosymfollow. Strip it.
  MountErrorType Mount(const std::string& source,
                       const std::string& target,
                       const std::string& filesystem_type,
                       uint64_t flags,
                       const std::string& options) const override {
    EXPECT_TRUE((flags & MS_NOSYMFOLLOW) == MS_NOSYMFOLLOW);
    return Platform::Mount(source, target, filesystem_type,
                           flags & ~MS_NOSYMFOLLOW, options);
  }
};

class MockPlatform : public Platform {
 public:
  MOCK_METHOD(MountErrorType,
              Mount,
              (const std::string& source,
               const std::string& target,
               const std::string& filesystem_type,
               uint64_t flags,
               const std::string& options),
              (const, override));
  MOCK_METHOD(MountErrorType,
              Unmount,
              (const std::string& target, int flags),
              (const, override));
};
}  // namespace

TEST(SystemMounterTest, RunAsRootMount) {
  PlatformForTest platform;
  SystemMounter mounter(&platform, "tmpfs", /* read_only= */ false, {});

  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  MountErrorType error = MOUNT_ERROR_NONE;
  auto mountpoint = mounter.Mount("/dev/null", temp_dir.GetPath(), {}, &error);
  EXPECT_TRUE(mountpoint);
  EXPECT_EQ(MOUNT_ERROR_NONE, error);
  error = mountpoint->Unmount();
  EXPECT_EQ(MOUNT_ERROR_NONE, error);
}

TEST(SystemMounterTest, RunAsRootMountWithNonexistentSourcePath) {
  PlatformForTest platform;
  SystemMounter mounter(&platform, "ext2", /* read_only= */ false, {});

  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  // To test mounting a nonexistent source path, use ext2 as the
  // filesystem type instead of tmpfs since tmpfs does not care
  // about source path.
  MountErrorType error = MOUNT_ERROR_NONE;
  auto mountpoint =
      mounter.Mount("/nonexistent", temp_dir.GetPath(), {}, &error);
  EXPECT_FALSE(mountpoint);
  EXPECT_EQ(MOUNT_ERROR_INVALID_PATH, error);
}

TEST(SystemMounterTest, RunAsRootMountWithNonexistentTargetPath) {
  PlatformForTest platform;
  SystemMounter mounter(&platform, "tmpfs", /* read_only= */ false, {});

  MountErrorType error = MOUNT_ERROR_NONE;
  auto mountpoint =
      mounter.Mount("/dev/null", base::FilePath("/nonexistent"), {}, &error);
  EXPECT_FALSE(mountpoint);
  EXPECT_EQ(MOUNT_ERROR_INVALID_PATH, error);
}

TEST(SystemMounterTest, RunAsRootMountWithNonexistentFilesystemType) {
  PlatformForTest platform;
  SystemMounter mounter(&platform, "nonexistentfs", /* read_only= */ false, {});

  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  MountErrorType error = MOUNT_ERROR_NONE;
  auto mountpoint = mounter.Mount("/dev/null", temp_dir.GetPath(), {}, &error);
  EXPECT_FALSE(mountpoint);
  EXPECT_EQ(MOUNT_ERROR_UNSUPPORTED_FILESYSTEM, error);
}

TEST(SystemMounterTest, MountFilesystem) {
  MockPlatform platform;
  SystemMounter mounter(&platform, "fstype", /* read_only= */ false, {});

  EXPECT_CALL(platform, Mount("/dev/block", "/mnt/dir", "fstype", _, _))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  MountErrorType error = MOUNT_ERROR_UNKNOWN;
  auto mountpoint =
      mounter.Mount("/dev/block", base::FilePath("/mnt/dir"), {}, &error);
  ASSERT_TRUE(mountpoint);
  EXPECT_EQ(MOUNT_ERROR_NONE, error);

  EXPECT_CALL(platform, Unmount("/mnt/dir", 0))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  mountpoint.reset();
}

TEST(SystemMounterTest, MountFailed) {
  MockPlatform platform;
  SystemMounter mounter(&platform, "fstype", /* read_only= */ false, {});

  EXPECT_CALL(platform, Mount("/dev/block", "/mnt/dir", "fstype", _, _))
      .WillOnce(Return(MOUNT_ERROR_PATH_NOT_MOUNTED));
  EXPECT_CALL(platform, Unmount).Times(0);

  MountErrorType error = MOUNT_ERROR_UNKNOWN;
  auto mountpoint =
      mounter.Mount("/dev/block", base::FilePath("/mnt/dir"), {}, &error);
  ASSERT_FALSE(mountpoint);
  EXPECT_EQ(MOUNT_ERROR_PATH_NOT_MOUNTED, error);
}

TEST(SystemMounterTest, UnmountFailedNoRetry) {
  MockPlatform platform;
  SystemMounter mounter(&platform, "fstype", /* read_only= */ false, {});

  EXPECT_CALL(platform, Mount(_, "/mnt/dir", "fstype", _, _))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  MountErrorType error = MOUNT_ERROR_UNKNOWN;
  auto mountpoint =
      mounter.Mount("/dev/block", base::FilePath("/mnt/dir"), {}, &error);

  EXPECT_CALL(platform, Unmount("/mnt/dir", 0))
      .WillOnce(Return(MOUNT_ERROR_INVALID_ARGUMENT))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  EXPECT_EQ(MOUNT_ERROR_INVALID_ARGUMENT, mountpoint->Unmount());
  mountpoint.reset();
}

TEST(SystemMounterTest, UnmountBusyRetry) {
  MockPlatform platform;
  SystemMounter mounter(&platform, "fstype", /* read_only= */ false, {});

  EXPECT_CALL(platform, Mount(_, "/mnt/dir", "fstype", _, _))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  MountErrorType error = MOUNT_ERROR_UNKNOWN;
  auto mountpoint =
      mounter.Mount("/dev/block", base::FilePath("/mnt/dir"), {}, &error);

  EXPECT_CALL(platform, Unmount("/mnt/dir", 0))
      .WillOnce(Return(MOUNT_ERROR_PATH_ALREADY_MOUNTED));
  EXPECT_CALL(platform, Unmount("/mnt/dir", MNT_DETACH | MNT_FORCE))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  EXPECT_EQ(MOUNT_ERROR_NONE, mountpoint->Unmount());
  mountpoint.reset();
}

TEST(SystemMounterTest, MountFlags) {
  MockPlatform platform;
  SystemMounter mounter(&platform, "fstype", /* read_only= */ false, {});

  EXPECT_CALL(platform, Mount(_, "/mnt/dir", "fstype", kDefaultMountFlags, _))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  MountErrorType error = MOUNT_ERROR_UNKNOWN;
  auto mountpoint =
      mounter.Mount("/dev/block", base::FilePath("/mnt/dir"), {}, &error);
}

TEST(SystemMounterTest, ReadOnlyForced) {
  MockPlatform platform;
  SystemMounter mounter(&platform, "fstype", /* read_only= */ true, {});

  EXPECT_CALL(platform,
              Mount(_, "/mnt/dir", "fstype", kDefaultMountFlags | MS_RDONLY, _))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  MountErrorType error = MOUNT_ERROR_UNKNOWN;
  auto mountpoint =
      mounter.Mount("/dev/block", base::FilePath("/mnt/dir"), {}, &error);
}

TEST(SystemMounterTest, ReadOnlyRequested) {
  MockPlatform platform;
  SystemMounter mounter(&platform, "fstype", /* read_only= */ false, {});

  EXPECT_CALL(platform,
              Mount(_, "/mnt/dir", "fstype", kDefaultMountFlags | MS_RDONLY, _))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  MountErrorType error = MOUNT_ERROR_UNKNOWN;
  auto mountpoint =
      mounter.Mount("/dev/block", base::FilePath("/mnt/dir"), {"ro"}, &error);
}

TEST(SystemMounterTest, MountOptionsPassedButParamsIgnored) {
  MockPlatform platform;
  SystemMounter mounter(&platform, "fstype", /* read_only= */ false,
                        {"foo", "bar=baz"});

  EXPECT_CALL(platform, Mount(_, "/mnt/dir", "fstype", _, "foo,bar=baz"))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  MountErrorType error = MOUNT_ERROR_UNKNOWN;
  auto mountpoint = mounter.Mount("/dev/block", base::FilePath("/mnt/dir"),
                                  {"abc=def", "xyz"}, &error);
}

}  // namespace cros_disks
