//===- unittests/Serialization/ForceCheckFileInputTest.cpp - CI 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 "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

#include "gtest/gtest.h"

using namespace llvm;
using namespace clang;

namespace {

class ForceCheckFileInputTest : public ::testing::Test {
  void SetUp() override {
    EXPECT_FALSE(sys::fs::createUniqueDirectory("modules-test", TestDir));
  }

  void TearDown() override { sys::fs::remove_directories(TestDir); }

public:
  SmallString<256> TestDir;

  void addFile(StringRef Path, StringRef Contents) {
    EXPECT_FALSE(sys::path::is_absolute(Path));

    SmallString<256> AbsPath(TestDir);
    sys::path::append(AbsPath, Path);

    EXPECT_FALSE(
        sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath)));

    std::error_code EC;
    llvm::raw_fd_ostream OS(AbsPath, EC);
    EXPECT_FALSE(EC);
    OS << Contents;
  }
};

TEST_F(ForceCheckFileInputTest, ForceCheck) {
  addFile("a.cppm", R"cpp(
export module a;
export int aa = 43;
  )cpp");

  std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str();

  {
    IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
        CompilerInstance::createDiagnostics(new DiagnosticOptions());
    CreateInvocationOptions CIOpts;
    CIOpts.Diags = Diags;
    CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();

    const char *Args[] = {"clang++",       "-std=c++20",
                          "--precompile",  "-working-directory",
                          TestDir.c_str(), "a.cppm"};
    std::shared_ptr<CompilerInvocation> Invocation =
        createInvocation(Args, CIOpts);
    EXPECT_TRUE(Invocation);
    Invocation->getFrontendOpts().DisableFree = false;

    auto Buf = CIOpts.VFS->getBufferForFile("a.cppm");
    EXPECT_TRUE(Buf);

    Invocation->getPreprocessorOpts().addRemappedFile("a.cppm", Buf->get());

    Buf->release();

    CompilerInstance Instance;
    Instance.setDiagnostics(Diags.get());
    Instance.setInvocation(Invocation);

    Instance.getFrontendOpts().OutputFile = BMIPath;

    if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
            Instance.getInvocation(), Instance.getDiagnostics(), CIOpts.VFS))
      CIOpts.VFS = VFSWithRemapping;
    Instance.createFileManager(CIOpts.VFS);

    Instance.getHeaderSearchOpts().ValidateASTInputFilesContent = true;

    GenerateReducedModuleInterfaceAction Action;
    EXPECT_TRUE(Instance.ExecuteAction(Action));
    EXPECT_FALSE(Diags->hasErrorOccurred());
  }

  {
    IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
        CompilerInstance::createDiagnostics(new DiagnosticOptions());
    CreateInvocationOptions CIOpts;
    CIOpts.Diags = Diags;
    CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();

    std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str();
    const char *Args[] = {
        "clang++",       "-std=c++20", "--precompile", "-working-directory",
        TestDir.c_str(), "a.cppm",     "-o",           BMIPath.c_str()};
    std::shared_ptr<CompilerInvocation> Invocation =
        createInvocation(Args, CIOpts);
    EXPECT_TRUE(Invocation);
    Invocation->getFrontendOpts().DisableFree = false;

    CompilerInstance Clang;

    Clang.setInvocation(Invocation);
    Clang.setDiagnostics(Diags.get());
    FileManager *FM = Clang.createFileManager(CIOpts.VFS);
    Clang.createSourceManager(*FM);

    EXPECT_TRUE(Clang.createTarget());
    Clang.createPreprocessor(TU_Complete);
    Clang.getHeaderSearchOpts().ForceCheckCXX20ModulesInputFiles = true;
    Clang.getHeaderSearchOpts().ValidateASTInputFilesContent = true;
    Clang.createASTReader();

    addFile("a.cppm", R"cpp(
export module a;
export int aa = 44;
  )cpp");

    auto ReadResult =
        Clang.getASTReader()->ReadAST(BMIPath, serialization::MK_MainFile,
                                      SourceLocation(), ASTReader::ARR_None);

    // We shall be able to detect the content change here.
    EXPECT_NE(ReadResult, ASTReader::Success);
  }
}

} // anonymous namespace
