1from clang.cindex import CompilationDatabase 2from clang.cindex import CompilationDatabaseError 3from clang.cindex import CompileCommands 4from clang.cindex import CompileCommand 5import os 6import gc 7import unittest 8 9 10kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') 11 12 13class TestCDB(unittest.TestCase): 14 def test_create_fail(self): 15 """Check we fail loading a database with an assertion""" 16 path = os.path.dirname(__file__) 17 with self.assertRaises(CompilationDatabaseError) as cm: 18 cdb = CompilationDatabase.fromDirectory(path) 19 e = cm.exception 20 self.assertEqual(e.cdb_error, 21 CompilationDatabaseError.ERROR_CANNOTLOADDATABASE) 22 23 def test_create(self): 24 """Check we can load a compilation database""" 25 cdb = CompilationDatabase.fromDirectory(kInputsDir) 26 27 def test_lookup_fail(self): 28 """Check file lookup failure""" 29 cdb = CompilationDatabase.fromDirectory(kInputsDir) 30 self.assertIsNone(cdb.getCompileCommands('file_do_not_exist.cpp')) 31 32 def test_lookup_succeed(self): 33 """Check we get some results if the file exists in the db""" 34 cdb = CompilationDatabase.fromDirectory(kInputsDir) 35 cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') 36 self.assertNotEqual(len(cmds), 0) 37 38 def test_all_compilecommand(self): 39 """Check we get all results from the db""" 40 cdb = CompilationDatabase.fromDirectory(kInputsDir) 41 cmds = cdb.getAllCompileCommands() 42 self.assertEqual(len(cmds), 3) 43 expected = [ 44 { 'wd': '/home/john.doe/MyProject', 45 'file': '/home/john.doe/MyProject/project.cpp', 46 'line': ['clang++', '-o', 'project.o', '-c', 47 '/home/john.doe/MyProject/project.cpp']}, 48 { 'wd': '/home/john.doe/MyProjectA', 49 'file': '/home/john.doe/MyProject/project2.cpp', 50 'line': ['clang++', '-o', 'project2.o', '-c', 51 '/home/john.doe/MyProject/project2.cpp']}, 52 { 'wd': '/home/john.doe/MyProjectB', 53 'file': '/home/john.doe/MyProject/project2.cpp', 54 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', 55 '/home/john.doe/MyProject/project2.cpp']}, 56 57 ] 58 for i in range(len(cmds)): 59 self.assertEqual(cmds[i].directory, expected[i]['wd']) 60 self.assertEqual(cmds[i].filename, expected[i]['file']) 61 for arg, exp in zip(cmds[i].arguments, expected[i]['line']): 62 self.assertEqual(arg, exp) 63 64 def test_1_compilecommand(self): 65 """Check file with single compile command""" 66 cdb = CompilationDatabase.fromDirectory(kInputsDir) 67 file = '/home/john.doe/MyProject/project.cpp' 68 cmds = cdb.getCompileCommands(file) 69 self.assertEqual(len(cmds), 1) 70 self.assertEqual(cmds[0].directory, os.path.dirname(file)) 71 self.assertEqual(cmds[0].filename, file) 72 expected = [ 'clang++', '-o', 'project.o', '-c', 73 '/home/john.doe/MyProject/project.cpp'] 74 for arg, exp in zip(cmds[0].arguments, expected): 75 self.assertEqual(arg, exp) 76 77 def test_2_compilecommand(self): 78 """Check file with 2 compile commands""" 79 cdb = CompilationDatabase.fromDirectory(kInputsDir) 80 cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp') 81 self.assertEqual(len(cmds), 2) 82 expected = [ 83 { 'wd': '/home/john.doe/MyProjectA', 84 'line': ['clang++', '-o', 'project2.o', '-c', 85 '/home/john.doe/MyProject/project2.cpp']}, 86 { 'wd': '/home/john.doe/MyProjectB', 87 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', 88 '/home/john.doe/MyProject/project2.cpp']} 89 ] 90 for i in range(len(cmds)): 91 self.assertEqual(cmds[i].directory, expected[i]['wd']) 92 for arg, exp in zip(cmds[i].arguments, expected[i]['line']): 93 self.assertEqual(arg, exp) 94 95 def test_compilecommand_iterator_stops(self): 96 """Check that iterator stops after the correct number of elements""" 97 cdb = CompilationDatabase.fromDirectory(kInputsDir) 98 count = 0 99 for cmd in cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp'): 100 count += 1 101 self.assertLessEqual(count, 2) 102 103 def test_compilationDB_references(self): 104 """Ensure CompilationsCommands are independent of the database""" 105 cdb = CompilationDatabase.fromDirectory(kInputsDir) 106 cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') 107 del cdb 108 gc.collect() 109 workingdir = cmds[0].directory 110 111 def test_compilationCommands_references(self): 112 """Ensure CompilationsCommand keeps a reference to CompilationCommands""" 113 cdb = CompilationDatabase.fromDirectory(kInputsDir) 114 cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') 115 del cdb 116 cmd0 = cmds[0] 117 del cmds 118 gc.collect() 119 workingdir = cmd0.directory 120