Skip to content

Commit ee8e9f4

Browse files
test(connect): the answer-bound tests sit beside their siblings, not at the end of the file
They merged in conflict with #110's tests, which also end the file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent a7eefee commit ee8e9f4

1 file changed

Lines changed: 89 additions & 86 deletions

File tree

‎testdata/connect/test_connect_gen.py‎

Lines changed: 89 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,95 @@ async def test_max_response_bytes_bounds_answers_when_set(media):
392392
await server.stop(None)
393393

394394

395+
@pytest.mark.parametrize("media", ["application/json", "application/connect+json"])
396+
async def test_max_response_bytes_counts_the_json_the_face_sends(media):
397+
# 2040 characters: 2043 bytes as proto, within 2048, and 2051 as JSON, past it.
398+
server = grpc.aio.server()
399+
server.add_generic_rpc_handlers((_handler(),))
400+
grpc_port = server.add_insecure_port("127.0.0.1:0")
401+
await server.start()
402+
listener = await connect_gen.serve(
403+
0, grpc_port, host="127.0.0.1", max_message_bytes=1024, max_response_bytes=2048
404+
)
405+
try:
406+
streaming = media.startswith("application/connect+")
407+
body = json.dumps({"text": "big", "count": 2040}).encode()
408+
async with httpx.AsyncClient() as client:
409+
proto = await client.post(
410+
_url(listener, "Say"),
411+
content=Msg(text="big", count=2040).SerializeToString(),
412+
headers={"content-type": "application/proto"},
413+
)
414+
r = await client.post(
415+
_url(listener, "Count" if streaming else "Say"),
416+
content=envelope(body) if streaming else body,
417+
headers={"content-type": media},
418+
)
419+
assert proto.status_code == 200 and len(proto.content) == 2043
420+
error = json.loads(frames(r.content)[-1][1])["error"] if streaming else r.json()
421+
assert r.status_code == (200 if streaming else 400)
422+
assert error == {
423+
"code": "failed_precondition",
424+
"message": (
425+
"the answer (2051 bytes) exceeds the Connect face's max_response_bytes (2048)"
426+
),
427+
}
428+
finally:
429+
await listener.stop()
430+
await server.stop(None)
431+
432+
433+
async def test_a_raised_message_bound_raises_the_answer_bound():
434+
# max_response_bytes defaults to the larger of DEFAULT_MAX_RESPONSE_BYTES and
435+
# max_message_bytes: a service that raised its bound to 100 MiB answers 70 MiB.
436+
server = grpc.aio.server(options=[("grpc.max_send_message_length", 100 * 2**20)])
437+
server.add_generic_rpc_handlers((_handler(),))
438+
grpc_port = server.add_insecure_port("127.0.0.1:0")
439+
await server.start()
440+
listener = await connect_gen.serve(
441+
0, grpc_port, host="127.0.0.1", max_message_bytes=100 * 2**20
442+
)
443+
try:
444+
size = 70 * 2**20
445+
async with httpx.AsyncClient(timeout=60) as client:
446+
r = await client.post(
447+
_url(listener, "Say"),
448+
content=Msg(text="big", count=size).SerializeToString(),
449+
headers={"content-type": "application/proto"},
450+
)
451+
assert r.status_code == 200, r.text[:200]
452+
assert len(Msg.FromString(r.content).text) == size
453+
finally:
454+
await listener.stop()
455+
await server.stop(None)
456+
457+
458+
async def test_the_default_answer_bound_is_16_mib():
459+
server = grpc.aio.server()
460+
server.add_generic_rpc_handlers((_handler(),))
461+
grpc_port = server.add_insecure_port("127.0.0.1:0")
462+
await server.start()
463+
listener = await connect_gen.serve(0, grpc_port, host="127.0.0.1")
464+
try:
465+
async with httpx.AsyncClient(timeout=60) as client:
466+
within = await client.post(
467+
_url(listener, "Say"),
468+
content=Msg(text="big", count=16 * 2**20 - 8).SerializeToString(),
469+
headers={"content-type": "application/proto"},
470+
)
471+
past = await client.post(
472+
_url(listener, "Say"),
473+
content=Msg(text="big", count=16 * 2**20).SerializeToString(),
474+
headers={"content-type": "application/proto"},
475+
)
476+
assert within.status_code == 200
477+
assert past.status_code == 400
478+
assert "max_response_bytes (16777216)" in past.json()["message"]
479+
finally:
480+
await listener.stop()
481+
await server.stop(None)
482+
483+
395484
async def test_one_connection_serves_several_calls(face):
396485
reader, writer = await asyncio.open_connection("127.0.0.1", face.port)
397486
body = json.dumps({"text": "k"}).encode()
@@ -655,89 +744,3 @@ async def test_the_relay_ends_when_the_grpc_server_hangs_up(silent_upstream):
655744
finally:
656745
writer.close()
657746

