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