| 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 |