def test_additional_request_post_headers(monkeypatch): """ Tests that the `PrestoRequest.post` function can take addtional headers and that it combines them with the existing ones to perform the request. """ post_recorder = ArgumentsRecorder() monkeypatch.setattr(PrestoRequest.http.Session, "post", post_recorder) req = PrestoRequest( host="coordinator", port=8080, user="******", source="test", catalog="test", schema="test", http_scheme="http", session_properties={}, ) sql = 'select 1' additional_headers = { 'X-Presto-Fake-1': 'one', 'X-Presto-Fake-2': 'two', } combined_headers = req.http_headers combined_headers.update(additional_headers) req.post(sql, additional_headers) # Validate that the post call was performed including the addtional headers assert post_recorder.kwargs['headers'] == combined_headers
def test_presto_fetch_error(monkeypatch): monkeypatch.setattr(PrestoRequest.http.Response, "json", get_json_get_error_0) req = PrestoRequest( host="coordinator", port=8080, user="******", source="test", catalog="test", schema="test", http_scheme="http", session_properties={}, ) http_resp = PrestoRequest.http.Response() http_resp.status_code = 200 with pytest.raises(presto.exceptions.PrestoUserError) as exception_info: req.process(http_resp) error = exception_info.value assert error.error_code == 1 assert error.error_name == "SYNTAX_ERROR" assert error.error_type == "USER_ERROR" assert error.error_exception == "com.facebook.presto.sql.analyzer.SemanticException" assert "stack" in error.failure_info assert len(error.failure_info["stack"]) == 25 assert "suppressed" in error.failure_info assert ( error.message == "line 1:15: Schema must be specified when session schema is not set") assert error.error_location == (1, 15) assert error.query_id == "20161116_205844_00002_xtnym"
def test_gateway_redirect(monkeypatch): http_resp = PrestoRequest.http.Response() http_resp.status_code = 200 gateway_response = FakeGatewayResponse(http_resp, redirect_count=3) monkeypatch.setattr(PrestoRequest.http.Session, "post", gateway_response) monkeypatch.setattr(socket, "gethostbyaddr", lambda *args: ("finalhost", ["finalhost"], "1.2.3.4")) req = PrestoRequest(host="coordinator", port=8080, user="******") result = req.post("http://host:80/path/") assert gateway_response.count == 3 assert result.ok
def test_request_invalid_http_headers(): with pytest.raises(ValueError) as value_error: PrestoRequest( host="coordinator", port=8080, user="******", http_headers={constants.HEADER_USER: "******"}, ) assert str( value_error.value).startswith("cannot override reserved HTTP header")
def test_presto_connection_error(monkeypatch, error_code, error_type, error_message): monkeypatch.setattr(PrestoRequest.http.Response, "json", lambda x: {}) req = PrestoRequest( host="coordinator", port=8080, user="******", source="test", catalog="test", schema="test", http_scheme="http", session_properties={}, ) http_resp = PrestoRequest.http.Response() http_resp.status_code = error_code with pytest.raises(error_type) as error: req.process(http_resp) assert error_message in str(error)
def test_presto_initial_request(monkeypatch): monkeypatch.setattr(PrestoRequest.http.Response, "json", get_json_post_0) req = PrestoRequest( host="coordinator", port=8080, user="******", source="test", catalog="test", schema="test", http_scheme="http", session_properties={}, ) http_resp = PrestoRequest.http.Response() http_resp.status_code = 200 status = req.process(http_resp) assert status.next_uri == RESP_DATA_POST_0["nextUri"] assert status.id == RESP_DATA_POST_0["id"]
def wait_for_presto_workers(host, port, timeout=180): request = PrestoRequest(host=host, port=port, user="******") sql = "SELECT state FROM system.runtime.nodes" t0 = time.time() while True: query = PrestoQuery(request, sql) rows = list(query.execute()) if any(row[0] == "active" for row in rows): break if time.time() - t0 > timeout: raise TimeoutError time.sleep(1)
def test_authentication_fail_retry(monkeypatch): post_retry = RetryRecorder(error=KerberosExchangeError()) monkeypatch.setattr(PrestoRequest.http.Session, "post", post_retry) get_retry = RetryRecorder(error=KerberosExchangeError()) monkeypatch.setattr(PrestoRequest.http.Session, "get", get_retry) attempts = 3 kerberos_auth = KerberosAuthentication() req = PrestoRequest( host="coordinator", port=8080, user="******", http_scheme=constants.HTTPS, auth=kerberos_auth, max_attempts=attempts, ) with pytest.raises(KerberosExchangeError): req.post("URL") assert post_retry.retry_count == attempts with pytest.raises(KerberosExchangeError): req.get("URL") assert post_retry.retry_count == attempts
def test_request_timeout(): timeout = 0.1 http_scheme = "http" host = "coordinator" port = 8080 url = http_scheme + "://" + host + ":" + str( port) + constants.URL_STATEMENT_PATH def long_call(request, uri, headers): time.sleep(timeout * 2) return (200, headers, "delayed success") httpretty.enable() for method in [httpretty.POST, httpretty.GET]: httpretty.register_uri(method, url, body=long_call) # timeout without retry for request_timeout in [timeout, (timeout, timeout)]: req = PrestoRequest( host=host, port=port, user="******", http_scheme=http_scheme, max_attempts=1, request_timeout=request_timeout, ) with pytest.raises(requests.exceptions.Timeout): req.get(url) with pytest.raises(requests.exceptions.Timeout): req.post("select 1") httpretty.disable() httpretty.reset()
def test_presto_query_response_headers(): """ Validates that the `PrestoQuery.execute` function can take addtional headers that are pass the the provided request instance post function call and it returns a `PrestoResult` instance. """ class MockResponse(mock.Mock): # Fake response class @property def headers(self): return { 'X-Presto-Fake-1': 'one', 'X-Presto-Fake-2': 'two', } def json(self): return get_json_post_0(self) req = PrestoRequest( host="coordinator", port=8080, user="******", source="test", catalog="test", schema="test", http_scheme="http", session_properties={}, ) sql = 'execute my_stament using 1, 2, 3' additional_headers = { constants.HEADER_PREPARED_STATEMENT: 'my_statement=added_prepare_statement_header' } # Patch the post function to avoid making the requests, as well as to # validate that the function was called with the right arguments. with mock.patch.object(req, 'post', return_value=MockResponse()) as mock_post: query = PrestoQuery(request=req, sql=sql) result = query.execute(additional_http_headers=additional_headers) # Validate the the post function was called with the right argguments mock_post.assert_called_once_with(sql, additional_headers) # Validate the result is an instance of PrestoResult assert isinstance(result, PrestoResult)
def test_request_headers(monkeypatch): post_recorder = ArgumentsRecorder() monkeypatch.setattr(PrestoRequest.http.Session, "post", post_recorder) get_recorder = ArgumentsRecorder() monkeypatch.setattr(PrestoRequest.http.Session, "get", get_recorder) catalog = "test_catalog" schema = "test_schema" user = "******" source = "test_source" accept_encoding_header = "accept-encoding" accept_encoding_value = "identity,deflate,gzip" client_info_header = constants.HEADER_PREFIX + "Client-Info" client_info_value = "some_client_info" req = PrestoRequest( host="coordinator", port=8080, user=user, source=source, catalog=catalog, schema=schema, http_scheme="http", session_properties={}, http_headers={ accept_encoding_header: accept_encoding_value, client_info_header: client_info_value, }, redirect_handler=None, ) def assert_headers(headers): assert headers[constants.HEADER_CATALOG] == catalog assert headers[constants.HEADER_SCHEMA] == schema assert headers[constants.HEADER_SOURCE] == source assert headers[constants.HEADER_USER] == user assert headers[constants.HEADER_SESSION] == "" assert headers[accept_encoding_header] == accept_encoding_value assert headers[client_info_header] == client_info_value assert len(headers.keys()) == 8 req.post("URL") assert_headers(post_recorder.kwargs["headers"]) req.get("URL") assert_headers(get_recorder.kwargs["headers"])
def test_503_error_retry(monkeypatch): http_resp = PrestoRequest.http.Response() http_resp.status_code = 503 post_retry = RetryRecorder(result=http_resp) monkeypatch.setattr(PrestoRequest.http.Session, "post", post_retry) get_retry = RetryRecorder(result=http_resp) monkeypatch.setattr(PrestoRequest.http.Session, "get", get_retry) attempts = 3 req = PrestoRequest(host="coordinator", port=8080, user="******", max_attempts=attempts) req.post("URL") assert post_retry.retry_count == attempts req.get("URL") assert post_retry.retry_count == attempts