// Copyright 2013 The Chromium 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 "storage/browser/fileapi/recursive_operation_delegate.h"

#include <memory>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/test/sandbox_file_system_test_helper.h"
#include "storage/browser/fileapi/file_system_file_util.h"
#include "storage/browser/fileapi/file_system_operation.h"
#include "storage/browser/fileapi/file_system_operation_runner.h"
#include "testing/gtest/include/gtest/gtest.h"

using storage::FileSystemContext;
using storage::FileSystemOperationContext;
using storage::FileSystemURL;

namespace content {
namespace {

class LoggingRecursiveOperation : public storage::RecursiveOperationDelegate {
 public:
  struct LogEntry {
    enum Type {
      PROCESS_FILE,
      PROCESS_DIRECTORY,
      POST_PROCESS_DIRECTORY
    };
    Type type;
    FileSystemURL url;
  };

  LoggingRecursiveOperation(FileSystemContext* file_system_context,
                            const FileSystemURL& root,
                            const StatusCallback& callback)
      : storage::RecursiveOperationDelegate(file_system_context),
        root_(root),
        callback_(callback),
        weak_factory_(this) {}
  ~LoggingRecursiveOperation() override {}

  const std::vector<LogEntry>& log_entries() const { return log_entries_; }

  // RecursiveOperationDelegate overrides.
  void Run() override { NOTREACHED(); }

  void RunRecursively() override {
    StartRecursiveOperation(
        root_, storage::FileSystemOperation::ERROR_BEHAVIOR_ABORT, callback_);
  }

  void RunRecursivelyWithIgnoringError() {
    StartRecursiveOperation(
        root_, storage::FileSystemOperation::ERROR_BEHAVIOR_SKIP, callback_);
  }

  void ProcessFile(const FileSystemURL& url,
                   const StatusCallback& callback) override {
    RecordLogEntry(LogEntry::PROCESS_FILE, url);

    if (error_url_.is_valid() && error_url_ == url) {
      callback.Run(base::File::FILE_ERROR_FAILED);
      return;
    }

    operation_runner()->GetMetadata(
        url, storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY,
        base::Bind(&LoggingRecursiveOperation::DidGetMetadata,
                   weak_factory_.GetWeakPtr(), callback));
  }

  void ProcessDirectory(const FileSystemURL& url,
                        const StatusCallback& callback) override {
    RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
    callback.Run(base::File::FILE_OK);
  }

  void PostProcessDirectory(const FileSystemURL& url,
                            const StatusCallback& callback) override {
    RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
    callback.Run(base::File::FILE_OK);
  }

  void SetEntryToFail(const FileSystemURL& url) { error_url_ = url; }

 private:
  void RecordLogEntry(LogEntry::Type type, const FileSystemURL& url) {
    LogEntry entry;
    entry.type = type;
    entry.url = url;
    log_entries_.push_back(entry);
  }

  void DidGetMetadata(const StatusCallback& callback,
                      base::File::Error result,
                      const base::File::Info& file_info) {
    if (result != base::File::FILE_OK) {
      callback.Run(result);
      return;
    }

    callback.Run(file_info.is_directory ?
                 base::File::FILE_ERROR_NOT_A_FILE :
                 base::File::FILE_OK);
  }

  FileSystemURL root_;
  StatusCallback callback_;
  std::vector<LogEntry> log_entries_;
  FileSystemURL error_url_;

  base::WeakPtrFactory<LoggingRecursiveOperation> weak_factory_;
  DISALLOW_COPY_AND_ASSIGN(LoggingRecursiveOperation);
};

void ReportStatus(base::File::Error* out_error,
                  base::File::Error error) {
  DCHECK(out_error);
  *out_error = error;
}

// To test the Cancel() during operation, calls Cancel() of |operation|
// after |counter| times message posting.
void CallCancelLater(storage::RecursiveOperationDelegate* operation,
                     int counter) {
  if (counter > 0) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::Bind(&CallCancelLater, base::Unretained(operation), counter - 1));
    return;
  }

  operation->Cancel();
}

}  // namespace

