tests.py 12 KB
Newer Older
Sergio Costas's avatar
Sergio Costas committed
1 2 3 4 5 6 7 8 9 10 11 12 13
#!/usr/bin/env python3

import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.getcwd(), os.pardir)))

import unittest
from crusty import crusty



class Test(unittest.TestCase):

14 15 16 17 18 19 20 21 22 23 24
    def _find_variable(self,var_container,var_name):
        for var_group in var_container:
            if var_name in var_group:
                return var_group[var_name]
        return None

    def _check_var_status(self,lib,variable,status):
        var = self._find_variable(lib.debug[0],variable)
        self.assertIsNot(var,None)
        self.assertEqual(var["status"],status)

25
    def _test_msg(self,lib,error_element,params):
Sergio Costas's avatar
Sergio Costas committed
26 27 28 29
        self.assertEqual(len(error_element),len(params))
        for index in range(len(error_element)):
            self.assertEqual(error_element[index],params[index])

30
    def _print_errors(self,filename,lib):
31
        if False:
32 33 34 35
            print("\rtest file: {:s}".format(filename))
            lib.print_errors()

    def _generic_test(self,filename,params):
Sergio Costas's avatar
Sergio Costas committed
36 37 38
        lib = crusty.crusty("lexyacclib/crusty.h","lexyacclib/crusty.so")
        tree = lib.read_file(filename,False)
        self.assertIsNot(tree,None)
39 40 41
        variables = lib.process_tree(tree)
        lib.process_functions(tree,variables)
        self._print_errors(filename,lib)
42 43 44
        self.assertEqual(len(lib.errors),len(params))
        for i in range(len(lib.errors)):
            self._test_msg(lib,lib.errors[i],params[i])
45
        return lib
Sergio Costas's avatar
Sergio Costas committed
46 47


Sergio Costas's avatar
Sergio Costas committed
48
    def _all_fine_test(self,filename):
Sergio Costas's avatar
Sergio Costas committed
49
        lib = crusty.crusty("lexyacclib/crusty.h","lexyacclib/crusty.so")
Sergio Costas's avatar
Sergio Costas committed
50
        tree = lib.read_file(filename,False)
Sergio Costas's avatar
Sergio Costas committed
51
        self.assertIsNot(tree,None)
52 53 54
        variables = lib.process_tree(tree)
        lib.process_functions(tree,variables)
        self._print_errors(filename,lib)
Sergio Costas's avatar
Sergio Costas committed
55
        self.assertEqual(len(lib.errors),0)
56
        return lib
Sergio Costas's avatar
Sergio Costas committed
57

58
    def _raise_test(self,filename,exception_class,params):
Sergio Costas's avatar
Sergio Costas committed
59
        lib = crusty.crusty("lexyacclib/crusty.h","lexyacclib/crusty.so")
60
        tree = lib.read_file(filename,False)
Sergio Costas's avatar
Sergio Costas committed
61
        self.assertIsNot(tree,None)
62
        variables = lib.process_tree(tree)
63
        with self.assertRaises(exception_class):
64 65
            lib.process_functions(tree,variables)
        self._print_errors(filename,lib)
66 67 68 69 70 71 72 73 74 75 76
        self.assertEqual(len(lib.errors),len(params))
        for i in range(len(lib.errors)):
            self._test_msg(lib,lib.errors[i],params[i])
        return lib

    def testAllFine(self):
        # This test just must work
        self._all_fine_test("unitest/test1.c")

    def testUnknownVariable(self):
        self._raise_test("unitest/test2.c",crusty.crusty.VarNotFoundException,[(crusty.crusty.MSG_CRITICAL,"Unknown variable '{:s}' at line {:d}", "var", 4)])
Sergio Costas's avatar
Sergio Costas committed
77 78

    def testOverwrite(self):
79
        self._generic_test("unitest/test3.c",[ (crusty.crusty.MSG_ERROR,"Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}", "param3", 5, 4) ])
Sergio Costas's avatar
Sergio Costas committed
80 81

    def testUseUninitialized(self):
82
        self._generic_test("unitest/test4.c",[ (crusty.crusty.MSG_ERROR,"Parameter {:d} when calling function '{:s}' at line {:d} isn't initialized",1,"function",5) ])
