import sys import threading import unittest from itertools import cycle from threading import Barrier, Event, Thread from unittest import TestCase from test.support import threading_helper @threading_helper.requires_working_threading() class TestStr(TestCase): def test_racing_join_extend(self): '''Test joining a string being extended by another thread''' l = [] ITERS = 100 READERS = 10 done_event = Event() def writer_func(): for i in range(ITERS): l.extend(map(str, range(i))) l.clear() done_event.set() def reader_func(): while not done_event.is_set(): ''.join(l) writer = Thread(target=writer_func) readers = [] for x in range(READERS): reader = Thread(target=reader_func) readers.append(reader) reader.start() writer.start() writer.join() for reader in readers: reader.join() def test_racing_join_replace(self): ''' Test joining a string of characters being replaced with ephemeral strings by another thread. ''' l = [*'abcdefg'] MAX_ORDINAL = 1_000 READERS = 10 done_event = Event() def writer_func(): for i, c in zip(cycle(range(len(l))), map(chr, range(128, MAX_ORDINAL))): l[i] = c done_event.set() def reader_func(): while not done_event.is_set(): ''.join(l) ''.join(l) ''.join(l) ''.join(l) writer = Thread(target=writer_func) readers = [] for x in range(READERS): reader = Thread(target=reader_func) readers.append(reader) reader.start() writer.start() writer.join() for reader in readers: reader.join() def test_intern_unowned_string(self): # Test interning strings owned by various threads. strings = [f"intern_race_owner_{i}" for i in range(50)] NUM_THREADS = 5 b = Barrier(NUM_THREADS) def interner(): tid = threading.get_ident() for i in range(20): strings.append(f"intern_{tid}_{i}") b.wait() for s in strings: r = sys.intern(s) self.assertTrue(sys._is_interned(r)) threading_helper.run_concurrently(interner, nthreads=NUM_THREADS) def test_maketrans_dict_concurrent_modification(self): for _ in range(5): d = {2000: 'a'} def work(dct): for i in range(100): str.maketrans(dct) dct[2000 + i] = chr(i % 16) dct.pop(2000 + i, None) threading_helper.run_concurrently( work, nthreads=5, args=(d,), ) if __name__ == "__main__": unittest.main()