// Copyright (c) 2012 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 <list>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/i18n/file_util_icu.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/directory_lister.h"
#include "net/base/net_errors.h"
#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

using net::test::IsError;
using net::test::IsOk;

namespace net {

namespace {

const int kMaxDepth = 3;
const int kBranchingFactor = 4;
const int kFilesPerDirectory = 5;

class ListerDelegate : public DirectoryLister::DirectoryListerDelegate {
 public:
  explicit ListerDelegate(DirectoryLister::ListingType type)
      : cancel_lister_on_list_file_(false),
        cancel_lister_on_list_done_(false),
        lister_(nullptr),
        done_(false),
        error_(-1),
        type_(type) {}

  // When set to true, this signals that the directory list operation should be
  // cancelled (And the run loop quit) in the first call to OnListFile.
  void set_cancel_lister_on_list_file(bool cancel_lister_on_list_file) {
    cancel_lister_on_list_file_ = cancel_lister_on_list_file;
  }

  // When set to true, this signals that the directory list operation should be
  // cancelled (And the run loop quit) when OnDone is called.
  void set_cancel_lister_on_list_done(bool cancel_lister_on_list_done) {
    cancel_lister_on_list_done_ = cancel_lister_on_list_done;
  }

  void OnListFile(const DirectoryLister::DirectoryListerData& data) override {
    ASSERT_FALSE(done_);

    file_list_.push_back(data.info);
    paths_.push_back(data.path);
    if (cancel_lister_on_list_file_) {
      lister_->Cancel();
      run_loop.Quit();
    }
  }

  void OnListDone(int error) override {
    ASSERT_FALSE(done_);

    done_ = true;
    error_ = error;
    if (type_ == DirectoryLister::ALPHA_DIRS_FIRST)
      CheckSort();

    if (cancel_lister_on_list_done_)
      lister_->Cancel();
    run_loop.Quit();
  }

  void CheckSort() {
    // Check that we got files in the right order.
    if (!file_list_.empty()) {
      for (size_t previous = 0, current = 1;
           current < file_list_.size();
           previous++, current++) {
        // Directories should come before files.
        if (file_list_[previous].IsDirectory() &&
            !file_list_[current].IsDirectory()) {
          continue;
        }
        EXPECT_NE(FILE_PATH_LITERAL(".."),
                  file_list_[current].GetName().BaseName().value());
        EXPECT_EQ(file_list_[previous].IsDirectory(),
                  file_list_[current].IsDirectory());
        EXPECT_TRUE(base::i18n::LocaleAwareCompareFilenames(
            file_list_[previous].GetName(),
            file_list_[current].GetName()));
      }
    }
  }

  void Run(DirectoryLister* lister) {
    lister_ = lister;
    lister_->Start(base::ThreadTaskRunnerHandle::Get().get());
    run_loop.Run();
  }

  int error() const { return error_; }

  int num_files() const { return file_list_.size(); }

  bool done() const { return done_; }

 private:
  bool cancel_lister_on_list_file_;
  bool cancel_lister_on_list_done_;

  // This is owned by the individual tests, rather than the ListerDelegate.
  DirectoryLister* lister_;

  base::RunLoop run_loop;

  bool done_;
  int error_;
  DirectoryLister::ListingType type_;

  std::vector<base::FileEnumerator::FileInfo> file_list_;
  std::vector<base::FilePath> paths_;
};

}  // namespace

class DirectoryListerTest : public PlatformTest {
 public:
  DirectoryListerTest()
      : total_created_file_system_objects_in_temp_root_dir_(0),
        created_file_system_objects_in_temp_root_dir_(0) {
  }

  void SetUp() override {
    // Randomly create a directory structure of depth 3 in a temporary root
    // directory.
    std::list<std::pair<base::FilePath, int> > directories;
    ASSERT_TRUE(temp_root_dir_.CreateUniqueTempDir());
    directories.push_back(std::make_pair(temp_root_dir_.GetPath(), 0));
    while (!directories.empty()) {
      std::pair<base::FilePath, int> dir_data = directories.front();
      directories.pop_front();
      for (int i = 0; i < kFilesPerDirectory; i++) {
        std::string file_name = base::StringPrintf("file_id_%d", i);
        base::FilePath file_path = dir_data.first.AppendASCII(file_name);
        base::File file(file_path,
                        base::File::FLAG_CREATE | base::File::FLAG_WRITE);
        ASSERT_TRUE(file.IsValid());
        ++total_created_file_system_objects_in_temp_root_dir_;
        if (dir_data.first == temp_root_dir_.GetPath())
          ++created_file_system_objects_in_temp_root_dir_;
      }
      if (dir_data.second < kMaxDepth - 1) {
        for (int i = 0; i < kBranchingFactor; i++) {
          std::string dir_name = base::StringPrintf("child_dir_%d", i);
          base::FilePath dir_path = dir_data.first.AppendASCII(dir_name);
          ASSERT_TRUE(base::CreateDirectory(dir_path));
          ++total_created_file_system_objects_in_temp_root_dir_;
          if (dir_data.first == temp_root_dir_.GetPath())
            ++created_file_system_objects_in_temp_root_dir_;
          directories.push_back(std::make_pair(dir_path, dir_data.second + 1));
        }
      }
    }
    PlatformTest::SetUp();
  }

