|
4 | 4 | importgc |
5 | 5 | importmath |
6 | 6 | importoperator |
| 7 | +importthreading |
7 | 8 | importunittest |
8 | 9 | importplatform |
9 | 10 | importstruct |
@@ -39,6 +40,24 @@ def bigendian_to_native(value): |
39 | 40 | else: |
40 | 41 | returnstring_reverse(value) |
41 | 42 |
|
| 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 | +exceptExceptionase: |
| 59 | +result.err=e |
| 60 | + |
42 | 61 | classStructTest(ComplexesAreIdenticalMixin,unittest.TestCase): |
43 | 62 | deftest_isbigendian(self): |
44 | 63 | self.assertEqual((struct.pack('=i',1)[0]==0),ISBIGENDIAN) |
@@ -800,6 +819,44 @@ def test_c_complex_round_trip(self): |
800 | 819 | round_trip=struct.unpack(f,struct.pack(f,z))[0] |
801 | 820 | self.assertComplexesAreIdentical(z,round_trip) |
802 | 821 |
|
| 822 | +deftest_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_inrange(num_threads)] |
| 841 | +threads= [ |
| 842 | +threading.Thread( |
| 843 | +target=_run_in_subinterp_worker, |
| 844 | +args=(code,barrier,results[i]) |
| 845 | + ) |
| 846 | +foriinrange(num_threads) |
| 847 | + ] |
| 848 | + |
| 849 | +fortinthreads: |
| 850 | +t.start() |
| 851 | + |
| 852 | +fortinthreads: |
| 853 | +t.join() |
| 854 | + |
| 855 | +forresultinresults: |
| 856 | +ifresult.err: |
| 857 | +raiseresult.err |
| 858 | +self.assertEqual(result.ret,0) |
| 859 | + |
803 | 860 |
|
804 | 861 | classUnpackIteratorTest(unittest.TestCase): |
805 | 862 | """ |
|