// Copyright 2018 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/drivefs_helper.h"

#include <sys/mount.h>

#include <base/check_op.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/notreached.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <brillo/process/process_reaper.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "cros-disks/fuse_mounter.h"
#include "cros-disks/mount_options.h"
#include "cros-disks/platform.h"
#include "cros-disks/uri.h"
#include "cros-disks/user.h"

namespace cros_disks {
namespace {

using testing::_;
using testing::DoAll;
using testing::EndsWith;
using testing::HasSubstr;
using testing::Invoke;
using testing::IsSupersetOf;
using testing::Return;
using testing::SaveArg;
using testing::SetArgPointee;
using testing::StrEq;
using testing::UnorderedElementsAre;

constexpr char kSource[] = "drivefs://id";
constexpr char kDataDir[] = "/home/chronos/user/GCache/foo";
constexpr char kMountPath[] = "/media/fuse/drivefs/id";

constexpr char kPrefixParam[] = "prefix=/media/fuse/drivefs/id";
constexpr char kDataDirParam[] = "datadir=/home/chronos/user/GCache/foo";
constexpr char kMyFilesParam[] = "myfiles=/home/chronos/user/MyFiles";

std::vector<std::string> ParseOptions(const SandboxedProcess& sandbox) {
  CHECK_EQ(2, sandbox.arguments().size());
  CHECK_EQ("-o", sandbox.arguments()[0]);
  return base::SplitString(sandbox.arguments()[1], ",",
                           base::WhitespaceHandling::KEEP_WHITESPACE,
                           base::SplitResult::SPLIT_WANT_ALL);
}

// Mock Platform implementation for testing.
class MockPlatform : public Platform {
 public:
  MockPlatform() {
    ON_CALL(*this, GetRealPath(_, _))
        .WillByDefault(Invoke(this, &MockPlatform::GetRealPathImpl));
    ON_CALL(*this, DirectoryExists(_)).WillByDefault(Return(true));
    ON_CALL(*this, GetOwnership(_, _, _))
        .WillByDefault(DoAll(SetArgPointee<1>(kChronosUID), Return(true)));
  }

  MOCK_METHOD(bool,
              GetRealPath,
              (const std::string&, std::string*),
              (const, override));
  MOCK_METHOD(bool, PathExists, (const std::string&), (const, override));
  MOCK_METHOD(bool, DirectoryExists, (const std::string&), (const, override));
  MOCK_METHOD(bool, CreateDirectory, (const std::string&), (const, override));
  MOCK_METHOD(bool,
              RemoveEmptyDirectory,
              (const std::string&),
              (const, override));
  MOCK_METHOD(bool,
              GetOwnership,
              (const std::string&, uid_t*, gid_t*),
              (const, override));
  MOCK_METHOD(bool,
              SetPermissions,
              (const std::string&, mode_t),
              (const, override));

  bool GetRealPathImpl(const std::string& path, std::string* real_path) const {
    std::vector<std::string> components;
    base::FilePath(path).GetComponents(&components);
    base::FilePath result(components[0]);
    components.erase(components.begin());
    for (const auto& part : components) {
      if (part != ".")
        result = result.Append(part);
    }
    *real_path = result.value();
    return true;
  }

  bool GetUserAndGroupId(const std::string& user,
                         uid_t* user_id,
                         gid_t* group_id) const override {
    NOTREACHED();
    return false;
  }

  bool GetGroupId(const std::string& group, gid_t* group_id) const override {
    NOTREACHED();
    return false;
  }

  bool SetOwnership(const std::string&, uid_t, gid_t) const override {
    NOTREACHED();
    return false;
  }
};

class TestDrivefsHelper : public DrivefsHelper {
 public:
  TestDrivefsHelper(const Platform* platform,
                    brillo::ProcessReaper* process_reaper)
      : DrivefsHelper(platform, process_reaper) {
  }
  using DrivefsHelper::ConfigureSandbox;
};

class DrivefsHelperTest : public ::testing::Test {
 public:
  DrivefsHelperTest() : helper_(&platform_, &process_reaper_) {}

