//===- unittests/Frontend/ASTUnitTest.cpp - ASTUnit tests -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <fstream>

#include "clang/Basic/FileManager.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/HeaderSearch.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
#include "gtest/gtest.h"

using namespace llvm;
using namespace clang;

namespace {

class ASTUnitTest : public ::testing::Test {
protected:
  int FD;
  llvm::SmallString<256> InputFileName;
  std::unique_ptr<ToolOutputFile> input_file;
  IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
  std::shared_ptr<CompilerInvocation> CInvok;
  std::shared_ptr<PCHContainerOperations> PCHContainerOps;

  std::unique_ptr<ASTUnit> createASTUnit(bool isVolatile) {
    EXPECT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD,
                                                    InputFileName));
    input_file = std::make_unique<ToolOutputFile>(InputFileName, FD);
    input_file->os() << "";

    const char *Args[] = {"clang", "-xc++", InputFileName.c_str()};

    Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());

    CreateInvocationOptions CIOpts;
    CIOpts.Diags = Diags;
    CInvok = createInvocation(Args, std::move(CIOpts));

    if (!CInvok)
      return nullptr;

    FileManager *FileMgr =
        new FileManager(FileSystemOptions(), vfs::getRealFileSystem());
    PCHContainerOps = std::make_shared<PCHContainerOperations>();

    return ASTUnit::LoadFromCompilerInvocation(
        CInvok, PCHContainerOps, Diags, FileMgr, false, CaptureDiagsKind::None,
        0, TU_Complete, false, false, isVolatile);
  }
};

TEST_F(ASTUnitTest, SaveLoadPreservesLangOptionsInPrintingPolicy) {
  // Check that the printing policy is restored with the correct language
  // options when loading an ASTUnit from a file.  To this end, an ASTUnit
  // for a C++ translation unit is set up and written to a temporary file.

  // By default `UseVoidForZeroParams` is true for non-C++ language options,
  // thus we can check this field after loading the ASTUnit to deduce whether
  // the correct (C++) language options were used when setting up the printing
  // policy.

  {
    PrintingPolicy PolicyWithDefaultLangOpt(LangOptions{});
    EXPECT_TRUE(PolicyWithDefaultLangOpt.UseVoidForZeroParams);
  }

  std::unique_ptr<ASTUnit> AST = createASTUnit(false);

  if (!AST)
    FAIL() << "failed to create ASTUnit";

  EXPECT_FALSE(AST->getASTContext().getPrintingPolicy().UseVoidForZeroParams);

  llvm::SmallString<256> ASTFileName;
  ASSERT_FALSE(
      llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName));
  ToolOutputFile ast_file(ASTFileName, FD);
  AST->Save(ASTFileName.str());

  EXPECT_TRUE(llvm::sys::fs::exists(ASTFileName));
  auto HSOpts = std::make_shared<HeaderSearchOptions>();

  std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
      std::string(ASTFileName.str()), PCHContainerOps->getRawReader(),
      ASTUnit::LoadEverything, Diags, FileSystemOptions(), HSOpts,
      /*UseDebugInfo=*/false);

  if (!AU)
    FAIL() << "failed to load ASTUnit";

  EXPECT_FALSE(AU->getASTContext().getPrintingPolicy().UseVoidForZeroParams);
}

TEST_F(ASTUnitTest, GetBufferForFileMemoryMapping) {
  std::unique_ptr<ASTUnit> AST = createASTUnit(true);

  if (!AST)
    FAIL() << "failed to create ASTUnit";

  std::unique_ptr<llvm::MemoryBuffer> memoryBuffer =
      AST->getBufferForFile(InputFileName);

  EXPECT_NE(memoryBuffer->getBufferKind(),
            llvm::MemoryBuffer::MemoryBuffer_MMap);
}

