// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "util/file/directory_reader.h"

#include <set>

#include "base/files/file_path.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "gtest/gtest.h"
#include "test/filesystem.h"
#include "test/scoped_temp_dir.h"
#include "util/file/file_io.h"
#include "util/file/filesystem.h"

namespace crashpad {
namespace test {
namespace {

TEST(DirectoryReader, BadPaths) {
  DirectoryReader reader;
  EXPECT_FALSE(reader.Open(base::FilePath()));

  ScopedTempDir temp_dir;
  base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
  ASSERT_TRUE(CreateFile(file));
  EXPECT_FALSE(reader.Open(file));

  EXPECT_FALSE(
      reader.Open(temp_dir.path().Append(FILE_PATH_LITERAL("doesntexist"))));
}

#if !defined(OS_FUCHSIA)

TEST(DirectoryReader, BadPaths_SymbolicLinks) {
  if (!CanCreateSymbolicLinks()) {
    GTEST_SKIP();
  }

  ScopedTempDir temp_dir;
  base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
  ASSERT_TRUE(CreateFile(file));

  base::FilePath link(temp_dir.path().Append(FILE_PATH_LITERAL("link")));
  ASSERT_TRUE(CreateSymbolicLink(file, link));

  DirectoryReader reader;
  EXPECT_FALSE(reader.Open(link));

  ASSERT_TRUE(LoggingRemoveFile(file));
  EXPECT_FALSE(reader.Open(link));
}

#endif  // !OS_FUCHSIA

TEST(DirectoryReader, EmptyDirectory) {
  ScopedTempDir temp_dir;
  DirectoryReader reader;

  ASSERT_TRUE(reader.Open(temp_dir.path()));
  base::FilePath filename;
  EXPECT_EQ(reader.NextFile(&filename), DirectoryReader::Result::kNoMoreFiles);
}

void ExpectFiles(const std::set<base::FilePath>& files,
                 const std::set<base::FilePath>& expected) {
  EXPECT_EQ(files.size(), expected.size());

  for (const auto& filename : expected) {
    SCOPED_TRACE(
        base::StringPrintf("Filename: %" PRFilePath, filename.value().c_str()));
    EXPECT_NE(files.find(filename), files.end());
  }
}

void TestFilesAndDirectories(bool symbolic_links) {
  ScopedTempDir temp_dir;
  std::set<base::FilePath> expected_files;

  base::FilePath file(FILE_PATH_LITERAL("file"));
  ASSERT_TRUE(CreateFile(temp_dir.path().Append(file)));
  EXPECT_TRUE(expected_files.insert(file).second);

  base::FilePath directory(FILE_PATH_LITERAL("directory"));
  ASSERT_TRUE(LoggingCreateDirectory(temp_dir.path().Append(directory),
                                     FilePermissions::kWorldReadable,
                                     false));
  EXPECT_TRUE(expected_files.insert(directory).second);

  base::FilePath nested_file(FILE_PATH_LITERAL("nested_file"));
  ASSERT_TRUE(
      CreateFile(temp_dir.path().Append(directory).Append(nested_file)));

#if !defined(OS_FUCHSIA)

  if (symbolic_links) {
    base::FilePath link(FILE_PATH_LITERAL("link"));
    ASSERT_TRUE(CreateSymbolicLink(temp_dir.path().Append(file),
                                   temp_dir.path().Append(link)));
    EXPECT_TRUE(expected_files.insert(link).second);

    base::FilePath dangling(FILE_PATH_LITERAL("dangling"));
    ASSERT_TRUE(
        CreateSymbolicLink(base::FilePath(FILE_PATH_LITERAL("not_a_file")),
                           temp_dir.path().Append(dangling)));
    EXPECT_TRUE(expected_files.insert(dangling).second);
  }

#endif  // !OS_FUCHSIA

  std::set<base::FilePath> files;
  DirectoryReader reader;
  ASSERT_TRUE(reader.Open(temp_dir.path()));
  DirectoryReader::Result result;
  base::FilePath filename;
  while ((result = reader.NextFile(&filename)) ==
         DirectoryReader::Result::kSuccess) {
    EXPECT_TRUE(files.insert(filename).second);
  }
  EXPECT_EQ(result, DirectoryReader::Result::kNoMoreFiles);
  EXPECT_EQ(reader.NextFile(&filename), DirectoryReader::Result::kNoMoreFiles);
  ExpectFiles(files, expected_files);
}

TEST(DirectoryReader, FilesAndDirectories) {
  TestFilesAndDirectories(false);
}

#if !defined(OS_FUCHSIA)

TEST(DirectoryReader, FilesAndDirectories_SymbolicLinks) {
  if (!CanCreateSymbolicLinks()) {
    GTEST_SKIP();
  }

  TestFilesAndDirectories(true);
}

#endif  // !OS_FUCHSIA

}  // namespace
}  // namespace test
}  // namespace crashpad
