char-slop/berry
multipurpose self-modifiable agentic harness
git clone https://git.t4t.associates/char-slop/berry
e5ec380
main
1import { assertEquals , assertRejects , assertStringIncludes } from "@std/assert" ; 2import { BACKGROUND_CONTEXT as context } from "@earendil-works/chord/context" ; 3import { until } from "@berry/util" ; 4import { BOOTSTRAP , Connection , RemoteEnvironment } from "./connection.ts" ; 5 6async function fixture ( handler :( request :Request ) => Response | Promise < Response >) { 7const server = Deno . serve ({ hostname :"127.0.0.1" , port :0 , onListen () {} }, handler ); 8const connection = await Connection . open ( "fetch-test" , [ 9Deno . execPath (), 10"eval" , 11"--quiet" , 12BOOTSTRAP , 13]); 14return { 15env :new RemoteEnvironment ( "fetch-test" , connection , "/" ), 16url :`http://127.0.0.1: ${ server . addr . port } ` , 17 connection, 18async [ Symbol . asyncDispose ]() { 19await connection . close (); 20await server . shutdown (); 21}, 22}; 23} 24 25Deno . test ( "remote fetch originates at the worker, preserving binary requests, metadata, and incremental bodies" , async () => { 26const release = Promise . withResolvers < void >(); 27const encoder = new TextEncoder (); 28await usingf = await fixture ( async ( request ) => { 29const path = new URL ( request . url ). pathname ; 30if ( path === "/redirect" ) { 31return new Response ( null , { status :302 , headers :{ location :"/stream" } }); 32} 33if ( path === "/stream" ) { 34return new Response ( 35new ReadableStream ({ 36start ( controller ) { 37controller . enqueue ( encoder . encode ( "first" )); 38}, 39async pull ( controller ) { 40await release . promise ; 41controller . enqueue ( encoder . encode ( "second" )); 42controller . close (); 43}, 44}), 45); 46} 47return new Response ( await request . arrayBuffer (), { 48status :201 , 49statusText :"Created" , 50headers :{ "x-seen" :request . headers . get ( "x-secret" ) ?? "" }, 51}); 52}); 53const fetchHere = globalThis . fetch ; 54globalThis . fetch = () => Promise . reject ( new Error ( "fetch must run on the worker" )); 55try { 56const echoed = await f . env . fetch ( f . url + "/echo" , { 57method :"POST" , 58headers :new Headers ({ "x-secret" :"from-remote" }), 59body :new Uint8Array ([ 0 , 255 , 10 ]), 60signal :AbortSignal . timeout ( 5000 ), 61}); 62assertEquals ( echoed . status , 201 ); 63assertEquals ( echoed . statusText , "Created" ); 64assertEquals ( echoed . headers . get ( "x-seen" ), "from-remote" ); 65assertEquals ( new Uint8Array ( await echoed . arrayBuffer ()), new Uint8Array ([ 0 , 255 , 10 ])); 66 67const response = await f . env . fetch ( f . url + "/redirect" , { signal :AbortSignal . timeout ( 5000 ) }); 68assertEquals ( response . redirected , true ); 69assertEquals ( response . url , f . url + "/stream" ); 70const reader = response . body ! . getReader (); 71assertEquals ( new TextDecoder (). decode (( await reader . read ()). value ), "first" ); 72release . resolve (); 73assertEquals ( new TextDecoder (). decode (( await reader . read ()). value ), "second" ); 74assertEquals (( await reader . read ()). done , true ); 75} finally { 76release . resolve (); 77globalThis . fetch = fetchHere ; 78} 79}); 80 81Deno . test ( "remote fetch aborts before headers and stops streaming bodies on abort, cancel, or environment cleanup" , async () => { 82const entered = Promise . withResolvers < void >(); 83const release = Promise . withResolvers < void >(); 84let cancelled = 0 ; 85await usingf = await fixture ( async ( request ) => { 86if ( new URL ( request . url ). pathname === "/headers" ) { 87entered . resolve (); 88await release . promise ; 89return new Response ( "late" ); 90} 91return new Response ( 92new ReadableStream ({ 93start ( controller ) { 94controller . enqueue ( new TextEncoder (). encode ( "first" )); 95}, 96cancel () { 97cancelled ++ ; 98}, 99}), 100); 101}); 102try { 103const beforeHeaders = new AbortController (); 104const pending = f . env . fetch ( f . url + "/headers" , { signal :beforeHeaders . signal }); 105const rejected = assertRejects (() => pending ); 106await entered . promise ; 107beforeHeaders . abort (); 108await rejected ; 109release . resolve (); 110 111const abort = new AbortController (); 112const response = await f . env . fetch ( f . url + "/body" , { signal :abort . signal }); 113const reader = response . body ! . getReader (); 114await reader . read (); 115const reading = assertRejects (() => reader . read ()); 116abort . abort (); 117await reading ; 118await until (() => cancelled === 1 ); 119 120const discard = await f . env . fetch ( f . url + "/body" ); 121await discard . body ! . cancel (); 122await until (() => cancelled === 2 ); 123 124const orphan = await f . env . fetch ( f . url + "/body" ); 125const orphanReader = orphan . body ! . getReader (); 126await orphanReader . read (); 127const lost = assertRejects (() => orphanReader . read ()); 128await f . env . cleanup ( context ); 129await lost ; 130await until (() => cancelled === 3 ); 131} finally { 132release . resolve (); 133} 134}); 135 136Deno . test ( "losing the worker fails a streaming response rather than silently ending it" , async () => { 137await usingf = await fixture (() => 138new Response ( 139new ReadableStream ({ 140start ( controller ) { 141controller . enqueue ( new TextEncoder (). encode ( "first" )); 142}, 143}), 144) 145); 146const response = await f . env . fetch ( f . url ); 147const reader = response . body ! . getReader (); 148await reader . read (); 149const reading = assertRejects (() => reader . read (), Error , "lost" ); 150await f . connection . close (); 151await reading ; 152}); 153 154Deno . test ( "remote fetch handles bodyless responses and reports network failures" , async () => { 155await usingf = await fixture (() => new Response ( null , { status :204 })); 156const response = await f . env . fetch ( f . url ); 157assertEquals ( response . status , 204 ); 158assertEquals ( response . body , null ); 159const failed = await assertRejects (() => f . env . fetch ( "http://127.0.0.1:1" ), TypeError ); 160assertStringIncludes ( failed . message , "fetch-test" ); 161});