From 251c0239475c442d8b00a2f4dd113121847fb5d9 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Wed, 28 Oct 2026 14:04:30 -0700 Subject: [PATCH] test(wsl): copy whole orcad startup profiles out of the lane distro (#35331) * test(wsl): copy whole orcad startup profiles out of the lane distro A guest command's output is capped at 1 MiB, which truncated orcad's own CPU profile. The lane now reads each profile in 512 KiB base64 chunks. * test(wsl): refuse a lane file read that did not come back whole execCommand keeps only the tail past its output cap; the chunked read now throws unless it got exactly the file's size. --- ...rcad-real-distro-idle-release-lane.test.ts | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/main/wsl/wsl-orcad-real-distro-idle-release-lane.test.ts b/src/main/wsl/wsl-orcad-real-distro-idle-release-lane.test.ts index 3701928902a..33e77e449d9 100644 --- a/src/main/wsl/wsl-orcad-real-distro-idle-release-lane.test.ts +++ b/src/main/wsl/wsl-orcad-real-distro-idle-release-lane.test.ts @@ -411,6 +411,29 @@ async function restartThroughBridgeExec(): Promise { return { firstOutputMs } } +// A guest command's output is capped at 1 MiB; read big files in base64 chunks below that. +const GUEST_READ_BLOCK_BYTES = 64 * 1024 +const GUEST_READ_BLOCKS_PER_CHUNK = 8 + +async function readGuestFile(path: string): Promise { + const quoted = quotePosixShell(path) + const size = Number((await guest(`wc -c < ${quoted}`)).trim()) + const chunkBytes = GUEST_READ_BLOCK_BYTES * GUEST_READ_BLOCKS_PER_CHUNK + const chunks: Buffer[] = [] + for (let offset = 0; offset < size; offset += chunkBytes) { + const encoded = await guest( + `dd if=${quoted} bs=${GUEST_READ_BLOCK_BYTES} skip=${offset / GUEST_READ_BLOCK_BYTES} count=${GUEST_READ_BLOCKS_PER_CHUNK} 2>/dev/null | base64 | tr -d '\\n'` + ) + chunks.push(Buffer.from(encoded.trim(), 'base64')) + } + const result = Buffer.concat(chunks) + // execCommand keeps only the tail past its cap, so a short or odd read must not pass as whole. + if (!Number.isFinite(size) || result.length !== size) { + throw new Error(`Read ${result.length} of ${size} bytes of ${path} from the lane distro`) + } + return result +} + /** * One extra, unrecorded restart with orcad (and the Node children it starts) under --cpu-prof. * Profiles are written on exit, so wait for the idle exit, then copy them into the receipts. @@ -433,10 +456,7 @@ async function profileOrcadRestart(repoPath: string): Promise { ) const names = (await guest(`ls ${PROFILE_DIR} 2>/dev/null || true`)).split('\n').filter(Boolean) for (const name of names) { - writeFileSync( - join(RECEIPT_DIR, name), - await guest(`cat ${quotePosixShell(`${PROFILE_DIR}/${name}`)}`) - ) + writeFileSync(join(RECEIPT_DIR, name), await readGuestFile(`${PROFILE_DIR}/${name}`)) } return names }