google-adk 0.0.3__py3-none-any.whl → 0.0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google/adk/agents/run_config.py +4 -0
- google/adk/auth/auth_preprocessor.py +19 -16
- google/adk/cli/browser/index.html +1 -1
- google/adk/cli/browser/{main-SY2WYYGV.js → main-SLIAU2JL.js} +46 -30
- google/adk/cli/cli.py +8 -8
- google/adk/cli/cli_deploy.py +2 -4
- google/adk/cli/cli_tools_click.py +6 -6
- google/adk/flows/llm_flows/base_llm_flow.py +1 -1
- google/adk/flows/llm_flows/contents.py +21 -1
- google/adk/flows/llm_flows/functions.py +3 -1
- google/adk/models/google_llm.py +0 -1
- google/adk/runners.py +13 -2
- google/adk/version.py +1 -1
- {google_adk-0.0.3.dist-info → google_adk-0.0.5.dist-info}/METADATA +4 -2
- google_adk-0.0.5.dist-info/RECORD +175 -0
- {google_adk-0.0.3.dist-info → google_adk-0.0.5.dist-info}/WHEEL +1 -1
- google_adk-0.0.5.dist-info/licenses/LICENSE +202 -0
- google/adk/._version.py +0 -0
- google/adk/docs/Makefile +0 -20
- google/adk/docs/build/doctrees/google-adk.doctree +0 -0
- google/adk/docs/build/html/_sources/google-adk.rst.txt +0 -98
- google/adk/docs/build/html/_sources/index.rst.txt +0 -7
- google/adk/docs/build/html/_static/autodoc_pydantic.css +0 -27
- google/adk/docs/build/html/_static/basic.css +0 -925
- google/adk/docs/build/html/_static/debug.css +0 -85
- google/adk/docs/build/html/_static/doctools.js +0 -156
- google/adk/docs/build/html/_static/documentation_options.js +0 -29
- google/adk/docs/build/html/_static/file.png +0 -0
- google/adk/docs/build/html/_static/language_data.js +0 -199
- google/adk/docs/build/html/_static/minus.png +0 -0
- google/adk/docs/build/html/_static/plus.png +0 -0
- google/adk/docs/build/html/_static/pygments.css +0 -274
- google/adk/docs/build/html/_static/scripts/furo-extensions.js +0 -16
- google/adk/docs/build/html/_static/scripts/furo.js +0 -19
- google/adk/docs/build/html/_static/scripts/furo.js.LICENSE.txt +0 -7
- google/adk/docs/build/html/_static/scripts/furo.js.map +0 -1
- google/adk/docs/build/html/_static/searchtools.js +0 -620
- google/adk/docs/build/html/_static/skeleton.css +0 -312
- google/adk/docs/build/html/_static/sphinx_highlight.js +0 -170
- google/adk/docs/build/html/_static/styles/furo-extensions.css +0 -18
- google/adk/docs/build/html/_static/styles/furo-extensions.css.map +0 -1
- google/adk/docs/build/html/_static/styles/furo.css +0 -18
- google/adk/docs/build/html/_static/styles/furo.css.map +0 -1
- google/adk/docs/build/html/genindex.html +0 -861
- google/adk/docs/build/html/google-adk.html +0 -5461
- google/adk/docs/build/html/index.html +0 -567
- google/adk/docs/build/html/objects.inv +0 -0
- google/adk/docs/build/html/py-modindex.html +0 -373
- google/adk/docs/build/html/search.html +0 -333
- google/adk/docs/build/html/searchindex.js +0 -17
- google/adk/docs/source/conf.py +0 -133
- google/adk/docs/source/google-adk.rst +0 -98
- google/adk/docs/source/index.rst +0 -7
- google/adk/tests/__init__.py +0 -14
- google/adk/tests/integration/.env.example +0 -10
- google/adk/tests/integration/__init__.py +0 -18
- google/adk/tests/integration/conftest.py +0 -119
- google/adk/tests/integration/fixture/__init__.py +0 -14
- google/adk/tests/integration/fixture/agent_with_config/__init__.py +0 -15
- google/adk/tests/integration/fixture/agent_with_config/agent.py +0 -88
- google/adk/tests/integration/fixture/callback_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/callback_agent/agent.py +0 -105
- google/adk/tests/integration/fixture/context_update_test/OWNERS +0 -1
- google/adk/tests/integration/fixture/context_update_test/__init__.py +0 -15
- google/adk/tests/integration/fixture/context_update_test/agent.py +0 -43
- google/adk/tests/integration/fixture/context_update_test/successful_test.session.json +0 -582
- google/adk/tests/integration/fixture/context_variable_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/context_variable_agent/agent.py +0 -115
- google/adk/tests/integration/fixture/customer_support_ma/__init__.py +0 -15
- google/adk/tests/integration/fixture/customer_support_ma/agent.py +0 -172
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/agent.py +0 -338
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/order_query.test.json +0 -69
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/test_config.json +0 -6
- google/adk/tests/integration/fixture/flow_complex_spark/__init__.py +0 -15
- google/adk/tests/integration/fixture/flow_complex_spark/agent.py +0 -182
- google/adk/tests/integration/fixture/flow_complex_spark/sample.session.json +0 -190
- google/adk/tests/integration/fixture/hello_world_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/hello_world_agent/agent.py +0 -95
- google/adk/tests/integration/fixture/hello_world_agent/roll_die.test.json +0 -24
- google/adk/tests/integration/fixture/hello_world_agent/test_config.json +0 -6
- google/adk/tests/integration/fixture/home_automation_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/home_automation_agent/agent.py +0 -304
- google/adk/tests/integration/fixture/home_automation_agent/simple_test.test.json +0 -5
- google/adk/tests/integration/fixture/home_automation_agent/simple_test2.test.json +0 -5
- google/adk/tests/integration/fixture/home_automation_agent/test_config.json +0 -5
- google/adk/tests/integration/fixture/home_automation_agent/test_files/dependent_tool_calls.test.json +0 -18
- google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/eval_data.test.json +0 -17
- google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/test_config.json +0 -6
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_multi_turn_conversation.test.json +0 -18
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test.test.json +0 -17
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test2.test.json +0 -5
- google/adk/tests/integration/fixture/home_automation_agent/test_files/test_config.json +0 -5
- google/adk/tests/integration/fixture/tool_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/tool_agent/agent.py +0 -218
- google/adk/tests/integration/fixture/tool_agent/files/Agent_test_plan.pdf +0 -0
- google/adk/tests/integration/fixture/trip_planner_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/trip_planner_agent/agent.py +0 -110
- google/adk/tests/integration/fixture/trip_planner_agent/initial.session.json +0 -13
- google/adk/tests/integration/fixture/trip_planner_agent/test_config.json +0 -5
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/initial.session.json +0 -13
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/test_config.json +0 -5
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/trip_inquiry_sub_agent.test.json +0 -7
- google/adk/tests/integration/fixture/trip_planner_agent/trip_inquiry.test.json +0 -19
- google/adk/tests/integration/models/__init__.py +0 -14
- google/adk/tests/integration/models/test_google_llm.py +0 -65
- google/adk/tests/integration/test_callback.py +0 -70
- google/adk/tests/integration/test_context_variable.py +0 -67
- google/adk/tests/integration/test_evalute_agent_in_fixture.py +0 -76
- google/adk/tests/integration/test_multi_agent.py +0 -28
- google/adk/tests/integration/test_multi_turn.py +0 -42
- google/adk/tests/integration/test_single_agent.py +0 -23
- google/adk/tests/integration/test_sub_agent.py +0 -26
- google/adk/tests/integration/test_system_instruction.py +0 -177
- google/adk/tests/integration/test_tools.py +0 -287
- google/adk/tests/integration/test_with_test_file.py +0 -34
- google/adk/tests/integration/tools/__init__.py +0 -14
- google/adk/tests/integration/utils/__init__.py +0 -16
- google/adk/tests/integration/utils/asserts.py +0 -75
- google/adk/tests/integration/utils/test_runner.py +0 -97
- google/adk/tests/unittests/__init__.py +0 -14
- google/adk/tests/unittests/agents/__init__.py +0 -14
- google/adk/tests/unittests/agents/test_base_agent.py +0 -407
- google/adk/tests/unittests/agents/test_langgraph_agent.py +0 -191
- google/adk/tests/unittests/agents/test_llm_agent_callbacks.py +0 -138
- google/adk/tests/unittests/agents/test_llm_agent_fields.py +0 -231
- google/adk/tests/unittests/agents/test_loop_agent.py +0 -136
- google/adk/tests/unittests/agents/test_parallel_agent.py +0 -92
- google/adk/tests/unittests/agents/test_sequential_agent.py +0 -114
- google/adk/tests/unittests/artifacts/__init__.py +0 -14
- google/adk/tests/unittests/artifacts/test_artifact_service.py +0 -276
- google/adk/tests/unittests/auth/test_auth_handler.py +0 -575
- google/adk/tests/unittests/conftest.py +0 -73
- google/adk/tests/unittests/fast_api/__init__.py +0 -14
- google/adk/tests/unittests/fast_api/test_fast_api.py +0 -269
- google/adk/tests/unittests/flows/__init__.py +0 -14
- google/adk/tests/unittests/flows/llm_flows/__init__.py +0 -14
- google/adk/tests/unittests/flows/llm_flows/_test_examples.py +0 -142
- google/adk/tests/unittests/flows/llm_flows/test_agent_transfer.py +0 -311
- google/adk/tests/unittests/flows/llm_flows/test_functions_long_running.py +0 -244
- google/adk/tests/unittests/flows/llm_flows/test_functions_request_euc.py +0 -346
- google/adk/tests/unittests/flows/llm_flows/test_functions_sequential.py +0 -93
- google/adk/tests/unittests/flows/llm_flows/test_functions_simple.py +0 -258
- google/adk/tests/unittests/flows/llm_flows/test_identity.py +0 -66
- google/adk/tests/unittests/flows/llm_flows/test_instructions.py +0 -164
- google/adk/tests/unittests/flows/llm_flows/test_model_callbacks.py +0 -142
- google/adk/tests/unittests/flows/llm_flows/test_other_configs.py +0 -46
- google/adk/tests/unittests/flows/llm_flows/test_tool_callbacks.py +0 -269
- google/adk/tests/unittests/models/__init__.py +0 -14
- google/adk/tests/unittests/models/test_google_llm.py +0 -224
- google/adk/tests/unittests/models/test_litellm.py +0 -804
- google/adk/tests/unittests/models/test_models.py +0 -60
- google/adk/tests/unittests/sessions/__init__.py +0 -14
- google/adk/tests/unittests/sessions/test_session_service.py +0 -227
- google/adk/tests/unittests/sessions/test_vertex_ai_session_service.py +0 -246
- google/adk/tests/unittests/streaming/__init__.py +0 -14
- google/adk/tests/unittests/streaming/test_streaming.py +0 -50
- google/adk/tests/unittests/tools/__init__.py +0 -14
- google/adk/tests/unittests/tools/apihub_tool/clients/test_apihub_client.py +0 -499
- google/adk/tests/unittests/tools/apihub_tool/test_apihub_toolset.py +0 -204
- google/adk/tests/unittests/tools/application_integration_tool/clients/test_connections_client.py +0 -600
- google/adk/tests/unittests/tools/application_integration_tool/clients/test_integration_client.py +0 -630
- google/adk/tests/unittests/tools/application_integration_tool/test_application_integration_toolset.py +0 -345
- google/adk/tests/unittests/tools/google_api_tool/__init__.py +0 -13
- google/adk/tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py +0 -657
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_auto_auth_credential_exchanger.py +0 -145
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_base_auth_credential_exchanger.py +0 -68
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_oauth2_exchanger.py +0 -153
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_service_account_exchanger.py +0 -196
- google/adk/tests/unittests/tools/openapi_tool/auth/test_auth_helper.py +0 -573
- google/adk/tests/unittests/tools/openapi_tool/common/test_common.py +0 -436
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test.yaml +0 -1367
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_spec_parser.py +0 -628
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_toolset.py +0 -139
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_operation_parser.py +0 -406
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_rest_api_tool.py +0 -966
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_tool_auth_handler.py +0 -201
- google/adk/tests/unittests/tools/retrieval/__init__.py +0 -14
- google/adk/tests/unittests/tools/retrieval/test_vertex_ai_rag_retrieval.py +0 -147
- google/adk/tests/unittests/tools/test_agent_tool.py +0 -167
- google/adk/tests/unittests/tools/test_base_tool.py +0 -141
- google/adk/tests/unittests/tools/test_build_function_declaration.py +0 -277
- google/adk/tests/unittests/utils.py +0 -304
- google_adk-0.0.3.dist-info/RECORD +0 -340
- {google_adk-0.0.3.dist-info → google_adk-0.0.5.dist-info}/entry_points.txt +0 -0
google/adk/tests/unittests/tools/application_integration_tool/clients/test_connections_client.py
DELETED
@@ -1,600 +0,0 @@
|
|
1
|
-
# Copyright 2025 Google LLC
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
|
15
|
-
import json
|
16
|
-
from unittest import mock
|
17
|
-
|
18
|
-
from google.adk.tools.application_integration_tool.clients.connections_client import ConnectionsClient
|
19
|
-
import google.auth
|
20
|
-
import pytest
|
21
|
-
import requests
|
22
|
-
from requests import exceptions
|
23
|
-
|
24
|
-
|
25
|
-
@pytest.fixture
|
26
|
-
def project():
|
27
|
-
return "test-project"
|
28
|
-
|
29
|
-
|
30
|
-
@pytest.fixture
|
31
|
-
def location():
|
32
|
-
return "us-central1"
|
33
|
-
|
34
|
-
|
35
|
-
@pytest.fixture
|
36
|
-
def connection_name():
|
37
|
-
return "test-connection"
|
38
|
-
|
39
|
-
|
40
|
-
@pytest.fixture
|
41
|
-
def mock_credentials():
|
42
|
-
creds = mock.create_autospec(google.auth.credentials.Credentials)
|
43
|
-
creds.token = "test_token"
|
44
|
-
creds.expired = False
|
45
|
-
return creds
|
46
|
-
|
47
|
-
|
48
|
-
@pytest.fixture
|
49
|
-
def mock_auth_request():
|
50
|
-
return mock.create_autospec(google.auth.transport.requests.Request)
|
51
|
-
|
52
|
-
|
53
|
-
class TestConnectionsClient:
|
54
|
-
|
55
|
-
def test_initialization(self, project, location, connection_name):
|
56
|
-
credentials = {"email": "test@example.com"}
|
57
|
-
client = ConnectionsClient(
|
58
|
-
project, location, connection_name, json.dumps(credentials)
|
59
|
-
)
|
60
|
-
assert client.project == project
|
61
|
-
assert client.location == location
|
62
|
-
assert client.connection == connection_name
|
63
|
-
assert client.connector_url == "https://connectors.googleapis.com"
|
64
|
-
assert client.service_account_json == json.dumps(credentials)
|
65
|
-
assert client.credential_cache is None
|
66
|
-
|
67
|
-
def test_execute_api_call_success(
|
68
|
-
self, project, location, connection_name, mock_credentials
|
69
|
-
):
|
70
|
-
credentials = {"email": "test@example.com"}
|
71
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
72
|
-
mock_response = mock.MagicMock()
|
73
|
-
mock_response.status_code = 200
|
74
|
-
mock_response.raise_for_status.return_value = None
|
75
|
-
mock_response.json.return_value = {"data": "test"}
|
76
|
-
|
77
|
-
with mock.patch.object(
|
78
|
-
client, "_get_access_token", return_value=mock_credentials.token
|
79
|
-
), mock.patch("requests.get", return_value=mock_response):
|
80
|
-
response = client._execute_api_call("https://test.url")
|
81
|
-
assert response.json() == {"data": "test"}
|
82
|
-
requests.get.assert_called_once_with(
|
83
|
-
"https://test.url",
|
84
|
-
headers={
|
85
|
-
"Content-Type": "application/json",
|
86
|
-
"Authorization": f"Bearer {mock_credentials.token}",
|
87
|
-
},
|
88
|
-
)
|
89
|
-
|
90
|
-
def test_execute_api_call_credential_error(
|
91
|
-
self, project, location, connection_name
|
92
|
-
):
|
93
|
-
credentials = {"email": "test@example.com"}
|
94
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
95
|
-
with mock.patch.object(
|
96
|
-
client,
|
97
|
-
"_get_access_token",
|
98
|
-
side_effect=google.auth.exceptions.DefaultCredentialsError("Test"),
|
99
|
-
):
|
100
|
-
with pytest.raises(PermissionError, match="Credentials error: Test"):
|
101
|
-
client._execute_api_call("https://test.url")
|
102
|
-
|
103
|
-
@pytest.mark.parametrize(
|
104
|
-
"status_code, response_text",
|
105
|
-
[(404, "Not Found"), (400, "Bad Request")],
|
106
|
-
)
|
107
|
-
def test_execute_api_call_request_error_not_found_or_bad_request(
|
108
|
-
self,
|
109
|
-
project,
|
110
|
-
location,
|
111
|
-
connection_name,
|
112
|
-
mock_credentials,
|
113
|
-
status_code,
|
114
|
-
response_text,
|
115
|
-
):
|
116
|
-
credentials = {"email": "test@example.com"}
|
117
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
118
|
-
mock_response = mock.MagicMock()
|
119
|
-
mock_response.status_code = status_code
|
120
|
-
mock_response.raise_for_status.side_effect = exceptions.HTTPError(
|
121
|
-
f"HTTP error {status_code}: {response_text}"
|
122
|
-
)
|
123
|
-
|
124
|
-
with mock.patch.object(
|
125
|
-
client, "_get_access_token", return_value=mock_credentials.token
|
126
|
-
), mock.patch("requests.get", return_value=mock_response):
|
127
|
-
with pytest.raises(
|
128
|
-
ValueError, match="Invalid request. Please check the provided"
|
129
|
-
):
|
130
|
-
client._execute_api_call("https://test.url")
|
131
|
-
|
132
|
-
def test_execute_api_call_other_request_error(
|
133
|
-
self, project, location, connection_name, mock_credentials
|
134
|
-
):
|
135
|
-
credentials = {"email": "test@example.com"}
|
136
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
137
|
-
mock_response = mock.MagicMock()
|
138
|
-
mock_response.status_code = 500
|
139
|
-
mock_response.raise_for_status.side_effect = exceptions.HTTPError(
|
140
|
-
"Internal Server Error"
|
141
|
-
)
|
142
|
-
|
143
|
-
with mock.patch.object(
|
144
|
-
client, "_get_access_token", return_value=mock_credentials.token
|
145
|
-
), mock.patch("requests.get", return_value=mock_response):
|
146
|
-
with pytest.raises(ValueError, match="Request error: "):
|
147
|
-
client._execute_api_call("https://test.url")
|
148
|
-
|
149
|
-
def test_execute_api_call_unexpected_error(
|
150
|
-
self, project, location, connection_name, mock_credentials
|
151
|
-
):
|
152
|
-
credentials = {"email": "test@example.com"}
|
153
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
154
|
-
with mock.patch.object(
|
155
|
-
client, "_get_access_token", return_value=mock_credentials.token
|
156
|
-
), mock.patch(
|
157
|
-
"requests.get", side_effect=Exception("Something went wrong")
|
158
|
-
):
|
159
|
-
with pytest.raises(
|
160
|
-
Exception, match="An unexpected error occurred: Something went wrong"
|
161
|
-
):
|
162
|
-
client._execute_api_call("https://test.url")
|
163
|
-
|
164
|
-
def test_get_connection_details_success_with_host(
|
165
|
-
self, project, location, connection_name, mock_credentials
|
166
|
-
):
|
167
|
-
credentials = {"email": "test@example.com"}
|
168
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
169
|
-
mock_response = mock.MagicMock()
|
170
|
-
mock_response.status_code = 200
|
171
|
-
mock_response.json.return_value = {
|
172
|
-
"serviceDirectory": "test_service",
|
173
|
-
"host": "test.host",
|
174
|
-
"tlsServiceDirectory": "tls_test_service",
|
175
|
-
"authOverrideEnabled": True,
|
176
|
-
}
|
177
|
-
|
178
|
-
with mock.patch.object(
|
179
|
-
client, "_execute_api_call", return_value=mock_response
|
180
|
-
):
|
181
|
-
details = client.get_connection_details()
|
182
|
-
assert details == {
|
183
|
-
"serviceName": "tls_test_service",
|
184
|
-
"host": "test.host",
|
185
|
-
"authOverrideEnabled": True,
|
186
|
-
}
|
187
|
-
|
188
|
-
def test_get_connection_details_success_without_host(
|
189
|
-
self, project, location, connection_name, mock_credentials
|
190
|
-
):
|
191
|
-
credentials = {"email": "test@example.com"}
|
192
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
193
|
-
mock_response = mock.MagicMock()
|
194
|
-
mock_response.status_code = 200
|
195
|
-
mock_response.json.return_value = {
|
196
|
-
"serviceDirectory": "test_service",
|
197
|
-
"authOverrideEnabled": False,
|
198
|
-
}
|
199
|
-
|
200
|
-
with mock.patch.object(
|
201
|
-
client, "_execute_api_call", return_value=mock_response
|
202
|
-
):
|
203
|
-
details = client.get_connection_details()
|
204
|
-
assert details == {
|
205
|
-
"serviceName": "test_service",
|
206
|
-
"host": "",
|
207
|
-
"authOverrideEnabled": False,
|
208
|
-
}
|
209
|
-
|
210
|
-
def test_get_connection_details_error(
|
211
|
-
self, project, location, connection_name
|
212
|
-
):
|
213
|
-
credentials = {"email": "test@example.com"}
|
214
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
215
|
-
with mock.patch.object(
|
216
|
-
client, "_execute_api_call", side_effect=ValueError("Request error")
|
217
|
-
):
|
218
|
-
with pytest.raises(ValueError, match="Request error"):
|
219
|
-
client.get_connection_details()
|
220
|
-
|
221
|
-
def test_get_entity_schema_and_operations_success(
|
222
|
-
self, project, location, connection_name, mock_credentials
|
223
|
-
):
|
224
|
-
credentials = {"email": "test@example.com"}
|
225
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
226
|
-
mock_execute_response_initial = mock.MagicMock()
|
227
|
-
mock_execute_response_initial.status_code = 200
|
228
|
-
mock_execute_response_initial.json.return_value = {
|
229
|
-
"name": "operations/test_op"
|
230
|
-
}
|
231
|
-
|
232
|
-
mock_execute_response_poll_done = mock.MagicMock()
|
233
|
-
mock_execute_response_poll_done.status_code = 200
|
234
|
-
mock_execute_response_poll_done.json.return_value = {
|
235
|
-
"done": True,
|
236
|
-
"response": {
|
237
|
-
"jsonSchema": {"type": "object"},
|
238
|
-
"operations": ["LIST", "GET"],
|
239
|
-
},
|
240
|
-
}
|
241
|
-
|
242
|
-
with mock.patch.object(
|
243
|
-
client,
|
244
|
-
"_execute_api_call",
|
245
|
-
side_effect=[
|
246
|
-
mock_execute_response_initial,
|
247
|
-
mock_execute_response_poll_done,
|
248
|
-
],
|
249
|
-
):
|
250
|
-
schema, operations = client.get_entity_schema_and_operations("entity1")
|
251
|
-
assert schema == {"type": "object"}
|
252
|
-
assert operations == ["LIST", "GET"]
|
253
|
-
assert (
|
254
|
-
mock.call(
|
255
|
-
f"https://connectors.googleapis.com/v1/projects/{project}/locations/{location}/connections/{connection_name}/connectionSchemaMetadata:getEntityType?entityId=entity1"
|
256
|
-
)
|
257
|
-
in client._execute_api_call.mock_calls
|
258
|
-
)
|
259
|
-
assert (
|
260
|
-
mock.call(f"https://connectors.googleapis.com/v1/operations/test_op")
|
261
|
-
in client._execute_api_call.mock_calls
|
262
|
-
)
|
263
|
-
|
264
|
-
def test_get_entity_schema_and_operations_no_operation_id(
|
265
|
-
self, project, location, connection_name, mock_credentials
|
266
|
-
):
|
267
|
-
credentials = {"email": "test@example.com"}
|
268
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
269
|
-
mock_execute_response = mock.MagicMock()
|
270
|
-
mock_execute_response.status_code = 200
|
271
|
-
mock_execute_response.json.return_value = {}
|
272
|
-
|
273
|
-
with mock.patch.object(
|
274
|
-
client, "_execute_api_call", return_value=mock_execute_response
|
275
|
-
):
|
276
|
-
with pytest.raises(
|
277
|
-
ValueError,
|
278
|
-
match=(
|
279
|
-
"Failed to get entity schema and operations for entity: entity1"
|
280
|
-
),
|
281
|
-
):
|
282
|
-
client.get_entity_schema_and_operations("entity1")
|
283
|
-
|
284
|
-
def test_get_entity_schema_and_operations_execute_api_call_error(
|
285
|
-
self, project, location, connection_name
|
286
|
-
):
|
287
|
-
credentials = {"email": "test@example.com"}
|
288
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
289
|
-
with mock.patch.object(
|
290
|
-
client, "_execute_api_call", side_effect=ValueError("Request error")
|
291
|
-
):
|
292
|
-
with pytest.raises(ValueError, match="Request error"):
|
293
|
-
client.get_entity_schema_and_operations("entity1")
|
294
|
-
|
295
|
-
def test_get_action_schema_success(
|
296
|
-
self, project, location, connection_name, mock_credentials
|
297
|
-
):
|
298
|
-
credentials = {"email": "test@example.com"}
|
299
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
300
|
-
mock_execute_response_initial = mock.MagicMock()
|
301
|
-
mock_execute_response_initial.status_code = 200
|
302
|
-
mock_execute_response_initial.json.return_value = {
|
303
|
-
"name": "operations/test_op"
|
304
|
-
}
|
305
|
-
|
306
|
-
mock_execute_response_poll_done = mock.MagicMock()
|
307
|
-
mock_execute_response_poll_done.status_code = 200
|
308
|
-
mock_execute_response_poll_done.json.return_value = {
|
309
|
-
"done": True,
|
310
|
-
"response": {
|
311
|
-
"inputJsonSchema": {
|
312
|
-
"type": "object",
|
313
|
-
"properties": {"input": {"type": "string"}},
|
314
|
-
},
|
315
|
-
"outputJsonSchema": {
|
316
|
-
"type": "object",
|
317
|
-
"properties": {"output": {"type": "string"}},
|
318
|
-
},
|
319
|
-
"description": "Test Action Description",
|
320
|
-
"displayName": "TestAction",
|
321
|
-
},
|
322
|
-
}
|
323
|
-
|
324
|
-
with mock.patch.object(
|
325
|
-
client,
|
326
|
-
"_execute_api_call",
|
327
|
-
side_effect=[
|
328
|
-
mock_execute_response_initial,
|
329
|
-
mock_execute_response_poll_done,
|
330
|
-
],
|
331
|
-
):
|
332
|
-
schema = client.get_action_schema("action1")
|
333
|
-
assert schema == {
|
334
|
-
"inputSchema": {
|
335
|
-
"type": "object",
|
336
|
-
"properties": {"input": {"type": "string"}},
|
337
|
-
},
|
338
|
-
"outputSchema": {
|
339
|
-
"type": "object",
|
340
|
-
"properties": {"output": {"type": "string"}},
|
341
|
-
},
|
342
|
-
"description": "Test Action Description",
|
343
|
-
"displayName": "TestAction",
|
344
|
-
}
|
345
|
-
assert (
|
346
|
-
mock.call(
|
347
|
-
f"https://connectors.googleapis.com/v1/projects/{project}/locations/{location}/connections/{connection_name}/connectionSchemaMetadata:getAction?actionId=action1"
|
348
|
-
)
|
349
|
-
in client._execute_api_call.mock_calls
|
350
|
-
)
|
351
|
-
assert (
|
352
|
-
mock.call(f"https://connectors.googleapis.com/v1/operations/test_op")
|
353
|
-
in client._execute_api_call.mock_calls
|
354
|
-
)
|
355
|
-
|
356
|
-
def test_get_action_schema_no_operation_id(
|
357
|
-
self, project, location, connection_name, mock_credentials
|
358
|
-
):
|
359
|
-
credentials = {"email": "test@example.com"}
|
360
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
361
|
-
mock_execute_response = mock.MagicMock()
|
362
|
-
mock_execute_response.status_code = 200
|
363
|
-
mock_execute_response.json.return_value = {}
|
364
|
-
|
365
|
-
with mock.patch.object(
|
366
|
-
client, "_execute_api_call", return_value=mock_execute_response
|
367
|
-
):
|
368
|
-
with pytest.raises(
|
369
|
-
ValueError, match="Failed to get action schema for action: action1"
|
370
|
-
):
|
371
|
-
client.get_action_schema("action1")
|
372
|
-
|
373
|
-
def test_get_action_schema_execute_api_call_error(
|
374
|
-
self, project, location, connection_name
|
375
|
-
):
|
376
|
-
credentials = {"email": "test@example.com"}
|
377
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
378
|
-
with mock.patch.object(
|
379
|
-
client, "_execute_api_call", side_effect=ValueError("Request error")
|
380
|
-
):
|
381
|
-
with pytest.raises(ValueError, match="Request error"):
|
382
|
-
client.get_action_schema("action1")
|
383
|
-
|
384
|
-
def test_get_connector_base_spec(self):
|
385
|
-
spec = ConnectionsClient.get_connector_base_spec()
|
386
|
-
assert "openapi" in spec
|
387
|
-
assert spec["info"]["title"] == "ExecuteConnection"
|
388
|
-
assert "components" in spec
|
389
|
-
assert "schemas" in spec["components"]
|
390
|
-
assert "operation" in spec["components"]["schemas"]
|
391
|
-
|
392
|
-
def test_get_action_operation(self):
|
393
|
-
operation = ConnectionsClient.get_action_operation(
|
394
|
-
"TestAction", "EXECUTE_ACTION", "TestActionDisplayName", "test_tool"
|
395
|
-
)
|
396
|
-
assert "post" in operation
|
397
|
-
assert operation["post"]["summary"] == "TestActionDisplayName"
|
398
|
-
assert "operationId" in operation["post"]
|
399
|
-
assert operation["post"]["operationId"] == "test_tool_TestActionDisplayName"
|
400
|
-
|
401
|
-
def test_list_operation(self):
|
402
|
-
operation = ConnectionsClient.list_operation(
|
403
|
-
"Entity1", '{"type": "object"}', "test_tool"
|
404
|
-
)
|
405
|
-
assert "post" in operation
|
406
|
-
assert operation["post"]["summary"] == "List Entity1"
|
407
|
-
assert "operationId" in operation["post"]
|
408
|
-
assert operation["post"]["operationId"] == "test_tool_list_Entity1"
|
409
|
-
|
410
|
-
def test_get_operation_static(self):
|
411
|
-
operation = ConnectionsClient.get_operation(
|
412
|
-
"Entity1", '{"type": "object"}', "test_tool"
|
413
|
-
)
|
414
|
-
assert "post" in operation
|
415
|
-
assert operation["post"]["summary"] == "Get Entity1"
|
416
|
-
assert "operationId" in operation["post"]
|
417
|
-
assert operation["post"]["operationId"] == "test_tool_get_Entity1"
|
418
|
-
|
419
|
-
def test_create_operation(self):
|
420
|
-
operation = ConnectionsClient.create_operation("Entity1", "test_tool")
|
421
|
-
assert "post" in operation
|
422
|
-
assert operation["post"]["summary"] == "Create Entity1"
|
423
|
-
assert "operationId" in operation["post"]
|
424
|
-
assert operation["post"]["operationId"] == "test_tool_create_Entity1"
|
425
|
-
|
426
|
-
def test_update_operation(self):
|
427
|
-
operation = ConnectionsClient.update_operation("Entity1", "test_tool")
|
428
|
-
assert "post" in operation
|
429
|
-
assert operation["post"]["summary"] == "Update Entity1"
|
430
|
-
assert "operationId" in operation["post"]
|
431
|
-
assert operation["post"]["operationId"] == "test_tool_update_Entity1"
|
432
|
-
|
433
|
-
def test_delete_operation(self):
|
434
|
-
operation = ConnectionsClient.delete_operation("Entity1", "test_tool")
|
435
|
-
assert "post" in operation
|
436
|
-
assert operation["post"]["summary"] == "Delete Entity1"
|
437
|
-
assert operation["post"]["operationId"] == "test_tool_delete_Entity1"
|
438
|
-
|
439
|
-
def test_create_operation_request(self):
|
440
|
-
schema = ConnectionsClient.create_operation_request("Entity1")
|
441
|
-
assert "type" in schema
|
442
|
-
assert schema["type"] == "object"
|
443
|
-
assert "properties" in schema
|
444
|
-
assert "connectorInputPayload" in schema["properties"]
|
445
|
-
|
446
|
-
def test_update_operation_request(self):
|
447
|
-
schema = ConnectionsClient.update_operation_request("Entity1")
|
448
|
-
assert "type" in schema
|
449
|
-
assert schema["type"] == "object"
|
450
|
-
assert "properties" in schema
|
451
|
-
assert "entityId" in schema["properties"]
|
452
|
-
|
453
|
-
def test_get_operation_request_static(self):
|
454
|
-
schema = ConnectionsClient.get_operation_request()
|
455
|
-
assert "type" in schema
|
456
|
-
assert schema["type"] == "object"
|
457
|
-
assert "properties" in schema
|
458
|
-
assert "entityId" in schema["properties"]
|
459
|
-
|
460
|
-
def test_delete_operation_request(self):
|
461
|
-
schema = ConnectionsClient.delete_operation_request()
|
462
|
-
assert "type" in schema
|
463
|
-
assert schema["type"] == "object"
|
464
|
-
assert "properties" in schema
|
465
|
-
assert "entityId" in schema["properties"]
|
466
|
-
|
467
|
-
def test_list_operation_request(self):
|
468
|
-
schema = ConnectionsClient.list_operation_request()
|
469
|
-
assert "type" in schema
|
470
|
-
assert schema["type"] == "object"
|
471
|
-
assert "properties" in schema
|
472
|
-
assert "filterClause" in schema["properties"]
|
473
|
-
|
474
|
-
def test_action_request(self):
|
475
|
-
schema = ConnectionsClient.action_request("TestAction")
|
476
|
-
assert "type" in schema
|
477
|
-
assert schema["type"] == "object"
|
478
|
-
assert "properties" in schema
|
479
|
-
assert "connectorInputPayload" in schema["properties"]
|
480
|
-
|
481
|
-
def test_action_response(self):
|
482
|
-
schema = ConnectionsClient.action_response("TestAction")
|
483
|
-
assert "type" in schema
|
484
|
-
assert schema["type"] == "object"
|
485
|
-
assert "properties" in schema
|
486
|
-
assert "connectorOutputPayload" in schema["properties"]
|
487
|
-
|
488
|
-
def test_execute_custom_query_request(self):
|
489
|
-
schema = ConnectionsClient.execute_custom_query_request()
|
490
|
-
assert "type" in schema
|
491
|
-
assert schema["type"] == "object"
|
492
|
-
assert "properties" in schema
|
493
|
-
assert "query" in schema["properties"]
|
494
|
-
|
495
|
-
def test_connector_payload(self):
|
496
|
-
client = ConnectionsClient("test-project", "us-central1", "test-connection")
|
497
|
-
schema = client.connector_payload(
|
498
|
-
json_schema={
|
499
|
-
"type": "object",
|
500
|
-
"properties": {
|
501
|
-
"input": {
|
502
|
-
"type": ["null", "string"],
|
503
|
-
"description": "description",
|
504
|
-
}
|
505
|
-
},
|
506
|
-
}
|
507
|
-
)
|
508
|
-
assert schema == {
|
509
|
-
"type": "object",
|
510
|
-
"properties": {
|
511
|
-
"input": {
|
512
|
-
"type": "string",
|
513
|
-
"nullable": True,
|
514
|
-
"description": "description",
|
515
|
-
}
|
516
|
-
},
|
517
|
-
}
|
518
|
-
|
519
|
-
def test_get_access_token_uses_cached_token(
|
520
|
-
self, project, location, connection_name, mock_credentials
|
521
|
-
):
|
522
|
-
credentials = {"email": "test@example.com"}
|
523
|
-
client = ConnectionsClient(project, location, connection_name, credentials)
|
524
|
-
client.credential_cache = mock_credentials
|
525
|
-
token = client._get_access_token()
|
526
|
-
assert token == "test_token"
|
527
|
-
|
528
|
-
def test_get_access_token_with_service_account_credentials(
|
529
|
-
self, project, location, connection_name
|
530
|
-
):
|
531
|
-
service_account_json = json.dumps({
|
532
|
-
"client_email": "test@example.com",
|
533
|
-
"private_key": "test_key",
|
534
|
-
})
|
535
|
-
client = ConnectionsClient(
|
536
|
-
project, location, connection_name, service_account_json
|
537
|
-
)
|
538
|
-
mock_creds = mock.create_autospec(google.oauth2.service_account.Credentials)
|
539
|
-
mock_creds.token = "sa_token"
|
540
|
-
mock_creds.expired = False
|
541
|
-
|
542
|
-
with mock.patch(
|
543
|
-
"google.oauth2.service_account.Credentials.from_service_account_info",
|
544
|
-
return_value=mock_creds,
|
545
|
-
), mock.patch.object(mock_creds, "refresh", return_value=None):
|
546
|
-
token = client._get_access_token()
|
547
|
-
assert token == "sa_token"
|
548
|
-
google.oauth2.service_account.Credentials.from_service_account_info.assert_called_once_with(
|
549
|
-
json.loads(service_account_json),
|
550
|
-
scopes=["https://www.googleapis.com/auth/cloud-platform"],
|
551
|
-
)
|
552
|
-
mock_creds.refresh.assert_called_once()
|
553
|
-
|
554
|
-
def test_get_access_token_with_default_credentials(
|
555
|
-
self, project, location, connection_name, mock_credentials
|
556
|
-
):
|
557
|
-
client = ConnectionsClient(project, location, connection_name, None)
|
558
|
-
with mock.patch(
|
559
|
-
"google.adk.tools.application_integration_tool.clients.connections_client.default_service_credential",
|
560
|
-
return_value=(mock_credentials, "test_project_id"),
|
561
|
-
), mock.patch.object(mock_credentials, "refresh", return_value=None):
|
562
|
-
token = client._get_access_token()
|
563
|
-
assert token == "test_token"
|
564
|
-
|
565
|
-
def test_get_access_token_no_valid_credentials(
|
566
|
-
self, project, location, connection_name
|
567
|
-
):
|
568
|
-
client = ConnectionsClient(project, location, connection_name, None)
|
569
|
-
with mock.patch(
|
570
|
-
"google.adk.tools.application_integration_tool.clients.connections_client.default_service_credential",
|
571
|
-
return_value=(None, None),
|
572
|
-
):
|
573
|
-
with pytest.raises(
|
574
|
-
ValueError,
|
575
|
-
match=(
|
576
|
-
"Please provide a service account that has the required"
|
577
|
-
" permissions"
|
578
|
-
),
|
579
|
-
):
|
580
|
-
client._get_access_token()
|
581
|
-
|
582
|
-
def test_get_access_token_refreshes_expired_token(
|
583
|
-
self, project, location, connection_name, mock_credentials
|
584
|
-
):
|
585
|
-
client = ConnectionsClient(project, location, connection_name, None)
|
586
|
-
mock_credentials.expired = True
|
587
|
-
mock_credentials.token = "old_token"
|
588
|
-
mock_credentials.refresh.return_value = None
|
589
|
-
|
590
|
-
client.credential_cache = mock_credentials
|
591
|
-
with mock.patch(
|
592
|
-
"google.adk.tools.application_integration_tool.clients.connections_client.default_service_credential",
|
593
|
-
return_value=(mock_credentials, "test_project_id"),
|
594
|
-
):
|
595
|
-
# Mock the refresh method directly on the instance within the context
|
596
|
-
with mock.patch.object(mock_credentials, "refresh") as mock_refresh:
|
597
|
-
mock_credentials.token = "new_token" # Set the expected new token
|
598
|
-
token = client._get_access_token()
|
599
|
-
assert token == "new_token"
|
600
|
-
mock_refresh.assert_called_once()
|