google-adk 0.0.2__py3-none-any.whl → 0.0.4__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.
Files changed (153) hide show
  1. google/adk/agents/run_config.py +4 -0
  2. google/adk/auth/auth_preprocessor.py +19 -16
  3. google/adk/cli/agent_graph.py +31 -5
  4. google/adk/cli/browser/index.html +1 -1
  5. google/adk/cli/browser/{main-XUU6OGCC.js → main-CU22TRPI.js} +30 -30
  6. google/adk/cli/cli.py +8 -8
  7. google/adk/cli/cli_deploy.py +2 -4
  8. google/adk/cli/cli_tools_click.py +57 -12
  9. google/adk/cli/fast_api.py +19 -9
  10. google/adk/flows/llm_flows/contents.py +21 -1
  11. google/adk/flows/llm_flows/functions.py +3 -1
  12. google/adk/models/google_llm.py +0 -1
  13. google/adk/runners.py +13 -2
  14. google/adk/version.py +1 -1
  15. {google_adk-0.0.2.dist-info → google_adk-0.0.4.dist-info}/METADATA +4 -2
  16. google_adk-0.0.4.dist-info/RECORD +175 -0
  17. {google_adk-0.0.2.dist-info → google_adk-0.0.4.dist-info}/WHEEL +1 -1
  18. google/adk/cli/media_streamer/__init__.py +0 -19
  19. google/adk/cli/media_streamer/index.html +0 -228
  20. google/adk/tests/__init__.py +0 -14
  21. google/adk/tests/integration/.env.example +0 -10
  22. google/adk/tests/integration/__init__.py +0 -18
  23. google/adk/tests/integration/conftest.py +0 -119
  24. google/adk/tests/integration/fixture/__init__.py +0 -14
  25. google/adk/tests/integration/fixture/agent_with_config/__init__.py +0 -15
  26. google/adk/tests/integration/fixture/agent_with_config/agent.py +0 -88
  27. google/adk/tests/integration/fixture/callback_agent/__init__.py +0 -15
  28. google/adk/tests/integration/fixture/callback_agent/agent.py +0 -105
  29. google/adk/tests/integration/fixture/context_update_test/OWNERS +0 -1
  30. google/adk/tests/integration/fixture/context_update_test/__init__.py +0 -15
  31. google/adk/tests/integration/fixture/context_update_test/agent.py +0 -43
  32. google/adk/tests/integration/fixture/context_update_test/successful_test.session.json +0 -582
  33. google/adk/tests/integration/fixture/context_variable_agent/__init__.py +0 -15
  34. google/adk/tests/integration/fixture/context_variable_agent/agent.py +0 -115
  35. google/adk/tests/integration/fixture/customer_support_ma/__init__.py +0 -15
  36. google/adk/tests/integration/fixture/customer_support_ma/agent.py +0 -172
  37. google/adk/tests/integration/fixture/ecommerce_customer_service_agent/__init__.py +0 -15
  38. google/adk/tests/integration/fixture/ecommerce_customer_service_agent/agent.py +0 -338
  39. google/adk/tests/integration/fixture/ecommerce_customer_service_agent/order_query.test.json +0 -69
  40. google/adk/tests/integration/fixture/ecommerce_customer_service_agent/test_config.json +0 -6
  41. google/adk/tests/integration/fixture/flow_complex_spark/__init__.py +0 -15
  42. google/adk/tests/integration/fixture/flow_complex_spark/agent.py +0 -182
  43. google/adk/tests/integration/fixture/flow_complex_spark/sample.debug.log +0 -243
  44. google/adk/tests/integration/fixture/flow_complex_spark/sample.session.json +0 -190
  45. google/adk/tests/integration/fixture/hello_world_agent/__init__.py +0 -15
  46. google/adk/tests/integration/fixture/hello_world_agent/agent.py +0 -95
  47. google/adk/tests/integration/fixture/hello_world_agent/roll_die.test.json +0 -24
  48. google/adk/tests/integration/fixture/hello_world_agent/test_config.json +0 -6
  49. google/adk/tests/integration/fixture/home_automation_agent/__init__.py +0 -15
  50. google/adk/tests/integration/fixture/home_automation_agent/agent.py +0 -304
  51. google/adk/tests/integration/fixture/home_automation_agent/simple_test.test.json +0 -5
  52. google/adk/tests/integration/fixture/home_automation_agent/simple_test2.test.json +0 -5
  53. google/adk/tests/integration/fixture/home_automation_agent/test_config.json +0 -5
  54. google/adk/tests/integration/fixture/home_automation_agent/test_files/dependent_tool_calls.test.json +0 -18
  55. google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/eval_data.test.json +0 -17
  56. google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/test_config.json +0 -6
  57. google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_multi_turn_conversation.test.json +0 -18
  58. google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test.test.json +0 -17
  59. google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test2.test.json +0 -5
  60. google/adk/tests/integration/fixture/home_automation_agent/test_files/test_config.json +0 -5
  61. google/adk/tests/integration/fixture/tool_agent/__init__.py +0 -15
  62. google/adk/tests/integration/fixture/tool_agent/agent.py +0 -218
  63. google/adk/tests/integration/fixture/tool_agent/files/Agent_test_plan.pdf +0 -0
  64. google/adk/tests/integration/fixture/trip_planner_agent/__init__.py +0 -15
  65. google/adk/tests/integration/fixture/trip_planner_agent/agent.py +0 -110
  66. google/adk/tests/integration/fixture/trip_planner_agent/initial.session.json +0 -13
  67. google/adk/tests/integration/fixture/trip_planner_agent/test_config.json +0 -5
  68. google/adk/tests/integration/fixture/trip_planner_agent/test_files/initial.session.json +0 -13
  69. google/adk/tests/integration/fixture/trip_planner_agent/test_files/test_config.json +0 -5
  70. google/adk/tests/integration/fixture/trip_planner_agent/test_files/trip_inquiry_sub_agent.test.json +0 -7
  71. google/adk/tests/integration/fixture/trip_planner_agent/trip_inquiry.test.json +0 -19
  72. google/adk/tests/integration/models/__init__.py +0 -14
  73. google/adk/tests/integration/models/test_google_llm.py +0 -65
  74. google/adk/tests/integration/test_callback.py +0 -70
  75. google/adk/tests/integration/test_context_variable.py +0 -67
  76. google/adk/tests/integration/test_evalute_agent_in_fixture.py +0 -76
  77. google/adk/tests/integration/test_multi_agent.py +0 -28
  78. google/adk/tests/integration/test_multi_turn.py +0 -42
  79. google/adk/tests/integration/test_single_agent.py +0 -23
  80. google/adk/tests/integration/test_sub_agent.py +0 -26
  81. google/adk/tests/integration/test_system_instruction.py +0 -177
  82. google/adk/tests/integration/test_tools.py +0 -287
  83. google/adk/tests/integration/test_with_test_file.py +0 -34
  84. google/adk/tests/integration/tools/__init__.py +0 -14
  85. google/adk/tests/integration/utils/__init__.py +0 -16
  86. google/adk/tests/integration/utils/asserts.py +0 -75
  87. google/adk/tests/integration/utils/test_runner.py +0 -97
  88. google/adk/tests/unittests/__init__.py +0 -14
  89. google/adk/tests/unittests/agents/__init__.py +0 -14
  90. google/adk/tests/unittests/agents/test_base_agent.py +0 -407
  91. google/adk/tests/unittests/agents/test_langgraph_agent.py +0 -191
  92. google/adk/tests/unittests/agents/test_llm_agent_callbacks.py +0 -138
  93. google/adk/tests/unittests/agents/test_llm_agent_fields.py +0 -231
  94. google/adk/tests/unittests/agents/test_loop_agent.py +0 -136
  95. google/adk/tests/unittests/agents/test_parallel_agent.py +0 -92
  96. google/adk/tests/unittests/agents/test_sequential_agent.py +0 -114
  97. google/adk/tests/unittests/artifacts/__init__.py +0 -14
  98. google/adk/tests/unittests/artifacts/test_artifact_service.py +0 -276
  99. google/adk/tests/unittests/auth/test_auth_handler.py +0 -575
  100. google/adk/tests/unittests/conftest.py +0 -73
  101. google/adk/tests/unittests/fast_api/__init__.py +0 -14
  102. google/adk/tests/unittests/fast_api/test_fast_api.py +0 -269
  103. google/adk/tests/unittests/flows/__init__.py +0 -14
  104. google/adk/tests/unittests/flows/llm_flows/__init__.py +0 -14
  105. google/adk/tests/unittests/flows/llm_flows/_test_examples.py +0 -142
  106. google/adk/tests/unittests/flows/llm_flows/test_agent_transfer.py +0 -311
  107. google/adk/tests/unittests/flows/llm_flows/test_functions_long_running.py +0 -244
  108. google/adk/tests/unittests/flows/llm_flows/test_functions_request_euc.py +0 -346
  109. google/adk/tests/unittests/flows/llm_flows/test_functions_sequential.py +0 -93
  110. google/adk/tests/unittests/flows/llm_flows/test_functions_simple.py +0 -258
  111. google/adk/tests/unittests/flows/llm_flows/test_identity.py +0 -66
  112. google/adk/tests/unittests/flows/llm_flows/test_instructions.py +0 -164
  113. google/adk/tests/unittests/flows/llm_flows/test_model_callbacks.py +0 -142
  114. google/adk/tests/unittests/flows/llm_flows/test_other_configs.py +0 -46
  115. google/adk/tests/unittests/flows/llm_flows/test_tool_callbacks.py +0 -269
  116. google/adk/tests/unittests/models/__init__.py +0 -14
  117. google/adk/tests/unittests/models/test_google_llm.py +0 -224
  118. google/adk/tests/unittests/models/test_litellm.py +0 -804
  119. google/adk/tests/unittests/models/test_models.py +0 -60
  120. google/adk/tests/unittests/sessions/__init__.py +0 -14
  121. google/adk/tests/unittests/sessions/test_session_service.py +0 -227
  122. google/adk/tests/unittests/sessions/test_vertex_ai_session_service.py +0 -246
  123. google/adk/tests/unittests/streaming/__init__.py +0 -14
  124. google/adk/tests/unittests/streaming/test_streaming.py +0 -50
  125. google/adk/tests/unittests/tools/__init__.py +0 -14
  126. google/adk/tests/unittests/tools/apihub_tool/clients/test_apihub_client.py +0 -499
  127. google/adk/tests/unittests/tools/apihub_tool/test_apihub_toolset.py +0 -204
  128. google/adk/tests/unittests/tools/application_integration_tool/clients/test_connections_client.py +0 -600
  129. google/adk/tests/unittests/tools/application_integration_tool/clients/test_integration_client.py +0 -630
  130. google/adk/tests/unittests/tools/application_integration_tool/test_application_integration_toolset.py +0 -345
  131. google/adk/tests/unittests/tools/google_api_tool/__init__.py +0 -13
  132. google/adk/tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py +0 -657
  133. google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_auto_auth_credential_exchanger.py +0 -145
  134. google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_base_auth_credential_exchanger.py +0 -68
  135. google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_oauth2_exchanger.py +0 -153
  136. google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_service_account_exchanger.py +0 -196
  137. google/adk/tests/unittests/tools/openapi_tool/auth/test_auth_helper.py +0 -573
  138. google/adk/tests/unittests/tools/openapi_tool/common/test_common.py +0 -436
  139. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test.yaml +0 -1367
  140. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_spec_parser.py +0 -628
  141. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_toolset.py +0 -139
  142. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_operation_parser.py +0 -406
  143. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_rest_api_tool.py +0 -966
  144. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_tool_auth_handler.py +0 -201
  145. google/adk/tests/unittests/tools/retrieval/__init__.py +0 -14
  146. google/adk/tests/unittests/tools/retrieval/test_vertex_ai_rag_retrieval.py +0 -147
  147. google/adk/tests/unittests/tools/test_agent_tool.py +0 -167
  148. google/adk/tests/unittests/tools/test_base_tool.py +0 -141
  149. google/adk/tests/unittests/tools/test_build_function_declaration.py +0 -277
  150. google/adk/tests/unittests/utils.py +0 -304
  151. google_adk-0.0.2.dist-info/RECORD +0 -308
  152. {google_adk-0.0.2.dist-info → google_adk-0.0.4.dist-info}/entry_points.txt +0 -0
  153. {google_adk-0.0.2.dist-info → google_adk-0.0.4.dist-info/licenses}/LICENSE +0 -0
