python-boto3/tests/unit/resources/test_response.py

426 lines
12 KiB
Python
Raw Normal View History

2015-11-27 23:25:33 +01:00
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the 'License'). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
2021-09-22 18:34:33 +02:00
# https://aws.amazon.com/apache2.0/
2015-11-27 23:25:33 +01:00
#
# or in the 'license' file accompanying this file. This file 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.
2021-10-04 19:51:32 +02:00
import pytest
2015-11-27 23:25:33 +01:00
from tests import BaseTestCase, mock
from boto3.utils import ServiceContext
from boto3.resources.base import ResourceMeta, ServiceResource
from boto3.resources.model import ResponseResource, Parameter
from boto3.resources.factory import ResourceFactory
from boto3.resources.response import build_identifiers, build_empty_response,\
RawHandler, ResourceHandler
class TestBuildIdentifiers(BaseTestCase):
def test_build_identifier_from_res_path_scalar(self):
identifiers = [Parameter(target='Id', source='response',
path='Container.Frob.Id')]
parent = mock.Mock()
params = {}
response = {
'Container': {
'Frob': {
'Id': 'response-path'
}
}
}
values = build_identifiers(identifiers, parent, params, response)
2021-10-04 19:51:32 +02:00
# Verify identifier loaded from responsePath scalar set
assert values[0][1] == 'response-path'
2015-11-27 23:25:33 +01:00
def test_build_identifier_from_res_path_list(self):
identifiers = [Parameter(target='Id', source='response',
path='Container.Frobs[].Id')]
parent = mock.Mock()
params = {}
response = {
'Container': {
'Frobs': [
{
'Id': 'response-path'
}
]
}
}
values = build_identifiers(identifiers, parent, params, response)
2021-10-04 19:51:32 +02:00
# Verify identifier loaded from responsePath scalar set
assert values[0][1] == ['response-path']
2015-11-27 23:25:33 +01:00
def test_build_identifier_from_parent_identifier(self):
identifiers = [Parameter(target='Id', source='identifier',
name='Id')]
parent = mock.Mock()
parent.id = 'identifier'
params = {}
response = {
'Container': {
'Frobs': []
}
}
values = build_identifiers(identifiers, parent, params, response)
2021-10-04 19:51:32 +02:00
# Verify identifier loaded from responsePath scalar set
assert values[0][1] == 'identifier'
2015-11-27 23:25:33 +01:00
def test_build_identifier_from_parent_data_member(self):
identifiers = [Parameter(target='Id', source='data',
path='Member')]
parent = mock.Mock()
parent.meta = ResourceMeta('test', data={
'Member': 'data-member'
})
params = {}
response = {
'Container': {
'Frobs': []
}
}
values = build_identifiers(identifiers, parent, params, response)
2021-10-04 19:51:32 +02:00
# Verify identifier loaded from responsePath scalar set
assert values[0][1] == 'data-member'
2015-11-27 23:25:33 +01:00
def test_build_identifier_from_req_param(self):
identifiers = [Parameter(target='Id', source='requestParameter',
path='Param')]
parent = mock.Mock()
params = {
'Param': 'request-param'
}
response = {
'Container': {
'Frobs': []
}
}
values = build_identifiers(identifiers, parent, params, response)
2021-10-04 19:51:32 +02:00
# Verify identifier loaded from responsePath scalar set
assert values[0][1] == 'request-param'
2015-11-27 23:25:33 +01:00
def test_build_identifier_from_invalid_source_type(self):
identifiers = [Parameter(target='Id', source='invalid')]
parent = mock.Mock()
params = {}
response = {
'Container': {
'Frobs': []
}
}
2021-10-04 19:51:32 +02:00
with pytest.raises(NotImplementedError):
2015-11-27 23:25:33 +01:00
build_identifiers(identifiers, parent, params, response)
class TestBuildEmptyResponse(BaseTestCase):
def setUp(self):
super(TestBuildEmptyResponse, self).setUp()
self.search_path = ''
self.operation_name = 'GetFrobs'
self.output_shape = mock.Mock()
operation_model = mock.Mock()
operation_model.output_shape = self.output_shape
self.service_model = mock.Mock()
self.service_model.operation_model.return_value = operation_model
def get_response(self):
return build_empty_response(self.search_path, self.operation_name,
self.service_model)
def test_empty_structure(self):
self.output_shape.type_name = 'structure'
response = self.get_response()
2021-10-04 19:51:32 +02:00
# Structure should default to empty dictionary
assert isinstance(response, dict)
assert response == {}
2015-11-27 23:25:33 +01:00
def test_empty_list(self):
self.output_shape.type_name = 'list'
response = self.get_response()
2021-10-04 19:51:32 +02:00
assert isinstance(response, list)
assert len(response) == 0
2015-11-27 23:25:33 +01:00
def test_empty_map(self):
self.output_shape.type_name = 'map'
response = self.get_response()
2021-10-04 19:51:32 +02:00
assert isinstance(response, dict)
assert response == {}
2015-11-27 23:25:33 +01:00
def test_empty_string(self):
2021-10-04 19:51:32 +02:00
self.output_shape.type_name = "string"
2015-11-27 23:25:33 +01:00
response = self.get_response()
2021-10-04 19:51:32 +02:00
assert response is None
2015-11-27 23:25:33 +01:00
def test_empty_integer(self):
2021-10-04 19:51:32 +02:00
self.output_shape.type_name = "integer"
2015-11-27 23:25:33 +01:00
response = self.get_response()
2021-10-04 19:51:32 +02:00
assert response is None
2015-11-27 23:25:33 +01:00
2021-10-04 19:51:32 +02:00
def test_empty_unknown_returns_none(self):
self.output_shape.type_name = "invalid"
2015-11-27 23:25:33 +01:00
response = self.get_response()
2021-10-04 19:51:32 +02:00
assert response is None
2015-11-27 23:25:33 +01:00
def test_path_structure(self):
self.search_path = 'Container.Frob'
frob = mock.Mock()
frob.type_name = 'integer'
container = mock.Mock()
container.type_name = 'structure'
container.members = {
'Frob': frob
}
self.output_shape.type_name = 'structure'
self.output_shape.members = {
'Container': container
}
response = self.get_response()
2021-10-04 19:51:32 +02:00
assert response is None
2015-11-27 23:25:33 +01:00
def test_path_list(self):
self.search_path = 'Container[1].Frob'
frob = mock.Mock()
frob.type_name = 'integer'
container = mock.Mock()
container.type_name = 'list'
container.member = frob
self.output_shape.type_name = 'structure'
self.output_shape.members = {
'Container': container
}
response = self.get_response()
2021-10-04 19:51:32 +02:00
assert response is None
2015-11-27 23:25:33 +01:00
def test_path_invalid(self):
self.search_path = 'Container.Invalid'
container = mock.Mock()
container.type_name = 'invalid'
self.output_shape.type_name = 'structure'
self.output_shape.members = {
'Container': container
}
2021-10-04 19:51:32 +02:00
with pytest.raises(NotImplementedError):
2015-11-27 23:25:33 +01:00
self.get_response()
class TestRawHandler(BaseTestCase):
def test_raw_handler_response(self):
parent = mock.Mock()
params = {}
response = {
'Id': 'foo'
}
handler = RawHandler(search_path=None)
parsed_response = handler(parent, params, response)
2021-10-04 19:51:32 +02:00
# verify response is unmodified
assert parsed_response == response
2015-11-27 23:25:33 +01:00
def test_raw_handler_response_path(self):
parent = mock.Mock()
params = {}
frob = {
'Id': 'foo'
}
response = {
'Container': {
'Frob': frob
}
}
handler = RawHandler(search_path='Container.Frob')
parsed_response = handler(parent, params, response)
2021-10-04 19:51:32 +02:00
assert parsed_response == frob
2015-11-27 23:25:33 +01:00
class TestResourceHandler(BaseTestCase):
def setUp(self):
super(TestResourceHandler, self).setUp()
self.identifier_path = ''
self.factory = ResourceFactory(mock.Mock())
self.resource_defs = {
'Frob': {
'shape': 'Frob',
'identifiers': [
{'name': 'Id'}
]
}
}
self.service_model = mock.Mock()
shape = mock.Mock()
shape.members = {}
self.service_model.shape_for.return_value = shape
frobs = mock.Mock()
frobs.type_name = 'list'
container = mock.Mock()
container.type_name = 'structure'
container.members = {
'Frobs': frobs
}
self.output_shape = mock.Mock()
self.output_shape.type_name = 'structure'
self.output_shape.members = {
'Container': container
}
operation_model = mock.Mock()
operation_model.output_shape = self.output_shape
self.service_model.operation_model.return_value = operation_model
self.parent = mock.Mock()
self.parent.meta = ResourceMeta('test', client=mock.Mock())
self.params = {}
def get_resource(self, search_path, response):
request_resource_def = {
'type': 'Frob',
'identifiers': [
{'target': 'Id', 'source': 'response',
'path': self.identifier_path},
]
}
resource_model = ResponseResource(
request_resource_def, self.resource_defs)
handler = ResourceHandler(
search_path=search_path, factory=self.factory,
resource_model=resource_model,
service_context=ServiceContext(
service_name='myservice',
resource_json_definitions=self.resource_defs,
service_model=self.service_model,
service_waiter_model=None
),
operation_name='GetFrobs'
)
return handler(self.parent, self.params, response)
def test_create_resource_scalar(self):
self.identifier_path = 'Container.Id'
search_path = 'Container'
response = {
'Container': {
'Id': 'a-frob',
'OtherValue': 'other',
}
}
resource = self.get_resource(search_path, response)
2021-10-04 19:51:32 +02:00
assert isinstance(resource, ServiceResource)
2015-11-27 23:25:33 +01:00
@mock.patch('boto3.resources.response.build_empty_response')
def test_missing_data_scalar_builds_empty_response(self, build_mock):
self.identifier_path = 'Container.Id'
search_path = 'Container'
response = {
'something': 'irrelevant'
}
resources = self.get_resource(search_path, response)
2021-10-04 19:51:32 +02:00
assert build_mock.called
assert resources == build_mock.return_value
2015-11-27 23:25:33 +01:00
def test_create_resource_list(self):
self.identifier_path = 'Container.Frobs[].Id'
search_path = 'Container.Frobs[]'
response = {
'Container': {
'Frobs': [
{
'Id': 'a-frob',
'OtherValue': 'other',
},
{
'Id': 'another-frob',
'OtherValue': 'foo',
}
]
}
}
resources = self.get_resource(search_path, response)
2021-10-04 19:51:32 +02:00
assert isinstance(resources, list)
assert len(resources) == 2
assert isinstance(resources[0], ServiceResource)
2015-11-27 23:25:33 +01:00
def test_create_resource_list_no_search_path(self):
self.identifier_path = '[].Id'
search_path = ''
response = [
{
'Id': 'a-frob',
'OtherValue': 'other'
}
]
resources = self.get_resource(search_path, response)
2021-10-04 19:51:32 +02:00
assert isinstance(resources, list)
assert len(resources) == 1
assert isinstance(resources[0], ServiceResource)
2015-11-27 23:25:33 +01:00
@mock.patch('boto3.resources.response.build_empty_response')
def test_missing_data_list_builds_empty_response(self, build_mock):
self.identifier_path = 'Container.Frobs[].Id'
search_path = 'Container.Frobs[]'
response = {
'something': 'irrelevant'
}
resources = self.get_resource(search_path, response)
2021-10-04 19:51:32 +02:00
assert build_mock.called, 'build_empty_response was never called'
assert resources == build_mock.return_value