Sergio Costas's avatar
Sergio Costas committed
83 84

    def testUseFreed(self):
85
        self._generic_test("unitest/test5.c",[ (crusty.crusty.MSG_ERROR,"Parameter {:d} when calling function '{:s}' at line {:d} was freed at line {:d}",1,"function",6,5) ])
Sergio Costas's avatar
Sergio Costas committed
86 87

    def testPassedNonCrustyToCrusty(self):
88
        self._generic_test("unitest/test6.c",[ (crusty.crusty.MSG_CRITICAL,"Expected a __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}, but passed non __crust_t__ variable",1,"function",6) ])
Sergio Costas's avatar
Sergio Costas committed
89 90

    def testPassedCrustyToNonCrusty(self):
91
        self._generic_test("unitest/test7.c",[ (crusty.crusty.MSG_CRITICAL,"Expected a non __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}, but passed a __crust_t__ variable",1,"function",6) ])
Sergio Costas's avatar
Sergio Costas committed
92 93

    def testPassedOtherToCrusty(self):
94
        self._generic_test("unitest/test8.c",[ (crusty.crusty.MSG_CRITICAL,"Expected a __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}",1,"function",5) ])
Sergio Costas's avatar
Sergio Costas committed
95 96

    def testPassedIncorrectNumberOfParameters(self):
97
        self._generic_test("unitest/test9.c",[ (crusty.crusty.MSG_CRITICAL,"Calling function '{:s}' at line {:d} with an incorrect number of parameters","function",5) ])
Sergio Costas's avatar
Sergio Costas committed
98 99

    def testNonExistingFunction(self):
100
        self._raise_test("unitest/test10.c",crusty.crusty.FunctionNotFoundException, [ (crusty.crusty.MSG_CRITICAL,"Calling function '{:s}' at line {:d}, but it is not declared or defined","function3",5) ])
Sergio Costas's avatar
Sergio Costas committed
101 102

    def testCrustParameterNotPointer(self):
103
        self._generic_test("unitest/test11.c",[ (crusty.crusty.MSG_CRITICAL,"A parameter is defined as __crust_t__ type at line {:d}, but it is not a pointer",1) ])
Sergio Costas's avatar
Sergio Costas committed
104 105

    def testCrustNamedParameterNotPointer(self):
106
        self._generic_test("unitest/test12.c",[ (crusty.crusty.MSG_CRITICAL,"Parameter '{:s}' defined as __crust_t__ type at line {:d}, but it is not a pointer","parameter",1) ])
Sergio Costas's avatar
Sergio Costas committed
107

Sergio Costas's avatar
Sergio Costas committed
108
    def testCrustVariableNotPointer(self):
109
        self._generic_test("unitest/test13.c",[ (crusty.crusty.MSG_CRITICAL,"Variable '{:s}' is defined as __crust_t__ type at line {:d}, but it is not a pointer","retval",5) ])
110

Sergio Costas's avatar
Sergio Costas committed
111
    def testCrustRetvalNotPointer(self):
112
        self._generic_test("unitest/test14.c",[ (crusty.crusty.MSG_CRITICAL,"Return value for function '{:s}', defined at line {:d}, is defined as __crust_t__ type, but it is not a pointer","function",1) ])
Sergio Costas's avatar
Sergio Costas committed
113

Sergio Costas's avatar
Sergio Costas committed
114
    def testCrustOnlyVarNoOthers(self):
115
        self._generic_test("unitest/test15.c",[ (crusty.crusty.MSG_CRITICAL,"Variable '{:s}', defined at line {:d}, have __crust_ modifiers other than __crust_t__","var",1) ])
Sergio Costas's avatar
Sergio Costas committed
116 117

    def testRecycleOrBorrowNotBoth(self):
118
        self._generic_test("unitest/test16.c",[ (crusty.crusty.MSG_CRITICAL,"A parameter can be BORROW or RECYCLE, not both. (error at line {:d})",1) ])
Sergio Costas's avatar
Sergio Costas committed
119 120

    def testNamedRecycleOrBorrowNotBoth(self):
