示例#1
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"]
示例#2
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"]
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
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"
示例#5
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
示例#6
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")
示例#7
0
def test_list_jobs(timer_client):
    meta = load_response(timer_client.list_jobs).metadata
    response = timer_client.list_jobs()
    assert response.http_status == 200
    assert set(
        meta["job_ids"]) == {job["job_id"]
                             for job in response.data["jobs"]}
示例#8
0
def test_create_job(timer_client, start, interval):
    meta = load_response(timer_client.create_job).metadata
    transfer_client = TransferClient()
    transfer_client.get_submission_id = lambda *_0, **_1: {"value": "mock"}
    transfer_data = TransferData(transfer_client, GO_EP1_ID, GO_EP2_ID)
    timer_job = TimerJob.from_transfer_data(transfer_data, start, interval)
    response = timer_client.create_job(timer_job)
    assert response.http_status == 201
    assert response.data["job_id"] == meta["job_id"]
    timer_job = TimerJob.from_transfer_data(dict(transfer_data), start,
                                            interval)
    response = timer_client.create_job(timer_job)
    assert response.http_status == 201
    assert response.data["job_id"] == meta["job_id"]
    req_body = json.loads(get_last_request().body)
    if isinstance(start, datetime):
        assert req_body["start"] == start.isoformat()
    else:
        assert req_body["start"] == start
    if isinstance(interval, timedelta):
        assert req_body["interval"] == interval.total_seconds()
    else:
        assert req_body["interval"] == interval
    assert req_body["callback_url"] == slash_join(get_service_url("actions"),
                                                  "/transfer/transfer/run")
def test_identity_map_batch_limit(client):
    meta1 = load_response(client.get_identities).metadata
    meta2 = load_response(client.get_identities, case="sirosen").metadata

    # setup the ID map with a size limit of 1
    idmap = globus_sdk.IdentityMap(client, id_batch_size=1)
    idmap.add(meta2["id"])
    idmap.add(meta1["id"])

    # no requests yet...
    assert len(responses.calls) == 0

    # do the first lookup, using the second ID to be added
    # only one call should be made
    assert idmap[meta1["id"]]["username"] == meta1["username"]
    assert len(responses.calls) == 1
    # 1 ID left unresolved
    assert len(idmap.unresolved_ids) == 1
    # the last (only) API call was by ID with one ID
    last_req = get_last_request()
    assert "usernames" not in last_req.params
    assert last_req.params == {"ids": meta1["id"]}

    # second lookup works as well
    assert idmap[meta2["id"]]["username"] == meta2["username"]
    assert len(responses.calls) == 2
    # no IDs left unresolved
    assert len(idmap.unresolved_ids) == 0
    # the last API call was by ID with one ID
    last_req = get_last_request()
    assert "usernames" not in last_req.params
    assert last_req.params == {"ids": meta2["id"]}
示例#10
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()
示例#11
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()
def test_search_role_list(search_client):
    meta = load_response(search_client.get_role_list).metadata

    res = search_client.get_role_list(meta["index_id"])
    assert res.http_status == 200
    role_list = res["role_list"]
    assert isinstance(role_list, list)
    assert len(role_list) == 2
示例#13
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
def test_search_role_delete(search_client):
    meta = load_response(search_client.delete_role).metadata

    res = search_client.delete_role(meta["index_id"], meta["role_id"])
    assert res.http_status == 200
    assert res["success"] is True
    assert res["deleted"]["index_id"] == meta["index_id"]
    assert res["deleted"]["id"] == meta["role_id"]
示例#15
0
def test_delete_storage_gateway(client):
    meta = load_response(client.delete_storage_gateway).metadata

    res = client.delete_storage_gateway(meta["id"])
    assert res.http_status == 200

    # confirm top level access to response data
    assert res["code"] == "success"
    assert res["message"] == "Operation successful"
示例#16
0
def test_my_groups_simple(groups_client):
    meta = load_response(groups_client.get_my_groups).metadata

    res = groups_client.get_my_groups()
    assert res.http_status == 200

    assert isinstance(res, ArrayResponse)
    assert isinstance(res.data, list)
    assert set(meta["group_names"]) == {g["name"] for g in res}
示例#17
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()
示例#18
0
def test_update_storage_gateway(client):
    meta = load_response(client.update_storage_gateway).metadata

    # as in the create test, an empty update document is not very realistic
    # but because there's no request validation, this is fine
    res = client.update_storage_gateway(meta["id"], {})
    assert res.http_status == 200

    # confirm top level access to response data
    assert res["code"] == "success"
    assert res["message"] == "Operation successful"
示例#19
0
def test_get_identities_success(usernames, client):
    data = load_response(client.get_identities)
    res = client.get_identities(usernames=usernames)

    assert [x["id"] for x in res] == [data.metadata["id"]]

    lastreq = get_last_request()
    assert lastreq.params == {
        "usernames": "*****@*****.**",
        "provision": "false",  # provision defaults to false
    }
示例#20
0
def test_create_storage_gateway(client):
    meta = load_response(client.create_storage_gateway).metadata

    # the SDK does not validate the create document, so an empty document is fine, if
    # unrealistic, with a mocked response
    res = client.create_storage_gateway({})
    assert res.http_status == 200

    # confirm top level access to storage gateway data
    assert res["id"] == meta["id"]
    assert res["display_name"] == meta["display_name"]
