// Copyright 2020 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 "smbfs/recursive_delete_operation.h"

#include <sys/stat.h>
#include <sys/types.h>

#include <list>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/bind_helpers.h>
#include <base/test/task_environment.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "smbfs/samba_interface_impl.h"
#include "smbfs/smb_credential.h"
#include "smbfs/smb_filesystem.h"

namespace smbfs {
namespace {

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

constexpr char kSharePath[] = "smb://server/share";
constexpr char kDirectoryToDelete[] = "/the/directory";
constexpr char kFileToDelete[] = "/the/directory/file";

class MockSmbFilesystemDelegate : public SmbFilesystem::Delegate {
 public:
  MOCK_METHOD(void,
              RequestCredentials,
              (RequestCredentialsCallback),
              (override));
};

class MockSambaInterface : public SambaInterfaceImpl {
 public:
  MOCK_METHOD(int, UnlinkFile, (const std::string&), (override));
  MOCK_METHOD(int, RemoveDirectory, (const std::string&), (override));
  MOCK_METHOD(int, CloseDirectory, (SMBCFILE*), (override));
  MOCK_METHOD(int, OpenDirectory, (const std::string&, SMBCFILE**), (override));
  MOCK_METHOD(int,
              ReadDirectory,
              (SMBCFILE*, const struct libsmb_file_info**, struct stat*),
              (override));
};

class MockSmbFilesystem : public SmbFilesystem {
 public:
  MockSmbFilesystem()
      : SmbFilesystem(&mock_delegate_, kSharePath),
        mock_samba_impl_(new MockSambaInterface()) {
    const std::vector<uint8_t> empty_ip_address;
    SetResolvedAddress(empty_ip_address);
    SetSambaInterface(std::unique_ptr<SambaInterface>(mock_samba_impl_));
  }

  MockSambaInterface* samba_impl() { return mock_samba_impl_; }

 private:
  MockSmbFilesystemDelegate mock_delegate_;
  MockSambaInterface* mock_samba_impl_;
};

class TestRecursiveDeleteOperation : public RecursiveDeleteOperation {
 public:
  explicit TestRecursiveDeleteOperation(CompletionCallback callback)
      : RecursiveDeleteOperation(nullptr,
                                 kSharePath,
                                 base::FilePath(kDirectoryToDelete),
                                 std::move(callback)) {
    SetSambaInterface(fs_.samba_impl());
  }

  MockSmbFilesystem& fs() { return fs_; }

 private:
  MockSmbFilesystem fs_;
};

}  // namespace

class RecursiveDeleteOperationTest : public testing::Test {
 protected:
  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY,
      base::test::TaskEnvironment::MainThreadType::IO};
};

TEST_F(RecursiveDeleteOperationTest, DeleteFile) {
  TestRecursiveDeleteOperation delete_operation((base::DoNothing()));

  base::FilePath file_path(kFileToDelete);
  std::string share_path = std::string(kSharePath) + file_path.value();

  EXPECT_CALL(*(delete_operation.fs().samba_impl()), UnlinkFile(_))
      .WillOnce([&](const std::string& share_file_path) -> int {
        EXPECT_EQ(share_path, share_file_path);
        return 0;
      });
  delete_operation.DeleteFile(file_path);
}

TEST_F(RecursiveDeleteOperationTest, DeleteDirectory) {
  TestRecursiveDeleteOperation delete_operation(
      base::BindOnce([](mojom::DeleteRecursivelyError error) {}));

  base::FilePath dir_path(kDirectoryToDelete);
  std::string share_path = std::string(kSharePath) + dir_path.value();

  EXPECT_CALL(*(delete_operation.fs().samba_impl()), RemoveDirectory(_))
      .WillOnce([&](const std::string& share_dir_path) -> int {
        EXPECT_EQ(share_path, share_dir_path);
        return 0;
      });
  delete_operation.DeleteDirectory(dir_path);
}

TEST_F(RecursiveDeleteOperationTest, CloseDirectory) {
  TestRecursiveDeleteOperation delete_operation(
      base::BindOnce([](mojom::DeleteRecursivelyError error) {}));

  EXPECT_CALL(*(delete_operation.fs().samba_impl()), CloseDirectory(_))
      .WillOnce([&](SMBCFILE* dir) -> int { return 0; });
  delete_operation.CloseDirectory(nullptr);
}

TEST_F(RecursiveDeleteOperationTest, GetDirectoryListing) {
  TestRecursiveDeleteOperation delete_operation(
      base::BindOnce([](mojom::DeleteRecursivelyError error) {}));

  EXPECT_CALL(*(delete_operation.fs().samba_impl()), OpenDirectory(_, _))
      .Times(1)
      .WillOnce(Return(0));
  EXPECT_CALL(*(delete_operation.fs().samba_impl()), CloseDirectory(_))
      .Times(1)
      .WillOnce(Return(0));

  // Mock out the listing of a directory with two entries: a file and a
  // subdirectory.
  struct MockEntry {
    std::string entry_name;
    struct libsmb_file_info entry_info;
    struct stat entry_stat;
  };

  int entry_count = 0;
  std::vector<MockEntry> mock_entries = {{"file_name", {0}, {0}},
                                         {"dir_name", {0}, {0}}};
  mock_entries[1].entry_stat.st_mode |= S_IFDIR;

  EXPECT_CALL(*(delete_operation.fs().samba_impl()), ReadDirectory(_, _, _))
      .Times(mock_entries.size() + 1)
      .WillRepeatedly([&](SMBCFILE* dir,
                          const struct libsmb_file_info** file_info,
                          struct stat* file_stat) -> int {
        if (entry_count < mock_entries.size()) {
          *file_info = &(mock_entries[entry_count].entry_info);
          struct libsmb_file_info** inner_file_info =
              const_cast<struct libsmb_file_info**>(file_info);
          (*inner_file_info)->name =
              const_cast<char*>(mock_entries[entry_count].entry_name.c_str());
          *file_stat = mock_entries[entry_count].entry_stat;
        } else {
          *file_info = nullptr;
        }

        entry_count++;
        return 0;
      });

  base::FilePath dir_path(kDirectoryToDelete);
  std::list<struct RecursiveDeleteOperation::Entry> entries;
  bool success = delete_operation.GetDirectoryListing(dir_path, &entries);
  EXPECT_TRUE(success);

  EXPECT_EQ(mock_entries.size(), entries.size());

  RecursiveDeleteOperation::Entry entry = entries.front();
  EXPECT_EQ(entry.path, dir_path.Append(mock_entries[0].entry_name));
  EXPECT_FALSE(entry.is_directory);

  entries.pop_front();
  entry = entries.front();
  EXPECT_EQ(entry.path.value(),
            dir_path.Append(mock_entries[1].entry_name).value());
  EXPECT_TRUE(entry.is_directory);
}

}  // namespace smbfs
