Author: Anton Gulenko <[email protected]>
Branch: storage-context-state-v2
Changeset: r956:f500ff8dea45
Date: 2014-07-25 16:33 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/f500ff8dea45/
Log: Added some Squeak image tests.
diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py
--- a/spyvm/test/test_interpreter.py
+++ b/spyvm/test/test_interpreter.py
@@ -979,7 +979,7 @@
test)
def test_frame_dirty_if_active():
- bytes = reduce(operator.add, map(chr, [0x84, 0xc0, 0x00])) +
returnReceiverBytecode
+ bytes = reduce(operator.add, map(chr, [0x84, 0xc0, 0x00]))
w_frame, s_frame = new_frame(bytes)
s_frame.store_w_receiver(w_frame)
s_frame.push(w_frame)
@@ -988,7 +988,7 @@
assert s_frame.state is shadow.DirtyContext
def test_frame_not_dirty_if_inactive():
- bytes = reduce(operator.add, map(chr, [0x84, 0xc0, 0x00])) +
returnReceiverBytecode
+ bytes = reduce(operator.add, map(chr, [0x84, 0xc0, 0x00]))
w_frame, s_frame = new_frame(bytes)
w_other_frame, s_other_frame = new_frame("")
s_frame.store_w_receiver(w_other_frame)
@@ -998,12 +998,14 @@
assert s_frame.state is shadow.ActiveContext
assert s_other_frame.state is shadow.InactiveContext
-def test_raise_SenderManipulation_on_dirty_frame():
- w_frame, s_frame = new_frame(returnReceiverBytecode)
- s_frame.state = shadow.DirtyContext
- def run_frame():
- #import pdb; pdb.set_trace()
- interp._loop = True
+def test_raise_NonVirtualReturn_on_dirty_frame():
+ bytes = reduce(operator.add, map(chr, [0x84, 0xc0, 0x00])) +
returnTopFromMethodBytecode
+ w_frame, s_frame = new_frame(bytes)
+ s_frame.store_w_receiver(w_frame)
+ s_frame.push(w_frame)
+
+ interp._loop = True
+ def do_test():
interp.stack_frame(s_frame, None)
- py.test.raises(interpreter.SenderChainManipulation, run_frame)
+ py.test.raises(interpreter.NonVirtualReturn, do_test)
\ No newline at end of file
diff --git a/spyvm/test/test_zin_squeak_4_5_image.py
b/spyvm/test/test_zin_squeak_4_5_image.py
--- a/spyvm/test/test_zin_squeak_4_5_image.py
+++ b/spyvm/test/test_zin_squeak_4_5_image.py
@@ -1,6 +1,8 @@
from spyvm import squeakimage, model, constants, interpreter, shadow, objspace
from .util import read_image, find_symbol_in_methoddict_of, copy_to_module,
cleanup_module
+import operator
+
def setup_module():
space, interp, image, reader = read_image('Squeak4.5-12568.image')
w = space.w
@@ -25,21 +27,13 @@
w_method.setliterals(literals)
return w_method
-def test_ensure():
- #ensure
- # [^'b1'] ensure: [^'b2']
- import operator
- bytes = reduce(operator.add, map(chr, [0x8F, 0, 0, 2, 0x21, 0x7c,
- 0x8F, 0, 0, 2, 0x22, 0x7c,
- 0xe0, 0x87, 0x78]))
-
- s_class = space.w_BlockClosure.as_class_get_shadow(space)
- ensure_ = find_symbol_in_methoddict_of('ensure:', s_class)
- assert ensure_ is not None, 'Using image without #ensure:-method.'
-
- w_method = create_method(bytes, [ensure_, w('b1'), w('b2'),
- w('ensure'), space.w_BlockClosure])
-
+def find_symbol(w_class, symbolname):
+ s_class = w_class.as_class_get_shadow(space)
+ symbol = find_symbol_in_methoddict_of(symbolname, s_class)
+ assert symbol is not None, 'Using image without %s method.' % symbolname
+ return symbol
+
+def execute_frame(w_method):
# create a frame for our newly crafted method with a valid sender (to
avoid raising returnFromTop to early)
s_initial_frame = create_method(chr(0x7c)).create_frame(space, w(0), [])
s_frame = w_method.create_frame(space, w(0))
@@ -48,33 +42,141 @@
try:
interp.loop(s_frame.w_self())
except interpreter.ReturnFromTopLevel, e:
- assert e.object.as_string() == 'b2'
- except interpreter.StackOverflow, e:
- assert False
+ return e.object
+
+def test_ensure():
+ #ensure
+ # [^'b1'] ensure: [^'b2']
+
+ ensure_ = find_symbol(space.w_BlockClosure, "ensure:")
+ bytes = reduce(operator.add, map(chr, [0x8F, 0, 0, 2, 0x21, 0x7c,
+ 0x8F, 0, 0, 2, 0x22, 0x7c,
+ 0xe0, 0x87, 0x78]))
+
+ w_method = create_method(bytes, [ensure_, w('b1'), w('b2'),
+ w('ensure'), space.w_BlockClosure])
+ result = execute_frame(w_method)
+ assert result.as_string() == 'b2'
def test_ensure_save_original_nlr():
#ensure
# [^'b1'] ensure: ['b2']
- import operator
+
+ ensure_ = find_symbol(space.w_BlockClosure, "ensure:")
bytes = reduce(operator.add, map(chr, [0x8F, 0, 0, 2, 0x21, 0x7c,
0x8F, 0, 0, 2, 0x22, 0x7d,
0xe0, 0x87, 0x78]))
- s_class = space.w_BlockClosure.as_class_get_shadow(space)
- ensure_ = find_symbol_in_methoddict_of('ensure:', s_class)
- assert ensure_ is not None, 'Using image without #ensure:-method.'
-
w_method = create_method(bytes, [ensure_, w('b1'), w('b2'),
w('ensure'), space.w_BlockClosure])
+ result = execute_frame(w_method)
+ assert result.as_string() == 'b1'
- # create a frame for our newly crafted method with a valid sender (to
avoid raising returnFromTop to early)
- s_initial_frame = create_method(chr(0x7c)).create_frame(space, w(0))
- s_frame = w_method.create_frame(space, w(0))
- s_frame.store_s_sender(s_initial_frame)
+def test_ContextPart_jump():
+ """
+ Code: Create a Block context that jumps back to its sender, instead of
returning normally.
+ The Block is not executed to the end, the sender chain is manipulated.
+ The local variable should be the value pushed on the sender context before
jumping to it.
+ a := 5.
+ a := [ thisContext sender push: 2. thisContext sender jump. 10 ] value.
+ ^ a
+ """
+ ContextPart =
space.w_MethodContext.as_class_get_shadow(space).s_superclass().w_self()
+ push = find_symbol(ContextPart, "push:")
+ sender = find_symbol(ContextPart, "sender")
+ jump = find_symbol(ContextPart, "jump")
- try:
- interp.loop(s_frame.w_self())
- except interpreter.ReturnFromTopLevel, e:
- assert e.object.as_string() == 'b1'
- except interpreter.StackOverflow, e:
- assert False
+ bytes = reduce(operator.add, map(chr, [0x21, 0x82, 0xc0, # Set a
+ 0x8f, 0x00, 0x00, 0x0b, # Push block
+ 0x89, 0xd3, # Send sender
+ 0x77, 0xe2, # Send push
+ 0x87, 0x89, 0xd3, 0xd4, # Send
jump
+ 0x87, 0x25, 0x7d, # Block rest
(not executed)
+ 0xc9, 0x82, 0xc0, 0x40, 0x7c])) #
Send value and return
+
+ Association = space.classtable["w_Point"] # Wrong class, doesn't matter.
+ assoc = model.W_PointersObject(space, Association, 2)
+ assoc.store(space, 0, w('a'))
+ assoc.store(space, 1, w(3))
+ w_method = create_method(bytes, [assoc, w(5), push, sender, jump, w(10)])
+ result = execute_frame(w_method)
+ assert isinstance(result, model.W_SmallInteger)
+ assert result.value == 2
+
+def test_ContextPart_jump_nonlocal():
+ """
+ Like above test, but with three blocks to make the return non-local.
+ Also, store the outer context beforehand.
+ a := 5.
+ outer := thisContext.
+ a := [[[ outer push: 2. outer jump. 10 ] value ] value] value.
+ ^ a
+ """
+ ContextPart =
space.w_MethodContext.as_class_get_shadow(space).s_superclass().w_self()
+ push = find_symbol(ContextPart, "push:")
+ jump = find_symbol(ContextPart, "jump")
+
+ bytes = reduce(operator.add, map(chr, [0x21, 0x82, 0xc0, # Set a
+ 0x89, 0x82, 0xc2, # Set outer
+ 0x8f, 0x00, 0x00, 0x15, # Push block
+ 0x8f, 0x00, 0x00, 0x0f, # Push
block
+ 0x8f, 0x00, 0x00, 0x09, #
Push block
+ 0x42, 0x77, 0xe3, #
Push 2
+ 0x87, 0x42, 0xd4, #
Send jump
+ 0x87, 0x25, 0x7d, #
Block rest (not executed)
+ 0xc9, 0x7d, # Send value
and return
+ 0xc9, 0x7d, # Send value and
return
+ 0xc9, 0x82, 0xc0, 0x40, 0x7c])) #
Send value and return
+
+ Association = space.classtable["w_Point"] # Wrong class, doesn't matter.
+ assoc = model.W_PointersObject(space, Association, 2)
+ assoc.store(space, 0, w('a'))
+ assoc.store(space, 1, space.w_nil)
+ assoc2 = model.W_PointersObject(space, Association, 2)
+ assoc2.store(space, 0, w('outer'))
+ assoc2.store(space, 1, space.w_nil)
+ w_method = create_method(bytes, [assoc, w(5), assoc2, push, jump, w(10)])
+ result = execute_frame(w_method)
+ assert isinstance(result, model.W_SmallInteger)
+ assert result.value == 2
+
+def test_contextOn_do_():
+ """
+ contextOn:do: is some very heavy meta programming. It creates and returns
a separate stack frame,
+ settings it's sender to nil, thereby manipulating the senders of two
contexts.
+ The Point in there should actually be UnhandledError or something.
+ The test here is just that this works.
+ ctx := ContextPart contextOn: Point do: ['nothing']
+ """
+ ContextPart =
space.w_MethodContext.as_class_get_shadow(space).s_superclass().w_self()
+ ContextPartClass =
ContextPart.getclass(space).as_class_get_shadow(space).w_self()
+ contextOnDo = find_symbol(ContextPartClass, "contextOn:do:")
+
+ bytes = reduce(operator.add, map(chr, [
+ 0x42, 0x43, # Push the classes
+ 0x8f, 0x00, 0x00, 0x02, # Push block,
+ 0x24, 0x7d, # in the block
+ 0xf1, 0x81, 0xc0, 0x7c # Send contextOn:do:
+ ]))
+
+ Association = space.classtable["w_Point"] # Wrong class, doesn't matter.
+ ctxAssoc = model.W_PointersObject(space, Association, 2)
+ ctxAssoc.store(space, 0, w('ctx'))
+ ctxAssoc.store(space, 1, space.w_nil)
+ contextPartAssoc = model.W_PointersObject(space, Association, 2)
+ contextPartAssoc.store(space, 0, w('ContextPart'))
+ contextPartAssoc.store(space, 1, ContextPart)
+ errorAssoc = model.W_PointersObject(space, Association, 2)
+ errorAssoc.store(space, 0, w('Point'))
+ errorAssoc.store(space, 1, Association)
+ w_method = create_method(bytes, [ctxAssoc, contextOnDo, contextPartAssoc,
errorAssoc, w('nothing')])
+
+ interp.trace = True
+
+ result = execute_frame(w_method)
+ assert isinstance(result, model.W_PointersObject)
+ s = result.as_context_get_shadow(space)
+ assert s.w_method().lookup_selector == "on:do:"
+ assert s.w_method().primitive() == 199
+ assert s.s_sender() == None
+
\ No newline at end of file
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit