|
| 1 | +importthreading |
| 2 | +fromunittestimportTestCase |
| 3 | +fromtest.supportimportthreading_helper |
| 4 | +fromrandomimportrandint |
| 5 | +fromioimportBytesIO |
| 6 | +fromsysimportgetsizeof |
| 7 | + |
| 8 | + |
| 9 | +classTestBytesIO(TestCase): |
| 10 | +# Test pretty much everything that can break under free-threading. |
| 11 | +# Non-deterministic, but at least one of these things will fail if |
| 12 | +# BytesIO object is not free-thread safe. |
| 13 | + |
| 14 | +defcheck(self,funcs,*args): |
| 15 | +barrier=threading.Barrier(len(funcs)) |
| 16 | +threads= [] |
| 17 | + |
| 18 | +forfuncinfuncs: |
| 19 | +thread=threading.Thread(target=func,args=(barrier,*args)) |
| 20 | + |
| 21 | +threads.append(thread) |
| 22 | + |
| 23 | +withthreading_helper.start_threads(threads): |
| 24 | +pass |
| 25 | + |
| 26 | +@threading_helper.requires_working_threading() |
| 27 | +@threading_helper.reap_threads |
| 28 | +deftest_free_threading(self): |
| 29 | +"""Test for segfaults and aborts.""" |
| 30 | + |
| 31 | +defwrite(barrier,b,*ignore): |
| 32 | +barrier.wait() |
| 33 | +try:b.write(b'0'*randint(100,1000)) |
| 34 | +exceptValueError:pass# ignore write fail to closed file |
| 35 | + |
| 36 | +defwritelines(barrier,b,*ignore): |
| 37 | +barrier.wait() |
| 38 | +b.write(b'0\n'*randint(100,1000)) |
| 39 | + |
| 40 | +deftruncate(barrier,b,*ignore): |
| 41 | +barrier.wait() |
| 42 | +try:b.truncate(0) |
| 43 | +except:BufferError# ignore exported buffer |
| 44 | + |
| 45 | +defread(barrier,b,*ignore): |
| 46 | +barrier.wait() |
| 47 | +b.read() |
| 48 | + |
| 49 | +defread1(barrier,b,*ignore): |
| 50 | +barrier.wait() |
| 51 | +b.read1() |
| 52 | + |
| 53 | +defreadline(barrier,b,*ignore): |
| 54 | +barrier.wait() |
| 55 | +b.readline() |
| 56 | + |
| 57 | +defreadlines(barrier,b,*ignore): |
| 58 | +barrier.wait() |
| 59 | +b.readlines() |
| 60 | + |
| 61 | +defreadinto(barrier,b,into,*ignore): |
| 62 | +barrier.wait() |
| 63 | +b.readinto(into) |
| 64 | + |
| 65 | +defclose(barrier,b,*ignore): |
| 66 | +barrier.wait() |
| 67 | +b.close() |
| 68 | + |
| 69 | +defgetvalue(barrier,b,*ignore): |
| 70 | +barrier.wait() |
| 71 | +b.getvalue() |
| 72 | + |
| 73 | +defgetbuffer(barrier,b,*ignore): |
| 74 | +barrier.wait() |
| 75 | +b.getbuffer() |
| 76 | + |
| 77 | +defiter(barrier,b,*ignore): |
| 78 | +barrier.wait() |
| 79 | +list(b) |
| 80 | + |
| 81 | +defgetstate(barrier,b,*ignore): |
| 82 | +barrier.wait() |
| 83 | +b.__getstate__() |
| 84 | + |
| 85 | +defsetstate(barrier,b,st,*ignore): |
| 86 | +barrier.wait() |
| 87 | +b.__setstate__(st) |
| 88 | + |
| 89 | +defsizeof(barrier,b,*ignore): |
| 90 | +barrier.wait() |
| 91 | +getsizeof(b) |
| 92 | + |
| 93 | +self.check([write]*10,BytesIO()) |
| 94 | +self.check([writelines]*10,BytesIO()) |
| 95 | +self.check([write]*10+ [truncate]*10,BytesIO()) |
| 96 | +self.check([truncate]+ [read]*10,BytesIO(b'0\n'*204800)) |
| 97 | +self.check([truncate]+ [read1]*10,BytesIO(b'0\n'*204800)) |
| 98 | +self.check([truncate]+ [readline]*10,BytesIO(b'0\n'*20480)) |
| 99 | +self.check([truncate]+ [readlines]*10,BytesIO(b'0\n'*20480)) |
| 100 | +self.check([truncate]+ [readinto]*10,BytesIO(b'0\n'*204800),bytearray(b'0\n'*204800)) |
| 101 | +self.check([close]+ [write]*10,BytesIO()) |
| 102 | +self.check([truncate]+ [getvalue]*10,BytesIO(b'0\n'*204800)) |
| 103 | +self.check([truncate]+ [getbuffer]*10,BytesIO(b'0\n'*204800)) |
| 104 | +self.check([truncate]+ [iter]*10,BytesIO(b'0\n'*20480)) |
| 105 | +self.check([truncate]+ [getstate]*10,BytesIO(b'0\n'*204800)) |
| 106 | +self.check([truncate]+ [setstate]*10,BytesIO(b'0\n'*204800), (b'123',0,None)) |
| 107 | +self.check([truncate]+ [sizeof]*10,BytesIO(b'0\n'*204800)) |
| 108 | + |
| 109 | +# no tests for seek or tell because they don't break anything |