def test_isolation(self): local = gruvi.local.local() interleaved = [] def fiber1(): local.foo = 10 interleaved.append(1) util.sleep(0) assert local.foo == 10 local.foo = 30 interleaved.append(1) util.sleep(0) assert local.foo == 30 def fiber2(): assert not hasattr(local, 'foo') local.foo = 20 interleaved.append(2) util.sleep(0) assert local.foo == 20 local.foo = 40 interleaved.append(2) util.sleep(0) assert local.foo == 40 hub = gruvi.Hub.get() gr1 = gruvi.Fiber(fiber1) gr2 = gruvi.Fiber(fiber2) gr1.start() gr2.start() hub.switch() assert not hasattr(local, 'foo') assert interleaved == [1, 2, 1, 2]
def test_log_exception(self): hub = gruvi.Hub.get() def target(): raise ValueError gr1 = gruvi.Fiber(target) gr1.start() hub.switch()
def run_thread(): fibers = [] for i in range(self.nfibers): fiber = gruvi.Fiber(run_test) fiber.start() fibers.append(fiber) for fib in fibers: fib.join()
def test_pass_args(self): hub = gruvi.Hub.get() result = [] def target1(*args): result.extend(args) hub.switch_back()(1, 2) args = hub.switch() result.extend(args) def target2(*args): result.extend(args) hub.switch_back()(3, 4) args = hub.switch() result.extend(args) gr1 = gruvi.Fiber(target1, args=('a', 'b')) gr2 = gruvi.Fiber(target2, args=('c', 'd')) gr1.start() gr2.start() hub.switch() assert result == ['a', 'b', 'c', 'd', 1, 2, 3, 4]
def test_run_fibers(self): hub = gruvi.Hub.get() counter = [0] def worker(): counter[0] += 1 for i in range(10000): gr = gruvi.Fiber(worker) gr.start() hub.switch() assert counter[0] == 10000
def test_wait_exception(self): fut = Future() def set_result(): gruvi.sleep(0.1) fut.set_exception(RuntimeError) fib = gruvi.Fiber(set_result) fib.start() self.assertEqual(fut.exception(), RuntimeError)
def test_wait_result(self): fut = Future() def set_result(): gruvi.sleep(0.1) fut.set_result('foo') fib = gruvi.Fiber(set_result) fib.start() self.assertEqual(fut.result(), 'foo')
def test_fiber_safety(self): # Start a bunch of fibers, each locking the rlock a few times before # unlocking it again. Ensure that the locks don't overlap. lock = self.Lock() failed = [0] def run_test(): failed[0] += self.lock_unlock(lock, 20) fibers = [] for i in range(self.nfibers): fiber = gruvi.Fiber(run_test) fiber.start() fibers.append(fiber) for fib in fibers: fib.join() self.assertEqual(failed[0], 0)
def test_cleanup_on_fiber_exit(self): hub = gruvi.Hub.get() local = gruvi.local.local() def fiber1(): local.foo = 10 gr1 = gruvi.Fiber(fiber1) gr1.start() hub.switch() # Access the local object as if access was from gr1 assert 'foo' in local._keys[gr1] assert local._keys[gr1]['foo'] == 10 # Is the following enough to have PyPy/Jython/IronPython finalize # `gr1` and call its weakref callbacks? del gr1 gc.collect() gc.collect() gc.collect() assert len(local._keys) == 0
def test_switch_hub_only(self): # Ensure that only the hub may switch to or throw into a fiber. ready = [] exceptions = [] def worker(): ready.append(gruvi.current_fiber()) try: gruvi.sleep(0.1) except Exception as e: exceptions.append(e) fiber = gruvi.Fiber(worker) self.assertRaises(RuntimeError, fiber.switch) self.assertRaises(RuntimeError, fiber.throw) hub = gruvi.get_hub() hub.run_callback(fiber.switch) gruvi.sleep(0) self.assertEqual(ready, [fiber]) error = RuntimeError('foo') hub.run_callback(fiber.throw, RuntimeError, error) gruvi.sleep(0) self.assertEqual(exceptions, [error])
def mem_fiber(self): self.add_result( sizeof(gruvi.Fiber(lambda: None), exclude=('_log', '_hub', '_thread')))