[pypy-svn] r20965 - pypy/dist/pypy/translator/js/test
rxe at codespeak.net
rxe at codespeak.net
Fri Dec 9 19:30:10 CET 2005
Author: rxe
Date: Fri Dec 9 19:30:09 2005
New Revision: 20965
Added:
pypy/dist/pypy/translator/js/test/test_tasklets.py (contents, props changed)
Log:
Add bunch of failing tests from genc.
Added: pypy/dist/pypy/translator/js/test/test_tasklets.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js/test/test_tasklets.py Fri Dec 9 19:30:09 2005
@@ -0,0 +1,430 @@
+import os
+
+from pypy.rpython.memory.lladdress import NULL
+from pypy.rpython.rstack import yield_current_frame_to_caller
+
+
+# ____________________________________________________________
+
+def wrap_stackless_function(fn):
+ from pypy.translator.js.test.runtest import compile_function
+ jsfn = compile_function(fn, [], stackless=True)
+ return str(jsfn()) + "\n"
+# ____________________________________________________________
+# For testing
+debug_flag = True
+
+# count of loops in tests (set lower to speed up)
+loops = 10
+
+def debug(s):
+ if debug_flag:
+ os.write(2, "%s\n" % s)
+
+class Globals:
+ def __init__(self):
+ pass
+
+globals = Globals()
+globals.count = 0
+
+
+# ____________________________________________________________
+
+class Resumable(object):
+ def __init__(self, fn):
+ self.fn = fn
+ self.alive = False
+
+ def start(self):
+ self.caller = yield_current_frame_to_caller()
+ self.fn(self.name)
+ return self.caller
+
+ def set_resumable(self, resumable):
+ self.resumable = resumable
+
+ def suspend(self):
+ # we suspend ourself
+ self.caller = self.caller.switch()
+
+ def resume(self):
+ # the caller resumes me
+ self.resumable = self.resumable.switch()
+ self.alive = self.resumable is not None
+
+class Tasklet(Resumable):
+ def __init__(self, name, fn):
+ Resumable.__init__(self, fn)
+ self.name = name
+ self.blocked = 0
+
+ # propogates round suspend-resume to tell scheduler in run()
+ # XXX too late to think this thru
+ self.remove = False
+
+ def suspend_and_remove(self, remove):
+ self.remove = remove
+ self.suspend()
+
+ def resume(self):
+ assert not self.remove
+ Resumable.resume(self)
+
+ # not sure what to do with alive yetXXX
+
+ #XXX arggh - why NOT??
+ #if not alive:
+ # self.caller = # None / NULL
+ return self.alive and not self.remove
+
+class Channel:
+ def __init__(self):
+ self.queue = []
+ self.balance = 0
+
+ def send(self, value):
+ self.balance += 1
+ if self.balance <= 0:
+ t = self.queue.pop(0)
+ t.data = value
+ t.blocked = 0
+ t.remove = False
+ scheduler.run_immediately(t)
+ scheduler.schedule()
+
+ # resuming
+ t = getcurrent()
+ assert t.blocked == 0
+
+ else:
+ t = getcurrent()
+ assert isinstance(t, Tasklet)
+ t.data = value
+ # let it wait for a receiver to come along
+ self.queue.append(t)
+ t.blocked = 1
+ schedule_remove()
+
+ # resuming
+ assert t == getcurrent()
+ assert t.blocked == 0
+
+ def receive(self):
+ self.balance -= 1
+ # good to go
+ if self.balance >= 0:
+ t = self.queue.pop(0)
+ t.blocked = 0
+ t.remove = False
+ data = t.data
+ scheduler.add_tasklet(t)
+ return data
+ else:
+ # queue ourself
+ t = getcurrent()
+ assert isinstance(t, Tasklet)
+ self.queue.append(t)
+
+ # block until send has reenabled me
+ t.blocked = -1
+ schedule_remove()
+
+ # resuming
+ assert t == getcurrent()
+ assert t.blocked == 0
+
+ return t.data
+
+class Scheduler(object):
+ def __init__(self):
+ self.runnables = []
+ self.current_tasklet = None
+ self.immediately_schedule = None
+
+ def add_tasklet(self, tasklet):
+ self.runnables.append(tasklet)
+
+ def run_immediately(self, tasklet):
+ self.immediately_schedule = tasklet
+
+ def run(self):
+ while self.runnables:
+ runnables = self.runnables
+ self.runnables = []
+ count = 0
+ for t in runnables:
+ assert self.current_tasklet is None
+
+ self.current_tasklet = t
+ if t.resume():
+ self.runnables.append(self.current_tasklet)
+ self.current_tasklet = None
+ count += 1
+
+ if self.immediately_schedule:
+ self.runnables = [self.immediately_schedule] \
+ + runnables[count:] + self.runnables
+ self.immediately_schedule = None
+ break
+
+ def schedule(self, remove=False):
+ assert self.current_tasklet is not None
+ self.current_tasklet.suspend_and_remove(remove)
+
+# ____________________________________________________________
+
+scheduler = Scheduler()
+def start_tasklet(tasklet):
+ res = tasklet.start()
+ tasklet.set_resumable(res)
+ scheduler.add_tasklet(tasklet)
+
+def start_tasklet_now(tasklet):
+ res = tasklet.start()
+ tasklet.set_resumable(res)
+ scheduler.run_immediately(tasklet)
+
+def schedule():
+ scheduler.schedule()
+
+def schedule_remove():
+ scheduler.schedule(remove=True)
+
+def run():
+ scheduler.run()
+
+def getcurrent():
+ return scheduler.current_tasklet
+
+# ____________________________________________________________
+
+def test_simple():
+
+ def simple(name):
+ for ii in range(5):
+ globals.count += 1
+ schedule()
+
+ def f():
+ for ii in range(loops):
+ start_tasklet(Tasklet("T%s" % ii, simple))
+ run()
+ return globals.count == loops * 5
+
+ res = wrap_stackless_function(f)
+ assert res == '1'
+
+def test_multiple_simple():
+
+ def simple(name):
+ for ii in range(5):
+ globals.count += 1
+ schedule()
+
+ def simple2(name):
+ for ii in range(5):
+ globals.count += 1
+ schedule()
+ globals.count += 1
+
+ def simple3(name):
+ schedule()
+ for ii in range(10):
+ globals.count += 1
+ if ii % 2:
+ schedule()
+ schedule()
+
+ def f():
+ for ii in range(loops):
+ start_tasklet(Tasklet("T1%s" % ii, simple))
+ start_tasklet(Tasklet("T2%s" % ii, simple2))
+ start_tasklet(Tasklet("T3%s" % ii, simple3))
+ run()
+ return globals.count == loops * 25
+
+ res = wrap_stackless_function(f)
+ assert res == '1'
+
+def test_schedule_remove():
+
+ def simple(name):
+ for ii in range(20):
+ if ii < 10:
+ schedule()
+ else:
+ schedule_remove()
+ globals.count += 1
+
+ def f():
+ for ii in range(loops):
+ start_tasklet(Tasklet("T%s" % ii, simple))
+ run()
+ for ii in range(loops):
+ start_tasklet(Tasklet("T%s" % ii, simple))
+ run()
+ return globals.count == loops * 10 * 2
+
+ res = wrap_stackless_function(f)
+ assert res == '1'
+
+def test_run_immediately():
+ globals.intermediate = 0
+ globals.count = 0
+ def simple(name):
+ for ii in range(20):
+ globals.count += 1
+ schedule()
+
+ def run_immediately(name):
+ globals.intermediate = globals.count
+ schedule()
+
+ def simple2(name):
+ for ii in range(20):
+ globals.count += 1
+ if ii == 10:
+ start_tasklet_now(Tasklet("intermediate", run_immediately))
+ schedule()
+
+ def f():
+ start_tasklet(Tasklet("simple2", simple2))
+ for ii in range(loops):
+ start_tasklet(Tasklet("T%s" % ii, simple))
+ run()
+ total_expected = (loops + 1) * 20
+ return (globals.intermediate == total_expected / 2 + 1 and
+ globals.count == total_expected)
+
+ res = wrap_stackless_function(f)
+ assert res == '1'
+
+def test_channel1():
+ ch = Channel()
+
+ def f1(name):
+ for ii in range(5):
+ ch.send(ii)
+
+ def f2(name):
+ #while True:
+ for ii in range(6):
+ globals.count += ch.receive()
+
+ def f():
+ start_tasklet(Tasklet("f2", f2))
+ start_tasklet(Tasklet("f1", f1))
+ run()
+ return (globals.count == 10)
+
+ res = wrap_stackless_function(f)
+ assert res == '1'
+
+def test_channel2():
+ ch = Channel()
+
+ def f1(name):
+ for ii in range(5):
+ ch.send(ii)
+
+ def f2(name):
+ #while True:
+ for ii in range(6):
+ res = ch.receive()
+ globals.count += res
+
+ def f():
+ start_tasklet(Tasklet("f1", f1))
+ start_tasklet(Tasklet("f2", f2))
+ run()
+ return (globals.count == 10)
+
+ res = wrap_stackless_function(f)
+ assert res == '1'
+
+
+def test_channel3():
+ ch = Channel()
+
+ def f1(name):
+ for ii in range(5):
+ ch.send(ii)
+
+ def f2(name):
+ #while True:
+ for ii in range(16):
+ res = ch.receive()
+ globals.count += res
+
+ def f():
+ start_tasklet(Tasklet("f1x", f1))
+ start_tasklet(Tasklet("f1xx", f1))
+ start_tasklet(Tasklet("f1xxx", f1))
+ start_tasklet(Tasklet("f2", f2))
+ run()
+ return (globals.count == 30)
+
+ res = wrap_stackless_function(f)
+ assert res == '1'
+
+
+def test_channel4():
+ """ test with something other than int """
+
+ class A:
+ pass
+
+ class Data(object):
+ pass
+
+ class IntData(Data):
+ def __init__(self, d):
+ self.d = d
+
+ class StringData(Data):
+ def __init__(self, d):
+ self.d = d
+
+ class InstanceAData(Data):
+ def __init__(self, d):
+ self.d = d
+
+ ch1 = Channel()
+ ch2 = Channel()
+ ch3 = Channel()
+
+ def f1(name):
+ for ii in range(5):
+ ch1.send(IntData(ii))
+
+ def f2(name):
+ for ii in range(5):
+ ch2.send(StringData("asda"))
+
+ def f3(name):
+ for ii in range(5):
+ ch3.send(StringData("asda"))
+
+ def fr(name):
+ #while True:
+ for ii in range(11):
+ data3 = ch3.receive()
+ globals.count += 1
+ data1 = ch1.receive()
+ globals.count += 1
+ data2 = ch2.receive()
+ globals.count += 1
+
+ def f():
+ start_tasklet(Tasklet("fr", fr))
+ start_tasklet(Tasklet("f1", f1))
+ start_tasklet(Tasklet("f2", f2))
+ start_tasklet(Tasklet("f3", f3))
+ run()
+ debug("asd %s" % globals.count)
+ return (globals.count == 15)
+
+ res = wrap_stackless_function(f)
+ assert res == '1'
+
More information about the Pypy-commit
mailing list