示例#1
0
    async def test_blocking_tasks_while_draining(self):
        rewait = 2
        barrier = asyncio.Barrier(self.N)
        barrier_nowaiting = asyncio.Barrier(self.N - rewait)
        results = []
        rewait_n = rewait
        counter = 0

        async def coro():
            nonlocal rewait_n

            # first time waiting
            await barrier.wait()

            # after wainting once for all tasks
            if rewait_n > 0:
                rewait_n -= 1
                # wait again only for rewait tasks
                await barrier.wait()
            else:
                # wait for end of draining state`
                await barrier_nowaiting.wait()
                # wait for other waiting tasks
                await barrier.wait()

        # a success means that barrier_nowaiting
        # was waited for exactly N-rewait=3 times
        await self.gather_tasks(self.N, coro)
示例#2
0
    async def test_reset_barrier_while_tasks_waiting(self):
        barrier = asyncio.Barrier(self.N)
        results = []

        async def coro():
            try:
                await barrier.wait()
            except asyncio.BrokenBarrierError:
                results.append(True)

        async def coro_reset():
            await barrier.reset()

        # N-1 tasks waiting on barrier with N parties
        tasks  = self.make_tasks(self.N-1, coro)
        await asyncio.sleep(0)

        # reset the barrier
        asyncio.create_task(coro_reset())
        await asyncio.gather(*tasks)

        self.assertEqual(len(results), self.N-1)
        self.assertTrue(all(results))
        self.assertEqual(barrier.n_waiting, 0)
        self.assertNotIn("resetting", repr(barrier))
        self.assertFalse(barrier.broken)
示例#3
0
    async def test_abort_barrier_when_tasks_half_draining_half_blocking(self):
        barrier = asyncio.Barrier(self.N)
        results1 = []
        results2 = []
        blocking_tasks = self.N//2
        count = 0

        async def coro():
            nonlocal count
            try:
                await barrier.wait()
            except asyncio.BrokenBarrierError:
                # here catch tasks waiting to drain
                results1.append(True)
            else:
                count += 1
                if count > blocking_tasks:
                    # abort now: raise asyncio.BrokenBarrierError for all tasks
                    await barrier.abort()
                else:
                    try:
                        await barrier.wait()
                    except asyncio.BrokenBarrierError:
                        # here catch blocked tasks (already drained)
                        results2.append(True)

        await self.gather_tasks(self.N, coro)

        self.assertTrue(barrier.broken)
        self.assertEqual(results1, [True]*blocking_tasks)
        self.assertEqual(results2, [True]*(self.N-blocking_tasks-1))
        self.assertEqual(barrier.n_waiting, 0)
        self.assertNotIn("resetting", repr(barrier))
示例#4
0
    async def test_abort_barrier_when_exception(self):
        # test from threading.Barrier: see `lock_tests.test_reset`
        barrier = asyncio.Barrier(self.N)
        results1 = []
        results2 = []

        async def coro():
            try:
                async with barrier as i :
                    if i == self.N//2:
                        raise RuntimeError
                async with barrier:
                    results1.append(True)
            except asyncio.BrokenBarrierError:
                results2.append(True)
            except RuntimeError:
                await barrier.abort()

        await self.gather_tasks(self.N, coro)

        self.assertTrue(barrier.broken)
        self.assertEqual(len(results1), 0)
        self.assertEqual(len(results2), self.N-1)
        self.assertTrue(all(results2))
        self.assertEqual(barrier.n_waiting, 0)
示例#5
0
    async def test_abort_barrier(self):
        barrier = asyncio.Barrier(1)

        asyncio.create_task(barrier.abort())
        await asyncio.sleep(0)

        self.assertEqual(barrier.n_waiting, 0)
        self.assertTrue(barrier.broken)
示例#6
0
    async def test_reset_barrier(self):
        barrier = asyncio.Barrier(1)

        asyncio.create_task(barrier.reset())
        await asyncio.sleep(0)

        self.assertEqual(barrier.n_waiting, 0)
        self.assertFalse(barrier.broken)
