コード例 #1
0
def test_no_retry_with_authorizer_no_handler(client):
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           status=401,
                           body="Unauthorized"))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    # an authorizer class which does nothing and does not claim to handle
    # unauthorized errors
    dummy_authz_calls = []

    class DummyAuthorizer(globus_sdk.authorizers.GlobusAuthorizer):
        def get_authorization_header(self):
            dummy_authz_calls.append("set_authz")
            return "foo"

        def handle_missing_authorization(self):
            dummy_authz_calls.append("handle_missing")
            return False

    authorizer = DummyAuthorizer()
    client.authorizer = authorizer

    # error gets raised in client (no retry)
    with pytest.raises(globus_sdk.GlobusAPIError) as excinfo:
        client.get("/bar")
    assert excinfo.value.http_status == 401

    # only two calls, single setting of authz and a call to ask about handling the error
    assert dummy_authz_calls == ["set_authz", "handle_missing"]
コード例 #2
0
def test_retry_with_authorizer(client):
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           status=401,
                           body="Unauthorized"))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    # an authorizer class which does nothing but claims to support handling of
    # unauthorized errors
    dummy_authz_calls = []

    class DummyAuthorizer(globus_sdk.authorizers.GlobusAuthorizer):
        def get_authorization_header(self):
            dummy_authz_calls.append("set_authz")
            return "foo"

        def handle_missing_authorization(self):
            dummy_authz_calls.append("handle_missing")
            return True

    authorizer = DummyAuthorizer()
    client.authorizer = authorizer

    # no sign of an error in the client
    res = client.get("/bar")
    assert res.http_status == 200
    assert res["baz"] == 1

    # ensure that setting authz was called twice (once for each request)
    # and that between the two calls, handle_missing_authorization was called once
    assert dummy_authz_calls == ["set_authz", "handle_missing", "set_authz"]
コード例 #3
0
def test_no_retry_401_no_authorizer(client):
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           status=401,
                           body="Unauthorized"))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    # error gets raised in client (no retry)
    with pytest.raises(globus_sdk.GlobusAPIError) as excinfo:
        client.get("/bar")
    assert excinfo.value.http_status == 401
コード例 #4
0
def test_persistent_connection_error(client):
    for _i in range(6):
        load_response(
            RegisteredResponse(
                path="https://foo.api.globus.org/bar",
                body=requests.ConnectionError("foo-err"),
            ))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    with pytest.raises(globus_sdk.GlobusConnectionError):
        client.get("/bar")
コード例 #5
0
def test_allow_redirects_false(client):
    # based on a real response from 'GET https://auth.globus.org/'
    load_response(
        RegisteredResponse(
            path="https://foo.api.globus.org/bar",
            status=302,
            headers={
                "Date": "Fri, 15 Apr 2022 15:35:44 GMT",
                "Content-Type": "text/html",
                "Content-Length": "138",
                "Connection": "keep-alive",
                "Server": "nginx",
                "Location": "https://www.globus.org/",
            },
            body="""\
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
""",
        ))
    # NOTE: this test isn't very "real" because of where `responses` intercepts the
    # request/response action
    # even without `allow_redirects=False`, this test would pass
    # if we find a better way of testing redirect behavior, consider removing this test
    res = client.request("GET", "/bar", allow_redirects=False)
    assert res.http_status == 302
コード例 #6
0
def test_retry_on_transient_error(client, mocksleep, error_status):
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           status=error_status,
                           body="Uh-oh!"))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    # no sign of an error in the client
    res = client.get("/bar")
    assert res.http_status == 200
    assert res["baz"] == 1

    # there was a sleep (retry was triggered)
    mocksleep.assert_called_once()
コード例 #7
0
def test_transport_retry_limit(client, mocksleep):
    # this limit is a safety to protect against a bad policy causing infinite retries
    client.transport.max_retries = 2

    for _i in range(3):
        load_response(
            RegisteredResponse(path="https://foo.api.globus.org/bar",
                               status=500,
                               body="Uh-oh!"))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    with pytest.raises(globus_sdk.GlobusAPIError):
        client.get("/bar")

    assert mocksleep.call_count == 2
コード例 #8
0
def test_retry_disabled_via_tune(client, mocksleep):
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           status=500,
                           body="Uh-oh!"))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    # the error is seen by the client (automatic retry does not hide it)
    with pytest.raises(globus_sdk.GlobusAPIError) as excinfo:
        with client.transport.tune(max_retries=0):
            client.get("/bar")
    assert excinfo.value.http_status == 500

    # there was a no sleep (retry was not triggered)
    mocksleep.assert_not_called()
コード例 #9
0
def test_retry_on_network_error(client, mocksleep):
    # set the response to be a requests NetworkError -- responses will raise the
    # exception when the call is made
    load_response(
        RegisteredResponse(
            path="https://foo.api.globus.org/bar",
            body=requests.ConnectionError("foo-err"),
        ))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    # no sign of an error in the client
    res = client.get("/bar")
    assert res.http_status == 200
    assert res["baz"] == 1

    # there was a sleep (retry was triggered)
    mocksleep.assert_called_once()
コード例 #10
0
def test_stream_true(client):
    load_response(
        RegisteredResponse(
            path="https://foo.api.globus.org/bar",
            json={"foo": "bar"},
        ))
    res = client.request("GET", "/bar", stream=True)
    assert res.http_status == 200
    # forcing JSON evaluation still works as expected (this must force the download /
    # evaluation of content)
    assert res["foo"] == "bar"
コード例 #11
0
def test_retry_limit(client, mocksleep, num_errors, expect_err):
    # N errors followed by a success
    for _i in range(num_errors):
        load_response(
            RegisteredResponse(path="https://foo.api.globus.org/bar",
                               status=500,
                               body="Uh-oh!"))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    if expect_err:
        with pytest.raises(globus_sdk.GlobusAPIError):
            client.get("/bar")
    else:
        # no sign of an error in the client
        res = client.get("/bar")
        assert res.http_status == 200
        assert res["baz"] == 1

    # default num retries = 5
    assert mocksleep.call_count == min(num_errors, 5)
コード例 #12
0
def test_retry_with_authorizer_persistent_401(client):
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           status=401,
                           body="Unauthorized"))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           status=401,
                           body="Unauthorized"))
    load_response(
        RegisteredResponse(path="https://foo.api.globus.org/bar",
                           json={"baz": 1}))

    # an authorizer class which does nothing but claims to support handling of
    # unauthorized errors
    dummy_authz_calls = []

    class DummyAuthorizer(globus_sdk.authorizers.GlobusAuthorizer):
        def get_authorization_header(self):
            dummy_authz_calls.append("set_authz")
            return "foo"

        def handle_missing_authorization(self):
            dummy_authz_calls.append("handle_missing")
            return True

    authorizer = DummyAuthorizer()
    client.authorizer = authorizer

    # the error gets raised in this case because it persists -- the authorizer only gets
    # one chance to resolve the issue
    with pytest.raises(globus_sdk.GlobusAPIError) as excinfo:
        client.get("/bar")
    assert excinfo.value.http_status == 401

    # ensure that setting authz was called twice (once for each request)
    # and that between the two calls, handle_missing_authorization was called once
    # but the handler should not be called a second time because the 401 repeated
    assert dummy_authz_calls == ["set_authz", "handle_missing", "set_authz"]