  const base::FilePath& root_path() const { return temp_root_dir_.GetPath(); }

  int expected_list_length_recursive() const {
    // List should include everything but the top level directory, and does not
    // include "..".
    return total_created_file_system_objects_in_temp_root_dir_;
  }

  int expected_list_length_non_recursive() const {
    // List should include everything in the top level directory, and "..".
    return created_file_system_objects_in_temp_root_dir_ + 1;
  }

 private:
  // Number of files and directories created in SetUp, excluding
  // |temp_root_dir_| itself.  Includes all nested directories and their files.
  int total_created_file_system_objects_in_temp_root_dir_;
  // Number of files and directories created directly in |temp_root_dir_|.
  int created_file_system_objects_in_temp_root_dir_;

  base::ScopedTempDir temp_root_dir_;
};

TEST_F(DirectoryListerTest, BigDirTest) {
  ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST);
  DirectoryLister lister(root_path(), &delegate);
  delegate.Run(&lister);

  EXPECT_TRUE(delegate.done());
  EXPECT_THAT(delegate.error(), IsOk());
  EXPECT_EQ(expected_list_length_non_recursive(), delegate.num_files());
}

TEST_F(DirectoryListerTest, BigDirRecursiveTest) {
  ListerDelegate delegate(DirectoryLister::NO_SORT_RECURSIVE);
  DirectoryLister lister(root_path(), DirectoryLister::NO_SORT_RECURSIVE,
                         &delegate);
  delegate.Run(&lister);

  EXPECT_TRUE(delegate.done());
  EXPECT_THAT(delegate.error(), IsOk());
  EXPECT_EQ(expected_list_length_recursive(), delegate.num_files());
}

TEST_F(DirectoryListerTest, EmptyDirTest) {
  base::ScopedTempDir tempDir;
  EXPECT_TRUE(tempDir.CreateUniqueTempDir());

  ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST);
  DirectoryLister lister(tempDir.GetPath(), &delegate);
  delegate.Run(&lister);

  EXPECT_TRUE(delegate.done());
  EXPECT_THAT(delegate.error(), IsOk());
  // Contains only the parent directory ("..").
  EXPECT_EQ(1, delegate.num_files());
}

// This doesn't really test much, except make sure calling cancel before any
// callbacks are invoked doesn't crash.  Can't wait for all tasks running on a
// worker pool to complete, unfortunately.
// TODO(mmenke):  See if there's a way to make this fail more reliably on
// regression.
TEST_F(DirectoryListerTest, BasicCancelTest) {
  ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST);
  std::unique_ptr<DirectoryLister> lister(
      new DirectoryLister(root_path(), &delegate));
  lister->Start(base::ThreadTaskRunnerHandle::Get().get());
  lister->Cancel();
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(delegate.done());
  EXPECT_EQ(0, delegate.num_files());
}

TEST_F(DirectoryListerTest, CancelOnListFileTest) {
  ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST);
  DirectoryLister lister(root_path(), &delegate);
  delegate.set_cancel_lister_on_list_file(true);
  delegate.Run(&lister);

  EXPECT_FALSE(delegate.done());
  EXPECT_EQ(1, delegate.num_files());
}

TEST_F(DirectoryListerTest, CancelOnListDoneTest) {
  ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST);
  DirectoryLister lister(root_path(), &delegate);
  delegate.set_cancel_lister_on_list_done(true);
  delegate.Run(&lister);

  EXPECT_TRUE(delegate.done());
  EXPECT_THAT(delegate.error(), IsOk());
  EXPECT_EQ(expected_list_length_non_recursive(), delegate.num_files());
}

TEST_F(DirectoryListerTest, CancelOnLastElementTest) {
  base::ScopedTempDir tempDir;
  EXPECT_TRUE(tempDir.CreateUniqueTempDir());

  ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST);
  DirectoryLister lister(tempDir.GetPath(), &delegate);
  delegate.set_cancel_lister_on_list_file(true);
  delegate.Run(&lister);

  EXPECT_FALSE(delegate.done());
  // Contains only the parent directory ("..").
  EXPECT_EQ(1, delegate.num_files());
}

TEST_F(DirectoryListerTest, NoSuchDirTest) {
  base::ScopedTempDir tempDir;
  EXPECT_TRUE(tempDir.CreateUniqueTempDir());

  ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST);
  DirectoryLister lister(
      tempDir.GetPath().AppendASCII("this_path_does_not_exist"), &delegate);
  delegate.Run(&lister);

  EXPECT_THAT(delegate.error(), IsError(ERR_FILE_NOT_FOUND));
  EXPECT_EQ(0, delegate.num_files());
}

}  // namespace net
