//===- 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());

    CInvok = createInvocationFromCommandLine(Args, Diags);

    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));

  std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
      std::string(ASTFileName.str()), PCHContainerOps->getRawReader(),
      ASTUnit::LoadEverything, Diags, FileSystemOptions(),
      /*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());
  CInvok = createInvocationFromCommandLine(Args, Diags);
  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;

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

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

} // anonymous namespace
