Skip to content

Commit c4f577f

Browse files
committed
add test
1 parent d33514b commit c4f577f

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

Lib/test/test_struct.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import gc
55
import math
66
import operator
7+
import threading
78
import unittest
89
import platform
910
import struct
@@ -39,6 +40,24 @@ def bigendian_to_native(value):
3940
else:
4041
return string_reverse(value)
4142

43+
# Helper for test_endian_table_init_subinterpreters
44+
class _Result:
45+
def __init__(self):
46+
self.ret = -1
47+
self.err = None
48+
49+
def _run_in_subinterp_worker(code, barrier, result):
50+
"""
51+
Worker function for a thread. Waits on the barrier, then runs the
52+
code in a subinterpreter.
53+
"""
54+
try:
55+
# Wait until all threads are ready to start simultaneously.
56+
barrier.wait()
57+
result.ret = support.run_in_subinterp(code)
58+
except Exception as e:
59+
result.err = e
60+
4261
class StructTest(ComplexesAreIdenticalMixin, unittest.TestCase):
4362
def test_isbigendian(self):
4463
self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN)
@@ -800,6 +819,44 @@ def test_c_complex_round_trip(self):
800819
round_trip = struct.unpack(f, struct.pack(f, z))[0]
801820
self.assertComplexesAreIdentical(z, round_trip)
802821

822+
def test_endian_table_init_subinterpreters(self):
823+
# Verify that struct works correctly in subinterpreters after
824+
# once-only endian table initialization (gh-140260), when
825+
# initialized concurrently.
826+
# Use struct in the main interpreter first.
827+
self.assertEqual(struct.unpack('>i', struct.pack('>i', 1))[0], 1)
828+
self.assertEqual(struct.unpack('<i', struct.pack('<i', 1))[0], 1)
829+
830+
code = (
831+
"import struct\n"
832+
"x = struct.pack('>i', 1)\n"
833+
"assert struct.unpack('>i', x)[0] == 1\n"
834+
"y = struct.pack('<i', 1)\n"
835+
"assert struct.unpack('<i', y)[0] == 1\n"
836+
)
837+
838+
num_threads = 3
839+
barrier = threading.Barrier(num_threads)
840+
results = [_Result() for _ in range(num_threads)]
841+
threads = [
842+
threading.Thread(
843+
target=_run_in_subinterp_worker,
844+
args=(code, barrier, results[i])
845+
)
846+
for i in range(num_threads)
847+
]
848+
849+
for t in threads:
850+
t.start()
851+
852+
for t in threads:
853+
t.join()
854+
855+
for result in results:
856+
if result.err:
857+
raise result.err
858+
self.assertEqual(result.ret, 0)
859+
803860

804861
class UnpackIteratorTest(unittest.TestCase):
805862
"""

0 commit comments

Comments
 (0)