658-
659-
@pytest.mark.parametrize("media", ["application/json", "application/connect+json"])
660-
async def test_max_response_bytes_counts_the_json_the_face_sends(media):
661-
# 2040 characters: 2043 bytes as proto, within 2048, and 2051 as JSON, past it.
662-
server = grpc.aio.server()
663-
server.add_generic_rpc_handlers((_handler(),))
664-
grpc_port = server.add_insecure_port("127.0.0.1:0")
665-
await server.start()
666-
listener = await connect_gen.serve(
667-
0, grpc_port, host="127.0.0.1", max_message_bytes=1024, max_response_bytes=2048
668-
)
669-
try:
670-
streaming = media.startswith("application/connect+")
671-
body = json.dumps({"text": "big", "count": 2040}).encode()
672-
async with httpx.AsyncClient() as client:
673-
proto = await client.post(
674-
_url(listener, "Say"),
675-
content=Msg(text="big", count=2040).SerializeToString(),
676-
headers={"content-type": "application/proto"},
677-
)
678-
r = await client.post(
679-
_url(listener, "Count" if streaming else "Say"),
680-
content=envelope(body) if streaming else body,
681-
headers={"content-type": media},
682-
)
683-
assert proto.status_code == 200 and len(proto.content) == 2043
684-
error = json.loads(frames(r.content)[-1][1])["error"] if streaming else r.json()
685-
assert r.status_code == (200 if streaming else 400)
686-
assert error == {
687-
"code": "failed_precondition",
688-
"message": "the answer (2051 bytes) exceeds the Connect face's max_response_bytes (2048)",
689-
}
690-
finally:
691-
await listener.stop()
692-
await server.stop(None)
693-
694-
695-
async def test_a_raised_message_bound_raises_the_answer_bound():
696-
# max_response_bytes defaults to the larger of DEFAULT_MAX_RESPONSE_BYTES and
697-
# max_message_bytes: a service that raised its bound to 100 MiB answers 70 MiB.
698-
server = grpc.aio.server(options=[("grpc.max_send_message_length", 100 * 2**20)])
699-
server.add_generic_rpc_handlers((_handler(),))
700-
grpc_port = server.add_insecure_port("127.0.0.1:0")
701-
await server.start()
702-
listener = await connect_gen.serve(
703-
0, grpc_port, host="127.0.0.1", max_message_bytes=100 * 2**20
704-
)
705-
try:
706-
size = 70 * 2**20
707-
async with httpx.AsyncClient(timeout=60) as client:
708-
r = await client.post(
709-
_url(listener, "Say"),
710-
content=Msg(text="big", count=size).SerializeToString(),
711-
headers={"content-type": "application/proto"},
712-
)
713-
assert r.status_code == 200, r.text[:200]
714-
assert len(Msg.FromString(r.content).text) == size
715-
finally:
716-
await listener.stop()
717-
await server.stop(None)
718-
719-
720-
async def test_the_default_answer_bound_is_16_mib():
721-
server = grpc.aio.server()
722-
server.add_generic_rpc_handlers((_handler(),))
723-
grpc_port = server.add_insecure_port("127.0.0.1:0")
724-
await server.start()
725-
listener = await connect_gen.serve(0, grpc_port, host="127.0.0.1")
726-
try:
727-
async with httpx.AsyncClient(timeout=60) as client:
728-
within = await client.post(
729-
_url(listener, "Say"),
730-
content=Msg(text="big", count=16 * 2**20 - 8).SerializeToString(),
731-
headers={"content-type": "application/proto"},
732-
)
733-
past = await client.post(
734-
_url(listener, "Say"),
735-
content=Msg(text="big", count=16 * 2**20).SerializeToString(),
736-
headers={"content-type": "application/proto"},
737-
)
738-
assert within.status_code == 200
739-
assert past.status_code == 400
740-
assert "max_response_bytes (16777216)" in past.json()["message"]
741-
finally:
742-
await listener.stop()
743-
await server.stop(None)

0 commit comments

Comments
 (0)