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