| import os |
| from clang.cindex import Config |
| |
| if "CLANG_LIBRARY_PATH" in os.environ: |
| Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"]) |
| |
| from clang.cindex import CompilationDatabase |
| from clang.cindex import CompilationDatabaseError |
| from clang.cindex import CompileCommands |
| from clang.cindex import CompileCommand |
| import os |
| import gc |
| import unittest |
| import sys |
| from .util import skip_if_no_fspath |
| from .util import str_to_path |
| |
| |
| kInputsDir = 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. |
| stderr = os.dup(2) |
| with open(os.devnull, "wb") as null: |
| os.dup2(null.fileno(), 2) |
| with self.assertRaises(CompilationDatabaseError) as cm: |
| cdb = CompilationDatabase.fromDirectory(path) |
| 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""" |
| cdb = CompilationDatabase.fromDirectory(kInputsDir) |
| |
| def test_lookup_succeed(self): |
| """Check we get some results if the file exists in the db""" |
| cdb = CompilationDatabase.fromDirectory(kInputsDir) |
| cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp") |
| self.assertNotEqual(len(cmds), 0) |
| |
| @skip_if_no_fspath |
| def test_lookup_succeed_pathlike(self): |
| """Same as test_lookup_succeed, but with PathLikes""" |
| cdb = CompilationDatabase.fromDirectory(str_to_path(kInputsDir)) |
| cmds = cdb.getCompileCommands( |
| str_to_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(kInputsDir) |
| 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(kInputsDir) |
| 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(kInputsDir) |
| 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(kInputsDir) |
| 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(kInputsDir) |
| cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp") |
| del cdb |
| gc.collect() |
| workingdir = cmds[0].directory |
| |
| def test_compilationCommands_references(self): |
| """Ensure CompilationsCommand keeps a reference to CompilationCommands""" |
| cdb = CompilationDatabase.fromDirectory(kInputsDir) |
| cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp") |
| del cdb |
| cmd0 = cmds[0] |
| del cmds |
| gc.collect() |
| workingdir = cmd0.directory |