Skip to content

Commit ae2029f

Browse files
committed
Add test
1 parent 9168e62 commit ae2029f

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

tests/test_base.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import random
66
import sys
7+
import subprocess
78
import threading
89
import time
910
import uvloop
@@ -735,6 +736,68 @@ def scheduler():
735736
thread.join()
736737
self.assertEqual(counter[0], ITERATIONS)
737738

739+
def test_freethreading(self):
740+
if not hasattr(sys, "_is_gil_enabled"):
741+
raise unittest.SkipTest("No sys._is_gil_enabled()")
742+
if os.cpu_count() < 2:
743+
raise unittest.SkipTest("Flaky on single CPU machines")
744+
prog = """\
745+
import asyncio
746+
import os
747+
import sys
748+
import threading
749+
import time
750+
751+
752+
counter = 0
753+
754+
755+
def job(barrier):
756+
global counter
757+
barrier.wait()
758+
start_time = time.monotonic()
759+
rv = 0
760+
while time.monotonic() - start_time < 1:
761+
for _i in range(10**4):
762+
counter += 1
763+
rv += 1
764+
return rv
765+
766+
767+
async def main():
768+
if sys._is_gil_enabled():
769+
print("{impl} turned on GIL")
770+
return False
771+
loop = asyncio.get_running_loop()
772+
n_jobs = os.cpu_count()
773+
barrier = threading.Barrier(n_jobs)
774+
fs = [loop.run_in_executor(None, job, barrier) for _ in range(n_jobs)]
775+
result = sum(await asyncio.gather(*fs))
776+
if counter == result:
777+
print("Expected race condition did not happen")
778+
return False
779+
return True
780+
781+
782+
if __name__ == "__main__":
783+
if sys._is_gil_enabled():
784+
sys.exit(2) # Skip test if not running with GIL disabled
785+
786+
import {impl}
787+
788+
if not {impl}.run(main()):
789+
sys.exit(1)
790+
"""
791+
result = subprocess.run(
792+
[sys.executable, '-c', prog.format(impl=self.implementation)],
793+
stdout=subprocess.PIPE,
794+
text=True,
795+
)
796+
if result.returncode == 2:
797+
raise unittest.SkipTest(result.stdout)
798+
elif result.returncode != 0:
799+
self.fail(result.stdout)
800+
738801

739802
class TestBaseUV(_TestBase, UVTestCase):
740803

0 commit comments

Comments
 (0)