From e7d77ca2323d2a531431bc8e1e5b4cad7516603f Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Wed, 4 Nov 2026 08:50:22 +0000 Subject: [PATCH] Report Journal recovery phase and CLI output on failure --- test/e2e-cli/test-journal-chunk-recovery.ts | 34 ++++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/test/e2e-cli/test-journal-chunk-recovery.ts b/test/e2e-cli/test-journal-chunk-recovery.ts index 345fbc88..6bf03389 100644 --- a/test/e2e-cli/test-journal-chunk-recovery.ts +++ b/test/e2e-cli/test-journal-chunk-recovery.ts @@ -3,7 +3,7 @@ import assert from "node:assert/strict"; import { mkdir, readFile, rename, writeFile } from "node:fs/promises"; import { dirname, join } from "node:path"; import { TempDir } from "./helpers/temp.ts"; -import { assertFilesEqual, runCliOrFail, sanitiseCatStdout } from "./helpers/cli.ts"; +import { assertFilesEqual, runCli, runCliOrFail, sanitiseCatStdout, type CliResult } from "./helpers/cli.ts"; import { applyRemoteSyncSettings, initSettingsFile } from "./helpers/settings.ts"; import { startMinio, stopMinio } from "./helpers/docker.ts"; @@ -34,6 +34,20 @@ function createJournalFixture(): string { ].join(""); } +async function assertFetchedVaultMatches( + sourceFile: string, + receiverFile: string, + result: CliResult, + message: string +): Promise { + assert.equal(result.code, 0, `${message}\nCLI exit code: ${result.code}\n${result.combined}`); + try { + await assertFilesEqual(sourceFile, receiverFile, message); + } catch (error) { + throw new Error(`${message}\nCLI output:\n${result.combined}`, { cause: error }); + } +} + async function runScenario(encrypt: boolean): Promise { const suffix = `${encrypt ? "enc1" : "enc0"}-${Date.now()}-${Math.floor(Math.random() * 100000)}`; const minioEndpoint = requireEnv("MINIO_ENDPOINT", "minioEndpoint").replace(/\/$/, ""); @@ -99,7 +113,7 @@ async function runScenario(encrypt: boolean): Promise { "--force", "--write-settings" ); - await runCliOrFail( + const initialFetch = await runCli( receiverDatabase, "--settings", receiverSettings, @@ -110,7 +124,12 @@ async function runScenario(encrypt: boolean): Promise { "--write-settings" ); - await assertFilesEqual(sourceFile, receiverFile, "Fetched Vault file does not match the rebuild source"); + await assertFetchedVaultMatches( + sourceFile, + receiverFile, + initialFetch, + "Initial fetch did not reproduce the rebuild source in the receiver Vault" + ); const fetchedContent = sanitiseCatStdout( await runCliOrFail(receiverDatabase, "--settings", receiverSettings, "cat", targetPath) ); @@ -163,7 +182,7 @@ async function runScenario(encrypt: boolean): Promise { "Fetch should retain both the intact remote and differing local contents without inferring their ancestry" ); await rename(receiverFile, workDir.join("damaged-vault-backup.md")); - await runCliOrFail( + const restoreFetch = await runCli( receiverDatabase, "--settings", receiverSettings, @@ -173,7 +192,12 @@ async function runScenario(encrypt: boolean): Promise { "--force", "--write-settings" ); - await assertFilesEqual(sourceFile, receiverFile, "Fetching into an empty Vault should restore the remote file"); + await assertFetchedVaultMatches( + sourceFile, + receiverFile, + restoreFetch, + "Fetch did not restore the remote file after the damaged Vault copy was moved" + ); assert.equal(await readFile(workDir.join("damaged-vault-backup.md"), "utf8"), damagedContent); const restoredContent = sanitiseCatStdout( await runCliOrFail(receiverDatabase, "--settings", receiverSettings, "cat", targetPath)