예제 #1
0
async def test_merger_active_connection_prevents_ending(
        outside_source_stream, mock_merge_strategy, mock_stream_builder,
        mock_connection_streams, mock_connections, event_loop):
    connection = mock_connections()
    connection_stream = mock_connection_streams()
    mock_stream_builder.side_effect = [connection_stream]
    canonical_stream = outside_source_stream

    async def long_read():
        await asyncio.sleep(0.05)
        return b""

    connection_stream.read.side_effect = long_read
    connection_stream.ended.side_effect = lambda: connection_stream.read.called

    merger = Merger(mock_stream_builder, 0.01, mock_merge_strategy,
                    canonical_stream)
    f = asyncio.ensure_future(merger.wait_for_ended())
    h = asyncio.ensure_future(merger.handle_connection(connection))
    await asyncio.sleep(0.02)
    exhaust_callbacks(event_loop)
    assert not f.done()
    await h
    await asyncio.sleep(0.02)
    exhaust_callbacks(event_loop)
    assert f.done()
예제 #2
0
async def test_merger_ends_when_refusing_conns_and_no_connections(
        outside_source_stream, mock_merge_strategy, mock_reader_builder,
        mock_delayed_stream_builder):
    canonical_stream = outside_source_stream
    merger = Merger(mock_reader_builder, mock_delayed_stream_builder,
                    mock_merge_strategy, canonical_stream)
    merger.stop_accepting_connections()
    await merger.wait_for_ended()
    mock_merge_strategy.finalize.assert_called()
    assert canonical_stream.ended()
예제 #3
0
async def test_merger_rejects_writers_when_asked(outside_source_stream,
                                                 mock_merge_strategy,
                                                 mock_reader_builder,
                                                 mock_delayed_stream_builder,
                                                 mock_connections):
    connection = mock_connections()
    canonical_stream = outside_source_stream

    merger = Merger(mock_reader_builder, mock_delayed_stream_builder,
                    mock_merge_strategy, canonical_stream)
    merger.stop_accepting_connections()
    with pytest.raises(CannotAcceptConnectionError):
        await merger.handle_connection(connection)
    mock_reader_builder.assert_not_called()
    await merger.wait_for_ended()
예제 #4
0
async def test_merger_times_out_after_creation(outside_source_stream,
                                               mock_merge_strategy,
                                               mock_stream_builder):
    canonical_stream = outside_source_stream
    merger = Merger(mock_stream_builder, 0.01, mock_merge_strategy,
                    canonical_stream)
    await merger.wait_for_ended()
    canonical_stream.finish.assert_called()
예제 #5
0
async def test_merger_no_connections_wait_empty(outside_source_stream,
                                                mock_merge_strategy,
                                                mock_reader_builder,
                                                mock_delayed_stream_builder,
                                                event_loop):
    canonical_stream = outside_source_stream
    merger = Merger(mock_reader_builder, mock_delayed_stream_builder,
                    mock_merge_strategy, canonical_stream)
    f = asyncio.ensure_future(merger.no_connections_for(0.01))
    exhaust_callbacks(event_loop)
    assert not f.done()
    await asyncio.sleep(0.02)
    exhaust_callbacks(event_loop)
    assert f.done()
    await f

    merger.stop_accepting_connections()
    await merger.wait_for_ended()
예제 #6
0
async def test_merger_read_exception(outside_source_stream,
                                     mock_merge_strategy, mock_reader_builder,
                                     mock_delayed_stream_builder, mock_readers,
                                     mock_connections):
    connection = mock_connections()
    canonical_stream = outside_source_stream
    reader = mock_readers()
    mock_reader_builder.side_effect = [reader]
    reader.read.side_effect = BadConnectionError

    merger = Merger(mock_reader_builder, mock_delayed_stream_builder,
                    mock_merge_strategy, canonical_stream)
    with pytest.raises(BadConnectionError):
        await merger.handle_connection(connection)

    mock_merge_strategy.track_stream.assert_awaited_with(reader.stream)
    merger.stop_accepting_connections()
    await merger.wait_for_ended()
async def test_merger_successful_connection(event_loop, mock_connections,
                                            data_send_mixin):
    conn = mock_connections()
    replay_data = example_replay.data
    data_send_mixin(conn, replay_data, 0.25, 200)

    merger = Merger.build(**config)
    await merger.handle_connection(conn)
    await verify_merger_ending_with_data(merger, replay_data)
예제 #8
0
async def test_merger_successful_connection(event_loop, mock_connections,
                                            mock_conn_read_data_mixin):
    conn = mock_connections()
    mock_conn_read_data_mixin(conn, example_replay.data, 0.25, 200)

    merger = Merger.build(merger_config(merger_dict),
                          delay_config(delay_dict))
    await merger.handle_connection(conn)
    await verify_merger_ending_with_data(merger, example_replay.data)