121
        self._generic_test("unitest/test17.c",[ (crusty.crusty.MSG_CRITICAL,"A parameter can be BORROW or RECYCLE, not both. (parameter '{:s}' at line {:d})","param",1) ])
Sergio Costas's avatar
Sergio Costas committed
122 123

    def testRecycleReturnsCrust(self):
124
        self._generic_test("unitest/test18.c",[ (crusty.crusty.MSG_CRITICAL,"The function '{:s}', at line {:d}, has a RECYCLE parameter, but doesn't return a CRUST pointer","function",1) ])
Sergio Costas's avatar
Sergio Costas committed
125 126

    def testOnlyOneRecycle(self):
127
        self._generic_test("unitest/test19.c",[ (crusty.crusty.MSG_CRITICAL,"The function '{:s}', at line {:d}, has more than one RECYCLE parameter","function",1) ])
Sergio Costas's avatar
Sergio Costas committed
128 129

    def testUninitializedVariable(self):
130
        self._generic_test("unitest/test20.c",[ (crusty.crusty.MSG_ERROR,"Using uninitialized variable '{:s}' at line {:d}","param4",5) ])
Sergio Costas's avatar
Sergio Costas committed
131 132

    def testFreedVariable(self):
133
        self._generic_test("unitest/test21.c",[ (crusty.crusty.MSG_ERROR,"Using variable '{:s}' at line {:d}, after being freed at line {:d}","param4",6,5) ])
Sergio Costas's avatar
Sergio Costas committed
134

135
    def testAssignFreedVariable(self):
136
        self._generic_test("unitest/test22.c",[ (crusty.crusty.MSG_ERROR,"Using the value of '{:s}' at line {:d} in an assignment, but it was freed at line {:d}","param1",5,4) ])
137 138

    def testAssignUninitializedVariable(self):
139
        self._generic_test("unitest/test23.c",[ (crusty.crusty.MSG_ERROR,"Using the value of '{:s}' at line {:d} in an assignment, but it is uninitialized","param4",5) ])
140

141
    def testAssignNonCrustToCrust(self):
142
        self._generic_test("unitest/test24.c",[ (crusty.crusty.MSG_CRITICAL,"Assigning the non-crust variable '{:s}' to the crust variable '{:s}' at line {:d}","param4","param5",5) ])
143 144

    def testAssignCrustToNonCrust(self):
145
        self._generic_test("unitest/test25.c",[ (crusty.crusty.MSG_CRITICAL,"Assigning the crust pointer '{:s}' to the non-crust variable '{:s}' at line {:d}","param4","param5",5) ])
146

Sergio Costas's avatar
Sergio Costas committed
147 148
    def testTypeCast(self):
        self._all_fine_test("unitest/test26.c")
149

Sergio Costas's avatar
Sergio Costas committed
150
    def testAssignNonCrustToCrust2(self):
151
        self._generic_test("unitest/test27.c",[ (crusty.crusty.MSG_CRITICAL,"Assigning a non-crust value to the crust variable '{:s}' at line {:d}","param",5) ])
152 153

    def testCrustRetVal(self):
154
        self._generic_test("unitest/test28.c",[ (crusty.crusty.MSG_ERROR,"Calling the function '{:s}' at line {:d}, but ignoring the crust-type return value","function",5) ])
155 156

    def testUseUninitialized2(self):
157
        self._generic_test("unitest/test29.c",[ (crusty.crusty.MSG_ERROR,"Parameter {:d} when calling function '{:s}' at line {:d} isn't initialized",1,"function",5) ])
158 159

    def testUseFreed2(self):
160
        self._generic_test("unitest/test30.c",[ (crusty.crusty.MSG_ERROR,"Parameter {:d} when calling function '{:s}' at line {:d} was freed at line {:d}",1,"function",6,5) ])
161 162

    def testPassedNonCrustyToCrusty2(self):
163
        self._generic_test("unitest/test31.c",[ (crusty.crusty.MSG_CRITICAL,"Expected a __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}, but passed non __crust_t__ variable",1,"function",6) ])
164 165

    def testPassedCrustyToNonCrusty2(self):
166
        self._generic_test("unitest/test32.c",[ (crusty.crusty.MSG_CRITICAL,"Expected a non __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}, but passed a __crust_t__ variable",1,"function",6) ])
