summaryrefslogtreecommitdiff
path: root/libs/python/pyste/tests/GCCXMLParserUT.py
blob: 7175c9c68492ca4f8e5cd3024e747223f4a8c827 (plain)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and 
# distribution is subject to the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at 
# http://www.boost.org/LICENSE_1_0.txt)

import sys
sys.path.append('../src') 
import unittest
import tempfile
import os.path
from Pyste import GCCXMLParser
from Pyste.declarations import *

    
class Tester(unittest.TestCase):

    def TestConstructor(self, class_, method, visib):
        self.assert_(isinstance(method, Constructor))
        self.assertEqual(method.FullName(), class_.FullName() + '::' + method.name)
        self.assertEqual(method.result, None)
        self.assertEqual(method.visibility, visib)
        self.assert_(not method.virtual)
        self.assert_(not method.abstract)
        self.assert_(not method.static)
        
    def TestDefaultConstructor(self, class_, method, visib):
        self.TestConstructor(class_, method, visib)
        self.assert_(method.IsDefault())

    def TestCopyConstructor(self, class_, method, visib):    
        self.TestConstructor(class_, method, visib)
        self.assertEqual(len(method.parameters), 1)
        param = method.parameters[0]
        self.TestType(
            param, 
            ReferenceType, 
            class_.FullName(), 
            'const %s&' % class_.FullName(),
            True)
        self.assert_(method.IsCopy())


    def TestType(self, type_, classtype_, name, fullname, const):
        self.assert_(isinstance(type_, classtype_))
        self.assertEqual(type_.name, name)
        self.assertEqual(type_.namespace, None)
        self.assertEqual(type_.FullName(), fullname)
        self.assertEqual(type_.const, const)
        
        
class ClassBaseTest(Tester):

    def setUp(self):
        self.base = GetDecl('Base')
        
    def testClass(self):
        'test the properties of the class Base'
        self.assert_(isinstance(self.base, Class))
        self.assert_(self.base.abstract)
                

    def testFoo(self):
        'test function foo in class Base' 
        foo = GetMember(self.base, 'foo')
        self.assert_(isinstance(foo, Method))
        self.assertEqual(foo.visibility, Scope.public)
        self.assert_(foo.virtual)
        self.assert_(foo.abstract)
        self.failIf(foo.static)
        self.assertEqual(foo.class_, 'test::Base')
        self.failIf(foo.const)
        self.assertEqual(foo.FullName(), 'test::Base::foo')        
        self.assertEqual(foo.result.name, 'void')
        self.assertEqual(len(foo.parameters), 1)
        param = foo.parameters[0]
        self.TestType(param, FundamentalType, 'int', 'int', False)  
        self.assertEqual(foo.namespace, None)
        self.assertEqual(
            foo.PointerDeclaration(1), '(void (test::Base::*)(int) )&test::Base::foo')

    def testX(self):
        'test the member x in class Base'
        x = GetMember(self.base, 'x')
        self.assertEqual(x.class_, 'test::Base')
        self.assertEqual(x.FullName(), 'test::Base::x')
        self.assertEqual(x.namespace, None)
        self.assertEqual(x.visibility, Scope.private)
        self.TestType(x.type, FundamentalType, 'int', 'int', False)  
        self.assertEqual(x.static, False)

    def testConstructors(self):
        'test constructors in class Base'
        constructors = GetMembers(self.base, 'Base')
        for cons in constructors:
            if len(cons.parameters) == 0:
                self.TestDefaultConstructor(self.base, cons, Scope.public)
            elif len(cons.parameters) == 1: # copy constructor
                self.TestCopyConstructor(self.base, cons, Scope.public)
            elif len(cons.parameters) == 2: # other constructor
                intp, floatp = cons.parameters
                self.TestType(intp, FundamentalType, 'int', 'int', False)
                self.TestType(floatp, FundamentalType, 'float', 'float', False)

    def testSimple(self):
        'test function simple in class Base'
        simple = GetMember(self.base, 'simple')
        self.assert_(isinstance(simple, Method))
        self.assertEqual(simple.visibility, Scope.protected)
        self.assertEqual(simple.FullName(), 'test::Base::simple')
        self.assertEqual(len(simple.parameters), 1)
        param = simple.parameters[0]
        self.TestType(param, ReferenceType, 'std::string', 'const std::string&', True)
        self.TestType(simple.result, FundamentalType, 'bool', 'bool', False)
        self.assertEqual(
            simple.PointerDeclaration(1), 
            '(bool (test::Base::*)(const std::string&) )&test::Base::simple')
        
          
    def testZ(self):
        z = GetMember(self.base, 'z')
        self.assert_(isinstance(z, Variable))
        self.assertEqual(z.visibility, Scope.public)
        self.assertEqual(z.FullName(), 'test::Base::z')
        self.assertEqual(z.type.name, 'int')
        self.assertEqual(z.type.const, False)
        self.assert_(z.static)
        
        
