async def test_store(app, client, store, client_mock):
    await store.startup(app)
    assert store.active
    assert not store.volatile
    assert store.rev is None

    default_length = len(datastore.SYS_OBJECTS)
    read_length = default_length + len(
        read_objects()) - 1  # overlapping item is merged

    assert len(store.items()) == default_length
    await datastore.check_remote(app)
    await store.read('doc')
    assert len(store.items()) == read_length
    assert store.rev == 'rev_read'

    # Defaults were added to read objects, so those were flushed
    await asyncio.sleep(0.05)
    assert client_mock.write.call_count == 1
    assert store.rev == 'rev_write'

    # write on add
    store['inserted', 9001] = 'val'
    await asyncio.sleep(0.05)
    assert client_mock.write.call_count == 2
    assert len(store.items()) == read_length + 1

    # write on delete
    del store['inserted', 9001]
    assert len(store.items()) == read_length
    await asyncio.sleep(0.05)
    assert client_mock.write.call_count == 3

    # handle read error
    client_mock.read.side_effect = return_once(RuntimeError,
                                               then=('rev_read',
                                                     read_objects()))
    with pytest.warns(UserWarning, match='read error'):
        await store.read('doc')

    assert store.rev is None
    assert store.document is None
    with pytest.warns(UserWarning, match='flush error'):
        await asyncio.sleep(0.05)

    # reset to normal
    await store.read('doc')

    # continue on write error
    with pytest.warns(UserWarning, match='flush error'):
        client_mock.write.side_effect = return_once(RuntimeError,
                                                    then='rev_write')
        store['inserted2', 9002] = 'val'
        await asyncio.sleep(0.05)
    assert client_mock.write.call_count == 5

    # write on shutdown
    store['inserted3', 9003] = 'val'
    await store.shutdown(app)
    assert client_mock.write.call_count == 6
async def test_config(app, client, config, client_mock):
    def vals():
        return {'k1': 1, 'k2': 2}

    client_mock.read.return_value = ('rev_read', vals())

    await config.startup(app)
    assert config.active
    assert config.rev is None

    cb = Mock()
    config.subscribe(cb)

    with config.open() as cfg:
        cfg['key'] = 'val'

    with config.open() as cfg:
        assert 'key' in cfg

    # values are cleared when reading
    await config.read('doc')
    cb.assert_called_once_with(vals())
    assert config.rev == 'rev_read'
    assert client_mock.write.call_count == 0

    with config.open() as cfg:
        assert cfg == vals()
        cfg['key'] = 'val'

    await asyncio.sleep(0.05)
    assert config.rev == 'rev_write'
    assert client_mock.write.call_count == 1

    # handle read error
    client_mock.read.side_effect = return_once(RuntimeError,
                                               then=('rev_read', vals()))
    with pytest.warns(UserWarning, match='read error'):
        await config.read('doc')

    assert config.rev is None
    assert config.document is None

    with config.open() as cfg:
        assert cfg == {}
        cfg['key'] = 'val'

    with pytest.warns(UserWarning, match='flush error'):
        await asyncio.sleep(0.05)

    # reset to normal
    await config.read('doc')

    # continue on write error
    with pytest.warns(UserWarning, match='flush error'):
        client_mock.write.side_effect = return_once(RuntimeError,
                                                    then='rev_write')
        with config.open() as cfg:
            cfg['insert'] = 'outsert'
        await asyncio.sleep(0.05)
    assert client_mock.write.call_count == 3
Esempio n. 3
0
async def test_granular_poll_access(query_kind, app, access_token_builder,
                                    dummy_zmq_server):
    """
    Test that tokens grant granular access to checking query status.

    """
    client, db, log_dir = app
    token = access_token_builder({query_kind: {"permissions": {"poll": True}}})
    expected_responses = dict.fromkeys(query_kinds, 401)
    expected_responses[query_kind] = 303

    responses = {}
    for q_kind in query_kinds:
        dummy_zmq_server.side_effect = return_once(
            {
                "id": 10,
                "query_kind": q_kind
            },
            then={
                "id": 10,
                "status": "done"
            })
        response = await client.get(
            f"/api/0/poll/0",
            headers={"Authorization": f"Bearer {token}"},
            json={"query_kind": q_kind},
        )
        responses[q_kind] = response.status_code
    assert expected_responses == responses