예제 #9
0
async def test_merger_one_connection_lifetime(outside_source_stream,
                                              mock_merge_strategy,
                                              mock_reader_builder,
                                              mock_delayed_stream_builder,
                                              mock_readers, mock_connections):
    connection = mock_connections()
    reader = mock_readers()
    mock_reader_builder.side_effect = [reader]
    canonical_stream = outside_source_stream

    merger = Merger(mock_reader_builder, mock_delayed_stream_builder,
                    mock_merge_strategy, canonical_stream)
    await merger.handle_connection(connection)

    reader.read.assert_awaited()
    mock_merge_strategy.track_stream.assert_awaited_with(reader.stream)

    merger.stop_accepting_connections()
    await merger.wait_for_ended()
async def test_merger_incomplete_header(event_loop, mock_connections,
                                        data_send_mixin):
    conn = mock_connections()
    replay_data = example_replay.header_data[:-100]
    data_send_mixin(conn, replay_data, 0.25, 200)

    merger = Merger.build(**config)
    with pytest.raises(MalformedDataError):
        await merger.handle_connection(conn)
    await verify_merger_ending_with_data(merger, None)
예제 #11
0
async def test_merger_connection_extends_grace_period(
        outside_source_stream, mock_merge_strategy, mock_stream_builder,
        mock_connection_streams, mock_connections, event_loop):
    connection = mock_connections()
    connection_stream = mock_connection_streams()
    mock_stream_builder.side_effect = [connection_stream]
    canonical_stream = outside_source_stream

    connection_stream.ended.return_value = True

    merger = Merger(mock_stream_builder, 0.03, mock_merge_strategy,
                    canonical_stream)
    f = asyncio.ensure_future(merger.wait_for_ended())
    await asyncio.sleep(0.02)
    await merger.handle_connection(connection)
    await asyncio.sleep(0.02)
    exhaust_callbacks(event_loop)
    assert not f.done()
    await f
예제 #12
0
async def test_merger_no_connection_wait_active_connection(
        outside_source_stream, mock_merge_strategy, mock_reader_builder,
        mock_delayed_stream_builder, mock_readers, mock_connections,
        event_loop):
    connection = mock_connections()
    reader = mock_readers()
    mock_reader_builder.side_effect = [reader]
    canonical_stream = outside_source_stream

    async def long_read():
        await asyncio.sleep(0.05)
        return

    reader.read.side_effect = long_read

    merger = Merger(mock_reader_builder, mock_delayed_stream_builder,
                    mock_merge_strategy, canonical_stream)
    f = asyncio.ensure_future(merger.no_connections_for(0.01))
    h = asyncio.ensure_future(merger.handle_connection(connection))

    await asyncio.sleep(0.02)
    exhaust_callbacks(event_loop)
    assert not f.done()
    await h
    exhaust_callbacks(event_loop)
    assert not f.done()
    await asyncio.sleep(0.02)
    exhaust_callbacks(event_loop)
    assert f.done()
    await f

    merger.stop_accepting_connections()
    await merger.wait_for_ended()
async def test_merger_closes_fast(event_loop, mock_connections,
                                  data_send_mixin):
    conn = mock_connections()
    replay_data = example_replay.data
    data_send_mixin(conn, replay_data, 0.6, 160)

    merger = Merger.build(**config)
    f = asyncio.ensure_future(merger.handle_connection(conn))
    await asyncio.sleep(45)
    conn.read.side_effect = lambda _: b""   # Simulate connection.close()
    merger.close()
    await asyncio.wait_for(merger.wait_for_ended(), 1)
    await asyncio.wait_for(f, 1)
async def test_merger_ends(event_loop, mock_connections, data_send_mixin):
    conn_1 = mock_connections()
    conn_2 = mock_connections()
    replay_data = example_replay.data

    data_send_mixin(conn_1, replay_data, 0.6, 160)
    data_send_mixin(conn_2, replay_data, 0.6, 160)

    merger = Merger.build(**config)
    await merger.handle_connection(conn_1)
    await asyncio.sleep(45)
    with pytest.raises(CannotAcceptConnectionError):
        await merger.handle_connection(conn_2)
    await verify_merger_ending_with_data(merger, replay_data)
async def test_merger_sequential_connections(event_loop, mock_connections,
                                             data_send_mixin):
    conn_1 = mock_connections()
    conn_2 = mock_connections()
    replay_data = example_replay.data

    # First has incomplete data, but sends faster
    data_send_mixin(conn_1, replay_data[:-100], 0.4, 160)
    data_send_mixin(conn_2, replay_data, 0.6, 160)

    merger = Merger.build(**config)
    await merger.handle_connection(conn_1)
    await asyncio.sleep(15)
    await merger.handle_connection(conn_2)
    await verify_merger_ending_with_data(merger, replay_data)
