DependencyScannerTest.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "clang/AST/ASTConsumer.h"
  9. #include "clang/AST/DeclCXX.h"
  10. #include "clang/AST/DeclGroup.h"
  11. #include "clang/Frontend/ASTUnit.h"
  12. #include "clang/Frontend/CompilerInstance.h"
  13. #include "clang/Frontend/FrontendAction.h"
  14. #include "clang/Frontend/FrontendActions.h"
  15. #include "clang/Tooling/CompilationDatabase.h"
  16. #include "clang/Tooling/Tooling.h"
  17. #include "llvm/ADT/STLExtras.h"
  18. #include "llvm/Support/Path.h"
  19. #include "llvm/Support/TargetRegistry.h"
  20. #include "llvm/Support/TargetSelect.h"
  21. #include "gtest/gtest.h"
  22. #include <algorithm>
  23. #include <string>
  24. namespace clang {
  25. namespace tooling {
  26. namespace {
  27. /// Prints out all of the gathered dependencies into a string.
  28. class TestFileCollector : public DependencyFileGenerator {
  29. public:
  30. TestFileCollector(DependencyOutputOptions &Opts,
  31. std::vector<std::string> &Deps)
  32. : DependencyFileGenerator(Opts), Deps(Deps) {}
  33. void finishedMainFile(DiagnosticsEngine &Diags) override {
  34. Deps = getDependencies();
  35. }
  36. private:
  37. std::vector<std::string> &Deps;
  38. };
  39. class TestDependencyScanningAction : public tooling::ToolAction {
  40. public:
  41. TestDependencyScanningAction(std::vector<std::string> &Deps) : Deps(Deps) {}
  42. bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
  43. FileManager *FileMgr,
  44. std::shared_ptr<PCHContainerOperations> PCHContainerOps,
  45. DiagnosticConsumer *DiagConsumer) override {
  46. CompilerInstance Compiler(std::move(PCHContainerOps));
  47. Compiler.setInvocation(std::move(Invocation));
  48. Compiler.setFileManager(FileMgr);
  49. Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
  50. if (!Compiler.hasDiagnostics())
  51. return false;
  52. Compiler.createSourceManager(*FileMgr);
  53. Compiler.addDependencyCollector(std::make_shared<TestFileCollector>(
  54. Compiler.getInvocation().getDependencyOutputOpts(), Deps));
  55. auto Action = std::make_unique<PreprocessOnlyAction>();
  56. return Compiler.ExecuteAction(*Action);
  57. }
  58. private:
  59. std::vector<std::string> &Deps;
  60. };
  61. } // namespace
  62. TEST(DependencyScanner, ScanDepsReuseFilemanager) {
  63. std::vector<std::string> Compilation = {"-c", "-E", "-MT", "test.cpp.o"};
  64. StringRef CWD = "/root";
  65. FixedCompilationDatabase CDB(CWD, Compilation);
  66. auto VFS = new llvm::vfs::InMemoryFileSystem();
  67. VFS->setCurrentWorkingDirectory(CWD);
  68. VFS->addFile("/root/header.h", 0, llvm::MemoryBuffer::getMemBuffer("\n"));
  69. VFS->addHardLink("/root/symlink.h", "/root/header.h");
  70. VFS->addFile("/root/test.cpp", 0,
  71. llvm::MemoryBuffer::getMemBuffer(
  72. "#include \"symlink.h\"\n#include \"header.h\"\n"));
  73. ClangTool Tool(CDB, {"test.cpp"}, std::make_shared<PCHContainerOperations>(),
  74. VFS);
  75. Tool.clearArgumentsAdjusters();
  76. std::vector<std::string> Deps;
  77. TestDependencyScanningAction Action(Deps);
  78. Tool.run(&Action);
  79. // The first invocation should return dependencies in order of access.
  80. ASSERT_EQ(Deps.size(), 3u);
  81. EXPECT_EQ(Deps[0], "/root/test.cpp");
  82. EXPECT_EQ(Deps[1], "/root/symlink.h");
  83. EXPECT_EQ(Deps[2], "/root/header.h");
  84. // The file manager should still have two FileEntries, as one file is a
  85. // hardlink.
  86. FileManager &Files = Tool.getFiles();
  87. EXPECT_EQ(Files.getNumUniqueRealFiles(), 2u);
  88. Deps.clear();
  89. Tool.run(&Action);
  90. // The second invocation should have the same order of dependencies.
  91. ASSERT_EQ(Deps.size(), 3u);
  92. EXPECT_EQ(Deps[0], "/root/test.cpp");
  93. EXPECT_EQ(Deps[1], "/root/symlink.h");
  94. EXPECT_EQ(Deps[2], "/root/header.h");
  95. EXPECT_EQ(Files.getNumUniqueRealFiles(), 2u);
  96. }
  97. } // end namespace tooling
  98. } // end namespace clang