Skip to content

Commit 78d8f6b

Browse files
Add HTTP deserializer tests
1 parent 2de8dc9 commit 78d8f6b

File tree

1 file changed

+69
-6
lines changed

1 file changed

+69
-6
lines changed

packages/smithy-http/tests/unit/test_serializers.py

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
# SPDX-License-Identifier: Apache-2.0
33
import datetime
4+
from asyncio import iscoroutinefunction
45
from decimal import Decimal
56
from dataclasses import dataclass, field
67
from typing import ClassVar, Self, Any, Protocol
@@ -40,8 +41,9 @@
4041
TIMESTAMP,
4142
)
4243
from smithy_core.aio.types import AsyncBytesReader
44+
from smithy_http.deserializers import HTTPResponseDeserializer
4345
from smithy_json import JSONCodec
44-
46+
from smithy_http.aio import HTTPResponse as _HTTPResponse
4547
from smithy_http import tuples_to_fields, Fields
4648
from smithy_http.serializers import HTTPRequestSerializer, HTTPResponseSerializer
4749

@@ -388,6 +390,7 @@ def _consumer(schema: Schema, de: ShapeDeserializer) -> None:
388390
cls.SCHEMA.members["boolean_list_member"],
389391
lambda d: list_value.append(d.read_boolean(BOOLEAN)),
390392
)
393+
kwargs["boolean_list_member"] = list_value
391394
case 2:
392395
kwargs["integer_member"] = de.read_integer(
393396
cls.SCHEMA.members["integer_member"]
@@ -564,7 +567,7 @@ class HTTPImplicitPayload:
564567
"target": STRING,
565568
"traits": [HTTPHeaderTrait("header")],
566569
},
567-
"payload_member": {"index": 0, "target": STRING},
570+
"payload_member": {"index": 1, "target": STRING},
568571
},
569572
)
570573

@@ -587,7 +590,11 @@ def deserialize(cls, deserializer: ShapeDeserializer) -> Self:
587590
def _consumer(schema: Schema, de: ShapeDeserializer) -> None:
588591
match schema.expect_member_index():
589592
case 0:
590-
kwargs["payload"] = de.read_string(cls.SCHEMA.members["payload"])
593+
kwargs["header"] = de.read_string(cls.SCHEMA.members["header"])
594+
case 1:
595+
kwargs["payload_member"] = de.read_string(
596+
cls.SCHEMA.members["payload_member"]
597+
)
591598
case _:
592599
raise Exception(f"Unexpected schema: {schema}")
593600

@@ -1281,6 +1288,21 @@ class HTTPMessageTestCase:
12811288
]
12821289

12831290

1291+
EMPTY_PREFIX_HEADER_DESER_CASES: list[HTTPMessageTestCase] = [
1292+
HTTPMessageTestCase(
1293+
HTTPEmptyPrefixHeaders(
1294+
string_member="string",
1295+
string_map_member={"foo": "bar", "baz": "bam", "string": "string"},
1296+
),
1297+
HTTPMessage(
1298+
fields=tuples_to_fields(
1299+
[("foo", "bar"), ("baz", "bam"), ("string", "string")]
1300+
),
1301+
),
1302+
),
1303+
]
1304+
1305+
12841306
QUERY_CASES: list[HTTPMessageTestCase] = [
12851307
HTTPMessageTestCase(
12861308
HTTPQuery(boolean_member=True),
@@ -1529,6 +1551,9 @@ class HTTPMessageTestCase:
15291551
HTTPStructuredPayload(payload=HTTPStringPayload(payload="foo")),
15301552
HTTPMessage(body=BytesIO(b'{"payload":"foo"}')),
15311553
),
1554+
]
1555+
1556+
ASYNC_STREAMING_PAYLOAD_CASES: list[HTTPMessageTestCase] = [
15321557
HTTPMessageTestCase(
15331558
HTTPStreamingPayload(payload=AsyncBytesReader(b"\xde\xad\xbe\xef")),
15341559
HTTPMessage(body=AsyncBytesReader(b"\xde\xad\xbe\xef")),
@@ -1544,8 +1569,9 @@ class HTTPMessageTestCase:
15441569
REQUEST_CASES.extend(PAYLOAD_CASES)
15451570

15461571
REQUEST_SER_CASES: list[HTTPMessageTestCase] = []
1547-
REQUEST_CASES.extend(REQUEST_CASES)
1548-
REQUEST_CASES.extend(EMPTY_PREFIX_HEADER_SER_CASES)
1572+
REQUEST_SER_CASES.extend(REQUEST_CASES)
1573+
REQUEST_SER_CASES.extend(EMPTY_PREFIX_HEADER_SER_CASES)
1574+
REQUEST_SER_CASES.extend(ASYNC_STREAMING_PAYLOAD_CASES)
15491575

15501576

15511577
@pytest.mark.parametrize("case", REQUEST_SER_CASES)
@@ -1580,7 +1606,7 @@ async def test_serialize_http_request(case: HTTPMessageTestCase) -> None:
15801606
RESPONSE_CASES.extend(PAYLOAD_CASES)
15811607

15821608
RESPONSE_SER_CASES: list[HTTPMessageTestCase] = []
1583-
RESPONSE_CASES.extend(RESPONSE_CASES)
1609+
RESPONSE_SER_CASES.extend(RESPONSE_CASES)
15841610
RESPONSE_SER_CASES.extend(EMPTY_PREFIX_HEADER_SER_CASES)
15851611

15861612

@@ -1602,3 +1628,40 @@ async def test_serialize_http_response(case: HTTPMessageTestCase) -> None:
16021628
expected_body_value = await AsyncBytesReader(case.request.body).read()
16031629
assert actual_body_value == expected_body_value
16041630
assert type(actual.body) is type(case.request.body)
1631+
1632+
1633+
RESPONSE_DESER_CASES: list[HTTPMessageTestCase] = []
1634+
RESPONSE_DESER_CASES.extend(RESPONSE_CASES)
1635+
RESPONSE_DESER_CASES.extend(EMPTY_PREFIX_HEADER_DESER_CASES)
1636+
1637+
1638+
# TODO: Move this to a separate file
1639+
@pytest.mark.parametrize("case", RESPONSE_DESER_CASES)
1640+
async def test_deserialize_http_response(case: HTTPMessageTestCase) -> None:
1641+
body = case.request.body
1642+
if (read := getattr(body, "read", None)) is not None and iscoroutinefunction(read):
1643+
body = BytesIO(await read())
1644+
deserializer = HTTPResponseDeserializer(
1645+
payload_codec=JSONCodec(),
1646+
http_trait=case.http_trait,
1647+
response=_HTTPResponse(
1648+
body=case.request.body,
1649+
status=case.request.status,
1650+
fields=case.request.fields,
1651+
),
1652+
body=body,
1653+
)
1654+
actual = type(case.shape).deserialize(deserializer)
1655+
assert actual == case.shape
1656+
1657+
1658+
async def test_deserialize_http_response_with_async_stream() -> None:
1659+
stream = AsyncBytesReader(b"\xde\xad\xbe\xef")
1660+
1661+
deserializer = HTTPResponseDeserializer(
1662+
payload_codec=JSONCodec(),
1663+
http_trait=HTTPTrait({"method": "POST", "code": 200, "uri": "/"}),
1664+
response=_HTTPResponse(body=stream, status=200, fields=Fields()),
1665+
)
1666+
actual = HTTPStreamingPayload.deserialize(deserializer)
1667+
assert actual == HTTPStreamingPayload(stream)

0 commit comments

Comments
 (0)