示例#7
0
    async def test_barrier(self):
        barrier = asyncio.Barrier(self.N)
        self.assertIn("filling", repr(barrier))
        with self.assertRaisesRegex(
            TypeError,
            "object Barrier can't be used in 'await' expression",
        ):
            await barrier

        self.assertIn("filling", repr(barrier))
示例#8
0
    async def test_filling_one_task(self):
        barrier = asyncio.Barrier(1)

        async def f():
            async with barrier as i:
                return True

        ret = await f()

        self.assertTrue(ret)
        self.assertEqual(barrier.n_waiting, 0)
        self.assertFalse(barrier.broken)
示例#9
0
    async def test_abort_barrier_when_exception_then_resetting(self):
        # test from threading.Barrier: see `lock_tests.test_abort_and_reset``
        barrier1 = asyncio.Barrier(self.N)
        barrier2 = asyncio.Barrier(self.N)
        results1 = []
        results2 = []
        results3 = []

        async def coro():
            try:
                i = await barrier1.wait()
                if i == self.N//2:
                    raise RuntimeError
                await barrier1.wait()
                results1.append(True)
            except asyncio.BrokenBarrierError:
                results2.append(True)
            except RuntimeError:
                await barrier1.abort()

            # Synchronize and reset the barrier.  Must synchronize first so
            # that everyone has left it when we reset, and after so that no
            # one enters it before the reset.
            i = await barrier2.wait()
            if  i == self.N//2:
                await barrier1.reset()
            await barrier2.wait()
            await barrier1.wait()
            results3.append(True)

        await self.gather_tasks(self.N, coro)

        self.assertFalse(barrier1.broken)
        self.assertEqual(len(results1), 0)
        self.assertEqual(len(results2), self.N-1)
        self.assertTrue(all(results2))
        self.assertEqual(len(results3), self.N)
        self.assertTrue(all(results3))

        self.assertEqual(barrier1.n_waiting, 0)
示例#10
0
    async def test_repr(self):
        barrier = asyncio.Barrier(self.N)

        self.assertTrue(RGX_REPR.match(repr(barrier)))
        self.assertIn("filling", repr(barrier))

        waiters = []

        async def wait(barrier):
            await barrier.wait()

        incr = 2
        for i in range(incr):
            waiters.append(asyncio.create_task(wait(barrier)))
        await asyncio.sleep(0)

        self.assertTrue(RGX_REPR.match(repr(barrier)))
        self.assertTrue(f"waiters:{incr}/{self.N}" in repr(barrier))
        self.assertIn("filling", repr(barrier))

        # create missing waiters
        for i in range(barrier.parties - barrier.n_waiting):
            waiters.append(asyncio.create_task(wait(barrier)))
        await asyncio.sleep(0)

        self.assertTrue(RGX_REPR.match(repr(barrier)))
        self.assertIn("draining", repr(barrier))

        # add a part of waiters
        for i in range(incr):
            waiters.append(asyncio.create_task(wait(barrier)))
        await asyncio.sleep(0)
        # and reset
        await barrier.reset()

        self.assertTrue(RGX_REPR.match(repr(barrier)))
        self.assertIn("resetting", repr(barrier))

        # add a part of waiters again
        for i in range(incr):
            waiters.append(asyncio.create_task(wait(barrier)))
        await asyncio.sleep(0)
        # and abort
        await barrier.abort()

        self.assertTrue(RGX_REPR.match(repr(barrier)))
        self.assertIn("broken", repr(barrier))
        self.assertTrue(barrier.broken)

        # suppress unhandled exceptions
        await asyncio.gather(*waiters, return_exceptions=True)
示例#11
0
    async def test_context_manager(self):
        self.N = 3
        barrier = asyncio.Barrier(self.N)
        results = []

        async def coro():
            async with barrier as i:
                results.append(i)

        await self.gather_tasks(self.N, coro)

        self.assertListEqual(sorted(results), list(range(self.N)))
        self.assertEqual(barrier.n_waiting, 0)
        self.assertFalse(barrier.broken)
