def test_newobj_no_parameters_initializes_int_field_to_zero(self): from VM import VM vm = VM() m = MethodDefinition() m.name = 'ctor' m.namespace = 'testnamespace.testclass' vm.methods.append(m) c = ClassDefinition() c.name = 'testclass' c.namespace = 'testnamespace' c.methods.append(m) v = Variable() v.name = 'xyz' v.type = Types.Int32 c.fieldDefinitions.append(v) t = Types.register_custom_type(c) n = newobj('instance void testnamespace.testclass::.ctor()') n.execute(vm) Types.unregister_custom_type(t) o = vm.stack.pop() self.assertEqual(o.type, t) self.assertEqual(len(o.fields), 1) self.assertEqual(o.fields[0].value, 0) self.assertEqual(len(o.fieldNames), 1) self.assertEqual(o.fieldNames[0], 'xyz')
def add_builtins(self): m = MethodDefinition() m.instructions.append(Ret()) m.name = 'ctor' m.namespace = '[mscorlib]System.Object' m.returnType = Types.Void self.methods.append(m)
def test_callvirt_one_parameter_int(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() paramObject = Variable() paramObject.type = Types.Int32 m = MethodDefinition() m.namespace = "A.B" m.name = "TestMethod" m.returnType = Types.Int32 m.parameters = [paramObject] vm.methods.append(m) param = Variable() param.value = 123 param.type = Types.Int32 vm.stack.push(param) c = callvirt("int32 A.B::TestMethod ( int32 )") c.execute(vm) self.assertEqual(vm.currentMethod.methodDefinition, m) self.assertEqual(vm.stack.get_number_of_frames(), 2) self.assertEqual(vm.current_method().parameters[0], param)
def add_builtins(self): m = MethodDefinition() m.instructions.append(Ret()) m.name = "ctor" m.namespace = "[mscorlib]System.Object" m.returnType = Types.Void self.methods.append(m)
def test_find_match(self): vm = VM() method = MethodDefinition() method.name = 'hello' method.returnType = Types.Int8 method.parameters = [Types.Int16, Types.Int32] vm.methods.append(method) m = vm.find_method_by_signature(None, 'hello', Types.Int8, [Types.Int16, Types.Int32]) self.assertEqual(m, method)
def test_find_match(self): vm = VM() method = MethodDefinition() method.name = "hello" method.returnType = Types.Int8 method.parameters = [Types.Int16, Types.Int32] vm.methods.append(method) m = vm.find_method_by_signature(None, "hello", Types.Int8, [Types.Int16, Types.Int32]) self.assertEqual(m, method)
def test_frame_methods(self): s = Stack(5) m1 = MethodDefinition() s.beginFrame(5, m1) self.assertEqual(s.currentFrame.method, m1) m2 = MethodDefinition() s.beginFrame(999, m2) self.assertEqual(s.currentFrame.method, m2) s.endFrame() self.assertEqual(s.currentFrame.method, m1) s.endFrame() self.assertEqual(s.currentFrame.method, None)
def test_callvirt_one_parameter_instance_puts_this_pointer_and_parameter_on_stack( self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() paramObject = Variable() paramObject.type = Types.Int32 m = MethodDefinition() m.name = 'TestMethod' m.namespace = 'A.B' m.returnType = Types.Int32 m.parameters = [paramObject] m.names = 'A.B' m.attributes.append(MethodDefinition.AttributeTypes['instance']) vm.methods.append(m) r = ReferenceType() vm.stack.push(r) v = Variable(8888) vm.stack.push(v) self.assertEqual(vm.currentMethod, None) c = callvirt('instance int32 A.B::TestMethod ( int32 )') c.execute(vm) self.assertEqual(vm.currentMethod.methodDefinition, m) self.assertEqual(vm.stack.get_number_of_frames(), 2) self.assertEqual(len(vm.current_method().parameters), 2) self.assertEqual(vm.current_method().parameters[1], v) self.assertEqual(vm.current_method().parameters[0], r)
def test_nop(self): from VM import VM vm = VM() m = MethodDefinition() m.name = 'TestMethod' m.returnType = Types.Void m.parameters = [] vm.methods.append(m) self.assertEqual(vm.currentMethod, None) c = nop() c.execute(vm) self.assertEqual(vm.stack.get_number_of_frames(), 1)
def parse(self, parserContext): self.context = parserContext method = MethodDefinition() token = self.context.get_next_token() while token != BlockStart: if token == '(': self.parse_parameters(method) elif token in MethodDefinition.AttributeTypes.keys(): method.attributes.append(token) elif token in Types.BuiltInTypes: method.returnType = Types.BuiltInTypes[token] elif token == '.method': pass else: try: type = Types.resolve_type(token) method.returnType = type except: # If the type isn't found it must be the name of the method parts = token.rpartition('.') method.namespace = parts[0] method.name = parts[2] self.parse_parameters(method) token = self.context.get_next_token() token = self.context.get_next_token() while token != BlockEnd or len(self.end_block_instructions) > 0: if token == '.maxstack': method.maxStack = int(self.context.get_next_token()) elif token == '.entrypoint': method.attributes.append(token) elif token == '.locals': method.locals = self.parse_locals(self.context) elif token == '.try': self.parse_try_block(method) elif token == 'catch': self.parse_catch_block(method) elif token == BlockEnd: self.parse_end_block(method) else: from InstructionParser import InstructionParser instruction = InstructionParser().parse_instruction( token, self.context) method.instructions.append(instruction) if token == 'ret': break token = self.context.get_next_token() return method
def test_execute_0(self): from VM import VM vm = VM() x = ldloc('0') m = MethodDefinition() m.locals.append(Variable(987)) vm.set_current_method(m) x.execute(vm) self.assertEqual(vm.stack.count(), 1) self.assertEqual(vm.stack.pop().value, 987)
def test_newobj_no_parameters_adds_this_pointer_to_parameters(self): from VM import VM vm = VM() m = MethodDefinition() m.name = 'ctor' m.namespace = 'testnamespace.testclass' vm.methods.append(m) c = ClassDefinition() c.name = 'testclass' c.namespace = 'testnamespace' c.methods.append(m) t = Types.register_custom_type(c) n = newobj('instance void testnamespace.testclass::.ctor()') n.execute(vm) self.assertEqual(len(vm.current_method().parameters), 1) Types.unregister_custom_type(t)
def test_execute_1(self): from VM import VM vm = VM() x = ldarg('1') m = MethodDefinition() m.parameters.append(Variable(0)) m.parameters.append(Variable(987)) vm.set_current_method(m) x.execute(vm) self.assertEqual(vm.stack.count(), 1) self.assertEqual(vm.stack.pop().value, 987)
def test_callvirt_one_parameter_int(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() paramObject = Variable() paramObject.type = Types.Int32 m = MethodDefinition() m.namespace = 'A.B' m.name = 'TestMethod' m.returnType = Types.Int32 m.parameters = [paramObject] vm.methods.append(m) param = Variable() param.value = 123 param.type = Types.Int32 vm.stack.push(param) c = callvirt('int32 A.B::TestMethod ( int32 )') c.execute(vm) self.assertEqual(vm.currentMethod.methodDefinition, m) self.assertEqual(vm.stack.get_number_of_frames(), 2) self.assertEqual(vm.current_method().parameters[0], param)
def test_callvirt_one_parameter_instance_puts_this_pointer_and_parameter_on_stack(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() paramObject = Variable() paramObject.type = Types.Int32 m = MethodDefinition() m.name = "TestMethod" m.namespace = "A.B" m.returnType = Types.Int32 m.parameters = [paramObject] m.names = "A.B" m.attributes.append(MethodDefinition.AttributeTypes["instance"]) vm.methods.append(m) r = ReferenceType() vm.stack.push(r) v = Variable(8888) vm.stack.push(v) self.assertEqual(vm.currentMethod, None) c = callvirt("instance int32 A.B::TestMethod ( int32 )") c.execute(vm) self.assertEqual(vm.currentMethod.methodDefinition, m) self.assertEqual(vm.stack.get_number_of_frames(), 2) self.assertEqual(len(vm.current_method().parameters), 2) self.assertEqual(vm.current_method().parameters[1], v) self.assertEqual(vm.current_method().parameters[0], r)
def test_end_frame_removes_stack_values(self): s = Stack(5) s.push(987) m1 = MethodDefinition() s.beginFrame(5, m1) s.push(123) s.push(456) s.push(99999) s.endFrame() self.assertEqual(s.currentFrame.method, None) self.assertEqual(s.count(), 1)
def parse(self, parserContext): self.context = parserContext method = MethodDefinition() token = self.context.get_next_token() while token != BlockStart: if token == '(': self.parse_parameters(method) elif token in MethodDefinition.AttributeTypes.keys(): method.attributes.append(token) elif token in Types.BuiltInTypes: method.returnType = Types.BuiltInTypes[token] elif token == '.method': pass else: try: type = Types.resolve_type(token) method.returnType = type except: # If the type isn't found it must be the name of the method parts = token.rpartition('.') method.namespace = parts[0] method.name = parts[2] self.parse_parameters(method) token = self.context.get_next_token() token = self.context.get_next_token() while token != BlockEnd or len(self.end_block_instructions) > 0: if token == '.maxstack': method.maxStack = int(self.context.get_next_token()) elif token == '.entrypoint': method.attributes.append(token) elif token == '.locals': method.locals = self.parse_locals(self.context) elif token == '.try': self.parse_try_block(method) elif token == 'catch': self.parse_catch_block(method) elif token == BlockEnd: self.parse_end_block(method) else: from InstructionParser import InstructionParser instruction = InstructionParser().parse_instruction(token, self.context) method.instructions.append(instruction) if token == 'ret': break token = self.context.get_next_token() return method
def test_execute_s_label(self): from VM import VM vm = VM() x = ldloc('s ghi') m = MethodDefinition() m.locals.append(Variable(0, name='abc')) m.locals.append(Variable(0, name='def')) m.locals.append(Variable(987, name='ghi')) m.locals.append(Variable(0, name='jkl')) vm.set_current_method(m) x.execute(vm) self.assertEqual(vm.stack.count(), 1) self.assertEqual(vm.stack.pop().value, 987)
def test_execute_1(self): from VM import VM vm = VM() x = stloc('1') m = MethodDefinition() m.locals.append(Variable(0)) m.locals.append(Variable(0)) vm.set_current_method(m) vm.stack.push(Variable(987)) x.execute(vm) self.assertEqual(vm.stack.count(), 0) self.assertEqual(m.locals[0].value, 0) self.assertEqual(m.locals[1].value, 987)
def test_newobj_no_parameters_calls_constructor(self): from VM import VM vm = VM() m = MethodDefinition() m.name = 'ctor' m.namespace = 'testnamespace.testclass' vm.methods.append(m) c = ClassDefinition() c.name = 'testclass' c.namespace = 'testnamespace' c.methods.append(m) t = Types.register_custom_type(c) n = newobj('instance void testnamespace.testclass::ctor()') n.execute(vm) Types.unregister_custom_type(t) o = vm.stack.pop() self.assertEqual(o.type, t) self.assertEquals(vm.current_method().methodDefinition, m)
def test_execute_true_s(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() m = MethodDefinition() m.maxStack = 3 x = ldc('i4.1') m.instructions.append(x) m.instructions.append(x) m.instructions.append(x) dest = ldc('i4.3') dest.label = 'asdf' m.instructions.append(dest) vm.set_current_method(m) vm.stack.push(Variable(222)) vm.stack.push(Variable(222)) x = beq('s asdf') # fixme optional parameters x.execute(vm) index = vm.get_instruction_pointer() self.assertEqual(3, index); self.assertEqual(vm.stack.count(), 0)
def test_execute_method(self): vm = VM() md = MethodDefinition() md.name = 'hello' md.returnType = Types.Int8 md.parameters = [Types.Int16, Types.Int32] md.maxStack = 77 m = md.get_method() self.assertEqual(vm.current_method(), None) vm.execute_method(m) self.assertEqual(vm.current_method(), m) self.assertEqual(vm.stack.get_frame_size(), 77)
def test_execute_reference_type_stores_reference_type_in_local_but_doesnt_change_name( self): from VM import VM vm = VM() x = stloc('0') m = MethodDefinition() localr = ReferenceType() localr.name = 'foobar' m.locals.append(localr) vm.set_current_method(m) r2 = ReferenceType() vm.stack.push(r2) x.execute(vm) self.assertEqual(vm.stack.count(), 0) self.assertEqual(m.locals[0], r2) self.assertEqual(m.locals[0].name, 'foobar')
def test_recursive_execute_method_each_instance_has_new_instance_variables(self): vm = VM() md = MethodDefinition() md.name = 'hello' md.returnType = Types.Int8 md.parameters = [Types.Int16, Types.Int32] md.maxStack = 77 self.assertEqual(vm.current_method(), None) m = md.get_method() vm.execute_method(m) self.assertEqual(vm.current_method(), m) self.assertEqual(vm.stack.get_frame_size(), 77)
def test_execute_s_label(self): from VM import VM vm = VM() x = stloc('s def') m = MethodDefinition() m.locals.append(Variable(0, name='xyz')) m.locals.append(Variable(0, name='abc')) m.locals.append(Variable(0, name='def')) m.locals.append(Variable(0, name='ghi')) vm.set_current_method(m) vm.stack.push(Variable(987)) x.execute(vm) self.assertEqual(vm.stack.count(), 0) self.assertEqual(m.locals[0].value, 0) self.assertEqual(m.locals[1].value, 0) self.assertEqual(m.locals[2].value, 987) self.assertEqual(m.locals[3].value, 0)
def test_execute_method(self): vm = VM() md = MethodDefinition() md.name = "hello" md.returnType = Types.Int8 md.parameters = [Types.Int16, Types.Int32] md.maxStack = 77 m = md.get_method() self.assertEqual(vm.current_method(), None) vm.execute_method(m) self.assertEqual(vm.current_method(), m) self.assertEqual(vm.stack.get_frame_size(), 77)
def test_br_s(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() m = MethodDefinition() x = ldc('i4.1') m.instructions.append(x) m.instructions.append(x) m.instructions.append(x) dest = ldc('i4.3') dest.label = 'zzz' m.instructions.append(dest) vm.set_current_method(m) x = br('s zzz') x.execute(vm) index = vm.get_instruction_pointer() self.assertEqual(3, index)
def test_leave(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() m = MethodDefinition() x = ldc('i4.1') m.instructions.append(x) m.instructions.append(x) m.instructions.append(x) dest = ldc('i4.3') dest.label = 'asdf' m.instructions.append(dest) vm.set_current_method(m) x = leave('asdf') # fixme optional parameters x.execute(vm) index = vm.get_instruction_pointer() self.assertEqual(3, index)
def test_recursive_execute_method_each_instance_has_new_instance_variables(self): vm = VM() md = MethodDefinition() md.name = "hello" md.returnType = Types.Int8 md.parameters = [Types.Int16, Types.Int32] md.maxStack = 77 self.assertEqual(vm.current_method(), None) m = md.get_method() vm.execute_method(m) self.assertEqual(vm.current_method(), m) self.assertEqual(vm.stack.get_frame_size(), 77)
def test_callvirt_constructor_strips_period(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() m = MethodDefinition() m.name = 'ctor()' m.namespace = 'A.B' m.returnType = Types.Int32 m.parameters = [] m.names = 'A.B' vm.methods.append(m) self.assertEqual(vm.currentMethod, None) c = callvirt('int32 A.B::.ctor()') c.execute(vm) self.assertEqual(vm.currentMethod.methodDefinition, m) self.assertEqual(vm.stack.get_number_of_frames(), 2)
def test_call_no_parameters_int(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() m = MethodDefinition() m.name = 'TestMethod()' m.namespace = 'A.B' m.returnType = Types.Int32 m.parameters = [] m.names = 'A.B' vm.methods.append(m) self.assertEqual(vm.currentMethod, None) c = call('int32 A.B::TestMethod()') c.execute(vm) self.assertEqual(vm.currentMethod.methodDefinition, m) self.assertEqual(vm.stack.get_number_of_frames(), 2)
def test_call_constructor_strips_period(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() m = MethodDefinition() m.name = 'ctor()' m.namespace = 'A.B' m.returnType = Types.Int32 m.parameters = [] m.names = 'A.B' vm.methods.append(m) self.assertEqual(vm.currentMethod, None) c = call('int32 A.B::.ctor()') c.execute(vm) self.assertEqual(vm.currentMethod.methodDefinition, m) self.assertEqual(vm.stack.get_number_of_frames(), 2)
def test_callvirt_no_parameters_int(self): from VM import VM from MethodDefinition import MethodDefinition vm = VM() m = MethodDefinition() m.name = "TestMethod()" m.namespace = "A.B" m.returnType = Types.Int32 m.parameters = [] m.names = "A.B" vm.methods.append(m) self.assertEqual(vm.currentMethod, None) c = callvirt("int32 A.B::TestMethod()") c.execute(vm) self.assertEqual(vm.currentMethod.methodDefinition, m) self.assertEqual(vm.stack.get_number_of_frames(), 2)
def get_constructor_definition(self): m = MethodDefinition() m.name = 'ctor' return m