def test_fork_pid_check(): q = MPQueue() pid = os.fork() # Generate random numbers in the parent and child processes after forking. # The child sends back their numbers to the parent where we check to see # if we get collisions or not. if pid > 0: # parent rns = {_rand.rand64bits(check_pid=True) for _ in range(100)} child_rns = q.get() if PYTHON_VERSION_INFO >= (3, 7): # Python 3.7+ have fork hooks which should be used # Hence we should not get any collisions assert rns & child_rns == set() else: # Python < 3.7 we have the pid check so there also # should not be any collisions. assert rns & child_rns == set() else: # child try: rngs = {_rand.rand64bits(check_pid=True) for _ in range(100)} q.put(rngs) finally: # Kill the process so it doesn't continue running the rest of the # test suite in a separate process. Note we can't use sys.exit() # as it raises an exception that pytest will detect as an error. os._exit(0)
def test_multiprocess(): q = MPQueue() def target(q): assert sum((_ is _rand.seed for _ in forksafe._registry)) == 1 q.put([_rand.rand64bits() for _ in range(100)]) ps = [mp.Process(target=target, args=(q,)) for _ in range(30)] for p in ps: p.start() for p in ps: p.join() assert p.exitcode == 0 ids_list = [_rand.rand64bits() for _ in range(1000)] ids = set(ids_list) assert len(ids_list) == len(ids), "Collisions found in ids" while not q.empty(): child_ids_list = q.get() child_ids = set(child_ids_list) assert len(child_ids_list) == len(child_ids), "Collisions found in subprocess ids" assert ids & child_ids == set() ids = ids | child_ids # accumulate the ids
def test_random(): m = set() for i in range(0, 2 ** 16): n = _rand.rand64bits() assert 0 <= n <= 2 ** 64 - 1 assert n not in m m.add(n)
def test_fork_pid_check(): q = MPQueue() pid = os.fork() # Generate random numbers in the parent and child processes after forking. # The child sends back their numbers to the parent where we check to see # if we get collisions or not. if pid > 0: # parent rns = {_rand.rand64bits() for _ in range(100)} child_rns = q.get() assert rns & child_rns == set() else: # child try: rngs = {_rand.rand64bits() for _ in range(100)} q.put(rngs) finally: # Kill the process so it doesn't continue running the rest of the # test suite in a separate process. Note we can't use sys.exit() # as it raises an exception that pytest will detect as an error. os._exit(0)
def target(q): assert sum((_ is _rand.seed for _ in forksafe._registry)) == 1 q.put([_rand.rand64bits() for _ in range(100)])
def _target(): # Generate a bunch of numbers to try to maximize the chance that # two threads will be calling rand64bits at the same time. rngs = [_rand.rand64bits() for _ in range(200000)] q.put(rngs)
def target(q): q.put([_rand.rand64bits() for _ in range(100)])
def f(): _ = _rand.rand64bits() _ = _rand.rand64bits()