ec2b666284
Continuous Integration / Pre-commit Linter (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.10) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.11) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.12) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.13) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.10) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.11) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.12) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.13) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.14) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.10) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.11) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.12) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.13) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.14) (push) Waiting to run
Copybara PR Handler / close-imported-pr (push) Waiting to run
245 lines
8.6 KiB
Python
245 lines
8.6 KiB
Python
# Copyright 2026 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
from unittest import mock
|
|
from unittest.mock import patch
|
|
|
|
from google.adk.cli import service_registry
|
|
import pytest
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def mock_services():
|
|
"""Mock all service implementation classes to avoid real instantiation."""
|
|
with (
|
|
patch(
|
|
"google.adk.sessions.vertex_ai_session_service.VertexAiSessionService"
|
|
) as mock_vertex_session,
|
|
patch(
|
|
"google.adk.sessions.database_session_service.DatabaseSessionService"
|
|
) as mock_db_session,
|
|
patch(
|
|
"google.adk.sessions.sqlite_session_service.SqliteSessionService"
|
|
) as mock_sqlite_session,
|
|
patch(
|
|
"google.adk.artifacts.gcs_artifact_service.GcsArtifactService"
|
|
) as mock_gcs_artifact,
|
|
patch(
|
|
"google.adk.memory.vertex_ai_rag_memory_service.VertexAiRagMemoryService"
|
|
) as mock_rag_memory,
|
|
patch(
|
|
"google.adk.memory.vertex_ai_memory_bank_service.VertexAiMemoryBankService"
|
|
) as mock_agentengine_memory,
|
|
):
|
|
yield {
|
|
"vertex_session": mock_vertex_session,
|
|
"db_session": mock_db_session,
|
|
"sqlite_session": mock_sqlite_session,
|
|
"gcs_artifact": mock_gcs_artifact,
|
|
"rag_memory": mock_rag_memory,
|
|
"agentengine_memory": mock_agentengine_memory,
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def registry():
|
|
from google.adk.cli.service_registry import get_service_registry
|
|
|
|
return get_service_registry()
|
|
|
|
|
|
# Session Service Tests
|
|
def test_create_session_service_sqlite(registry, mock_services):
|
|
registry.create_session_service("sqlite:///test.db")
|
|
mock_services["sqlite_session"].assert_called_once_with(db_path="test.db")
|
|
|
|
|
|
def test_create_session_service_sqlite_ignores_unsupported_kwargs(
|
|
registry, mock_services, caplog
|
|
):
|
|
"""Test that SqliteSessionService ignores unsupported kwargs and logs warning."""
|
|
import logging
|
|
|
|
with caplog.at_level(logging.WARNING):
|
|
registry.create_session_service(
|
|
"sqlite:///test.db", pool_size=10, agents_dir="foo"
|
|
)
|
|
|
|
# SqliteSessionService should only receive db_path, not pool_size
|
|
mock_services["sqlite_session"].assert_called_once_with(db_path="test.db")
|
|
|
|
# Verify warning was logged about ignored kwargs
|
|
assert (
|
|
"SqliteSessionService does not support additional kwargs" in caplog.text
|
|
)
|
|
assert "pool_size" in caplog.text
|
|
|
|
|
|
def test_create_session_service_postgresql(registry, mock_services):
|
|
registry.create_session_service("postgresql://user:pass@host/db")
|
|
mock_services["db_session"].assert_called_once_with(
|
|
db_url="postgresql://user:pass@host/db"
|
|
)
|
|
|
|
|
|
@patch("google.adk.cli.utils.envs.load_dotenv_for_agent")
|
|
def test_create_session_service_agentengine_short(
|
|
mock_load_dotenv, registry, mock_services, monkeypatch
|
|
):
|
|
monkeypatch.setenv("GOOGLE_CLOUD_PROJECT", "test-project")
|
|
monkeypatch.setenv("GOOGLE_CLOUD_LOCATION", "us-central1")
|
|
registry.create_session_service(
|
|
"agentengine://123", agents_dir="/path/to/agents"
|
|
)
|
|
mock_services["vertex_session"].assert_called_once_with(
|
|
project="test-project", location="us-central1", agent_engine_id="123"
|
|
)
|
|
mock_load_dotenv.assert_called_once_with("", "/path/to/agents")
|
|
|
|
|
|
def test_create_session_service_agentengine_full(registry, mock_services):
|
|
uri = "agentengine://projects/p/locations/l/reasoningEngines/123"
|
|
registry.create_session_service(uri, agents_dir="/path/to/agents")
|
|
mock_services["vertex_session"].assert_called_once_with(
|
|
project="p", location="l", agent_engine_id="123"
|
|
)
|
|
|
|
|
|
# Artifact Service Tests
|
|
def test_create_artifact_service_gcs(registry, mock_services):
|
|
registry.create_artifact_service(
|
|
"gs://my-bucket/path/prefix", agents_dir="foo", other_kwarg="bar"
|
|
)
|
|
mock_services["gcs_artifact"].assert_called_once_with(
|
|
bucket_name="my-bucket", other_kwarg="bar"
|
|
)
|
|
|
|
|
|
def test_file_artifact_factory_normalizes_windows_file_uri(monkeypatch):
|
|
monkeypatch.setattr(service_registry, "os", SimpleNamespace(name="nt"))
|
|
mocked_url2pathname = mock.Mock(return_value=r"C:\tmp\adk artifacts")
|
|
monkeypatch.setattr(service_registry, "url2pathname", mocked_url2pathname)
|
|
|
|
registry = service_registry.ServiceRegistry()
|
|
service_registry._register_builtin_services(registry)
|
|
|
|
with mock.patch(
|
|
"google.adk.artifacts.file_artifact_service.FileArtifactService"
|
|
) as mock_file_artifact_service:
|
|
registry.create_artifact_service("file:///C:/tmp/adk%20artifacts")
|
|
|
|
mocked_url2pathname.assert_called_once_with("/C:/tmp/adk artifacts")
|
|
mock_file_artifact_service.assert_called_once_with(
|
|
root_dir=Path(r"C:\tmp\adk artifacts")
|
|
)
|
|
|
|
|
|
def test_file_artifact_factory_rejects_non_local_authority():
|
|
registry = service_registry.ServiceRegistry()
|
|
service_registry._register_builtin_services(registry)
|
|
|
|
with pytest.raises(ValueError, match="local filesystem"):
|
|
registry.create_artifact_service("file://example.com/tmp/adk_artifacts")
|
|
|
|
|
|
# Memory Service Tests
|
|
@patch("google.adk.cli.utils.envs.load_dotenv_for_agent")
|
|
def test_create_memory_service_rag(
|
|
mock_load_dotenv, registry, mock_services, monkeypatch
|
|
):
|
|
monkeypatch.setenv("GOOGLE_CLOUD_PROJECT", "test-project")
|
|
monkeypatch.setenv("GOOGLE_CLOUD_LOCATION", "us-central1")
|
|
registry.create_memory_service(
|
|
"rag://corpus-123", agents_dir="/path/to/agents"
|
|
)
|
|
mock_services["rag_memory"].assert_called_once_with(
|
|
rag_corpus=(
|
|
"projects/test-project/locations/us-central1/ragCorpora/corpus-123"
|
|
)
|
|
)
|
|
mock_load_dotenv.assert_called_once_with("", "/path/to/agents")
|
|
|
|
|
|
@patch("google.adk.cli.utils.envs.load_dotenv_for_agent")
|
|
def test_create_memory_service_agentengine_short(
|
|
mock_load_dotenv, registry, mock_services, monkeypatch
|
|
):
|
|
monkeypatch.setenv("GOOGLE_CLOUD_PROJECT", "test-project")
|
|
monkeypatch.setenv("GOOGLE_CLOUD_LOCATION", "us-central1")
|
|
registry.create_memory_service(
|
|
"agentengine://456", agents_dir="/path/to/agents"
|
|
)
|
|
mock_services["agentengine_memory"].assert_called_once_with(
|
|
project="test-project", location="us-central1", agent_engine_id="456"
|
|
)
|
|
mock_load_dotenv.assert_called_once_with("", "/path/to/agents")
|
|
|
|
|
|
def test_create_memory_service_agentengine_full(registry, mock_services):
|
|
uri = "agentengine://projects/p/locations/l/reasoningEngines/456"
|
|
registry.create_memory_service(uri, agents_dir="/path/to/agents")
|
|
mock_services["agentengine_memory"].assert_called_once_with(
|
|
project="p", location="l", agent_engine_id="456"
|
|
)
|
|
|
|
|
|
def test_create_memory_service_memory(registry):
|
|
from google.adk.memory.in_memory_memory_service import InMemoryMemoryService
|
|
|
|
memory_service = registry.create_memory_service("memory://")
|
|
assert isinstance(memory_service, InMemoryMemoryService)
|
|
|
|
|
|
# Task Store Tests
|
|
def test_create_task_store_memory(registry):
|
|
from a2a.server.tasks import InMemoryTaskStore
|
|
|
|
task_store = registry._create_task_store_service("memory://")
|
|
assert isinstance(task_store, InMemoryTaskStore)
|
|
|
|
|
|
@patch("sqlalchemy.ext.asyncio.create_async_engine")
|
|
@patch("a2a.server.tasks.DatabaseTaskStore")
|
|
def test_create_task_store_postgresql(
|
|
mock_db_task_store, mock_create_engine, registry
|
|
):
|
|
mock_engine = mock_create_engine.return_value
|
|
registry._create_task_store_service("postgresql+asyncpg://user:pass@host/db")
|
|
mock_create_engine.assert_called_once_with(
|
|
"postgresql+asyncpg://user:pass@host/db"
|
|
)
|
|
mock_db_task_store.assert_called_once_with(engine=mock_engine)
|
|
|
|
|
|
# General Tests
|
|
def test_unsupported_scheme(registry, mock_services):
|
|
session_service = registry.create_session_service("unsupported://foo")
|
|
artifact_service = registry.create_artifact_service("unsupported://foo")
|
|
memory_service = registry.create_memory_service("unsupported://foo")
|
|
assert session_service is None
|
|
assert artifact_service is None
|
|
assert memory_service is None
|
|
with pytest.raises(ValueError, match="Unsupported A2A task store URI scheme"):
|
|
registry._create_task_store_service("unsupported://foo")
|
|
for service in [
|
|
"vertex_session",
|
|
"db_session",
|
|
"gcs_artifact",
|
|
"rag_memory",
|
|
"agentengine_memory",
|
|
]:
|
|
mock_services[service].assert_not_called()
|