class ClassTemplateTest(Tester):        
    
    def setUp(self):
        self.template = GetDecl('Template<int>')

    def testClass(self):
        'test the properties of the Template<int> class'
        self.assert_(isinstance(self.template, Class))
        self.assert_(not self.template.abstract)
        self.assertEqual(self.template.FullName(), 'Template<int>')
        self.assertEqual(self.template.namespace, '')
        self.assertEqual(self.template.name, 'Template<int>')

    def testConstructors(self):
        'test the automatic constructors of the class Template<int>'
        constructors = GetMembers(self.template, 'Template')
        for cons in constructors:
            if len(cons.parameters) == 0:
                self.TestDefaultConstructor(self.template, cons, Scope.public)
            elif len(cons.parameters) == 1:
                self.TestCopyConstructor(self.template, cons, Scope.public)
                    

    def testValue(self):
        'test the class variable value'
        value = GetMember(self.template, 'value')
        self.assert_(isinstance(value, ClassVariable))
        self.assert_(value.name, 'value')
        self.TestType(value.type, FundamentalType, 'int', 'int', False)  
        self.assert_(not value.static)
        self.assertEqual(value.visibility, Scope.public)
        self.assertEqual(value.class_, 'Template<int>')
        self.assertEqual(value.FullName(), 'Template<int>::value')

    def testBase(self):
        'test the superclasses of Template<int>'
        bases = self.template.bases
        self.assertEqual(len(bases), 1)
        base = bases[0]
        self.assert_(isinstance(base, Base))
        self.assertEqual(base.name, 'test::Base')
        self.assertEqual(base.visibility, Scope.protected)

        
        
class FreeFuncTest(Tester):

    def setUp(self):
        self.func = GetDecl('FreeFunc')

    def testFunc(self):
        'test attributes of FreeFunc'
        self.assert_(isinstance(self.func, Function))
        self.assertEqual(self.func.name, 'FreeFunc')
        self.assertEqual(self.func.FullName(), 'test::FreeFunc')
        self.assertEqual(self.func.namespace, 'test')
        self.assertEqual(
            self.func.PointerDeclaration(1), 
            '(const test::Base& (*)(const std::string&, int))&test::FreeFunc')


    def testResult(self):
        'test the return value of FreeFunc'
        res = self.func.result
        self.TestType(res, ReferenceType, 'test::Base', 'const test::Base&', True)

    def testParameters(self):
        'test the parameters of FreeFunc'
        self.assertEqual(len(self.func.parameters), 2)
        strp, intp = self.func.parameters
        self.TestType(strp, ReferenceType, 'std::string', 'const std::string&', True)
        self.assertEqual(strp.default, None)
        self.TestType(intp, FundamentalType, 'int', 'int', False)
        self.assertEqual(intp.default, '10')
        
        

class testFunctionPointers(Tester):

    def testMethodPointer(self):
        'test declaration of a pointer-to-method'
        meth = GetDecl('MethodTester')
        param = meth.parameters[0]
        fullname = 'void (test::Base::*)(int)'
        self.TestType(param, PointerType, fullname, fullname, False)

    def testFunctionPointer(self):
        'test declaration of a pointer-to-function'
        func = GetDecl('FunctionTester')
        param = func.parameters[0]
        fullname = 'void (*)(int)'
        self.TestType(param, PointerType, fullname, fullname, False)

        
        
# =============================================================================
# Support routines
# =============================================================================

cppcode = '''
namespace std {
    class string;
}
namespace test {
class Base
{
public:
    Base();
    Base(const Base&);
    Base(int, float);

    virtual void foo(int = 0.0) = 0;
    static int z;
protected:    
    bool simple(const std::string&);
private:
    int x;
};

void MethodTester( void (Base::*)(int) );
void FunctionTester( void (*)(int) );


const Base & FreeFunc(const std::string&, int=10);

}

template <class T>
struct Template: protected test::Base
{
    T value;        
    virtual void foo(int);
};
 
Template<int> __aTemplateInt;
'''

def GetXMLFile():
    '''Generates an gccxml file using the code from the global cppcode. 
    Returns the xml's filename.'''
    # write the code to a header file
    tmpfile = tempfile.mktemp() + '.h'
    f = file(tmpfile, 'w')
    f.write(cppcode)
    f.close()
    # run gccxml
    outfile = tmpfile + '.xml'
    if os.system('gccxml "%s" "-fxml=%s"' % (tmpfile, outfile)) != 0:
        raise RuntimeError, 'Error executing GCCXML.'
    # read the output file into the xmlcode
    f = file(outfile)
    xmlcode = f.read()
    #print xmlcode
    f.close()
    # remove the header
    os.remove(tmpfile)
    return outfile       



def GetDeclarations():
    'Uses the GCCXMLParser module to get the declarations.'
    xmlfile = GetXMLFile()
    declarations = GCCXMLParser.ParseDeclarations(xmlfile)
    os.remove(xmlfile)
    return declarations

# the declarations to be analysed
declarations = GetDeclarations()


def GetDecl(name):
    'returns one of the top declarations given its name'
    for decl in declarations:
        if decl.name == name:
            return decl
    else:
        raise RuntimeError, 'Declaration not found: %s' % name


def GetMember(class_, name):
    'gets the member of the given class by its name'
                
    res = None
    multipleFound = False
    for member in class_:
        if member.name == name:
            if res is not None:
                multipleFound = True
                break
            res = member
    if res is None or multipleFound:
        raise RuntimeError, \
            'No member or more than one member found in class %s: %s' \
                % (class_.name, name)
    return res            
    

def GetMembers(class_, name):
    'gets the members of the given class by its name'
    res = []
    for member in class_:
        if member.name == name:
            res.append(member)
    if len(res) in (0, 1):            
        raise RuntimeError, \
            'GetMembers: 0 or 1 members found in class %s: %s' \
                % (class_.name, name)
    return res            


if __name__ == '__main__':
    unittest.main()