summaryrefslogtreecommitdiff
path: root/Lib/test/test_threaded_import.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_threaded_import.py')
-rw-r--r--Lib/test/test_threaded_import.py58
1 files changed, 46 insertions, 12 deletions
diff --git a/Lib/test/test_threaded_import.py b/Lib/test/test_threaded_import.py
index 7791935fdf..6c2965ba6e 100644
--- a/Lib/test/test_threaded_import.py
+++ b/Lib/test/test_threaded_import.py
@@ -7,12 +7,13 @@
import os
import imp
+import importlib
import sys
import time
import shutil
import unittest
-from test.support import verbose, import_module, run_unittest, TESTFN
-thread = import_module('_thread')
+from test.support import (
+ verbose, import_module, run_unittest, TESTFN, reap_threads, forget, unlink)
threading = import_module('threading')
def task(N, done, done_tasks, errors):
@@ -30,7 +31,7 @@ def task(N, done, done_tasks, errors):
except Exception as e:
errors.append(e.with_traceback(None))
finally:
- done_tasks.append(thread.get_ident())
+ done_tasks.append(threading.get_ident())
finished = len(done_tasks) == N
if finished:
done.set()
@@ -62,16 +63,17 @@ class Finder:
def __init__(self):
self.numcalls = 0
self.x = 0
- self.lock = thread.allocate_lock()
+ self.lock = threading.Lock()
def find_module(self, name, path=None):
# Simulate some thread-unsafe behaviour. If calls to find_module()
# are properly serialized, `x` will end up the same as `numcalls`.
# Otherwise not.
+ assert imp.lock_held()
with self.lock:
self.numcalls += 1
x = self.x
- time.sleep(0.1)
+ time.sleep(0.01)
self.x = x + 1
class FlushingFinder:
@@ -113,8 +115,10 @@ class ThreadedImportTests(unittest.TestCase):
done_tasks = []
done.clear()
for i in range(N):
- thread.start_new_thread(task, (N, done, done_tasks, errors,))
- done.wait(60)
+ t = threading.Thread(target=task,
+ args=(N, done, done_tasks, errors,))
+ t.start()
+ self.assertTrue(done.wait(60))
self.assertFalse(errors)
if verbose:
print("OK.")
@@ -124,7 +128,7 @@ class ThreadedImportTests(unittest.TestCase):
def test_parallel_meta_path(self):
finder = Finder()
- sys.meta_path.append(finder)
+ sys.meta_path.insert(0, finder)
try:
self.check_parallel_module_init()
self.assertGreater(finder.numcalls, 0)
@@ -143,7 +147,7 @@ class ThreadedImportTests(unittest.TestCase):
def path_hook(path):
finder.find_module('')
raise ImportError
- sys.path_hooks.append(path_hook)
+ sys.path_hooks.insert(0, path_hook)
sys.meta_path.append(flushing_finder)
try:
# Flush the cache a first time
@@ -185,8 +189,9 @@ class ThreadedImportTests(unittest.TestCase):
contents = contents % {'delay': delay}
with open(os.path.join(TESTFN, name + ".py"), "wb") as f:
f.write(contents.encode('utf-8'))
- self.addCleanup(sys.modules.pop, name, None)
+ self.addCleanup(forget, name)
+ importlib.invalidate_caches()
results = []
def import_ab():
import A
@@ -202,9 +207,38 @@ class ThreadedImportTests(unittest.TestCase):
t2.join()
self.assertEqual(set(results), {'a', 'b'})
-
+ def test_side_effect_import(self):
+ code = """if 1:
+ import threading
+ def target():
+ import random
+ t = threading.Thread(target=target)
+ t.start()
+ t.join()"""
+ sys.path.insert(0, os.curdir)
+ self.addCleanup(sys.path.remove, os.curdir)
+ filename = TESTFN + ".py"
+ with open(filename, "wb") as f:
+ f.write(code.encode('utf-8'))
+ self.addCleanup(unlink, filename)
+ self.addCleanup(forget, TESTFN)
+ importlib.invalidate_caches()
+ __import__(TESTFN)
+
+
+@reap_threads
def test_main():
- run_unittest(ThreadedImportTests)
+ old_switchinterval = None
+ try:
+ old_switchinterval = sys.getswitchinterval()
+ sys.setswitchinterval(1e-5)
+ except AttributeError:
+ pass
+ try:
+ run_unittest(ThreadedImportTests)
+ finally:
+ if old_switchinterval is not None:
+ sys.setswitchinterval(old_switchinterval)
if __name__ == "__main__":
test_main()