def test_identity_map_del(client):
    meta = load_response(client.get_identities).metadata
    idmap = globus_sdk.IdentityMap(client)
    identity_id = idmap[meta["username"]]["id"]
    del idmap[identity_id]
    assert idmap.get(meta["username"])["id"] == identity_id
    # we've only made one request so far
    assert len(responses.calls) == 1
    # but a lookup by ID after a del is going to trigger another request because we've
    # invalidated the cached ID data and are asking the IDMap to look it up again
    assert idmap.get(identity_id)["username"] == meta["username"]
    assert len(responses.calls) == 2
def test_identity_map_prepopulated_cache(client):
    meta = load_response(client.get_identities).metadata

    # populate the cache, even with nulls it should stop any lookups from happening
    cache = {meta["id"]: None, meta["username"]: None}
    idmap = globus_sdk.IdentityMap(client, cache=cache)
    # no requests yet...
    assert len(responses.calls) == 0
    # do the lookups
    assert idmap[meta["id"]] is None
    assert idmap[meta["username"]] is None
    # still no calls made
    assert len(responses.calls) == 0
示例#23
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)
示例#24
0
def test_search_post_query_simple(search_client, query_doc):
    meta = load_response(search_client.post_search).metadata

    res = search_client.post_search(meta["index_id"], query_doc)
    assert res.http_status == 200

    data = res.data
    assert isinstance(data, dict)
    assert data["gmeta"][0]["entries"][0]["content"]["foo"] == "bar"

    req = get_last_request()
    assert req.body is not None
    req_body = json.loads(req.body)
    assert req_body == dict(query_doc)
示例#25
0
def test_get_group_include(groups_client, include_param):
    meta = load_response(groups_client.get_group).metadata
    expect_param = (",".join(include_param)
                    if not isinstance(include_param, str) else include_param)

    res = groups_client.get_group(group_id=meta["group_id"],
                                  include=include_param)
    assert res.http_status == 200
    assert "Claptrap" in res["name"]

    req = get_last_request()
    assert req.body is None
    parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query)
    assert len(parsed_qs["include"]) == 1
    assert parsed_qs["include"][0] == expect_param
def test_search_role_create(search_client):
    meta = load_response(search_client.create_role).metadata
    send_data = {
        "role_name": meta["role_name"],
        "principal": "urn:globus:auth:identity:" + meta["identity_id"],
    }

    res = search_client.create_role(meta["index_id"], send_data)
    assert res.http_status == 200
    assert res["index_id"] == meta["index_id"]
    assert res["role_name"] == "writer"

    last_req = get_last_request()
    sent = json.loads(last_req.body)
    assert sent == send_data
示例#27
0
def test_search_query_simple(search_client):
    meta = load_response(search_client.search).metadata

    res = search_client.search(meta["index_id"], q="foo")
    assert res.http_status == 200

    data = res.data
    assert isinstance(data, dict)
    assert data["gmeta"][0]["entries"][0]["content"]["foo"] == "bar"

    req = get_last_request()
    assert req.body is None
    parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query)
    assert parsed_qs == {
        "q": ["foo"],
        "advanced": ["False"],
        "limit": ["10"],
        "offset": ["0"],
    }
示例#28
0
def test_get_storage_gateway(client, include_param):
    meta = load_response(client.get_storage_gateway).metadata

    res = client.get_storage_gateway(meta["id"], include=include_param)
    assert res.http_status == 200

    # confirm top level access to storage gateway data
    assert res["id"] == meta["id"]
    assert res["display_name"] == meta["display_name"]

    req = get_last_request()
    assert req.body is None
    parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query)
    if include_param is None:
        assert parsed_qs == {}
    elif isinstance(include_param, str):
        assert parsed_qs == {"include": [include_param]}
    else:
        assert parsed_qs == {"include": [",".join(include_param)]}
示例#29
0
def test_search_post_query_arg_overrides(search_client, query_doc):
    meta = load_response(search_client.post_search).metadata

    res = search_client.post_search(meta["index_id"],
                                    query_doc,
                                    limit=100,
                                    offset=150)
    assert res.http_status == 200

    data = res.data
    assert isinstance(data, dict)
    assert data["gmeta"][0]["entries"][0]["content"]["foo"] == "bar"

    req = get_last_request()
    assert req.body is not None
    req_body = json.loads(req.body)
    assert req_body != dict(query_doc)
    assert req_body["q"] == query_doc["q"]
    assert req_body["limit"] == 100
    assert req_body["offset"] == 150
    # important! these should be unchanged (no side-effects)
    assert query_doc["limit"] == 10
    assert query_doc["offset"] == 0
示例#30
0
def test_get_storage_gateway_list(client, include_param):
    meta = load_response(client.get_storage_gateway_list).metadata
    expect_ids = meta["ids"]

    res = client.get_storage_gateway_list(include=include_param)
    assert res.http_status == 200

    # confirm iterable and sanity check some fields
    assert len(list(res)) > 0
    for sg in res:
        assert sg["DATA_TYPE"] == "storage_gateway#1.0.0"
        assert "id" in sg
        assert "display_name" in sg
    assert [sg["id"] for sg in res] == expect_ids

    req = get_last_request()
    assert req.body is None
    parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query)
    if include_param is None:
        assert parsed_qs == {}
    elif isinstance(include_param, str):
        assert parsed_qs == {"include": [include_param]}
    else:
        assert parsed_qs == {"include": [",".join(include_param)]}