Skip to content

Commit 3555a21

Browse files
author
Anselm Kruis
committed
Issue python#117: test suite: fix test cases with runAll.py option -R:
This commit fixes problems in the Stackless test suite at Python level. It does not fix failures caused by reference leaks. - Fix failures, which occurred during a second or further run of the test. - Mark test-cases, which inevitably leak references. These tests leave a C-stack without thread. No chance to clean the references. https://bitbucket.org/stackless-dev/stackless/issues/117 (grafted from 7ae818842aa4783eb33be6a6085535ba18db97bc)
1 parent 5ea55fe commit 3555a21

5 files changed

Lines changed: 32 additions & 12 deletions

File tree

Stackless/unittests/test_miscell.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
withThreads = False
2121

2222
from support import test_main # @UnusedImport
23-
from support import StacklessTestCase, AsTaskletTestCase, require_one_thread
23+
from support import StacklessTestCase, AsTaskletTestCase, require_one_thread, testcase_leaks_references
2424

2525

2626
def is_soft():
@@ -613,18 +613,22 @@ def other_thread_main():
613613
tlet.kill()
614614

615615
@unittest.skipUnless(withThreads, "requires thread support")
616+
@testcase_leaks_references("chatches TaskletExit and does not die in its own thread", soft_switching=False)
616617
def test_kill_without_thread_state_nl0(self):
617618
return self._test_kill_without_thread_state(0, False)
618619

619620
@unittest.skipUnless(withThreads, "requires thread support")
621+
@testcase_leaks_references("chatches TaskletExit and does not die in its own thread")
620622
def test_kill_without_thread_state_nl1(self):
621623
return self._test_kill_without_thread_state(1, False)
622624

623625
@unittest.skipUnless(withThreads, "requires thread support")
626+
@testcase_leaks_references("chatches TaskletExit and does not die in its own thread", soft_switching=False)
624627
def test_kill_without_thread_state_blocked_nl0(self):
625628
return self._test_kill_without_thread_state(0, True)
626629

627630
@unittest.skipUnless(withThreads, "requires thread support")
631+
@testcase_leaks_references("chatches TaskletExit and does not die in its own thread")
628632
def test_kill_without_thread_state_blocked_nl1(self):
629633
return self._test_kill_without_thread_state(1, True)
630634

@@ -1098,6 +1102,7 @@ def test():
10981102
self.assertEqual(self.recursion_depth_in_test, 1)
10991103

11001104
@unittest.skipUnless(withThreads, "requires thread support")
1105+
@testcase_leaks_references("Tasklet chatches TaskletExit and refuses to die in its thread")
11011106
def test_unbind_fail_cstate_no_thread(self):
11021107
# https://bitbucket.org/stackless-dev/stackless/issues/92
11031108
loop = True
@@ -1257,6 +1262,10 @@ def test_nesting_level(self):
12571262
self.assertIsInstance(l1, int)
12581263

12591264
def test_chain(self):
1265+
# create at least one additional C-stack
1266+
t = stackless.tasklet(apply_not_stackless)(stackless.main.switch,)
1267+
t.run()
1268+
self.addCleanup(t.run)
12601269
start = stackless.main.cstate
12611270
c = start.next
12621271
self.assertIsNot(c, start)

Stackless/unittests/test_pickle.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,13 @@ def b():
567567
def c():
568568
return b()
569569

570-
try:
571-
c()
572-
except ZeroDivisionError:
573-
tb = sys.exc_info()[2]
570+
def d():
571+
try:
572+
c()
573+
except ZeroDivisionError:
574+
return sys.exc_info()[2]
574575

576+
tb = d() # this way tb dosn't reference the current frame
575577
innerframes_orig = inspect.getinnerframes(tb)
576578
p = self.dumps(tb)
577579
tb2 = self.loads(p)

Stackless/unittests/test_thread.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from stackless import _test_nostacklesscall as apply_not_stackless
99

1010
from support import test_main # @UnusedImport
11-
from support import StacklessTestCase, AsTaskletTestCase
11+
from support import StacklessTestCase, AsTaskletTestCase, testcase_leaks_references
1212
try:
1313
import threading
1414
try:
@@ -18,6 +18,7 @@
1818
withThreads = True
1919
except:
2020
withThreads = False
21+
2122
class threading(object):
2223
Thread = object
2324

@@ -400,6 +401,7 @@ def test_rebind_from_dead(self):
400401
t.bind_thread()
401402
self.assertEqual(t.thread_id, stackless.getcurrent().thread_id)
402403

404+
@testcase_leaks_references("test catches TaskletExit and refuses to die in its own thread")
403405
def test_rebind_from_dead_fail_cstate(self):
404406
# A test for https://bitbucket.org/stackless-dev/stackless/issues/92
405407
loop = True

Stackless/unittests/test_tpflags_have_stackless_call.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,14 +252,18 @@ def func(obj=None):
252252
obj.nesting_level = stackless.current.nesting_level
253253
return None
254254

255+
cls(func).__class__ # the first access of __class__ releases 1 ref to None
255256
with stackless.atomic():
256-
# None-refcount it needs protection, it the test suite is multithreaded
257+
# None-refcount needs protection, it the test suite is multithreaded
257258
gc.collect()
258-
rc_none = sys.getrefcount(None)
259-
rc_cls = sys.getrefcount(cls)
259+
rc_none = rc_none2 = sys.getrefcount(None)
260+
rc_cls = rc_cls2 = sys.getrefcount(cls)
260261
c = cls(func)
261-
self.assertEqual(sys.getrefcount(None), rc_none)
262-
self.assertEqual(sys.getrefcount(c) - sys.getrefcount(object()), 1)
262+
rc_none2 = sys.getrefcount(None)
263+
rc_cls2 = sys.getrefcount(cls)
264+
self.assertEqual(rc_none, rc_none2)
265+
self.assertEqual(rc_cls + 1, rc_cls2) # one ref for c
266+
self.assertEqual(sys.getrefcount(c) - sys.getrefcount(object()), 1)
263267
self.assertIs(c.__class__, cls)
264268
current_nesting_level = stackless.current.nesting_level
265269
if hasattr(c, "nesting_level"):
@@ -328,6 +332,7 @@ def helper():
328332
return emsg
329333
self.fail("does not raise the expected exception")
330334

335+
helper() # warm up.
331336
gc.collect()
332337
with stackless.atomic():
333338
rc_none = sys.getrefcount(None)
@@ -367,6 +372,7 @@ def helper():
367372
self.fail("does not raise the expected exception")
368373

369374
emsg = ''
375+
helper() # warm up
370376
gc.collect()
371377
with stackless.atomic():
372378
rc_none = sys.getrefcount(None)

Stackless/unittests/test_watchdog.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,8 @@ def runner_func():
521521

522522
def _test_watchdog_on_tasklet(self, soft):
523523
def runner_func():
524-
stackless.run(2, soft=soft, totaltimeout=True, ignore_nesting=True)
524+
# run the watchdog long enough to start t1 and t2
525+
stackless.run(150, soft=soft, totaltimeout=True, ignore_nesting=True)
525526
if stackless.getruncount():
526527
self.done += 1 # we were interrupted
527528
t1.kill()

0 commit comments

Comments
 (0)