Commit e5e2e7f0 authored by Sergio Costas's avatar Sergio Costas

Added all extra tests

Now doesn't fail when a conditional is just a number or a variable name instead of a comparison
parent a35fad6a
......@@ -209,7 +209,6 @@ class crusty(object):
for var_group in var_container:
if var_name in var_group:
return var_group[var_name]
#added
self._add_error(self.MSG_CRITICAL,"Unknown variable '{:s}' at line {:d}",str(var_name),line_number)
raise self.VarNotFoundException()
......@@ -221,7 +220,6 @@ class crusty(object):
if (not force) and ((variable["properties"] & self.PROPERTY_CRUST_VARIABLE) != 0):
status = variable["status"]
if (status == crusty.STATUS_NOT_NULL) or (status == crusty.STATUS_NOT_NULL_OR_NULL):
#added
self._add_error(self.MSG_ERROR,"Assignment to '{:s}' at line {:d}, which was already assigned at line {:d}",var_name,line_number,variable["init_line"])
variable["init_line"] = line_number
if force_init_line:
......@@ -229,25 +227,39 @@ class crusty(object):
variable["status"] = value
def _check_can_be_used(self,variable,line_number):
if (variable.type != "IDENTIFIER") or (not variable.t_crusty):
def _check_can_be_used(self,var_container,variable,line_number):
if (variable.type != "IDENTIFIER"):
return
if variable.status == crusty.STATUS_UNINITIALIZED:
varname = self._find_variable(var_container,variable.name,line_number)
if not self._check_variable_properties(varname,self.PROPERTY_CRUST_VARIABLE):
return
if varname["status"] == crusty.STATUS_UNINITIALIZED:
self._add_error(self.MSG_ERROR,"Using uninitialized variable '{:s}' at line {:d}",variable.name,line_number)
return
if variable.status == crusty.STATUS_FREED:
self._add_error(self.MSG_ERROR,"Using variable '{:s}' at line {:d}, after being freed at line {:d}",variable.name,line_number,variable.line)
if varname["status"] == crusty.STATUS_FREED:
self._add_error(self.MSG_ERROR,"Using variable '{:s}' at line {:d}, after being freed at line {:d}",variable.name,line_number,varname["init_line"])
return
def _eval_condition(self,condition,var_container,function_container):
var_container = self._copy_container(var_container)
condition = condition[0]
print("Condicion: {:s}".format(condition.type))
op1 = condition.child1[0]
op2 = condition.child2[0]
self._check_can_be_used(op1,op1.line)
self._check_can_be_used(op2,op2.line)
if (condition.type == "CONSTANT"):
if condition.intval == 0:
return [ (crusty.CONDITION_FALSE, var_container) ]
else:
return [ (crusty.CONDITION_TRUE, var_container) ]
if (condition.type == "FCONSTANT"):
if condition.floatval == 0.0:
return [ (crusty.CONDITION_FALSE, var_container) ]
else:
return [ (crusty.CONDITION_TRUE, var_container) ]
if (condition.type == "EQ_OP") or (condition.type == "NE_OP"):
op1 = condition.child1[0]
op2 = condition.child2[0]
self._check_can_be_used(var_container,op1,op1.line)
self._check_can_be_used(var_container,op2,op2.line)
if op1.t_null:
op1 = condition.child2[0]
op2 = condition.child1[0]
......@@ -282,16 +294,13 @@ class crusty(object):
def _eval_function_call(self,node,var_container,function_container):
if node.name not in function_container:
#added
self._add_error(self.MSG_CRITICAL,"Calling function '{:s}' at line {:d}, but it is not declared or defined",node.name,node.line)
return [ (self.STATUS_NOT_NULL_OR_NULL, self._copy_container(var_container)) ]
function_data = function_container[node.name]
if ((node.function_params is None) and ((len(function_data)) > 1)):
#added
self._add_error(self.MSG_CRITICAL,"Calling function '{:s}' at line {:d} with an incorrect number of parameters",node.name,node.line)
return [ (self.STATUS_NOT_NULL_OR_NULL, self._copy_container(var_container)) ]
if ((node.function_params is not None) and (len(function_data) - 1) != len(node.function_params)):
#added
self._add_error(self.MSG_CRITICAL,"Calling function '{:s}' at line {:d} with an incorrect number of parameters",node.name,node.line)
return [ (self.STATUS_NOT_NULL_OR_NULL, self._copy_container(var_container)) ]
error_found = False
......@@ -302,7 +311,6 @@ class crusty(object):
variable = node.function_params[pos]
if variable.type != "IDENTIFIER":
if ((function_data[pos+1] & self.PROPERTY_CRUST_VARIABLE) != 0) and (not variable.t_null):
#added
self._add_error(self.MSG_CRITICAL,"Expected a __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}",pos+1,node.name,node.line)
error_found = True
continue
......@@ -312,24 +320,20 @@ class crusty(object):
param_is_borrowed = (function_data[pos+1] & self.PROPERTY_BORROWED) != 0
param_is_recycled = (function_data[pos+1] & self.PROPERTY_RECYCLED) != 0
if (not var_is_crusty) and param_is_crusty:
#added
self._add_error(self.MSG_CRITICAL,"Expected a __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}, but passed non __crust_t__ variable",pos+1,node.name,node.line)
error_found = True
continue
if var_is_crusty and (not param_is_crusty):
#added
self._add_error(self.MSG_CRITICAL,"Expected a non __crust_t__ variable at parameter {:d} when calling function '{:s}' at line {:d}, but passed a __crust_t__ variable",pos+1,node.name,node.line)
error_found = True
continue
if not param_is_crusty:
continue
if node_var["status"] == self.STATUS_UNINITIALIZED:
#added
self._add_error(self.MSG_ERROR,"Parameter {:d} when calling function '{:s}' at line {:d} isn't initialized",pos+1,node.name,node.line)
error_found = True
continue
if node_var["status"] == self.STATUS_FREED:
#added
self._add_error(self.MSG_ERROR,"Parameter {:d} when calling function '{:s}' at line {:d} was freed at line {:d}",pos+1,node.name,node.line,node_var["init_line"])
error_found = True
continue
......@@ -410,22 +414,18 @@ class crusty(object):
if node.pointer == 0:
if is_parameter:
if node.name is None:
#added
self._add_error(self.MSG_CRITICAL,"A parameter is defined as __crust_t__ type at line {:d}, but it is not a pointer",node.line)
else:
#added
self._add_error(self.MSG_CRITICAL,"Parameter '{:s}' defined as __crust_t__ type at line {:d}, but it is not a pointer",node.name,node.line)
else:
if is_retval:
#added
self._add_error(self.MSG_CRITICAL,"Return value for function '{:s}', defined at line {:d}, is defined as __crust_t__ type, but it is not a pointer",node.name,node.line)
else:
#added
self._add_error(self.MSG_CRITICAL,"Variable '{:s}' is defined as __crust_t__ type at line {:d}, but it is not a pointer",node.name,node.line)
retval += crusty.PROPERTY_CRUST_VARIABLE
if (node.t_crusty_borrow or node.t_crusty_recycle):
if not is_parameter:
self._add_error(self.MSG_CRITICAL,"A variable can have only __crust_t__ as modifier (error at line {:d} with variable '{:s}')",node.line,node.name)
self._add_error(self.MSG_CRITICAL,"Variable '{:s}', defined at line {:d}, have __crust_ modifiers other than __crust_t__",node.name,node.line)
if (node.t_crusty_borrow and node.t_crusty_recycle):
if is_parameter:
if node.name is None:
......@@ -459,7 +459,7 @@ class crusty(object):
if parameter.t_crusty_recycle:
counter += 1
if counter > 1:
self._add_error(self.MSG_CRITICAL,"The function '{:s}', at line {:d}, has more than one RECYCLE parameter.",node.name,node.line)
self._add_error(self.MSG_CRITICAL,"The function '{:s}', at line {:d}, has more than one RECYCLE parameter",node.name,node.line)
if (counter != 0) and (not node.t_crusty):
self._add_error(self.MSG_CRITICAL,"The function '{:s}', at line {:d}, has a RECYCLE parameter, but doesn't return a CRUST pointer",node.name,node.line)
if not node.t_typedef:
......
......@@ -85,5 +85,26 @@ class Test(unittest.TestCase):
def testCrustRetvalNotPointer(self):
self._generic_test("unitest/test14.c",False,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)
def testCrustOnlyVarNoOthers(self):
self._generic_test("unitest/test15.c",False,crusty.crusty.MSG_CRITICAL,"Variable '{:s}', defined at line {:d}, have __crust_ modifiers other than __crust_t__","var",1)
def testRecycleOrBorrowNotBoth(self):
self._generic_test("unitest/test16.c",False,crusty.crusty.MSG_CRITICAL,"A parameter can be BORROW or RECYCLE, not both. (error at line {:d})",1)
def testNamedRecycleOrBorrowNotBoth(self):
self._generic_test("unitest/test17.c",False,crusty.crusty.MSG_CRITICAL,"A parameter can be BORROW or RECYCLE, not both. (parameter '{:s}' at line {:d})","param",1)
def testRecycleReturnsCrust(self):
self._generic_test("unitest/test18.c",False,crusty.crusty.MSG_CRITICAL,"The function '{:s}', at line {:d}, has a RECYCLE parameter, but doesn't return a CRUST pointer","function",1)
def testOnlyOneRecycle(self):
self._generic_test("unitest/test19.c",False,crusty.crusty.MSG_CRITICAL,"The function '{:s}', at line {:d}, has more than one RECYCLE parameter","function",1)
def testUninitializedVariable(self):
self._generic_test("unitest/test20.c",False,crusty.crusty.MSG_ERROR,"Using uninitialized variable '{:s}' at line {:d}","param4",5)
def testFreedVariable(self):
self._generic_test("unitest/test21.c",False,crusty.crusty.MSG_ERROR,"Using variable '{:s}' at line {:d}, after being freed at line {:d}","param4",6,5)
if __name__ == '__main__':
unittest.main()
......@@ -6,4 +6,6 @@ __crust_t__ int * llamada(__crust_t__ int *param2, __crust_recycle__ int *param1
void main() {
int a = 1 ? 3 : 0;
}
__crust_recycle__ int *var;
__crust_t__ int * function(__crust_borrow__ __crust_recycle__ int *);
__crust_t__ int * function(__crust_borrow__ __crust_recycle__ int *param);
int * function(__crust_recycle__ int *param);
__crust_t__ int * function(__crust_recycle__ int *param, __crust_recycle__ int *param2);
typedef __crust_t__ unsigned char *crust_t;
void function(crust_t param1) {
crust_t param4;
int retval = (param4 == NULL) ? 1 : 0;
}
typedef __crust_t__ unsigned char *crust_t;
int function(crust_t param1) {
crust_t param4 = NULL;
int retval = function(param4);
int retval = (param4 == NULL) ? 1 : 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment