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