From eec6442bbed6e07f6c26725784bff958d98eb995 Mon Sep 17 00:00:00 2001 From: awalsh128 Date: Mon, 9 Nov 2026 11:35:54 -0800 Subject: [PATCH] test: cover cache restore and save failure paths Codecov flagged lines in #246 as uncovered patch lines; they were untested before the reformat touched them. Add behavior tests for: - Cache: cache miss, missing or empty manifests, unreadable cache dir, metapackage-only restore, install scripts running after their archive with dpkg actions, existing archives, unavailable cache service, and save failures. - ManifestEntry.fromJSON round trip. - buildFileList dropping missing files, updateAptLists skipping update for populated lists and searching only to max depth, and fromInput ignoring a version without a package name. Co-Authored-By: Claude Opus 5.5 --- test/cache-restore.test.ts | 118 ++++++++++++++++++++++++++++++++++++- test/manifest.test.ts | 11 ++++ test/packages.test.ts | 42 +++++++++++++ 3 files changed, 168 insertions(+), 3 deletions(-) diff --git a/test/cache-restore.test.ts b/test/cache-restore.test.ts index 35c3aa2..a5c2bf8 100644 --- a/test/cache-restore.test.ts +++ b/test/cache-restore.test.ts @@ -13,7 +13,7 @@ import { MANIFEST_MAIN_FILENAME, } from "../src/cache.js"; import { Manifest, ManifestEntry } from "../src/manifest.js"; -import { ActionPackageNames } from "../src/packages.js"; +import { ActionPackageNames, findInstallScript } from "../src/packages.js"; // Cache resolves its directory from os.homedir(), so point it at a temp dir. const { HOME_DIR } = await vi.hoisted(async () => { @@ -29,6 +29,11 @@ vi.mock("node:os", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, homedir: () => HOME_DIR }; }); +// Restore looks for install scripts under the real "/", so stub the lookup. +vi.mock("../src/packages.js", async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, findInstallScript: vi.fn() }; +}); vi.mock("@actions/cache", () => ({ restoreCache: vi.fn(), saveCache: vi.fn(), @@ -66,18 +71,20 @@ async function writeCache(archivedPackages = INSTALL_ORDER): Promise { archivedPackages.forEach((pkg) => fs.writeFileSync(archivePath(pkg), "")); } -/** Archive operations observed through the command runner. */ +/** Archive and install script operations observed through the command runner. */ interface TarCalls { created: [archive: string, files: string[]][]; extracted: string[]; /** Number of commands run that extracted archives. */ extractCommands?: number; + /** Extractions and script runs, in the order they ran. */ + events?: string[]; } const argValue = (args: string[], flag: string) => args.find((arg) => arg.startsWith(`${flag}=`))?.slice(flag.length + 1); -/** Records sudo tar calls, including the file list piped to tar create. */ +/** Records sudo tar and script calls, including the file list piped to tar create. */ function recordTar(calls: TarCalls) { return vi.fn(async (_command: string, args: string[] = [], options: CommandOptions = {}) => { const archive = argValue(args, "--file") ?? ""; @@ -88,6 +95,11 @@ function recordTar(calls: TarCalls) { if (args[0] === "sh" && args[1] === "-c") { calls.extracted.push(...args.slice(4)); calls.extractCommands = (calls.extractCommands ?? 0) + 1; + calls.events?.push(...args.slice(4).map((archive) => `extract ${path.basename(archive)}`)); + } + // Install scripts run as `sh -x