class RecursiveOperationDelegateTest : public testing::Test {
 protected:
  void SetUp() override {
    EXPECT_TRUE(base_.CreateUniqueTempDir());
    sandbox_file_system_.SetUp(base_.GetPath().AppendASCII("filesystem"));
  }

  void TearDown() override { sandbox_file_system_.TearDown(); }

  std::unique_ptr<FileSystemOperationContext> NewContext() {
    FileSystemOperationContext* context =
        sandbox_file_system_.NewOperationContext();
    // Grant enough quota for all test cases.
    context->set_allowed_bytes_growth(1000000);
    return base::WrapUnique(context);
  }

  storage::FileSystemFileUtil* file_util() {
    return sandbox_file_system_.file_util();
  }

  FileSystemURL URLForPath(const std::string& path) const {
    return sandbox_file_system_.CreateURLFromUTF8(path);
  }

  FileSystemURL CreateFile(const std::string& path) {
    FileSystemURL url = URLForPath(path);
    bool created = false;
    EXPECT_EQ(base::File::FILE_OK,
              file_util()->EnsureFileExists(NewContext().get(),
                                            url, &created));
    EXPECT_TRUE(created);
    return url;
  }

  FileSystemURL CreateDirectory(const std::string& path) {
    FileSystemURL url = URLForPath(path);
    EXPECT_EQ(base::File::FILE_OK,
              file_util()->CreateDirectory(NewContext().get(), url,
                                           false /* exclusive */, true));
    return url;
  }

 private:
  base::MessageLoop message_loop_;

  // Common temp base for nondestructive uses.
  base::ScopedTempDir base_;
  SandboxFileSystemTestHelper sandbox_file_system_;
};

TEST_F(RecursiveOperationDelegateTest, RootIsFile) {
  FileSystemURL src_file(CreateFile("src"));

  base::File::Error error = base::File::FILE_ERROR_FAILED;
  std::unique_ptr<FileSystemOperationContext> context = NewContext();
  std::unique_ptr<LoggingRecursiveOperation> operation(
      new LoggingRecursiveOperation(context->file_system_context(), src_file,
                                    base::Bind(&ReportStatus, &error)));
  operation->RunRecursively();
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(base::File::FILE_OK, error);

  const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
      operation->log_entries();
  ASSERT_EQ(1U, log_entries.size());
  const LoggingRecursiveOperation::LogEntry& entry = log_entries[0];
  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, entry.type);
  EXPECT_EQ(src_file, entry.url);
}

TEST_F(RecursiveOperationDelegateTest, RootIsDirectory) {
  FileSystemURL src_root(CreateDirectory("src"));
  FileSystemURL src_dir1(CreateDirectory("src/dir1"));
  FileSystemURL src_file1(CreateFile("src/file1"));
  FileSystemURL src_file2(CreateFile("src/dir1/file2"));
  FileSystemURL src_file3(CreateFile("src/dir1/file3"));

  base::File::Error error = base::File::FILE_ERROR_FAILED;
  std::unique_ptr<FileSystemOperationContext> context = NewContext();
  std::unique_ptr<LoggingRecursiveOperation> operation(
      new LoggingRecursiveOperation(context->file_system_context(), src_root,
                                    base::Bind(&ReportStatus, &error)));
  operation->RunRecursively();
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(base::File::FILE_OK, error);

  const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
      operation->log_entries();
  ASSERT_EQ(8U, log_entries.size());

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[0].type);
  EXPECT_EQ(src_root, log_entries[0].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
            log_entries[1].type);
  EXPECT_EQ(src_root, log_entries[1].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[2].type);
  EXPECT_EQ(src_file1, log_entries[2].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
            log_entries[3].type);
  EXPECT_EQ(src_dir1, log_entries[3].url);

  // The order of src/dir1/file2 and src/dir1/file3 depends on the file system
  // implementation (can be swapped).
  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[4].type);
  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[5].type);
  EXPECT_TRUE((src_file2 == log_entries[4].url &&
               src_file3 == log_entries[5].url) ||
              (src_file3 == log_entries[4].url &&
               src_file2 == log_entries[5].url));

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
            log_entries[6].type);
  EXPECT_EQ(src_dir1, log_entries[6].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
            log_entries[7].type);
  EXPECT_EQ(src_root, log_entries[7].url);
}