示例#12
0
    async def test_filling_one_task_twice(self):
        barrier = asyncio.Barrier(1)

        t1 = asyncio.create_task(barrier.wait())
        await asyncio.sleep(0)
        self.assertEqual(barrier.n_waiting, 0)

        t2 = asyncio.create_task(barrier.wait())
        await asyncio.sleep(0)

        self.assertEqual(t1.result(), t2.result())
        self.assertEqual(t1.done(), t2.done())

        self.assertEqual(barrier.n_waiting, 0)
        self.assertFalse(barrier.broken)
示例#13
0
    async def test_draining_state(self):
        barrier = asyncio.Barrier(self.N)
        results = []

        async def coro():
            async with barrier:
                # barrier state change to filling for the last task release
                results.append("draining" in repr(barrier))

        await self.gather_tasks(self.N, coro)

        self.assertEqual(len(results), self.N)
        self.assertEqual(results[-1], False)
        self.assertTrue(all(results[:self.N-1]))

        self.assertEqual(barrier.n_waiting, 0)
        self.assertFalse(barrier.broken)
示例#14
0
    async def test_reset_barrier_while_tasks_draining(self):
        barrier = asyncio.Barrier(self.N)
        results1 = []
        results2 = []
        results3 = []
        count = 0

        async def coro():
            nonlocal count

            i = await barrier.wait()
            count += 1
            if count == self.N:
                # last task exited from barrier
                await barrier.reset()

                # wait here to reach the `parties`
                await barrier.wait()
            else:
                try:
                    # second waiting
                    await barrier.wait()

                    # N-1 tasks here
                    results1.append(True)
                except Exception as e:
                    # never goes here
                    results2.append(True)

            # Now, pass the barrier again
            # last wait, must be completed
            k = await barrier.wait()
            results3.append(True)

        await self.gather_tasks(self.N, coro)

        self.assertFalse(barrier.broken)
        self.assertTrue(all(results1))
        self.assertEqual(len(results1), self.N-1)
        self.assertEqual(len(results2), 0)
        self.assertEqual(len(results3), self.N)
        self.assertTrue(all(results3))

        self.assertEqual(barrier.n_waiting, 0)
示例#15
0
    async def test_filling_tasks_wait_twice(self):
        barrier = asyncio.Barrier(self.N)
        results = []

        async def coro():
            async with barrier:
                results.append(True)

                async with barrier:
                    results.append(False)

        await self.gather_tasks(self.N, coro)

        self.assertEqual(len(results), self.N*2)
        self.assertEqual(results.count(True), self.N)
        self.assertEqual(results.count(False), self.N)

        self.assertEqual(barrier.n_waiting, 0)
        self.assertFalse(barrier.broken)
示例#16
0
    async def test_filling_task_by_task(self):
        self.N = 3
        barrier = asyncio.Barrier(self.N)

        t1 = asyncio.create_task(barrier.wait())
        await asyncio.sleep(0)
        self.assertEqual(barrier.n_waiting, 1)
        self.assertIn("filling", repr(barrier))

        t2 = asyncio.create_task(barrier.wait())
        await asyncio.sleep(0)
        self.assertEqual(barrier.n_waiting, 2)
        self.assertIn("filling", repr(barrier))

        t3 = asyncio.create_task(barrier.wait())
        await asyncio.sleep(0)

        await asyncio.wait([t1, t2, t3])

        self.assertEqual(barrier.n_waiting, 0)
        self.assertFalse(barrier.broken)
示例#17
0
    async def test_reset_barrier_when_tasks_half_draining_half_blocking(self):
        barrier = asyncio.Barrier(self.N)
        results1 = []
        results2 = []
        blocking_tasks = self.N//2
        count = 0

        async def coro():
            nonlocal count
            try:
                await barrier.wait()
            except asyncio.BrokenBarrierError:
                # here catch still waiting tasks
                results1.append(True)

                # so now waiting again to reach nb_parties
                await barrier.wait()
            else:
                count += 1
                if count > blocking_tasks:
                    # reset now: raise asyncio.BrokenBarrierError for waiting tasks
                    await barrier.reset()

                    # so now waiting again to reach nb_parties
                    await barrier.wait()
                else:
                    try:
                        await barrier.wait()
                    except asyncio.BrokenBarrierError:
                        # here no catch - blocked tasks go to wait
                        results2.append(True)

        await self.gather_tasks(self.N, coro)

        self.assertEqual(results1, [True]*blocking_tasks)
        self.assertEqual(results2, [])
        self.assertEqual(barrier.n_waiting, 0)
        self.assertNotIn("resetting", repr(barrier))
        self.assertFalse(barrier.broken)
