blob: 347fa4608664fea96064e4dfd12ff66b878581f6 [file] [log] [blame]
Jan Korousa6fcadd2019-09-03 22:01:46 +00001//===- unittests/libclang/TestUtils.h -------------------------------------===//
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
9#ifndef LLVM_CLANG_TEST_TESTUTILS_H
10#define LLVM_CLANG_TEST_TESTUTILS_H
11
12#include "clang-c/Index.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/Support/FileSystem.h"
15#include "llvm/Support/Path.h"
16
17#include <fstream>
18#include <memory>
19#include <string>
20#include <vector>
21#include "gtest/gtest.h"
22
23class LibclangParseTest : public ::testing::Test {
24 std::set<std::string> Files;
25 typedef std::unique_ptr<std::string> fixed_addr_string;
26 std::map<fixed_addr_string, fixed_addr_string> UnsavedFileContents;
27public:
28 std::string TestDir;
29 CXIndex Index;
30 CXTranslationUnit ClangTU;
31 unsigned TUFlags;
32 std::vector<CXUnsavedFile> UnsavedFiles;
33
34 void SetUp() override {
35 llvm::SmallString<256> Dir;
36 ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory("libclang-test", Dir));
Benjamin Krameradcd0262020-01-28 20:23:46 +010037 TestDir = std::string(Dir.str());
Jan Korousa6fcadd2019-09-03 22:01:46 +000038 TUFlags = CXTranslationUnit_DetailedPreprocessingRecord |
39 clang_defaultEditingTranslationUnitOptions();
40 Index = clang_createIndex(0, 0);
41 ClangTU = nullptr;
42 }
43 void TearDown() override {
44 clang_disposeTranslationUnit(ClangTU);
45 clang_disposeIndex(Index);
46 for (const std::string &Path : Files)
47 llvm::sys::fs::remove(Path);
48 llvm::sys::fs::remove(TestDir);
49 }
50 void WriteFile(std::string &Filename, const std::string &Contents) {
51 if (!llvm::sys::path::is_absolute(Filename)) {
52 llvm::SmallString<256> Path(TestDir);
53 llvm::sys::path::append(Path, Filename);
Benjamin Krameradcd0262020-01-28 20:23:46 +010054 Filename = std::string(Path.str());
Jan Korousa6fcadd2019-09-03 22:01:46 +000055 Files.insert(Filename);
56 }
57 llvm::sys::fs::create_directories(llvm::sys::path::parent_path(Filename));
58 std::ofstream OS(Filename);
59 OS << Contents;
60 assert(OS.good());
61 }
62 void MapUnsavedFile(std::string Filename, const std::string &Contents) {
63 if (!llvm::sys::path::is_absolute(Filename)) {
64 llvm::SmallString<256> Path(TestDir);
65 llvm::sys::path::append(Path, Filename);
Benjamin Krameradcd0262020-01-28 20:23:46 +010066 Filename = std::string(Path.str());
Jan Korousa6fcadd2019-09-03 22:01:46 +000067 }
68 auto it = UnsavedFileContents.insert(std::make_pair(
69 fixed_addr_string(new std::string(Filename)),
70 fixed_addr_string(new std::string(Contents))));
71 UnsavedFiles.push_back({
72 it.first->first->c_str(), // filename
73 it.first->second->c_str(), // contents
74 it.first->second->size() // length
75 });
76 }
77 template<typename F>
78 void Traverse(const F &TraversalFunctor) {
79 CXCursor TuCursor = clang_getTranslationUnitCursor(ClangTU);
80 std::reference_wrapper<const F> FunctorRef = std::cref(TraversalFunctor);
81 clang_visitChildren(TuCursor,
82 &TraverseStateless<std::reference_wrapper<const F>>,
83 &FunctorRef);
84 }
85private:
86 template<typename TState>
87 static CXChildVisitResult TraverseStateless(CXCursor cx, CXCursor parent,
88 CXClientData data) {
89 TState *State = static_cast<TState*>(data);
90 return State->get()(cx, parent);
91 }
92};
93
94#endif // LLVM_CLANG_TEST_TESTUTILS_H