TEST_F(RecursiveOperationDelegateTest, Cancel) {
  FileSystemURL src_root(CreateDirectory("src"));
  FileSystemURL src_dir1(CreateDirectory("src/dir1"));
  FileSystemURL src_file1(CreateFile("src/file1"));
  FileSystemURL src_file2(CreateFile("src/dir1/file2"));

  base::File::Error error = base::File::FILE_ERROR_FAILED;
  std::unique_ptr<FileSystemOperationContext> context = NewContext();
  std::unique_ptr<LoggingRecursiveOperation> operation(
      new LoggingRecursiveOperation(context->file_system_context(), src_root,
                                    base::Bind(&ReportStatus, &error)));
  operation->RunRecursively();

  // Invoke Cancel(), after 5 times message posting.
  CallCancelLater(operation.get(), 5);
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(base::File::FILE_ERROR_ABORT, error);
}

TEST_F(RecursiveOperationDelegateTest, AbortWithError) {
  FileSystemURL src_root(CreateDirectory("src"));
  FileSystemURL src_dir1(CreateDirectory("src/dir1"));
  FileSystemURL src_file1(CreateFile("src/file1"));
  FileSystemURL src_file2(CreateFile("src/dir1/file2"));
  FileSystemURL src_file3(CreateFile("src/dir1/file3"));

  base::File::Error error = base::File::FILE_ERROR_FAILED;
  std::unique_ptr<FileSystemOperationContext> context = NewContext();
  std::unique_ptr<LoggingRecursiveOperation> operation(
      new LoggingRecursiveOperation(context->file_system_context(), src_root,
                                    base::Bind(&ReportStatus, &error)));
  operation->SetEntryToFail(src_file1);
  operation->RunRecursively();
  base::RunLoop().RunUntilIdle();

  ASSERT_EQ(base::File::FILE_ERROR_FAILED, error);

  // Confirm that operation has been aborted in the middle.
  const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
      operation->log_entries();
  ASSERT_EQ(3U, log_entries.size());

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[0].type);
  EXPECT_EQ(src_root, log_entries[0].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
            log_entries[1].type);
  EXPECT_EQ(src_root, log_entries[1].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[2].type);
  EXPECT_EQ(src_file1, log_entries[2].url);
}

TEST_F(RecursiveOperationDelegateTest, ContinueWithError) {
  FileSystemURL src_root(CreateDirectory("src"));
  FileSystemURL src_dir1(CreateDirectory("src/dir1"));
  FileSystemURL src_file1(CreateFile("src/file1"));
  FileSystemURL src_file2(CreateFile("src/dir1/file2"));
  FileSystemURL src_file3(CreateFile("src/dir1/file3"));

  base::File::Error error = base::File::FILE_ERROR_FAILED;
  std::unique_ptr<FileSystemOperationContext> context = NewContext();
  std::unique_ptr<LoggingRecursiveOperation> operation(
      new LoggingRecursiveOperation(context->file_system_context(), src_root,
                                    base::Bind(&ReportStatus, &error)));
  operation->SetEntryToFail(src_file1);
  operation->RunRecursivelyWithIgnoringError();
  base::RunLoop().RunUntilIdle();

  // Error code should be base::File::FILE_ERROR_FAILED.
  ASSERT_EQ(base::File::FILE_ERROR_FAILED, error);

  // Confirm that operation continues after the error.
  const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
      operation->log_entries();
  ASSERT_EQ(8U, log_entries.size());

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[0].type);
  EXPECT_EQ(src_root, log_entries[0].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
            log_entries[1].type);
  EXPECT_EQ(src_root, log_entries[1].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[2].type);
  EXPECT_EQ(src_file1, log_entries[2].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
            log_entries[3].type);
  EXPECT_EQ(src_dir1, log_entries[3].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[4].type);
  EXPECT_EQ(src_file3, log_entries[4].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
            log_entries[5].type);
  EXPECT_EQ(src_file2, log_entries[5].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
            log_entries[6].type);
  EXPECT_EQ(src_dir1, log_entries[6].url);

  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
            log_entries[7].type);
  EXPECT_EQ(src_root, log_entries[7].url);
}

}  // namespace content