async def test_merger_two_connections(event_loop, mock_connections,
                                      data_send_mixin):
    conn_1 = mock_connections()
    conn_2 = mock_connections()
    replay_data = example_replay.data

    # First has incomplete data, but sends faster
    data_send_mixin(conn_1, replay_data[:-100], 0.4, 160)
    data_send_mixin(conn_2, replay_data, 0.6, 160)

    merger = Merger.build(**config)
    f_1 = asyncio.ensure_future(merger.handle_connection(conn_1))
    f_2 = asyncio.ensure_future(merger.handle_connection(conn_2))
    await f_1
    await f_2
    await verify_merger_ending_with_data(merger, replay_data)
예제 #17
0
async def test_merger_refuses_conns(event_loop, mock_connections,
                                    mock_conn_read_data_mixin):
    conn_1 = mock_connections()
    conn_2 = mock_connections()
    replay_data = example_replay.data

    mock_conn_read_data_mixin(conn_1, replay_data, 0.6, 160)
    mock_conn_read_data_mixin(conn_2, replay_data, 0.6, 160)

    merger = Merger.build(merger_config(merger_dict),
                          delay_config(delay_dict))
    await merger.handle_connection(conn_1)
    merger.stop_accepting_connections()
    with pytest.raises(CannotAcceptConnectionError):
        await merger.handle_connection(conn_2)
    await verify_merger_ending_with_data(merger, example_replay.data)
예제 #18
0
async def test_merger_incomplete_header_then_data(event_loop,
                                                  mock_connections,
                                                  mock_conn_read_data_mixin):
    conn_1 = mock_connections()
    conn_2 = mock_connections()
    replay_data = example_replay.header_data[:-100]
    mock_conn_read_data_mixin(conn_1, replay_data, 0.25, 200)
    mock_conn_read_data_mixin(conn_2, example_replay.data, 0.25, 200)

    merger = Merger.build(merger_config(merger_dict),
                          delay_config(delay_dict))
    with pytest.raises(MalformedDataError):
        await merger.handle_connection(conn_1)
    await merger.handle_connection(conn_2)

    await verify_merger_ending_with_data(merger, example_replay.data)
예제 #19
0
async def test_merger_read_header_exception(outside_source_stream,
                                            mock_merge_strategy,
                                            mock_stream_builder,
                                            mock_connection_streams,
                                            mock_connections):
    connection = mock_connections()
    connection_stream = mock_connection_streams()
    mock_stream_builder.side_effect = [connection_stream]
    canonical_stream = outside_source_stream

    connection_stream.read_header.side_effect = BadConnectionError

    merger = Merger(mock_stream_builder, 0.01, mock_merge_strategy,
                    canonical_stream)
    with pytest.raises(BadConnectionError):
        await merger.handle_connection(connection)

    mock_merge_strategy.stream_added.assert_called_with(connection_stream)
    mock_merge_strategy.stream_removed.assert_called_with(connection_stream)
    mock_merge_strategy.new_header.assert_not_called()
    await merger.wait_for_ended()
예제 #20
0
async def test_merger_one_connection_lifetime(outside_source_stream,
                                              mock_merge_strategy,
                                              mock_stream_builder,
                                              mock_connection_streams,
                                              mock_connections):
    connection = mock_connections()
    connection_stream = mock_connection_streams()
    mock_stream_builder.side_effect = [connection_stream]
    canonical_stream = outside_source_stream

    conn_data = b""

    async def mock_read():
        nonlocal conn_data
        conn_data = b"foo"

    def mock_ended():
        return conn_data == b"foo"

    connection_stream.read_header.return_value = "Header"
    connection_stream.read.side_effect = mock_read
    connection_stream.ended.side_effect = mock_ended

    merger = Merger(mock_stream_builder, 0.01, mock_merge_strategy,
                    canonical_stream)
    await merger.handle_connection(connection)

    connection_stream.read_header.assert_called()
    connection_stream.read.assert_called()

    mock_merge_strategy.stream_added.assert_called_with(connection_stream)
    mock_merge_strategy.stream_removed.assert_called_with(connection_stream)
    mock_merge_strategy.new_header.assert_called_with(connection_stream)
    mock_merge_strategy.new_data.assert_called_with(connection_stream)

    await asyncio.sleep(0.02)
    mock_merge_strategy.finalize.assert_called()
예제 #21
0
 def build(cls, game_id, bookkeeper, config):
     merger = Merger.build(config.merge, config.delay)
     sender = Sender.build(merger.canonical_stream)
     return cls(merger, sender, bookkeeper, config, game_id)
def test_merger_init():
    Merger.build(**config)
예제 #23
0
def test_merger_init():
    Merger.build(merger_config(merger_dict),
                 delay_config(delay_dict))
예제 #24
0
 def build(cls, game_id, bookkeeper, *, config_replay_forced_end_time,
           **kwargs):
     merger = Merger.build(**kwargs)
     sender = Sender.build(merger.canonical_stream, **kwargs)
     return cls(merger, sender, bookkeeper, config_replay_forced_end_time,
                game_id)