Files
google--adk-python/tests/unittests/utils/test_schema_utils.py
T
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:25:13 +08:00

211 lines
7.5 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.
"""Tests for _schema_utils module."""
from google.adk.utils._schema_utils import get_list_inner_type
from google.adk.utils._schema_utils import is_basemodel_schema
from google.adk.utils._schema_utils import is_list_of_basemodel
from google.adk.utils._schema_utils import validate_node_data
from google.adk.utils._schema_utils import validate_schema
from google.genai import types
from pydantic import BaseModel
from pydantic import ValidationError
import pytest
class SampleModel(BaseModel):
"""Sample model for testing."""
name: str
value: int
class TestIsBasemodelSchema:
"""Tests for is_basemodel_schema function."""
def test_basemodel_class_returns_true(self):
"""Test that a BaseModel class returns True."""
assert is_basemodel_schema(SampleModel)
def test_list_of_basemodel_returns_false(self):
"""Test that list[BaseModel] returns False."""
assert not is_basemodel_schema(list[SampleModel])
def test_list_of_str_returns_false(self):
"""Test that list[str] returns False."""
assert not is_basemodel_schema(list[str])
def test_dict_returns_false(self):
"""Test that dict types return False."""
assert not is_basemodel_schema(dict[str, int])
def test_plain_str_returns_false(self):
"""Test that plain str returns False."""
assert not is_basemodel_schema(str)
def test_plain_int_returns_false(self):
"""Test that plain int returns False."""
assert not is_basemodel_schema(int)
class TestIsListOfBasemodel:
"""Tests for is_list_of_basemodel function."""
def test_list_of_basemodel_returns_true(self):
"""Test that list[BaseModel] returns True."""
assert is_list_of_basemodel(list[SampleModel])
def test_basemodel_class_returns_false(self):
"""Test that a plain BaseModel class returns False."""
assert not is_list_of_basemodel(SampleModel)
def test_list_of_str_returns_false(self):
"""Test that list[str] returns False."""
assert not is_list_of_basemodel(list[str])
def test_list_of_int_returns_false(self):
"""Test that list[int] returns False."""
assert not is_list_of_basemodel(list[int])
def test_dict_returns_false(self):
"""Test that dict types return False."""
assert not is_list_of_basemodel(dict[str, int])
def test_plain_list_returns_false(self):
"""Test that plain list (no type arg) returns False."""
assert not is_list_of_basemodel(list)
class TestGetListInnerType:
"""Tests for get_list_inner_type function."""
def test_list_of_basemodel_returns_inner_type(self):
"""Test that list[BaseModel] returns the inner type."""
assert get_list_inner_type(list[SampleModel]) is SampleModel
def test_basemodel_class_returns_none(self):
"""Test that a plain BaseModel class returns None."""
assert get_list_inner_type(SampleModel) is None
def test_list_of_str_returns_none(self):
"""Test that list[str] returns None."""
assert get_list_inner_type(list[str]) is None
def test_dict_returns_none(self):
"""Test that dict types return None."""
assert get_list_inner_type(dict[str, int]) is None
class TestValidateSchema:
"""Tests for validate_schema function."""
def test_basemodel_schema(self):
"""Test validation with a BaseModel schema."""
json_text = '{"name": "test", "value": 42}'
result = validate_schema(SampleModel, json_text)
assert result == {'name': 'test', 'value': 42}
def test_basemodel_schema_excludes_none(self):
"""Test that None values are excluded from the result."""
class ModelWithOptional(BaseModel):
name: str
optional_field: str | None = None
json_text = '{"name": "test", "optional_field": null}'
result = validate_schema(ModelWithOptional, json_text)
assert result == {'name': 'test'}
def test_list_of_basemodel_schema(self):
"""Test validation with a list[BaseModel] schema."""
json_text = '[{"name": "item1", "value": 1}, {"name": "item2", "value": 2}]'
result = validate_schema(list[SampleModel], json_text)
assert result == [
{'name': 'item1', 'value': 1},
{'name': 'item2', 'value': 2},
]
def test_list_of_str_schema(self):
"""Test validation with a list[str] schema."""
json_text = '["a", "b", "c"]'
result = validate_schema(list[str], json_text)
assert result == ['a', 'b', 'c']
def test_dict_schema(self):
"""Test validation with a dict schema."""
json_text = '{"key1": 1, "key2": 2}'
result = validate_schema(dict[str, int], json_text)
assert result == {'key1': 1, 'key2': 2}
class TestValidateNodeData:
"""Tests for validate_node_data function."""
def test_none_schema_or_data_returns_data(self):
"""Bypasses validation if schema or data is None."""
assert validate_node_data(None, 'some_data') == 'some_data'
assert validate_node_data(SampleModel, None) is None
def test_dict_or_types_schema_returns_data(self):
"""Bypasses validation if schema is dict or types.Schema."""
assert validate_node_data({'key': int}, 'some_data') == 'some_data'
# Mock types.Schema
schema = types.Schema(type=types.Type.STRING)
assert validate_node_data(schema, 'some_data') == 'some_data'
def test_content_schema_returns_data(self):
"""Bypasses validation if target schema is types.Content or subclass."""
result = validate_node_data(
types.Content, types.Content(role='user', parts=[])
)
assert result == {'role': 'user', 'parts': []}
def test_plain_basemodel_schema_validates_raw_dict(self):
"""Validates raw dict data against BaseModel schema."""
result = validate_node_data(SampleModel, {'name': 'test', 'value': 42})
assert result == {'name': 'test', 'value': 42}
def test_content_data_and_preserve_content(self):
"""Validates wrapped content and wraps result back into Content."""
data = types.Content(
role='user',
parts=[types.Part(text='{"name": "test", "value": 42}')],
)
result = validate_node_data(SampleModel, data, preserve_content=True)
assert isinstance(result, types.Content)
assert result.role == 'user'
assert len(result.parts) == 1
assert result.parts[0].text == '{"name": "test", "value": 42}'
def test_content_data_no_preserve_content(self):
"""Validates wrapped content and returns unwrapped dictionary."""
data = types.Content(
role='user',
parts=[types.Part(text='{"name": "test", "value": 42}')],
)
result = validate_node_data(SampleModel, data, preserve_content=False)
assert isinstance(result, dict)
assert result == {'name': 'test', 'value': 42}
def test_raw_json_string_validated_against_basemodel_schema(self):
"""Raw JSON string fails validation against BaseModel schema (not auto-parsed)."""
with pytest.raises(ValidationError):
validate_node_data(SampleModel, '{"name": "test", "value": 42}')
def test_raw_string_not_parsed_with_str_schema(self):
"""Bypasses JSON parsing if schema is str."""
result = validate_node_data(str, 'hello')
assert result == 'hello'