async def test_alts_multiple_ready_first_fails(): """ WHEN No ready ports and priority is True. Multiple operations become ready while blocked, but the first ready channel is closed. EXPECT Return success and second channel. """ a = 'a' ch1 = create_channel() ch1.offer(a) b = 'b' ch2 = create_channel() ch2.offer(b) def ready_both_close_ch1(): ch1.poll() ch1.close() ch2.poll() asyncio.get_running_loop().call_later(0.05, ready_both_close_ch1) c, d = 'c', 'd' out = await asyncio.wait_for( complete_one((ch1, c), (ch2, d), priority=True), timeout=0.1) assert out == (True, ch2) assert ch1.empty() assert ch2.poll() == d
async def test_add_output(): """ GIVEN ChannelMultiple with multiple output channels. WHEN Item is put on src channel. EXPECT Item is put on all output channels. """ src = create_channel() out1 = create_channel() out2 = create_channel() m = create_multiple(src) assert m.add_output(out1) assert m.add_output(out2, close=False) x = 'x' src.offer(x) value1 = await out1.take(timeout=0.05) value2 = await out2.take(timeout=0.05) assert value1 == x assert value2 == x src.close() await asyncio.wait_for(out1.closed(), timeout=0.05) with pytest.raises(asyncio.TimeoutError): await asyncio.wait_for(out2.closed(), timeout=0.05)
async def test_remove_output(): """ GIVEN ChannelMultiple with multiple output channels. WHEN Output channel is removed then a item is put on src channel. EXPECT Item to not be copied to removed channel. """ src = create_channel() out1 = create_channel() out2 = create_channel() m = create_multiple(src) assert m.add_output(out1) assert m.add_output(out2) await asyncio.sleep(0.05) m.remove_output(out1) x = 'x' src.offer(x) value2 = await out2.take(timeout=0.05) assert value2 == x assert out1.empty() src.close() await asyncio.wait_for(out2.closed(), timeout=0.05) with pytest.raises(asyncio.TimeoutError): await asyncio.wait_for(out1.closed(), timeout=0.05)
async def test_publication_unsubscribe(): """ GIVEN Two topics with subscribed channels. WHEN A channel is unsubscribed then an item is put on src channel. EXPECT Item is put on subscribed topic channels, but not the unsubscribed channel. """ src = create_channel() get_type = operator.itemgetter('type') p = create_publication(src, get_type) a_ch = create_channel() p.subscribe('a', a_ch) b_ch = create_channel() p.subscribe('b', b_ch) b2_ch = create_channel() p.subscribe('b', b2_ch) p.unsubscribe('b', b_ch) x = {'type': 'b', 'value': 42} assert src.offer(x) r = await b2_ch.take(timeout=0.05) assert r is x assert a_ch.empty() assert b_ch.empty() src.close() await asyncio.sleep(0.05)
async def test_remove_all_outputs(): """ GIVEN ChannelMultiple with multiple output channels. WHEN All output channels are removed then a item is put on src channel. EXPECT Item is not copied to former output channels, but is removed from src channel. """ src = create_channel() out1 = create_channel() out2 = create_channel() m = create_multiple(src) assert m.add_output(out1) assert m.add_output(out2) await asyncio.sleep(0.05) m.remove_all_outputs() x = 'x' src.offer(x) await asyncio.sleep(0.05) assert src.empty() assert out1.empty() assert out2.empty() src.close() await asyncio.sleep(0.05)
async def test_mix_mute(): """ GIVEN A mix, in non-priority mode, with two input channels, one muted. WHEN An item is added to each input channel. EXPECT Item from non-muted channel is put on output channel. Item from muted channel is taken but not put on output channel. """ ch1 = create_channel() ch2 = create_channel() out = create_channel() m = create_mix(out) m.add_input(ch1) m.toggle(ch1, {}, ch2, {'mute': True}) a = 'a' b = 'b' assert ch1.offer(a) assert ch2.offer(b) x = await out.take(timeout=0.05) assert x == a assert out.empty() assert ch2.empty() out.close() await asyncio.sleep(0.05)
async def test_iterzip(): """ GIVEN Multiple input channels. WHEN Iterate over zip of channels. EXPECT An iteration when all channels have an item. """ async def put_seq(seq, ch): for x in seq: await asyncio.sleep(0.1 * random.random()) await ch.put(x) ch1 = create_channel() ch2 = create_channel() ch3 = create_channel() seq1 = ('a', 'b', 'c') seq2 = (1, 2, 3) seq3 = ('x', 'y', 'z') asyncio.create_task(put_seq(seq1, ch1)) asyncio.create_task(put_seq(seq2, ch2)) asyncio.create_task(put_seq(seq3, ch3)) i = 0 async for zs in iterzip(ch1, ch2, ch3): assert zs == (seq1[i], seq2[i], seq3[i]) i += 1 if i == len(seq2): ch2.close() await asyncio.sleep(0.05)
async def test_mix_toggle_error_cases(): """ WHEN Call toggle with invalid arguments. EXPECT Errors to be raised. """ out = create_channel() m = create_mix(out) with pytest.raises(ValueError, match='no arguments'): m.toggle() with pytest.raises(ValueError, match='odd number of arguments'): m.toggle(1) ch = create_channel() with pytest.raises(TypeError, match='argument 2 must be a channel, not a str'): m.toggle(ch, {}, '', {}) with pytest.raises(TypeError, match='argument 1 must be a dict, not a str'): m.toggle(ch, '') with pytest.raises(KeyError, match='argument 1 contains keys bar, foo, only ' 'mute, pause, priority are allowed'): m.toggle(ch, {'mute': True, 'foo': False, 'bar': True}) out.close() await asyncio.sleep(0.05)
async def test_mix_priority_pause(): """ GIVEN A mix, in priority-mode=pause, with two input channels, one with priority. WHEN An item is added to each input channel. EXPECT Item from priority channel is put on output channel. Item from non-priority channel is not taken. """ ch1 = create_channel() ch2 = create_channel() out = create_channel() m = create_mix(out) m.priority_mode = m.PRIORITY_PAUSE m.add_input(ch1) m.toggle(ch1, {}, ch2, {'priority': True}) a = 'a' b = 'b' assert ch1.offer(a) assert ch2.offer(b) x = await out.take(timeout=0.05) assert x == b assert out.empty() assert await out.take(timeout=0.05) is None assert not ch1.empty() out.close() await asyncio.sleep(0.05)
async def test_publication(): """ GIVEN Two topics with subscribed channels. Only one channel set to close when src channel closes. WHEN An item is put on src channel. EXPECT Item is put on topic channel. Subscribed channels are closed when src channel is closed. """ src = create_channel() get_type = operator.itemgetter('type') p = create_publication(src, get_type) a_ch = create_channel() p.subscribe('a', a_ch) b_ch = create_channel() p.subscribe('b', b_ch, close=False) x = {'type': 'b', 'value': 42} assert src.offer(x) r = await b_ch.take(timeout=0.05) assert r is x assert a_ch.empty() src.close() await asyncio.sleep(0.05) assert a_ch.is_closed() assert not b_ch.is_closed()
async def test_publication_unsubscribe_all_on_topic(): """ GIVEN Two topics with subscribed channels. WHEN All channels are unsubscribed then an item is put on src channel. EXPECT The item is taken from src channel and dropped. """ src = create_channel() get_type = operator.itemgetter('type') p = create_publication(src, get_type) a_ch = create_channel() p.subscribe('a', a_ch) b_ch = create_channel() p.subscribe('b', b_ch) b2_ch = create_channel() p.subscribe('b', b2_ch) p.unsubscribe_all('b') x = {'type': 'b', 'value': 42} assert src.offer(x) await asyncio.sleep(0.05) assert src.empty() assert a_ch.empty() assert b_ch.empty() assert b2_ch.empty() src.close() await asyncio.sleep(0.05)
async def test_mix_unmix(): """ GIVEN A mix, in non-priority mode, with two input channels. WHEN One input channel is unmix'd. EXPECT Item from the unmix'd channel is not taken. """ ch1 = create_channel() ch2 = create_channel() out = create_channel() m = create_mix(out) m.add_input(ch1) m.add_input(ch2) a = 'a' b = 'b' assert ch1.offer(a) assert ch2.offer(b) m.remove_input(ch2) x = await out.take(timeout=0.05) assert x == a assert await out.take(timeout=0.05) is None assert not ch2.empty() out.close() await asyncio.sleep(0.05)
def test_chan_nonpositive_int(): """ WHEN n is not a positive integer. EXPECT Throws a ValueError. """ with pytest.raises(ValueError): create_channel(0)
def test_chan_nonbuffer(): """ WHEN n is not an integer or a buffer-like object. EXPECT Throws an AttributeError. """ with pytest.raises(AttributeError): create_channel('a')
def test_chan_nonpositive_buffer(): """ WHEN n is buffer with a non-positive maxsize. EXPECT Throws a ValueError. """ buf = asyncio.Queue() with pytest.raises(ValueError): create_channel(buf)
async def test_alts_default(): """ WHEN No ready ports and a default value. EXPECT Immediately return default. """ ch1 = create_channel() ch2 = create_channel() x = 'x' out = await asyncio.wait_for(complete_one(ch1, ch2, default=x), timeout=0.05) assert out == (x, 'default')
async def test_alts_ready_take(): """ WHEN A ready "take" operation. EXPECT Return taken value and channel. """ ch1 = create_channel() ch2 = create_channel() x = 'x' ch2.offer(x) out = await asyncio.wait_for(complete_one(ch1, ch2), timeout=0.05) assert out == (x, ch2)
async def test_alts_wait_take(): """ WHEN No ready ports. A value put on channel while blocked. EXPECT Return (value, channel). """ ch1 = create_channel() ch2 = create_channel() x = 'x' asyncio.get_running_loop().call_later(0.05, ch2.offer, x) out = await asyncio.wait_for(complete_one(ch1, ch2), timeout=0.1) assert out == (x, ch2)
async def test_pipe_close_true(): """ GIVEN close argument is True. WHEN src channel closes. EXPECT dest channel to remain open. """ src = create_channel() dest = create_channel() pipe(src, dest) asyncio.get_running_loop().call_later(0.05, src.close) await asyncio.wait_for(src.closed(), timeout=0.05) await asyncio.wait_for(dest.closed(), timeout=0.05)
async def test_multiple_closed(): """ GIVEN Closed multiple. WHEN Channel is added to ChannelMultiple. EXPECT Return False. """ src = create_channel() src.close() m = create_multiple(src) await asyncio.sleep(0.05) ch = create_channel() assert not m.add_output(ch)
async def tests_alts_ready_put(): """ WHEN A ready "put" operation. EXPECT Return success and channel. """ ch1 = create_channel() ch2 = create_channel() a = 'a' ch1.offer(a) b, c = 'b', 'c' out = await asyncio.wait_for(complete_one((ch1, b), (ch2, c)), timeout=0.05) assert out == (True, ch2) assert ch1.poll() == a assert ch2.poll() == c
async def test_pipe_close_false(): """ GIVEN close argument is False. WHEN src channel closes. EXPECT dest channel to remain open. """ src = create_channel() dest = create_channel() pipe(src, dest, close=False) asyncio.get_running_loop().call_later(0.05, src.close) await asyncio.wait_for(src.closed(), timeout=0.05) with pytest.raises(asyncio.TimeoutError): await asyncio.wait_for(dest.closed(), timeout=0.05)
async def test_shield_from_close_forwarding(): """ GIVEN An open channel, shielded from close. WHEN Call forwarded methods, i.e. everything except 'close'. EXPECT Normal channel behavior. """ ch = create_channel() dch = shield_from_close(ch) assert dch.empty() assert not dch.full() a = 'a' assert dch.offer(a) assert not dch.empty() assert dch.full() assert dch.poll() == a b = 'b' assert await dch.put(b, timeout=0.05) assert await dch.take(timeout=0.05) == b asyncio.get_running_loop().call_later(0.05, dch.offer, a) assert await dch.item(timeout=0.1) asyncio.get_running_loop().call_later(0.05, dch.poll) assert await dch.capacity(timeout=0.1) assert not dch.is_closed() with pytest.raises(asyncio.TimeoutError): await asyncio.wait_for(dch.closed(), timeout=0.05) asyncio.get_running_loop().call_later(0.05, ch.close) await asyncio.wait_for(dch.closed(), timeout=0.1) assert dch.is_closed()
async def main(): ping = create_channel() pong = create_channel() # Stop the game after 10 seconds. # # Closing the ping channel will stop the ping player, # which will then close the pong channel, which then # stops the pong player. get_running_loop().call_later(10, ping.close) # Kick off the game! ping.offer('ping') # Wait until the game is done. await gather(player('ping', pong, ping), player(' pong', ping, pong))
async def test_split(): """ GIVEN An input channel and predicate, is_even. WHEN A number if put on the input channel. EXPECT Even number put on the true channel, odd numbe on the false channel. """ is_even = lambda n: n % 2 == 0 ch = create_channel() t_out, f_out = split(is_even, ch) x = 2 assert ch.offer(x) r = await t_out.take(timeout=0.05) assert x == r assert f_out.empty() x = 3 assert ch.offer(x) r = await f_out.take(timeout=0.05) assert x == r assert t_out.empty() ch.close() await asyncio.wait_for(asyncio.wait((t_out.closed(), f_out.closed())), timeout=0.05)
async def test_pipe(): """ WHEN Item put to src channel. EXPECT Item is transfered to dest channel. """ src = create_channel() dest = create_channel() pipe(src, dest) x = 'x' assert src.offer(x) assert await dest.take(timeout=0.05) == x assert src.empty() src.close() await asyncio.wait_for(dest.closed(), timeout=0.05)
def test_chan_int(): """ WHEN n is a positive integer. EXPECT Return a Channel. """ assert isinstance(create_channel(2), Channel)
def test_chan(): """ WHEN n is omitted. EXPECT Return a Channel. """ assert isinstance(create_channel(), Channel)
def test_chan_buffer(): """ WHEN n is a buffer. EXPECT Return a Channel. """ buf = create_sliding_buffer(2) assert isinstance(create_channel(buf), Channel)
async def test_alts_wait_put(): """ WHEN No ready ports. A channel opens capacity while blocked. EXPECT Return (True, channel). """ a = 'a' ch1 = create_channel() ch1.offer(a) b = 'b' ch2 = create_channel() ch2.offer(b) asyncio.get_running_loop().call_later(0.05, ch2.poll) c, d = 'c', 'd' out = await asyncio.wait_for(complete_one((ch1, c), (ch2, d)), timeout=0.1) assert out == (True, ch2) assert ch2.poll() == d