Clang Project

clang_source_code/bindings/python/tests/cindex/test_cdb.py
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