1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
import os
from clang.cindex import CompilationDatabase, CompilationDatabaseError, Config
if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])
import gc
import unittest
import sys
from pathlib import Path
INPUTS_DIR = os.path.join(os.path.dirname(__file__), "INPUTS")
@unittest.skipIf(sys.platform == "win32", "TODO: Fix these tests on Windows")
class TestCDB(unittest.TestCase):
def test_create_fail(self):
"""Check we fail loading a database with an assertion"""
path = os.path.dirname(__file__)
# clang_CompilationDatabase_fromDirectory calls fprintf(stderr, ...)
# Suppress its output.
try:
stderr = os.dup(2)
with open(os.devnull, "wb") as null:
os.dup2(null.fileno(), 2)
with self.assertRaises(CompilationDatabaseError) as cm:
CompilationDatabase.fromDirectory(path)
# Ensures that stderr is reset even if the above code crashes
finally:
os.dup2(stderr, 2)
os.close(stderr)
e = cm.exception
self.assertEqual(e.cdb_error, CompilationDatabaseError.ERROR_CANNOTLOADDATABASE)
def test_create(self):
"""Check we can load a compilation database"""
CompilationDatabase.fromDirectory(INPUTS_DIR)
def test_lookup_succeed(self):
"""Check we get some results if the file exists in the db"""
cdb = CompilationDatabase.fromDirectory(INPUTS_DIR)
cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp")
self.assertNotEqual(len(cmds), 0)
def test_lookup_succeed_pathlike(self):
"""Same as test_lookup_succeed, but with PathLikes"""
cdb = CompilationDatabase.fromDirectory(Path(INPUTS_DIR))
cmds = cdb.getCompileCommands(Path("/home/john.doe/MyProject/project.cpp"))
self.assertNotEqual(len(cmds), 0)
def test_all_compilecommand(self):
"""Check we get all results from the db"""
cdb = CompilationDatabase.fromDirectory(INPUTS_DIR)
cmds = cdb.getAllCompileCommands()
self.assertEqual(len(cmds), 3)
expected = [
{
"wd": "/home/john.doe/MyProject",
"file": "/home/john.doe/MyProject/project.cpp",
"line": [
"clang++",
"--driver-mode=g++",
"-o",
"project.o",
"-c",
"/home/john.doe/MyProject/project.cpp",
],
},
{
"wd": "/home/john.doe/MyProjectA",
"file": "/home/john.doe/MyProject/project2.cpp",
"line": [
"clang++",
"--driver-mode=g++",
"-o",
"project2.o",
"-c",
"/home/john.doe/MyProject/project2.cpp",
],
},
{
"wd": "/home/john.doe/MyProjectB",
"file": "/home/john.doe/MyProject/project2.cpp",
"line": [
"clang++",
"--driver-mode=g++",
"-DFEATURE=1",
"-o",
"project2-feature.o",
"-c",
"/home/john.doe/MyProject/project2.cpp",
],
},
]
for i in range(len(cmds)):
self.assertEqual(cmds[i].directory, expected[i]["wd"])
self.assertEqual(cmds[i].filename, expected[i]["file"])
for arg, exp in zip(cmds[i].arguments, expected[i]["line"]):
self.assertEqual(arg, exp)
def test_1_compilecommand(self):
"""Check file with single compile command"""
cdb = CompilationDatabase.fromDirectory(INPUTS_DIR)
file = "/home/john.doe/MyProject/project.cpp"
cmds = cdb.getCompileCommands(file)
self.assertEqual(len(cmds), 1)
self.assertEqual(cmds[0].directory, os.path.dirname(file))
self.assertEqual(cmds[0].filename, file)
expected = [
"clang++",
"--driver-mode=g++",
"-o",
"project.o",
"-c",
"/home/john.doe/MyProject/project.cpp",
]
for arg, exp in zip(cmds[0].arguments, expected):
self.assertEqual(arg, exp)
def test_2_compilecommand(self):
"""Check file with 2 compile commands"""
cdb = CompilationDatabase.fromDirectory(INPUTS_DIR)
cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project2.cpp")
self.assertEqual(len(cmds), 2)
expected = [
{
"wd": "/home/john.doe/MyProjectA",
"line": [
"clang++",
"--driver-mode=g++",
"-o",
"project2.o",
"-c",
"/home/john.doe/MyProject/project2.cpp",
],
},
{
"wd": "/home/john.doe/MyProjectB",
"line": [
"clang++",
"--driver-mode=g++",
"-DFEATURE=1",
"-o",
"project2-feature.o",
"-c",
"/home/john.doe/MyProject/project2.cpp",
],
},
]
for i in range(len(cmds)):
self.assertEqual(cmds[i].directory, expected[i]["wd"])
for arg, exp in zip(cmds[i].arguments, expected[i]["line"]):
self.assertEqual(arg, exp)
def test_compilecommand_iterator_stops(self):
"""Check that iterator stops after the correct number of elements"""
cdb = CompilationDatabase.fromDirectory(INPUTS_DIR)
count = 0
for cmd in cdb.getCompileCommands("/home/john.doe/MyProject/project2.cpp"):
count += 1
self.assertLessEqual(count, 2)
def test_compilationDB_references(self):
"""Ensure CompilationsCommands are independent of the database"""
cdb = CompilationDatabase.fromDirectory(INPUTS_DIR)
cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp")
del cdb
gc.collect()
cmds[0].directory
def test_compilationCommands_references(self):
"""Ensure CompilationsCommand keeps a reference to CompilationCommands"""
cdb = CompilationDatabase.fromDirectory(INPUTS_DIR)
cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp")
del cdb
cmd0 = cmds[0]
del cmds
gc.collect()
cmd0.directory
|