Esempio n. 4
0
async def test_poll_bad_query(app, access_token_builder, dummy_zmq_server):
    """
    Test that correct status code and any redirect is returned when polling a running query
    """
    client, db, log_dir, app = app

    token = access_token_builder({
        "modal_location": {
            "permissions": {
                "poll": True
            },
            "spatial_aggregation": ["DUMMY_AGGREGATION"],
        }
    })

    dummy_zmq_server.side_effect = return_once(
        ZMQReply(
            status="error",
            msg=f"Unknown query id: 'DUMMY_QUERY_ID'",
            payload={
                "query_id": "DUMMY_QUERY_ID",
                "query_state": "awol"
            },
        ).as_json())
    response = await client.get(f"/api/0/poll/DUMMY_QUERY_ID",
                                headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 404
Esempio n. 5
0
async def test_poll_query_query_error(app, access_token_builder,
                                      dummy_zmq_server):
    """
    Test that correct status code and any redirect is returned when polling a query that errored
    """
    client, db, log_dir, app = app

    token = access_token_builder(
        {"modal_location": {
            "permissions": {
                "poll": True
            }
        }})

    # TODO: Fix the logic that makes this necessary
    dummy_zmq_server.side_effect = return_once(
        ZMQReply(
            status="success",
            payload={
                "query_id": "DUMMY_QUERY_ID",
                "query_kind": "modal_location"
            },
        ).as_json(),
        then=ZMQReply(
            status="error",
            payload={
                "query_id": "DUMMY_QUERY_ID",
                "query_state": "error"
            },
        ).as_json(),
    )
    response = await client.get(f"/api/0/poll/DUMMY_QUERY_ID",
                                headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 500
Esempio n. 6
0
async def test_poll_query(status, http_code, app, dummy_zmq_server,
                          access_token_builder):
    """
    Test that correct status code and any redirect is returned when polling a running query
    """
    client, db, log_dir = app

    token = access_token_builder(
        {"modal_location": {
            "permissions": {
                "poll": True
            }
        }})
    dummy_zmq_server.side_effect = return_once(
        {
            "id": 0,
            "query_kind": "modal_location"
        },
        then={
            "status": status,
            "id": 0
        })
    response = await client.get(f"/api/0/poll/0",
                                headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == http_code
    if status == "done":
        assert "/api/0/get/0" == response.headers["Location"]
Esempio n. 7
0
    async def test_method__poll_with_reconnect_when_droped(self):
        with patch('ethereumd.poller.Poller.poll'):
            poller = Poller(self.rpc_proxy)

        with patch.object(AsyncIOHTTPClient,
                          '_call',
                          side_effect=return_once(
                              lambda: BadResponseError('test', code=-99999999),
                              then=fake_call())):
            poller._pending = '0x6f4111062b3db311e6521781f4ef0046'
            await poller._poll_with_reconnect('pending')
Esempio n. 8
0
async def test_poll_query(query_state, http_code, app, access_token_builder,
                          dummy_zmq_server):
    """
    Test that correct status code and any redirect is returned when polling a running query
    """
    client, db, log_dir, app = app

    token = access_token_builder({
        "modal_location": {
            "permissions": {
                "poll": True
            },
            "spatial_aggregation": ["DUMMY_AGGREGATION"],
        }
    })

    # The replies below are in response to the following messages:
    #  - get_query_kind
    #  - poll_query
    #
    # {'status': 'done', 'msg': '', 'payload': {'query_id': '5ffe4a96dbe33a117ae9550178b81836', 'query_kind': 'modal_location'}}
    # {'status': 'done', 'msg': '', 'payload': {'query_id': '5ffe4a96dbe33a117ae9550178b81836', 'query_kind': 'modal_location', 'query_state': 'completed'}}
    #
    dummy_zmq_server.side_effect = return_once(
        ZMQReply(
            status="success",
            payload={
                "query_id": "DUMMY_QUERY_ID",
                "query_params": {
                    "query_kind": "modal_location",
                    "aggregation_unit": "DUMMY_AGGREGATION",
                },
            },
        ).as_json(),
        then=ZMQReply(
            status="success",
            payload={
                "query_id": "DUMMY_QUERY_ID",
                "query_state": query_state
            },
        ).as_json(),
    )
    response = await client.get(f"/api/0/poll/DUMMY_QUERY_ID",
                                headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == http_code
    if query_state == "success":
        assert "/api/0/get/DUMMY_QUERY_ID" == response.headers["Location"]
Esempio n. 9
0
async def test_poll_query(action_right, query_state, http_code, app,
                          access_token_builder, dummy_zmq_server):
    """
    Test that correct status code and any redirect is returned when polling a running query
    """

    token = access_token_builder(
        [f"{action_right}&modal_location.aggregation_unit.DUMMY_AGGREGATION"])

    # The replies below are in response to the following messages:
    #  - get_query_kind
    #  - poll_query
    #
    # {'status': 'done', 'msg': '', 'payload': {'query_id': '5ffe4a96dbe33a117ae9550178b81836', 'query_kind': 'modal_location'}}
    # {'status': 'done', 'msg': '', 'payload': {'query_id': '5ffe4a96dbe33a117ae9550178b81836', 'query_kind': 'modal_location', 'query_state': 'completed'}}
    #
    dummy_zmq_server.side_effect = return_once(
        ZMQReply(
            status="success",
            payload={
                "query_id": "DUMMY_QUERY_ID",
                "query_params": {
                    "query_kind": "modal_location",
                    "aggregation_unit": "DUMMY_AGGREGATION",
                },
            },
        ),
        then=ZMQReply(
            status="success",
            payload={
                "query_id": "DUMMY_QUERY_ID",
                "query_state": query_state,
                "progress": {
                    "eligible": 0,
                    "queued": 0,
                    "executing": 0
                },
            },
        ),
    )
    response = await app.client.get(
        f"/api/0/poll/DUMMY_QUERY_ID",
        headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == http_code
    if query_state == "success":
        assert "/api/0/get/DUMMY_QUERY_ID" == response.headers["Location"]
Esempio n. 10
0
async def test_poll_bad_query(app, access_token_builder, dummy_zmq_server):
    """
    Test that correct status code and any redirect is returned when polling a running query
    """

    token = token = access_token_builder(
        [f"run&modal_location.aggregation_unit.DUMMY_AGGREGATION"])

    dummy_zmq_server.side_effect = return_once(
        ZMQReply(
            status="error",
            msg=f"Unknown query id: 'DUMMY_QUERY_ID'",
            payload={
                "query_id": "DUMMY_QUERY_ID",
                "query_state": "awol"
            },
        ))
    response = await app.client.get(
        f"/api/0/poll/DUMMY_QUERY_ID",
        headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 404