 protected:
  MockPlatform platform_;
  brillo::ProcessReaper process_reaper_;
  TestDrivefsHelper helper_;
};

TEST_F(DrivefsHelperTest, ConfigureSandbox) {
  FakeSandboxedProcess sandbox;
  auto error = helper_.ConfigureSandbox(
      kSource, base::FilePath(kMountPath),
      {"datadir=/home/chronos//user/GCache//foo/./"}, &sandbox);

  EXPECT_EQ(MOUNT_ERROR_NONE, error);
  auto options = ParseOptions(sandbox);
  EXPECT_THAT(options,
              UnorderedElementsAre(kDataDirParam, "identity=id", "uid=1000",
                                   "gid=1001", kPrefixParam));
}

TEST_F(DrivefsHelperTest, ConfigureSandboxWithMyFiles) {
  FakeSandboxedProcess sandbox;
  auto error = helper_.ConfigureSandbox(
      kSource, base::FilePath(kMountPath),
      {kDataDirParam, "myfiles=/home/chronos//user/.//MyFiles"}, &sandbox);

  EXPECT_EQ(MOUNT_ERROR_NONE, error);
  auto options = ParseOptions(sandbox);
  EXPECT_THAT(options, IsSupersetOf({StrEq(kMyFilesParam)}));
}

TEST_F(DrivefsHelperTest, ConfigureSandboxFailsIfInvalidSource) {
  FakeSandboxedProcess sandbox;
  auto error = helper_.ConfigureSandbox(
      "drive://id", base::FilePath(kMountPath), {kDataDirParam}, &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);

  error = helper_.ConfigureSandbox("/dev/block", base::FilePath(kMountPath),
                                   {kDataDirParam}, &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);

  error = helper_.ConfigureSandbox("drivefs:/foo", base::FilePath(kMountPath),
                                   {kDataDirParam}, &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);
}

TEST_F(DrivefsHelperTest, ConfigureSandboxFailsIfDataDirInvalid) {
  FakeSandboxedProcess sandbox;
  auto error = helper_.ConfigureSandbox(kSource, base::FilePath(kMountPath), {},
                                        &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);

  error = helper_.ConfigureSandbox(kSource, base::FilePath(kMountPath),
                                   {"datadir=dodgy/path"}, &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);

  error = helper_.ConfigureSandbox(kSource, base::FilePath(kMountPath),
                                   {"datadir=/nonhome/dir"}, &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);

  error = helper_.ConfigureSandbox(kSource, base::FilePath(kMountPath),
                                   {"datadir=/home/chronos/../../etc/passwd"},
                                   &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);
}

TEST_F(DrivefsHelperTest, ConfigureSandboxFailsIfDataDirDoesntExist) {
  EXPECT_CALL(platform_, DirectoryExists(kDataDir)).WillOnce(Return(false));
  FakeSandboxedProcess sandbox;
  auto error = helper_.ConfigureSandbox(kSource, base::FilePath(kMountPath),
                                        {kDataDirParam}, &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);
}

TEST_F(DrivefsHelperTest, ConfigureSandboxFailsWhenCantStat) {
  EXPECT_CALL(platform_, GetOwnership(kDataDir, _, _)).WillOnce(Return(false));
  FakeSandboxedProcess sandbox;
  auto error = helper_.ConfigureSandbox(kSource, base::FilePath(kMountPath),
                                        {kDataDirParam}, &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);
}

TEST_F(DrivefsHelperTest, ConfigureSandboxFailsWhenWrongOwner) {
  EXPECT_CALL(platform_, GetOwnership(kDataDir, _, _))
      .WillOnce(DoAll(SetArgPointee<1>(kChronosUID + 100), Return(false)));
  FakeSandboxedProcess sandbox;
  auto error = helper_.ConfigureSandbox(kSource, base::FilePath(kMountPath),
                                        {kDataDirParam}, &sandbox);
  EXPECT_NE(MOUNT_ERROR_NONE, error);
}

}  // namespace
}  // namespace cros_disks
