test: harden HTTP scenario execution evidence

This commit is contained in:
DongHyeonka
2026-08-02 11:36:27 +09:00
parent e08d8c2dd8
commit d2eb320936
6 changed files with 143 additions and 28 deletions
+17 -3
View File
@@ -166,6 +166,8 @@ export type ContractHttpExecutorDependencies = Readonly<{
}>,
): Promise<CredentialPatchOutcome> | CredentialPatchOutcome;
fetcher?: typeof fetch;
/** Adapter seam for the common bounded response reader. */
readBoundedResponseBytes?: typeof readBoundedBytes;
monotonicNow?: () => number;
sleep?: (ms: number, signal: AbortSignal) => Promise<void>;
random?: () => number;
@@ -276,6 +278,8 @@ export function createContractHttpExecutor(
dependencies: ContractHttpExecutorDependencies,
): ContractHttpExecutor {
const fetcher = dependencies.fetcher ?? fetch;
const readResponseBytes =
dependencies.readBoundedResponseBytes ?? readBoundedBytes;
const now = dependencies.monotonicNow ?? (() => performance.now());
const random = dependencies.random ?? Math.random;
const sleep =
@@ -647,6 +651,7 @@ export function createContractHttpExecutor(
response,
context,
attemptState,
readResponseBytes,
);
attemptState = "SETTLED";
if (
@@ -722,6 +727,7 @@ async function admitResponse<Input, WireOutput, Problem>(
response: Response,
context: HttpExecutionContext,
attemptState: PhysicalAttemptState,
readResponseBytes: typeof readBoundedBytes,
): Promise<AdmissionOutcome<WireOutput, Problem>> {
const contract = operation.contract;
const policy = operation.frontend;
@@ -777,7 +783,14 @@ async function admitResponse<Input, WireOutput, Problem>(
retryAfterMs,
});
}
return admitProblem(operation, response, status, metadata, attemptState);
return admitProblem(
operation,
response,
status,
metadata,
attemptState,
readResponseBytes,
);
}
// Success status: body policy first.
@@ -821,7 +834,7 @@ async function admitResponse<Input, WireOutput, Problem>(
const emptyAllowed = contract.emptyBodyStatuses.includes(status);
const mediaOk = isJsonMediaType(response.headers.get("content-type"));
const bytes = await readBoundedBytes(response, policy.responseByteLimit);
const bytes = await readResponseBytes(response, policy.responseByteLimit);
if (!bytes.ok) {
return settled(
bytes.code === "RESPONSE_TOO_LARGE"
@@ -958,12 +971,13 @@ async function admitProblem<Input, WireOutput, Problem>(
status: number,
metadata: SafeResponseMetadata,
attemptState: PhysicalAttemptState,
readResponseBytes: typeof readBoundedBytes,
): Promise<AdmissionOutcome<WireOutput, Problem>> {
const contract = operation.contract;
const isCommand = contract.commandEffect !== null;
const retryable = RETRYABLE_STATUSES.has(status);
const bytes = await readBoundedBytes(
const bytes = await readResponseBytes(
response,
HTTP_EXECUTION_CEILINGS.problemResponseBytes,
);