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_1_compilecommand():
36    """Check file with single compile command"""
37    cdb = CompilationDatabase.fromDirectory(kInputsDir)
38    cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp')
39    assert len(cmds) == 1
40    assert cmds[0].directory == '/home/john.doe/MyProject'
41    expected = [ 'clang++', '-o', 'project.o', '-c',
42                 '/home/john.doe/MyProject/project.cpp']
43    for arg, exp in zip(cmds[0].arguments, expected):
44        assert arg == exp
45
46def test_2_compilecommand():
47    """Check file with 2 compile commands"""
48    cdb = CompilationDatabase.fromDirectory(kInputsDir)
49    cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp')
50    assert len(cmds) == 2
51    expected = [
52        { 'wd': '/home/john.doe/MyProjectA',
53          'line': ['clang++', '-o', 'project2.o', '-c',
54                   '/home/john.doe/MyProject/project2.cpp']},
55        { 'wd': '/home/john.doe/MyProjectB',
56          'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c',
57                   '/home/john.doe/MyProject/project2.cpp']}
58        ]
59    for i in range(len(cmds)):
60        assert cmds[i].directory == expected[i]['wd']
61        for arg, exp in zip(cmds[i].arguments, expected[i]['line']):
62            assert arg == exp
63
64def test_compilecommand_iterator_stops():
65    """Check that iterator stops after the correct number of elements"""
66    cdb = CompilationDatabase.fromDirectory(kInputsDir)
67    count = 0
68    for cmd in cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp'):
69        count += 1
70        assert count <= 2
71
72def test_compilationDB_references():
73    """Ensure CompilationsCommands are independent of the database"""
74    cdb = CompilationDatabase.fromDirectory(kInputsDir)
75    cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp')
76    del cdb
77    gc.collect()
78    workingdir = cmds[0].directory
79
80def test_compilationCommands_references():
81    """Ensure CompilationsCommand keeps a reference to CompilationCommands"""
82    cdb = CompilationDatabase.fromDirectory(kInputsDir)
83    cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp')
84    del cdb
85    cmd0 = cmds[0]
86    del cmds
87    gc.collect()
88    workingdir = cmd0.directory
89
90