TEST_F(ASTUnitTest, ModuleTextualHeader) {
  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFs =
      new llvm::vfs::InMemoryFileSystem();
  InMemoryFs->addFile("test.cpp", 0, llvm::MemoryBuffer::getMemBuffer(R"cpp(
      #include "Textual.h"
      void foo() {}
    )cpp"));
  InMemoryFs->addFile("m.modulemap", 0, llvm::MemoryBuffer::getMemBuffer(R"cpp(
      module M {
        module Textual {
          textual header "Textual.h"
        }
      }
    )cpp"));
  InMemoryFs->addFile("Textual.h", 0, llvm::MemoryBuffer::getMemBuffer(R"cpp(
      void foo();
    )cpp"));

  const char *Args[] = {"clang", "test.cpp", "-fmodule-map-file=m.modulemap",
                        "-fmodule-name=M"};
  Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
  CreateInvocationOptions CIOpts;
  CIOpts.Diags = Diags;
  CInvok = createInvocation(Args, std::move(CIOpts));
  ASSERT_TRUE(CInvok);

  FileManager *FileMgr = new FileManager(FileSystemOptions(), InMemoryFs);
  PCHContainerOps = std::make_shared<PCHContainerOperations>();

  auto AU = ASTUnit::LoadFromCompilerInvocation(
      CInvok, PCHContainerOps, Diags, FileMgr, false, CaptureDiagsKind::None, 1,
      TU_Complete, false, false, false);
  ASSERT_TRUE(AU);
  auto File = AU->getFileManager().getFileRef("Textual.h", false, false);
  ASSERT_TRUE(bool(File));
  // Verify that we do not crash here.
  EXPECT_TRUE(AU->getPreprocessor().getHeaderSearchInfo().getExistingFileInfo(
      &File->getFileEntry()));
}

TEST_F(ASTUnitTest, LoadFromCommandLineEarlyError) {
  EXPECT_FALSE(
      llvm::sys::fs::createTemporaryFile("ast-unit", "c", FD, InputFileName));
  input_file = std::make_unique<ToolOutputFile>(InputFileName, FD);
  input_file->os() << "";

  const char *Args[] = {"clang", "-target", "foobar", InputFileName.c_str()};

  auto Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
  auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
  std::unique_ptr<clang::ASTUnit> ErrUnit;

  std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCommandLine(
      &Args[0], &Args[4], PCHContainerOps, Diags, "", false, "", false,
      CaptureDiagsKind::All, std::nullopt, true, 0, TU_Complete, false, false,
      false, SkipFunctionBodiesScope::None, false, true, false, false,
      std::nullopt, &ErrUnit, nullptr);

  ASSERT_EQ(AST, nullptr);
  ASSERT_NE(ErrUnit, nullptr);
  ASSERT_TRUE(Diags->hasErrorOccurred());
  ASSERT_NE(ErrUnit->stored_diag_size(), 0U);
}

TEST_F(ASTUnitTest, LoadFromCommandLineWorkingDirectory) {
  EXPECT_FALSE(
      llvm::sys::fs::createTemporaryFile("bar", "c", FD, InputFileName));
  auto Input = std::make_unique<ToolOutputFile>(InputFileName, FD);
  Input->os() << "";

  SmallString<128> WorkingDir;
  ASSERT_FALSE(sys::fs::createUniqueDirectory("foo", WorkingDir));
  const char *Args[] = {"clang", "-working-directory", WorkingDir.c_str(),
                        InputFileName.c_str()};

  auto Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
  auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
  std::unique_ptr<clang::ASTUnit> ErrUnit;

  std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCommandLine(
      &Args[0], &Args[4], PCHContainerOps, Diags, "", false, "", false,
      CaptureDiagsKind::All, std::nullopt, true, 0, TU_Complete, false, false,
      false, SkipFunctionBodiesScope::None, false, true, false, false,
      std::nullopt, &ErrUnit, nullptr);

  ASSERT_NE(AST, nullptr);
  ASSERT_FALSE(Diags->hasErrorOccurred());

  // Make sure '-working-directory' sets both the FileSystemOpts and underlying
  // VFS working directory.
  const auto &FM = AST->getFileManager();
  const auto &VFS = FM.getVirtualFileSystem();
  ASSERT_EQ(*VFS.getCurrentWorkingDirectory(), WorkingDir.str());
  ASSERT_EQ(FM.getFileSystemOpts().WorkingDir, WorkingDir.str());
}

} // anonymous namespace