167 168

    def testPassedOtherToCrusty2(self):
169
        self._generic_test("unitest/test33.c",[ (crusty.crusty.MSG_CRITICAL,"Expected a __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}",1,"function",5) ])
170 171

    def testMultiAssign(self):
172
        self._generic_test("unitest/test34.c",[ (crusty.crusty.MSG_CRITICAL,"Assigning a non-crust value to the crust variable '{:s}' at line {:d}","b",6), (crusty.crusty.MSG_CRITICAL,"Assigning a non-crust value to the crust variable '{:s}' at line {:d}","a",6) ])
Sergio Costas's avatar
Sergio Costas committed
173

174 175
    def testAmpPointer(self):
        self._all_fine_test("unitest/test35.c")
176

Sergio Costas's avatar
Sergio Costas committed
177 178 179 180
    def testStructElement(self):
        self._all_fine_test("unitest/test36.c")

    def testStructAssign(self):
181
        self._generic_test("unitest/test37.c",[ (crusty.crusty.MSG_CRITICAL,"Assigning the non-crust variable '{:s}' to the crust variable '{:s}' at line {:d}","test","param4",8) ])
Sergio Costas's avatar
Sergio Costas committed
182 183 184 185 186

    def testArrayElement(self):
        self._all_fine_test("unitest/test38.c")

    def testArrayAssign(self):
187
        self._generic_test("unitest/test39.c",[ (crusty.crusty.MSG_CRITICAL,"Assigning the non-crust variable '{:s}' to the crust variable '{:s}' at line {:d}","test","param4",6) ])
Sergio Costas's avatar
Sergio Costas committed
188

Sergio Costas's avatar
Sergio Costas committed
189 190 191 192
    def testStructAssignment(self):
        self._all_fine_test("unitest/test40.c")

    def testUsePostStructAssignment(self):
193
        self._generic_test("unitest/test41.c",[ (crusty.crusty.MSG_ERROR,"Parameter {:d} when calling function '{:s}' at line {:d} was freed at line {:d}",1,"function",9,8) ])
Sergio Costas's avatar
Sergio Costas committed
194

195
    def testUsePostStructAssignment2(self):
196
        self._generic_test("unitest/test42.c",[ (crusty.crusty.MSG_CRITICAL,"Assigning the crust pointer '{:s}' to the non-crust variable '{:s}' at line {:d}",'param3',"test",8) ])
Sergio Costas's avatar
Sergio Costas committed
197

Sergio Costas's avatar
Sergio Costas committed
198 199 200
    def testStructAssignmentByRef(self):
        self._all_fine_test("unitest/test43.c")

201 202 203 204 205 206
    def testIfEqNull(self):
        self._all_fine_test("unitest/test44.c")

    def testIfNoEqNull(self):
        self._all_fine_test("unitest/test45.c")

Sergio Costas's avatar
Sergio Costas committed
207 208 209
    def testIfElseNull(self):
        self._all_fine_test("unitest/test46.c")

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    def testRecycle(self):
        lib = self._all_fine_test("unitest/test47.c")
        self._check_var_status(lib,"var3",crusty.crusty.STATUS_NOT_NULL)

    def testBorrow(self):
        lib = self._all_fine_test("unitest/test48.c")
        self._check_var_status(lib,"var2",crusty.crusty.STATUS_NOT_NULL)

    def testBorrow2(self):
        lib = self._all_fine_test("unitest/test49.c")
        self._check_var_status(lib,"var2",crusty.crusty.STATUS_NULL)

    def testPassBorrowToNonBorrow(self):
        self._generic_test("unitest/test50.c",[ (crusty.crusty.MSG_CRITICAL,"Parameter '{:s}' at position {:d} when calling function '{:s}' at line {:d} is borrowed, but is used as a non-borrow parameter",'param',1,"test_function",9) ])

    def testPassBorrowToBorrow(self):
        self._all_fine_test("unitest/test51.c")

228 229 230
    def testPassBorrowToBorrow(self):
        self._all_fine_test("unitest/test52.c")

Sergio Costas's avatar
Sergio Costas committed
231 232
if __name__ == '__main__':
    unittest.main()