class TestResolve(InferTestCase): #{{{ def setUp(self): num_class = Typez(kind='classdef') num_class.scope['__add__'] = Typez(kind='funcdef') pr_num = Typez(kind='pr_num', __class__=num_class) pr_str = Typez(kind='pr_str') self.scope = Scope(is_root=True) self.scope.update({'xxx': pr_str}) scope1 = Scope(parent=self.scope) scope1.update({'a': pr_num, 'b': pr_str}) self.type1 = Typez(kind='obj', scope=scope1) scope2 = Scope(parent=self.scope) scope2.update({'c': pr_num, 'd': pr_str}) self.type2 = Typez(kind='obj', scope=scope2) self.type2 = scope2 scope12 = Scope(parent=self.scope) scope12.update({'a': self.type1, 'b': self.type2}) self.type12 = Typez(kind='obj', scope=scope12) self.scope.update({ 'type1': self.type1, 'type2': self.type2, 'type12': self.type12 }) def test_resolve_type1_in_scope(self): res = self.scope.resolve('type1', 'straight') self.assertEqual(res, self.type1) def test_resolve_in_type(self): res = self.type1.resolve('a', 'straight') self.assertEqual(res.kind, 'pr_num') self.assertEqual(self.scope.resolve('c'), None) def test_resolve_cascade(self): self.assertRaises(Exception, self.type1.resolve, 'xxx', 'cascade') res1 = self.type1.scope.resolve('xxx', 'cascade') res2 = self.scope.resolve('xxx', 'straight') self.assertEqual(res1, res2) def test_resolve_class(self): num = self.type1.resolve('a', 'straight') self.assertRaises(Exception, num.resolve, '__add__', 'cascade') add = num.resolve('__add__', 'straight') self.assertEqual(add, None) add = num.resolve('__add__', 'class') self.assertIsInstance(add, Typez) self.assertEqual(add.kind, 'funcdef')
class TestResolve(InferTestCase): #{{{ def setUp(self): num_class = Typez(kind = 'classdef') num_class.scope['__add__'] = Typez(kind = 'funcdef') pr_num = Typez(kind = 'pr_num', __class__ = num_class ) pr_str = Typez(kind = 'pr_str') self.scope = Scope(is_root = True) self.scope.update({'xxx':pr_str}) scope1 = Scope(parent = self.scope) scope1.update({'a': pr_num, 'b': pr_str}) self.type1 = Typez(kind = 'obj', scope = scope1) scope2 = Scope(parent = self.scope) scope2.update({'c': pr_num, 'd': pr_str}) self.type2 = Typez(kind = 'obj', scope = scope2) self.type2 = scope2 scope12 = Scope(parent = self.scope) scope12.update({'a':self.type1, 'b': self.type2}) self.type12 = Typez(kind = 'obj', scope = scope12) self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12}) def test_resolve_type1_in_scope(self): res = self.scope.resolve('type1', 'straight') self.assertEqual(res, self.type1) def test_resolve_in_type(self): res = self.type1.resolve('a', 'straight') self.assertEqual(res.kind,'pr_num') self.assertEqual(self.scope.resolve('c'), None) def test_resolve_cascade(self): self.assertRaises(Exception, self.type1.resolve, 'xxx','cascade') res1 = self.type1.scope.resolve('xxx','cascade') res2 = self.scope.resolve('xxx','straight') self.assertEqual(res1,res2) def test_resolve_class(self): num = self.type1.resolve('a', 'straight') self.assertRaises(Exception, num.resolve, '__add__', 'cascade') add = num.resolve('__add__', 'straight') self.assertEqual(add, None) add = num.resolve('__add__', 'class') self.assertIsInstance(add, Typez) self.assertEqual(add.kind, 'funcdef')
class TestResolve(unittest.TestCase): #{{{ def setUp(self): pr_num = Typez(kind = 'obj', node = ast.Num(), klass_name = 'num') pr_str = Typez(kind = 'obj', node = ast.Str(), klass_name = 'str') self.scope = Scope(is_root = True) self.scope.update({'xxx':pr_str}) scope1 = Scope(parent = self.scope) scope1.update({'a': pr_num, 'b': pr_str}) self.type1 = Typez(kind = 'obj', scope = scope1) scope2 = Scope(parent = self.scope) scope2.update({'c': pr_num, 'd': pr_str}) self.type2 = Typez(kind = 'obj', scope = scope2) self.type2 = scope2 scope12 = Scope(parent = self.scope) scope12.update({'a':self.type1, 'b': self.type2}) self.type12 = Typez(kind = 'obj', scope = scope12) self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12}) def test_resolve_type1_in_scope(self): res = self.scope.resolve('type1', 'straight') self.assertEqual(res, self.type1) def test_resolve_in_type(self): res = self.type1.resolve('a', 'straight') self.assertEqual(res.kind,'obj') self.assertIsInstance(res.node, ast.Num) self.assertEqual(self.scope.resolve('c'), None) def test_resolve_cascade(self): self.assertRaises(Exception, self.type1.resolve, 'xxx','cascade') res1 = self.type1.scope.resolve('xxx','cascade') res2 = self.scope.resolve('xxx','straight') self.assertEqual(res1,res2) def test_resolve_class(self): num = self.type1.resolve('a', 'straight') self.assertRaises(Exception, num.resolve, '__add__', 'cascade') add = num.resolve('__add__', 'straight') self.assertEqual(add, None) add = num.resolve('__add__', 'class') self.assertIsInstance(add, Typez) self.assertEqual(add.kind, 'func') self.assertIsInstance(add.node, ast.FunctionDef)
def exec_Set(self, node, scope): ''' Set in our implementation only holds info about one object - representant. This can be handful for numerous reasons: adding something in neverending while cycle would cause overflow in symbolic execution if we stored full set. Another advantage is quickness of execution. ''' new_set = Typez(kind = 'object', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_set']) init = new_set.resolve('__init__','class') self._exec_fun(init, [new_set],{}, new_set.scope, node) add = new_set.resolve('add', 'class') for item in node.elts: item_val = self.eval_code(item, scope) if item_val is not None: self._exec_fun(add, [new_set, item_val], {}, scope, node=node) return new_set
def exec_List(self, node, scope): ''' List in our implementation only holds info about one object - representant. This can be handful for numerous reasons: apending something in neverending while cycle would cause overflow in symbolic execution if we stored full list. Another advantage is quickness of execution. ''' new_list = Typez(kind = 'obj', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_list']) init = new_list.resolve('__init__','class') self._exec_fun(init, [new_list],{}, new_list.scope, node) append = new_list.resolve('append', 'class') for item in node.elts: if append: item_val = self.eval_code(item, scope) if item_val is None and hasattr(item, "id"): # self.warn(node, "NameError: Name '"+ item.id + "' is not defined", item.id) item_val = any_type self._exec_fun(append, [new_list, item_val], {}, scope, node=node) return new_list
def exec_Dict(self, node, scope): ''' Dictionary in our implementation only holds info only about two objects: key and value. Reasons are the same like in exec_List. ''' new_dict = Typez(kind = 'obj', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_dict']) init = new_dict.resolve('__init__','class') self._exec_fun(init, [new_dict],{}, new_dict.scope, node) setItem = new_dict.resolve('__setitem__', 'class') #self.nondet=False for i,item in enumerate(node.values): item_val = self.eval_code(item, scope) if item_val is None and hasattr(item, "id"): #self.warn(node, "NameError: Name '"+ item.id + "' is not defined", item.id) item_val = any_type key_val = self.eval_code(node.keys[i],scope) if key_val is None and hasattr(node.keys[i], "id"): #self.warn(node, "NameError: Name '"+ node.keys[i].id + "' is not defined", node.keys[i].id) key_val = any_type args = [new_dict, key_val, item_val] self._exec_fun(setItem, args, {}, scope, node=node) return new_dict
def exec_Tuple(self, node, scope): ''' Tuple in our implementation is of size 5. That should be enough for executing almost all operations between tuples (pairs, triples, adding them together). This can be handful for numerous reasons: adding something in neverending while cycle would cause overflow in symbolic execution if we stored full tuple. Another advantage is quickness of execution. ''' new_tuple = Typez(kind = 'object', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_tuple']) init = new_tuple.resolve('__init__','class') self._exec_fun(init, [new_tuple],{}, new_tuple.scope, node) set_item = new_tuple.resolve('inf__setitem__', 'class') i=0 for item in node.elts: item_val = self.eval_code(item, scope) if item_val is None: item_val = any_type else: #check whether item_val is a PlaceHolder by adding two tuples together if not item_val.resolve_class(self.extern_scope['PlaceHolder']): index = Typez(kind='const', value = i, __class__ = self.extern_scope['num']) self._exec_fun(set_item, [new_tuple, index, item_val], {}, scope, node=node) i+=1 return new_tuple
def exec_Slice(self,node,scope): ''' This method proceeds all the slicing in our implementation. The mock object inf_slice is created. ''' new_slice = Typez(kind = 'object', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_slice']) init = new_slice.resolve('__init__','class') args=[new_slice] if node.upper is not None: args.append(self.eval_code(node.upper, scope)) if node.lower is not None: args.append(self.eval_code(node.lower, scope)) if node.step is not None: args.append(self.eval_code(node.step, scope)) self._exec_fun(init, args,{}, new_slice.scope, node) return new_slice
def exec_List(self, node, scope): res = Typez(kind = 'obj', node = node, klass_name = 'inf_list') for item in node.elts: item_val = self.eval_code(item, scope) append = res.resolve('append', 'class') self._exec_fun(append, item_val, scope, node=node)