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
async def test_get_json_status_code( reply_msg_status, query_state, http_code, app, access_token_builder, dummy_zmq_server, ): """ Test that correct status code and any redirect is returned when getting json. """ client, db, log_dir, app = app token = access_token_builder({ "modal_location": { "permissions": { "get_result": True }, "spatial_aggregation": ["DUMMY_AGGREGATION"], } }) # The replies below are in response to the following messages: # - get_query_kind # - get_query_params # - get_sql_for_query_result dummy_zmq_server.side_effect = ( ZMQReply( status="success", payload={ "query_id": "DUMMY_QUERY_ID", "query_params": { "aggregation_unit": "DUMMY_AGGREGATION", "query_kind": "modal_location", }, }, ), ZMQReply( status=reply_msg_status, msg= "Some error", # note: in a real zmq message this would only be present in the "error" case, but we provide it for all test cases (it is simply ignored in the success case) payload={ "query_id": "DUMMY_QUERY_ID", "query_state": query_state, "sql": "SELECT 1;", # note: in a real zmq message this would only be present in the "success" case, but we provide it for all test cases (it is simply ignored in the error case) }, ), ) response = await client.get(f"/api/0/get/DUMMY_QUERY_ID", headers={"Authorization": f"Bearer {token}"}) assert http_code == response.status_code
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
async def test_post_query(app, dummy_zmq_server, access_token_builder): """ Test that correct status of 202 & redirect is returned when sending a query. """ token = access_token_builder([ "run&daily_location.aggregation_unit.admin2", "run&daily_location.aggregation_unit.admin3", ]) dummy_zmq_server.return_value = ZMQReply( status="success", payload={ "query_id": "DUMMY_QUERY_ID", "progress": { "eligible": 0, "queued": 0, "executing": 0 }, }, ) response = await app.client.post( f"/api/0/run", headers={"Authorization": f"Bearer {token}"}, json={ "query_kind": "daily_location", "date": "2016-01-01", "aggregation_unit": "admin3", }, ) assert response.status_code == 202 assert "/api/0/poll/DUMMY_QUERY_ID" == response.headers["Location"]
async def test_post_query(app, dummy_zmq_server, access_token_builder): """ Test that correct status of 202 & redirect is returned when sending a query. """ token = access_token_builder({ "daily_location": { "permissions": { "run": True }, "spatial_aggregation": ["admin3"], } }) dummy_zmq_server.return_value = ZMQReply( status="success", payload={"query_id": "DUMMY_QUERY_ID"}) response = await app.client.post( f"/api/0/run", headers={"Authorization": f"Bearer {token}"}, json={ "query_kind": "daily_location", "date": "2016-01-01", "aggregation_unit": "admin3", }, ) assert response.status_code == 202 assert "/api/0/poll/DUMMY_QUERY_ID" == response.headers["Location"]
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"]
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"]
async def test_get_geography(app, access_token_builder, dummy_zmq_server): """ Test that JSON is returned when getting a query. """ client, db, log_dir, app = app aggregation_unit = "DUMMY_AGGREGATION" # Set the rows returned by iterating over the rows from the db # This is a long chain of mocks corresponding to getting a connection using # the pool's context manager, getting the cursor on that, and then looping # over the values in cursor db.acquire.return_value.__aenter__.return_value.cursor.return_value.__aiter__.return_value = [ { "some": "valid" }, { "json": "bits" }, ] token = access_token_builder({ "geography": { "permissions": { "get_result": True }, "spatial_aggregation": [aggregation_unit], } }) zmq_reply = ZMQReply(status="success", payload={ "query_state": "completed", "sql": "SELECT 1;" }) dummy_zmq_server.side_effect = (zmq_reply.as_json(), ) response = await client.get( f"/api/0/geography/{aggregation_unit}", headers={"Authorization": f"Bearer {token}"}, ) gjs = loads(await response.get_data()) assert 200 == response.status_code assert "FeatureCollection" == gjs["type"] assert [{"some": "valid"}, {"json": "bits"}] == gjs["features"] assert "application/geo+json" == response.headers["content-type"] assert (f"attachment;filename={aggregation_unit}.geojson" == response.headers["content-disposition"])
async def test_get_geography_status(status, http_code, app, dummy_zmq_server, access_token_builder): """ Test that correct status code is returned when server returns an error. """ client, db, log_dir, app = app token = access_token_builder({ "geography": { "permissions": { "get_result": True }, "spatial_aggregation": ["DUMMY_AGGREGATION"], } }) zmq_reply = ZMQReply(status="error", msg="Some error") dummy_zmq_server.side_effect = (zmq_reply.as_json(), ) response = await client.get( f"/api/0/geography/DUMMY_AGGREGATION", headers={"Authorization": f"Bearer {token}"}, ) assert http_code == response.status_code
async def test_get_geography_status(status, http_code, app, dummy_zmq_server, access_token_builder): """ Test that correct status code is returned when server returns an error. """ token = access_token_builder( ["get_result&geography.aggregation_unit.DUMMY_AGGREGATION"]) zmq_reply = ZMQReply(status="error", msg="Some error") dummy_zmq_server.side_effect = (zmq_reply, ) response = await app.client.get( f"/api/0/geography/DUMMY_AGGREGATION", headers={"Authorization": f"Bearer {token}"}, ) assert http_code == response.status_code
async def test_post_query_error(query, expected_msg, app, dummy_zmq_server, access_token_builder): """ Test that correct status of 400 is returned for a broken query. """ token = access_token_builder([f"run&spatial_aggregate"]) dummy_zmq_server.return_value = ZMQReply(status="error", msg="Broken query") response = await app.client.post( f"/api/0/run", headers={"Authorization": f"Bearer {token}"}, json=query) json = await response.get_json() assert response.status_code == 400 assert expected_msg == json["msg"]
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
async def test_post_query_error(query, expected_msg, app, dummy_zmq_server, access_token_builder): """ Test that correct status of 400 is returned for a broken query. """ client, db, log_dir, app = app token = access_token_builder( {"daily_location": { "permissions": { "run": True } }}) dummy_zmq_server.return_value = ZMQReply(status="error", msg="Broken query") response = await client.post(f"/api/0/run", headers={"Authorization": f"Bearer {token}"}, json=query) json = await response.get_json() assert response.status_code == 400 assert expected_msg == json["msg"]
async def test_get_error_message_without_query_state( app, access_token_builder, dummy_zmq_server, monkeypatch ): """ Test that the get/ endpoint returns the correct error message if the reply payload does not contain a query state. """ # Monkeypatch can_get_results_by_query_id so that we don't have to set a sequence # of replies as side-effects of dummy_zmq_server just to verify token permissions monkeypatch.setattr( "flowapi.user_model.UserObject.can_get_results_by_query_id", CoroutineMock(return_value=True), ) dummy_zmq_server.return_value = ZMQReply(status="error", msg="DUMMY_ERROR_MESSAGE") response = await app.client.get( f"/api/0/get/DUMMY_QUERY_ID", headers={"Authorization": f"Bearer {access_token_builder({})}"}, ) json = await response.get_json() assert 500 == response.status_code assert "DUMMY_ERROR_MESSAGE" == json["msg"]