-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtest.py
executable file
·124 lines (105 loc) · 3.87 KB
/
test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python3
import clang.cindex
from clang.cindex import CursorKind, TranslationUnit
import unittest
import parse
import pprint
import ast_helpers
import override_scraper
from call_tree import build_call_tree
class TestCallGraph( unittest.TestCase ):
def test_callgraph_simple( self ):
call_tree = self.get_calltree( 'test_cases/1/main.cpp' )
self.assertEqual(
dict( call_tree.tree ),
{
'c:@F@main#': set( [ 'c:@F@do_stuff#' ] ),
'c:@F@do_stuff#': set( [ 'c:@F@save_the_pandas#' ] ),
},
)
def test_callgraph_complex( self ):
call_tree = self.get_calltree( 'test_cases/1/alt.cpp' )
expected_call_tree = {
'c:@F@save_the_pandas#': set( [
'c:alt.cpp@F@increase_environment#',
'c:alt.cpp@F@stop_deforestation#',
'c:alt.cpp@F@stop_hunting#I#',
] ),
'c:alt.cpp@F@stop_hunting#I#': set( [
'c:@F@malloc',
'c:@F@printf',
] ),
}
self.assertCallTreeMatch( call_tree, expected_call_tree )
def test_methods_inherited( self ):
"""
We should be able to detect calling of constructors and
using object methods
"""
call_tree = self.get_calltree( 'test_cases/2/main.cpp' )
call_tree.augment_with_overrides( get_overrides( 'test_cases/2/main.cpp' ) )
expected_call_tree = {
'c:@F@main#': set( [
'c:@S@Panda@F@Feed#I#',
'c:@S@RedPanda@F@Feed#I#',
'c:@S@RedPanda@F@RedPanda#',
] ),
'c:@S@Panda@F@Feed#I#': set( [
'c:@F@printf',
] ),
'c:@S@RedPanda@F@Feed#I#': set( [
'c:@F@malloc',
'c:@F@printf',
] ),
}
self.assertCallTreeMatch( call_tree, expected_call_tree )
def get_calltree( self, sourcefile ):
"""
Open the given source file, parse it, and determine the call tree
"""
index = clang.cindex.Index.create()
tu = index.parse( sourcefile )
call_tree = build_call_tree( tu )
return call_tree
def assertCallTreeMatch( self, call_tree, expectation ):
"""
Assert that for the functions defined in |expectation|, the
correspondings functions are populated similarly in |call_tree|
"""
for key in expectation.keys():
self.assertEqual(
call_tree.calls( key ),
expectation[ key ],
)
class TestOverrides( unittest.TestCase ):
def test_basic_inheritance_override( self ):
overrides = get_overrides( 'test_cases/2/main.cpp' )
self.assertEqual( dict( overrides ), {
'c:@S@Panda@F@Feed#I#': set( [ 'c:@S@RedPanda@F@Feed#I#' ] ),
} )
def test_multilevel_inheritance_override( self ):
overrides = get_overrides(
'test_cases/3/main.cpp', 'test_cases/3/Panda.cpp',
'test_cases/3/DomesticRedPanda.cpp',
'test_cases/3/RedPanda.cpp',
'test_cases/3/TrashPanda.cpp', )
self.assertEqual( overrides[ 'c:@S@Panda@F@Feed#I#' ],
set( [
'c:@S@DomesticRedPanda@F@Feed#I#',
'c:@S@RedPanda@F@Feed#I#',
'c:@S@TrashPanda@F@Feed#I#',
] ) )
def get_overrides( *sourcefiles ):
"""
Open the given source file, parse it and determine the overrides map
"""
overrides = [
override_scraper.get_overrides(
ast_helpers.get_translation_unit(
sourcefile ) )
for sourcefile
in sourcefiles
]
return override_scraper.merge( overrides )
if __name__ == '__main__':
unittest.main()