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"]}
def test_http_methods(method, allows_body, base_client): """ BaseClient.{get, delete, post, put, patch} on a path does "the right thing" Sends a text body or JSON body as requested Raises a GlobusAPIError if the response is not a 200 NOTE: tests sending request bodies even on GET (which *shouldn't* have bodies but *may* have them in reality). """ methodname = method.upper() resolved_method = getattr(base_client, method) path = "/madeuppath/objectname" register_api_route("transfer", path, method=methodname, json={"x": "y"}) # request with no body res = resolved_method(path) req = get_last_request() assert req.method == methodname assert req.body is None assert "x" in res assert res["x"] == "y" if allows_body: jsonbody = {"foo": "bar"} res = resolved_method(path, data=jsonbody) req = get_last_request() assert req.method == methodname assert req.body == json.dumps(jsonbody).encode("utf-8") assert "x" in res assert res["x"] == "y" res = resolved_method(path, data="abc") req = get_last_request() assert req.method == methodname assert req.body == "abc" assert "x" in res assert res["x"] == "y" # send "bad" request for status in ERROR_STATUS_CODES: register_api_route( "transfer", "/madeuppath/objectname", method=methodname, status=status, json={"x": "y", "code": "ErrorCode", "message": "foo"}, replace=True, ) with pytest.raises(globus_sdk.GlobusAPIError) as excinfo: resolved_method("/madeuppath/objectname") assert excinfo.value.http_status == status assert excinfo.value.raw_json["x"] == "y" assert excinfo.value.code == "ErrorCode" assert excinfo.value.message == "foo"
def test_set_group_policies_explicit_payload(groups_client): register_api_route_fixture_file( "groups", "/v2/groups/d3974728-6458-11e4-b72d-123139141556/policies", "set_group_policies.json", method="PUT", ) # same payload as the above test, but formulated without GroupsManager payload = GroupPolicies( is_high_assurance=False, group_visibility=GroupVisibility.private, group_members_visibility=GroupMemberVisibility.managers, join_requests=False, signup_fields=[GroupRequiredSignupFields.address1], authentication_assurance_timeout=28800, ) # set a string in the payload directly # this will pass through GroupPolicies.__setitem__ payload["group_visibility"] = "authenticated" # now send it... (but ignore the response) groups_client.set_group_policies("d3974728-6458-11e4-b72d-123139141556", payload) # ensure enums were stringified correctly, but also that the raw string came through req = get_last_request() req_body = json.loads(req.body) assert req_body["group_visibility"] == "authenticated" assert req_body["group_members_visibility"] == "managers" assert req_body["signup_fields"] == ["address1"]
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_operation_ls(client): """ Does an `ls` on go#ep1, validate results, and check that the request parameters were formatted and sent correctly. """ # register get_endpoint mock data register_api_route_fixture_file( "transfer", f"/operation/endpoint/{GO_EP1_ID}/ls", "operation_ls_goep1.json" ) ls_path = f"https://transfer.api.globus.org/v0.10/operation/endpoint/{GO_EP1_ID}/ls" # load the tutorial endpoint ls doc ls_doc = client.operation_ls(GO_EP1_ID) # check that the result is an iterable of file and dir dict objects count = 0 for x in ls_doc: assert "DATA_TYPE" in x assert x["DATA_TYPE"] in ("file", "dir") count += 1 # not exact, just make sure the fixture wasn't empty assert count > 3 req = get_last_request() assert req.url == ls_path # don't change the registered response # the resulting data might be "wrong", but we're just checking request formatting # orderby with a single str client.operation_ls(GO_EP1_ID, orderby="name") req = get_last_request() parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query) assert parsed_qs == {"orderby": ["name"]} # orderby multiple strs client.operation_ls(GO_EP1_ID, orderby=["size DESC", "name", "type"]) req = get_last_request() parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query) assert parsed_qs == {"orderby": ["size DESC,name,type"]} # orderby + filter client.operation_ls(GO_EP1_ID, orderby="name", filter="name:~*.png") req = get_last_request() parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query) assert parsed_qs == {"orderby": ["name"], "filter": ["name:~*.png"]}
def test_task_list(client, client_kwargs, qs): register_api_route_fixture_file("transfer", "/task_list", "task_list.json") client.task_list(**client_kwargs) req = get_last_request() parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query) # parsed_qs will have each value as a list (because query-params are a multidict) # so transform the test data to match before comparison assert parsed_qs == {k: [v] for k, v in qs.items()}
def test_get_role_list_params(client): """ confirms include, collection_id, and arbitrary query_params arguments to get_role_list are assembled correctly """ register_api_route_fixture_file("gcs", "/roles", "role_list.json") # no args res = client.get_role_list() assert res["code"] == "success" params = get_last_request().params assert params == {} # collection_id res = client.get_role_list(collection_id="{collection_id_1}") assert res["code"] == "success" params = get_last_request().params assert params == {"collection_id": "{collection_id_1}"} # include res = client.get_role_list(include="all_roles") assert res["code"] == "success" params = get_last_request().params assert params == {"include": "all_roles"} # query_params res = client.get_role_list(query_params={"foo": "bar"}) assert res["code"] == "success" params = get_last_request().params assert params == {"foo": "bar"} # everything together res = client.get_role_list( collection_id="{collection_id_1}", include="all_roles", query_params={"foo": "bar"}, ) assert res["code"] == "success" params = get_last_request().params assert params == { "collection_id": "{collection_id_1}", "include": "all_roles", "foo": "bar", }
def test_task_wait_bad_args_min_wait(client, mocksleep, add_kwargs): # register task mock data even though it should not be needed register_api_route_fixture_file("transfer", f"/task/{TASK1_ID}", "get_task1_active.json") with pytest.raises(globus_sdk.GlobusSDKUsageError): client.task_wait(TASK1_ID, **add_kwargs) # no requests sent, no sleep done assert get_last_request() is None mocksleep.assert_not_called()
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 }
def test_get_identities_multiple_ids_success(ids, client): data = load_response(client.get_identities, case="multiple") expect_param = ",".join(data.metadata["ids"]) res = client.get_identities(ids=ids) assert [x["id"] for x in res] == data.metadata["ids"] assert [x["username"] for x in res] == data.metadata["usernames"] lastreq = get_last_request() assert "ids" in lastreq.params assert lastreq.params["ids"] == expect_param
def test_identity_map_keyerror(client): load_response(client.get_identities, case="sirosen") idmap = globus_sdk.IdentityMap(client) # a name which doesn't come back, indicating that it was not found, will KeyError with pytest.raises(KeyError): idmap["*****@*****.**"] last_req = get_last_request() assert last_req.params == { "usernames": "*****@*****.**", "provision": "false" }
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)
def test_autoactivation(client): """ Do `autoactivate` on go#ep1, validate results, and check that `if_expires_in` can be passed correctly. """ # register get_endpoint mock data register_api_route_fixture_file( "transfer", f"/endpoint/{GO_EP1_ID}/autoactivate", "activation_stub.json", method="POST", ) # load and check the activation doc res = client.endpoint_autoactivate(GO_EP1_ID) assert res["code"] == "AutoActivated.CachedCredential" # check the formatted url for the request req = get_last_request() assert ( req.url == f"https://transfer.api.globus.org/v0.10/endpoint/{GO_EP1_ID}/autoactivate" ) register_api_route_fixture_file( "transfer", f"/endpoint/{GO_EP1_ID}/autoactivate", "activation_already_activated_stub.json", method="POST", replace=True, ) res = client.endpoint_autoactivate(GO_EP1_ID, if_expires_in=300) assert res["code"] == "AlreadyActivated" req = get_last_request() parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query) assert parsed_qs == {"if_expires_in": ["300"]}
def test_update_endpoint_rewrites_activation_servers(client): """ Update endpoint, validate results """ epid = "example-id" register_api_route_fixture_file( "transfer", f"/endpoint/{epid}", "ep_create.json", method="PUT" ) # sending myproxy_server implicitly adds oauth_server=null update_data = {"myproxy_server": "foo"} client.update_endpoint(epid, update_data.copy()) req = get_last_request() assert json.loads(req.body) != update_data update_data["oauth_server"] = None assert json.loads(req.body) == update_data # sending oauth_server implicitly adds myproxy_server=null update_data = {"oauth_server": "foo"} client.update_endpoint(epid, update_data.copy()) req = get_last_request() assert json.loads(req.body) != update_data update_data["myproxy_server"] = None assert json.loads(req.body) == update_data
def test_identity_map(client): meta = load_response(client.get_identities, case="sirosen").metadata idmap = globus_sdk.IdentityMap(client, [meta["username"]]) assert idmap[meta["username"]]["organization"] == meta["org"] # lookup by ID also works assert idmap[meta["id"]]["organization"] == meta["org"] # the last (only) API call was the one by username last_req = get_last_request() assert "ids" not in last_req.params assert last_req.params == { "usernames": meta["username"], "provision": "false" }
def test_get_identities_multiple_usernames_success(usernames, client): data = load_response(client.get_identities, case="multiple") if isinstance(usernames, str): expect_param = usernames else: expect_param = ",".join([str(x) for x in usernames]) res = client.get_identities(usernames=usernames) assert [x["username"] for x in res] == data.metadata["usernames"] assert [x["id"] for x in res] == data.metadata["ids"] lastreq = get_last_request() assert "usernames" in lastreq.params assert lastreq.params["usernames"] == 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
def test_create_endpoint(client): register_api_route_fixture_file( "transfer", "/endpoint", "ep_create.json", method="POST" ) create_data = {"display_name": "Name", "description": "desc"} create_doc = client.create_endpoint(create_data) # make sure response is a successful update assert create_doc["DATA_TYPE"] == "endpoint_create_result" assert create_doc["code"] == "Created" assert create_doc["message"] == "Endpoint created successfully" req = get_last_request() assert json.loads(req.body) == create_data
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_identity_map_multiple(client): meta = load_response(client.get_identities, case="multiple").metadata idmap = globus_sdk.IdentityMap(client, ["*****@*****.**", "*****@*****.**"]) assert idmap["*****@*****.**"]["organization"] == "Globus Team" assert idmap["*****@*****.**"]["organization"] is None last_req = get_last_request() # order doesn't matter, but it should be just these two # if IdentityMap doesn't deduplicate correctly, it could send # `[email protected],[email protected],[email protected]` on the first lookup assert last_req.params["usernames"].split(",") in [ meta["usernames"], meta["usernames"][::-1], ] assert last_req.params["provision"] == "false"
def test_update_endpoint(client): epid = uuid.uuid1() register_api_route_fixture_file( "transfer", f"/endpoint/{epid}", "ep_update.json", method="PUT" ) # NOTE: pass epid as UUID, not str # requires that TransferClient correctly translates it update_data = {"display_name": "Updated Name", "description": "Updated description"} update_doc = client.update_endpoint(epid, update_data) # make sure response is a successful update assert update_doc["DATA_TYPE"] == "result" assert update_doc["code"] == "Updated" assert update_doc["message"] == "Endpoint updated successfully" req = get_last_request() assert json.loads(req.body) == update_data
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"], }
def test_create_role(client): register_api_route_fixture_file("gcs", "/roles", "role_document.json", method="POST") data = GCSRoleDocument( collection="{collection_id_1}", principal="urn:globus:auth:identity:{user_id_1}", role="owner", ) res = client.create_role(data) assert res["id"] == "{role_id_1}" json_body = json.loads(get_last_request().body) assert json_body["collection"] in (None, "{collection_id_1}") assert json_body["principal"] == "urn:globus:auth:identity:{user_id_1}" assert json_body["role"] in ("owner", "administrator")
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)]}
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
def test_set_group_policies(groups_manager): register_api_route_fixture_file( "groups", "/v2/groups/d3974728-6458-11e4-b72d-123139141556/policies", "set_group_policies.json", method="PUT", ) resp = groups_manager.set_group_policies( "d3974728-6458-11e4-b72d-123139141556", is_high_assurance=False, group_visibility=GroupVisibility.private, group_members_visibility=GroupMemberVisibility.managers, join_requests=False, signup_fields=[GroupRequiredSignupFields.address1], authentication_assurance_timeout=28800, ) assert resp.http_status == 200 assert "address1" in resp.data["signup_fields"] # ensure enums were stringified correctly req = get_last_request() req_body = json.loads(req.body) assert req_body["group_visibility"] == "private" assert req_body["group_members_visibility"] == "managers" assert req_body["signup_fields"] == ["address1"]
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)]}
def get_last_params(): return get_last_request().params
def test_get_identities_provision(inval, outval, client): load_response(client.get_identities) client.get_identities(usernames="*****@*****.**", provision=inval) lastreq = get_last_request() assert "provision" in lastreq.params assert lastreq.params["provision"] == outval