@@ -1,499 +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 base64
16
- import json
17
- from unittest.mock import MagicMock, patch
18
- from google.adk.tools.apihub_tool.clients.apihub_client import APIHubClient
19
- import pytest
20
- from requests.exceptions import HTTPError
21
-
22
- # Mock data for API responses
23
- MOCK_API_LIST = {
24
- "apis": [
25
- {"name": "projects/test-project/locations/us-central1/apis/api1"},
26
- {"name": "projects/test-project/locations/us-central1/apis/api2"},
27
- ]
28
- }
29
- MOCK_API_DETAIL = {
30
- "name": "projects/test-project/locations/us-central1/apis/api1",
31
- "versions": [
32
- "projects/test-project/locations/us-central1/apis/api1/versions/v1"
33
- ],
34
- }
35
- MOCK_API_VERSION = {
36
- "name": "projects/test-project/locations/us-central1/apis/api1/versions/v1",
37
- "specs": [
38
- "projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1"
39
- ],
40
- }
41
- MOCK_SPEC_CONTENT = {"contents": base64.b64encode(b"spec content").decode()}
42
-
43
-
44
- # Test cases
45
- class TestAPIHubClient:
46
-
47
- @pytest.fixture
48
- def client(self):
49
- return APIHubClient(access_token="mocked_token")
50
-
51
- @pytest.fixture
52
- def service_account_config(self):
53
- return json.dumps({
54
- "type": "service_account",
55
- "project_id": "test",
56
- "token_uri": "test.com",
57
- "client_email": "test@example.com",
58
- "private_key": "1234",
59
- })
60
-
61
- @patch("requests.get")
62
- def test_list_apis(self, mock_get, client):
63
- mock_get.return_value.json.return_value = MOCK_API_LIST
64
- mock_get.return_value.status_code = 200
65
-
66
- apis = client.list_apis("test-project", "us-central1")
67
- assert apis == MOCK_API_LIST["apis"]
68
- mock_get.assert_called_once_with(
69
- "https://apihub.googleapis.com/v1/projects/test-project/locations/us-central1/apis",
70
- headers={
71
- "accept": "application/json, text/plain, */*",
72
- "Authorization": "Bearer mocked_token",
73
- },
74
- )
75
-
76
- @patch("requests.get")
77
- def test_list_apis_empty(self, mock_get, client):
78
- mock_get.return_value.json.return_value = {"apis": []}
79
- mock_get.return_value.status_code = 200
80
-
81
- apis = client.list_apis("test-project", "us-central1")
82
- assert apis == []
83
-
84
- @patch("requests.get")
85
- def test_list_apis_error(self, mock_get, client):
86
- mock_get.return_value.raise_for_status.side_effect = HTTPError
87
-
88
- with pytest.raises(HTTPError):
89
- client.list_apis("test-project", "us-central1")
90
-
91
- @patch("requests.get")
92
- def test_get_api(self, mock_get, client):
93
- mock_get.return_value.json.return_value = MOCK_API_DETAIL
94
- mock_get.return_value.status_code = 200
95
- api = client.get_api(
96
- "projects/test-project/locations/us-central1/apis/api1"
97
- )
98
- assert api == MOCK_API_DETAIL
99
- mock_get.assert_called_once_with(
100
- "https://apihub.googleapis.com/v1/projects/test-project/locations/us-central1/apis/api1",
101
- headers={
102
- "accept": "application/json, text/plain, */*",
103
- "Authorization": "Bearer mocked_token",
104
- },
105
- )
106
-
107
- @patch("requests.get")
108
- def test_get_api_error(self, mock_get, client):
109
- mock_get.return_value.raise_for_status.side_effect = HTTPError
110
- with pytest.raises(HTTPError):
111
- client.get_api("projects/test-project/locations/us-central1/apis/api1")
112
-
113
- @patch("requests.get")
114
- def test_get_api_version(self, mock_get, client):
115
- mock_get.return_value.json.return_value = MOCK_API_VERSION
116
- mock_get.return_value.status_code = 200
117
- api_version = client.get_api_version(
118
- "projects/test-project/locations/us-central1/apis/api1/versions/v1"
119
- )
120
- assert api_version == MOCK_API_VERSION
121
- mock_get.assert_called_once_with(
122
- "https://apihub.googleapis.com/v1/projects/test-project/locations/us-central1/apis/api1/versions/v1",
123
- headers={
124
- "accept": "application/json, text/plain, */*",
125
- "Authorization": "Bearer mocked_token",
126
- },
127
- )
128
-
129
- @patch("requests.get")
130
- def test_get_api_version_error(self, mock_get, client):
131
- mock_get.return_value.raise_for_status.side_effect = HTTPError
132
- with pytest.raises(HTTPError):
133
- client.get_api_version(
134
- "projects/test-project/locations/us-central1/apis/api1/versions/v1"
135
- )
136
-
137
- @patch("requests.get")
138
- def test_get_spec_content(self, mock_get, client):
139
- mock_get.return_value.json.return_value = MOCK_SPEC_CONTENT
140
- mock_get.return_value.status_code = 200
141
- spec_content = client.get_spec_content(
142
- "projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1"
143
- )
144
- assert spec_content == "spec content"
145
- mock_get.assert_called_once_with(
146
- "https://apihub.googleapis.com/v1/projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1:contents",
147
- headers={
148
- "accept": "application/json, text/plain, */*",
149
- "Authorization": "Bearer mocked_token",
150
- },
151
- )
152
-
153
- @patch("requests.get")
154
- def test_get_spec_content_empty(self, mock_get, client):
155
- mock_get.return_value.json.return_value = {"contents": ""}
156
- mock_get.return_value.status_code = 200
157
- spec_content = client.get_spec_content(
158
- "projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1"
159
- )
160
- assert spec_content == ""
161
-
162
- @patch("requests.get")
163
- def test_get_spec_content_error(self, mock_get, client):
164
- mock_get.return_value.raise_for_status.side_effect = HTTPError
165
- with pytest.raises(HTTPError):
166
- client.get_spec_content(
167
- "projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1"
168
- )
169
-
170
- @pytest.mark.parametrize(
171
- "url_or_path, expected",
172
- [
173
- (
174
- "projects/test-project/locations/us-central1/apis/api1",
175
- (
176
- "projects/test-project/locations/us-central1/apis/api1",
177
- None,
178
- None,
179
- ),
180
- ),
181
- (
182
- "projects/test-project/locations/us-central1/apis/api1/versions/v1",
183
- (
184
- "projects/test-project/locations/us-central1/apis/api1",
185
- "projects/test-project/locations/us-central1/apis/api1/versions/v1",
186
- None,
187
- ),
188
- ),
189
- (
190
- "projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1",
191
- (
192
- "projects/test-project/locations/us-central1/apis/api1",
193
- "projects/test-project/locations/us-central1/apis/api1/versions/v1",
194
- "projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1",
195
- ),
196
- ),
197
- (
198
- "https://console.cloud.google.com/apigee/api-hub/projects/test-project/locations/us-central1/apis/api1/versions/v1?project=test-project",
199
- (
200
- "projects/test-project/locations/us-central1/apis/api1",
201
- "projects/test-project/locations/us-central1/apis/api1/versions/v1",
202
- None,
203
- ),
204
- ),
205
- (
206
- "https://console.cloud.google.com/apigee/api-hub/projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1?project=test-project",
207
- (
208
- "projects/test-project/locations/us-central1/apis/api1",
209
- "projects/test-project/locations/us-central1/apis/api1/versions/v1",
210
- "projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1",
211
- ),
212
- ),
213
- (
214
- "/projects/test-project/locations/us-central1/apis/api1/versions/v1",
215
- (
216
- "projects/test-project/locations/us-central1/apis/api1",
217
- "projects/test-project/locations/us-central1/apis/api1/versions/v1",
218
- None,
219
- ),
220
- ),
221
- ( # Added trailing slashes
222
- "projects/test-project/locations/us-central1/apis/api1/",
223
- (
224
- "projects/test-project/locations/us-central1/apis/api1",
225
- None,
226
- None,
227
- ),
228
- ),
229
- ( # case location name
230
- "projects/test-project/locations/LOCATION/apis/api1/",
231
- (
232
- "projects/test-project/locations/LOCATION/apis/api1",
233
- None,
234
- None,
235
- ),
236
- ),
237
- (
238
- "projects/p1/locations/l1/apis/a1/versions/v1/specs/s1",
239
- (
240
- "projects/p1/locations/l1/apis/a1",
241
- "projects/p1/locations/l1/apis/a1/versions/v1",
242
- "projects/p1/locations/l1/apis/a1/versions/v1/specs/s1",
243
- ),
244
- ),
245
- ],
246
- )
247
- def test_extract_resource_name(self, client, url_or_path, expected):
248
- result = client._extract_resource_name(url_or_path)
249
- assert result == expected
250
-
251
- @pytest.mark.parametrize(
252
- "url_or_path, expected_error_message",
253
- [
254
- (
255
- "invalid-path",
256
- "Project ID not found in URL or path in APIHubClient.",
257
- ),
258
- (
259
- "projects/test-project",
260
- "Location not found in URL or path in APIHubClient.",
261
- ),
262
- (
263
- "projects/test-project/locations/us-central1",
264
- "API id not found in URL or path in APIHubClient.",
265
- ),
266
- ],
267
- )
268
- def test_extract_resource_name_invalid(
269
- self, client, url_or_path, expected_error_message
270
- ):
271
- with pytest.raises(ValueError, match=expected_error_message):
272
- client._extract_resource_name(url_or_path)
273
-
274
- @patch(
275
- "google.adk.tools.apihub_tool.clients.apihub_client.default_service_credential"
276
- )
277
- @patch(
278
- "google.adk.tools.apihub_tool.clients.apihub_client.service_account.Credentials.from_service_account_info"
279
- )
280
- def test_get_access_token_use_default_credential(
281
- self,
282
- mock_from_service_account_info,
283
- mock_default_service_credential,
284
- ):
285
- mock_credential = MagicMock()
286
- mock_credential.token = "default_token"
287
- mock_default_service_credential.return_value = (
288
- mock_credential,
289
- "project_id",
290
- )
291
- mock_config_credential = MagicMock()
292
- mock_config_credential.token = "config_token"
293
- mock_from_service_account_info.return_value = mock_config_credential
294
-
295
- client = APIHubClient()
296
- token = client._get_access_token()
297
- assert token == "default_token"
298
- mock_credential.refresh.assert_called_once()
299
- assert client.credential_cache == mock_credential
300
-
301
- @patch(
302
- "google.adk.tools.apihub_tool.clients.apihub_client.default_service_credential"
303
- )
304
- @patch(
305
- "google.adk.tools.apihub_tool.clients.apihub_client.service_account.Credentials.from_service_account_info"
306
- )
307
- def test_get_access_token_use_configured_service_account(
308
- self,
309
- mock_from_service_account_info,
310
- mock_default_service_credential,
311
- service_account_config,
312
- ):
313
- mock_credential = MagicMock()
314
- mock_credential.token = "default_token"
315
- mock_default_service_credential.return_value = (
316
- mock_credential,
317
- "project_id",
318
- )
319
- mock_config_credential = MagicMock()
320
- mock_config_credential.token = "config_token"
321
- mock_from_service_account_info.return_value = mock_config_credential
322
-
323
- client = APIHubClient(service_account_json=service_account_config)
324
- token = client._get_access_token()
325
-
326
- assert token == "config_token"
327
- mock_from_service_account_info.assert_called_once_with(
328
- json.loads(service_account_config),
329
- scopes=["https://www.googleapis.com/auth/cloud-platform"],
330
- )
331
- mock_config_credential.refresh.assert_called_once()
332
- assert client.credential_cache == mock_config_credential
333
-
334
- @patch(
335
- "google.adk.tools.apihub_tool.clients.apihub_client.default_service_credential"
336
- )
337
- def test_get_access_token_not_expired_use_cached_token(
338
- self, mock_default_credential
339
- ):
340
- mock_credentials = MagicMock()
341
- mock_credentials.token = "default_service_account_token"
342
- mock_default_credential.return_value = (mock_credentials, "")
343
-
344
- client = APIHubClient()
345
- # Call #1: Setup cache
346
- token = client._get_access_token()
347
- assert token == "default_service_account_token"
348
- mock_default_credential.assert_called_once()
349
-
350
- # Call #2: Reuse cache
351
- mock_credentials.reset_mock()
352
- mock_credentials.expired = False
353
- token = client._get_access_token()
354
- assert token == "default_service_account_token"
355
- mock_credentials.refresh.assert_not_called()
356
-
357
- @patch(
358
- "google.adk.tools.apihub_tool.clients.apihub_client.default_service_credential"
359
- )
360
- def test_get_access_token_expired_refresh(self, mock_default_credential):
361
- mock_credentials = MagicMock()
362
- mock_credentials.token = "default_service_account_token"
363
- mock_default_credential.return_value = (mock_credentials, "")
364
- client = APIHubClient()
365
-
366
- # Call #1: Setup cache
367
- token = client._get_access_token()
368
- assert token == "default_service_account_token"
369
- mock_default_credential.assert_called_once()
370
-
371
- # Call #2: Cache expired
372
- mock_credentials.reset_mock()
373
- mock_credentials.expired = True
374
- token = client._get_access_token()
375
- mock_credentials.refresh.assert_called_once()
376
- assert token == "default_service_account_token"
377
-
378
- @patch(
379
- "google.adk.tools.apihub_tool.clients.apihub_client.default_service_credential"
380
- )
381
- def test_get_access_token_no_credentials(
382
- self, mock_default_service_credential
383
- ):
384
- mock_default_service_credential.return_value = (None, None)
385
- with pytest.raises(
386
- ValueError,
387
- match=(
388
- "Please provide a service account or an access token to API Hub"
389
- " client."
390
- ),
391
- ):
392
- # no service account client
393
- APIHubClient()._get_access_token()
394
-
395
- @patch("requests.get")
396
- def test_get_spec_content_api_level(self, mock_get, client):
397
- mock_get.side_effect = [
398
- MagicMock(status_code=200, json=lambda: MOCK_API_DETAIL), # For get_api
399
- MagicMock(
400
- status_code=200, json=lambda: MOCK_API_VERSION
401
- ), # For get_api_version
402
- MagicMock(
403
- status_code=200, json=lambda: MOCK_SPEC_CONTENT
404
- ), # For get_spec_content
405
- ]
406
-
407
- content = client.get_spec_content(
408
- "projects/test-project/locations/us-central1/apis/api1"
409
- )
410
- assert content == "spec content"
411
- # Check calls - get_api, get_api_version, then get_spec_content
412
- assert mock_get.call_count == 3
413
-
414
- @patch("requests.get")
415
- def test_get_spec_content_version_level(self, mock_get, client):
416
- mock_get.side_effect = [
417
- MagicMock(
418
- status_code=200, json=lambda: MOCK_API_VERSION
419
- ), # For get_api_version
420
- MagicMock(
421
- status_code=200, json=lambda: MOCK_SPEC_CONTENT
422
- ), # For get_spec_content
423
- ]
424
-
425
- content = client.get_spec_content(
426
- "projects/test-project/locations/us-central1/apis/api1/versions/v1"
427
- )
428
- assert content == "spec content"
429
- assert mock_get.call_count == 2 # get_api_version and get_spec_content
430
-
431
- @patch("requests.get")
432
- def test_get_spec_content_spec_level(self, mock_get, client):
433
- mock_get.return_value.json.return_value = MOCK_SPEC_CONTENT
434
- mock_get.return_value.status_code = 200
435
-
436
- content = client.get_spec_content(
437
- "projects/test-project/locations/us-central1/apis/api1/versions/v1/specs/spec1"
438
- )
439
- assert content == "spec content"
440
- mock_get.assert_called_once() # Only get_spec_content should be called
441
-
442
- @patch("requests.get")
443
- def test_get_spec_content_no_versions(self, mock_get, client):
444
- mock_get.return_value.json.return_value = {
445
- "name": "projects/test-project/locations/us-central1/apis/api1",
446
- "versions": [],
447
- } # No versions
448
- mock_get.return_value.status_code = 200
449
- with pytest.raises(
450
- ValueError,
451
- match=(
452
- "No versions found in API Hub resource:"
453
- " projects/test-project/locations/us-central1/apis/api1"
454
- ),
455
- ):
456
- client.get_spec_content(
457
- "projects/test-project/locations/us-central1/apis/api1"
458
- )
459
-
460
- @patch("requests.get")
461
- def test_get_spec_content_no_specs(self, mock_get, client):
462
- mock_get.side_effect = [
463
- MagicMock(status_code=200, json=lambda: MOCK_API_DETAIL),
464
- MagicMock(
465
- status_code=200,
466
- json=lambda: {
467
- "name": (
468
- "projects/test-project/locations/us-central1/apis/api1/versions/v1"
469
- ),
470
- "specs": [],
471
- },
472
- ), # No specs
473
- ]
474
-
475
- with pytest.raises(
476
- ValueError,
477
- match=(
478
- "No specs found in API Hub version:"
479
- " projects/test-project/locations/us-central1/apis/api1/versions/v1"
480
- ),
481
- ):
482
- client.get_spec_content(
483
- "projects/test-project/locations/us-central1/apis/api1/versions/v1"
484
- )
485
-
486
- @patch("requests.get")
487
- def test_get_spec_content_invalid_path(self, mock_get, client):
488
- with pytest.raises(
489
- ValueError,
490
- match=(
491
- "Project ID not found in URL or path in APIHubClient. Input"
492
- " path is 'invalid-path'."
493
- ),
494
- ):
495
- client.get_spec_content("invalid-path")
496
-
497
-
498
- if __name__ == "__main__":
499
- pytest.main([__file__])
@@ -1,204 +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
- from unittest.mock import MagicMock
16
-
17
- from google.adk.auth.auth_credential import AuthCredential
18
- from google.adk.auth.auth_schemes import AuthScheme
19
- from google.adk.tools.apihub_tool.apihub_toolset import APIHubToolset
20
- from google.adk.tools.apihub_tool.clients.apihub_client import BaseAPIHubClient
21
- import pytest
22
- import yaml
23
-
24
-
25
- class MockAPIHubClient(BaseAPIHubClient):
26
-
27
- def get_spec_content(self, apihub_resource_name: str) -> str:
28
- return """
29
- openapi: 3.0.0
30
- info:
31
- version: 1.0.0
32
- title: Mock API
33
- description: Mock API Description
34
- paths:
35
- /test:
36
- get:
37
- summary: Test GET endpoint
38
- operationId: testGet
39
- responses:
40
- '200':
41
- description: Successful response
42
- """
43
-
44
-
45
- # Fixture for a basic APIHubToolset
46
- @pytest.fixture
47
- def basic_apihub_toolset():
48
- apihub_client = MockAPIHubClient()
49
- tool = APIHubToolset(
50
- apihub_resource_name='test_resource', apihub_client=apihub_client
51
- )
52
- return tool
53
-
54
-
55
- # Fixture for an APIHubToolset with lazy loading
56
- @pytest.fixture
57
- def lazy_apihub_toolset():
58
- apihub_client = MockAPIHubClient()
59
- tool = APIHubToolset(
60
- apihub_resource_name='test_resource',
61
- apihub_client=apihub_client,
62
- lazy_load_spec=True,
63
- )
64
- return tool
65
-
66
-
67
- # Fixture for auth scheme
68
- @pytest.fixture
69
- def mock_auth_scheme():
70
- return MagicMock(spec=AuthScheme)
71
-
72
-
73
- # Fixture for auth credential
74
- @pytest.fixture
75
- def mock_auth_credential():
76
- return MagicMock(spec=AuthCredential)
77
-
78
-
79
- # Test cases
80
- def test_apihub_toolset_initialization(basic_apihub_toolset):
81
- assert basic_apihub_toolset.name == 'mock_api'
82
- assert basic_apihub_toolset.description == 'Mock API Description'
83
- assert basic_apihub_toolset.apihub_resource_name == 'test_resource'
84
- assert not basic_apihub_toolset.lazy_load_spec
85
- assert len(basic_apihub_toolset.generated_tools) == 1
86
- assert 'test_get' in basic_apihub_toolset.generated_tools
87
-
88
-
89
- def test_apihub_toolset_lazy_loading(lazy_apihub_toolset):
90
- assert lazy_apihub_toolset.lazy_load_spec
91
- assert not lazy_apihub_toolset.generated_tools
92
-
93
- tools = lazy_apihub_toolset.get_tools()
94
- assert len(tools) == 1
95
- assert lazy_apihub_toolset.get_tool('test_get') == tools[0]
96
-
97
-
98
- def test_apihub_toolset_no_title_in_spec(basic_apihub_toolset):
99
- spec = """
100
- openapi: 3.0.0
101
- info:
102
- version: 1.0.0
103
- paths:
104
- /empty_desc_test:
105
- delete:
106
- summary: Test DELETE endpoint
107
- operationId: emptyDescTest
108
- responses:
109
- '200':
110
- description: Successful response
111
- """
112
-
113
- class MockAPIHubClientEmptySpec(BaseAPIHubClient):
114
-
115
- def get_spec_content(self, apihub_resource_name: str) -> str:
116
- return spec
117
-
118
- apihub_client = MockAPIHubClientEmptySpec()
119
- toolset = APIHubToolset(
120
- apihub_resource_name='test_resource',
121
- apihub_client=apihub_client,
122
- )
123
-
124
- assert toolset.name == 'unnamed'
125
-
126
-
127
- def test_apihub_toolset_empty_description_in_spec():
128
- spec = """
129
- openapi: 3.0.0
130
- info:
131
- version: 1.0.0
132
- title: Empty Description API
133
- paths:
134
- /empty_desc_test:
135
- delete:
136
- summary: Test DELETE endpoint
137
- operationId: emptyDescTest
138
- responses:
139
- '200':
140
- description: Successful response
141
- """
142
-
143
- class MockAPIHubClientEmptySpec(BaseAPIHubClient):
144
-
145
- def get_spec_content(self, apihub_resource_name: str) -> str:
146
- return spec
147
-
148
- apihub_client = MockAPIHubClientEmptySpec()
149
- toolset = APIHubToolset(
150
- apihub_resource_name='test_resource',
151
- apihub_client=apihub_client,
152
- )
153
-
154
- assert toolset.name == 'empty_description_api'
155
- assert toolset.description == ''
156
-
157
-
158
- def test_get_tools_with_auth(mock_auth_scheme, mock_auth_credential):
159
- apihub_client = MockAPIHubClient()
160
- tool = APIHubToolset(
161
- apihub_resource_name='test_resource',
162
- apihub_client=apihub_client,
163
- auth_scheme=mock_auth_scheme,
164
- auth_credential=mock_auth_credential,
165
- )
166
- tools = tool.get_tools()
167
- assert len(tools) == 1
168
-
169
-
170
- def test_apihub_toolset_get_tools_lazy_load_empty_spec():
171
-
172
- class MockAPIHubClientEmptySpec(BaseAPIHubClient):
173
-
174
- def get_spec_content(self, apihub_resource_name: str) -> str:
175
- return ''
176
-
177
- apihub_client = MockAPIHubClientEmptySpec()
178
- tool = APIHubToolset(
179
- apihub_resource_name='test_resource',
180
- apihub_client=apihub_client,
181
- lazy_load_spec=True,
182
- )
183
- tools = tool.get_tools()
184
- assert not tools
185
-
186
-
187
- def test_apihub_toolset_get_tools_invalid_yaml():
188
-
189
- class MockAPIHubClientInvalidYAML(BaseAPIHubClient):
190
-
191
- def get_spec_content(self, apihub_resource_name: str) -> str:
192
- return '{invalid yaml' # Return invalid YAML
193
-
194
- with pytest.raises(yaml.YAMLError):
195
- apihub_client = MockAPIHubClientInvalidYAML()
196
- tool = APIHubToolset(
197
- apihub_resource_name='test_resource',
198
- apihub_client=apihub_client,
199
- )
200
- tool.get_tools()
201
-
202
-
203
- if __name__ == '__main__':
204
- pytest.main([__file__])