| import gc |
| import threading |
| import unittest |
| from doctest import DocTestSuite |
| from test import test_support |
| |
| class ThreadingLocalTest(unittest.TestCase): |
| def test_derived(self): |
| # Issue 3088: if there is a threads switch inside the __init__ |
| # of a threading.local derived class, the per-thread dictionary |
| # is created but not correctly set on the object. |
| # The first member set may be bogus. |
| import time |
| class Local(threading.local): |
| def __init__(self): |
| time.sleep(0.01) |
| local = Local() |
| |
| def f(i): |
| local.x = i |
| # Simply check that the variable is correctly set |
| self.assertEqual(local.x, i) |
| |
| threads= [] |
| for i in range(10): |
| t = threading.Thread(target=f, args=(i,)) |
| t.start() |
| threads.append(t) |
| |
| for t in threads: |
| t.join() |
| |
| def test_derived_cycle_dealloc(self): |
| # http://bugs.python.org/issue6990 |
| class Local(threading.local): |
| pass |
| locals = None |
| passed = [False] |
| e1 = threading.Event() |
| e2 = threading.Event() |
| |
| def f(): |
| # 1) Involve Local in a cycle |
| cycle = [Local()] |
| cycle.append(cycle) |
| cycle[0].foo = 'bar' |
| |
| # 2) GC the cycle (triggers threadmodule.c::local_clear |
| # before local_dealloc) |
| del cycle |
| gc.collect() |
| e1.set() |
| e2.wait() |
| |
| # 4) New Locals should be empty |
| passed[0] = all(not hasattr(local, 'foo') for local in locals) |
| |
| t = threading.Thread(target=f) |
| t.start() |
| e1.wait() |
| |
| # 3) New Locals should recycle the original's address. Creating |
| # them in the thread overwrites the thread state and avoids the |
| # bug |
| locals = [Local() for i in range(10)] |
| e2.set() |
| t.join() |
| |
| self.assertTrue(passed[0]) |
| |
| |
| def test_main(): |
| suite = DocTestSuite('_threading_local') |
| |
| try: |
| from thread import _local |
| except ImportError: |
| pass |
| else: |
| import _threading_local |
| local_orig = _threading_local.local |
| def setUp(test): |
| _threading_local.local = _local |
| def tearDown(test): |
| _threading_local.local = local_orig |
| suite.addTest(DocTestSuite('_threading_local', |
| setUp=setUp, tearDown=tearDown) |
| ) |
| suite.addTest(unittest.makeSuite(ThreadingLocalTest)) |
| |
| test_support.run_suite(suite) |
| |
| if __name__ == '__main__': |
| test_main() |