示例#18
0
    async def test_reset_barrier_when_tasks_half_draining(self):
        barrier = asyncio.Barrier(self.N)
        results1 = []
        rest_of_tasks = self.N//2

        async def coro():
            try:
                await barrier.wait()
            except asyncio.BrokenBarrierError:
                # catch here waiting tasks
                results1.append(True)
            else:
                # here drained task outside the barrier
                if rest_of_tasks == barrier._count:
                    # tasks outside the barrier
                    await barrier.reset()

        await self.gather_tasks(self.N, coro)

        self.assertEqual(results1, [True]*rest_of_tasks)
        self.assertEqual(barrier.n_waiting, 0)
        self.assertNotIn("resetting", repr(barrier))
        self.assertFalse(barrier.broken)
示例#19
0
    async def test_filling_tasks_check_return_value(self):
        barrier = asyncio.Barrier(self.N)
        results1 = []
        results2 = []

        async def coro():
            async with barrier:
                results1.append(True)

                async with barrier as i:
                    results2.append(True)
                    return i

        res, _ = await self.gather_tasks(self.N, coro)

        self.assertEqual(len(results1), self.N)
        self.assertTrue(all(results1))
        self.assertEqual(len(results2), self.N)
        self.assertTrue(all(results2))
        self.assertListEqual(sorted(res), list(range(self.N)))

        self.assertEqual(barrier.n_waiting, 0)
        self.assertFalse(barrier.broken)
示例#20
0
    async def test_reset_barrier_while_tasks_waiting_and_waiting_again(self):
        barrier = asyncio.Barrier(self.N)
        results1 = []
        results2 = []

        async def coro1():
            try:
                await barrier.wait()
            except asyncio.BrokenBarrierError:
                results1.append(True)
            finally:
                await barrier.wait()
                results2.append(True)

        async def coro2():
            async with barrier:
                results2.append(True)

        tasks = self.make_tasks(self.N-1, coro1)

        # reset barrier, N-1 waiting tasks raise an BrokenBarrierError
        asyncio.create_task(barrier.reset())
        await asyncio.sleep(0)

        # complete waiting tasks in the `finally`
        asyncio.create_task(coro2())

        await asyncio.gather(*tasks)

        self.assertFalse(barrier.broken)
        self.assertEqual(len(results1), self.N-1)
        self.assertTrue(all(results1))
        self.assertEqual(len(results2), self.N)
        self.assertTrue(all(results2))

        self.assertEqual(barrier.n_waiting, 0)
示例#21
0
    async def test_filling_tasks_cancel_one(self):
        self.N = 3
        barrier = asyncio.Barrier(self.N)
        results = []

        async def coro():
            await barrier.wait()
            results.append(True)

        t1 = asyncio.create_task(coro())
        await asyncio.sleep(0)
        self.assertEqual(barrier.n_waiting, 1)

        t2 = asyncio.create_task(coro())
        await asyncio.sleep(0)
        self.assertEqual(barrier.n_waiting, 2)

        t1.cancel()
        await asyncio.sleep(0)
        self.assertEqual(barrier.n_waiting, 1)
        with self.assertRaises(asyncio.CancelledError):
            await t1
        self.assertTrue(t1.cancelled())

        t3 = asyncio.create_task(coro())
        await asyncio.sleep(0)
        self.assertEqual(barrier.n_waiting, 2)

        t4 = asyncio.create_task(coro())
        await asyncio.gather(t2, t3, t4)

        self.assertEqual(len(results), self.N)
        self.assertTrue(all(results))

        self.assertEqual(barrier.n_waiting, 0)
        self.assertFalse(barrier.broken)
示例#22
0
    async def test_barrier_parties(self):
        self.assertRaises(ValueError, lambda: asyncio.Barrier(0))
        self.assertRaises(ValueError, lambda: asyncio.Barrier(-4))

        self.assertIsInstance(asyncio.Barrier(self.N), asyncio.Barrier)