Skip to content

Commit 90af89e

Browse files
fix(config): mirror sync restore failure test and tidy warning format
Review follow-ups on #70515: add the parallel failure-injection test for maybeRecoverSuspiciousConfigReadSync so the sync path has the same coverage, and move the captured error message inside the suspicious- reason parentheses in the failure warning so the line no longer reads 'failed: <path> (...): <msg>' (double colon) — it now reads 'failed: <path> (..., <msg>)' with a single trailing colon after 'failed'.
1 parent 2bee293 commit 90af89e

2 files changed

Lines changed: 44 additions & 7 deletions

File tree

src/config/io.observe-recovery.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,44 @@ describe("config observe recovery", () => {
316316
});
317317
});
318318

319+
it("sync recovery records copyFileSync failure instead of falsely claiming restore succeeded", async () => {
320+
await withSuiteHome(async (home) => {
321+
const { deps, configPath, auditPath, warn } = makeDeps(home);
322+
await seedConfigBackup(configPath, recoverableTelegramConfig);
323+
const clobbered = await writeClobberedUpdateChannel(configPath);
324+
325+
const copyError = Object.assign(new Error("EACCES: permission denied"), { code: "EACCES" });
326+
const failingFs: ObserveRecoveryDeps["fs"] = {
327+
...deps.fs,
328+
copyFileSync: () => {
329+
throw copyError;
330+
},
331+
};
332+
const recovered = maybeRecoverSuspiciousConfigReadSync({
333+
deps: { ...deps, fs: failingFs },
334+
configPath,
335+
raw: clobbered.raw,
336+
parsed: clobbered.parsed,
337+
});
338+
339+
expect((recovered.parsed as { gateway?: { mode?: string } }).gateway?.mode).toBe("local");
340+
await expect(fsp.readFile(configPath, "utf-8")).resolves.toBe(clobbered.raw);
341+
expect(warn).toHaveBeenCalledWith(
342+
expect.stringContaining("Config auto-restore from backup failed:"),
343+
);
344+
expect(warn).toHaveBeenCalledWith(expect.stringContaining("EACCES: permission denied"));
345+
expect(warn).not.toHaveBeenCalledWith(
346+
expect.stringContaining("Config auto-restored from backup:"),
347+
);
348+
349+
const observe = await readLastObserveEvent(auditPath);
350+
expect(observe?.restoredFromBackup).toBe(false);
351+
expect(observe?.valid).toBe(false);
352+
expect(observe?.restoreErrorCode).toBe("EACCES");
353+
expect(observe?.restoreErrorMessage).toBe("EACCES: permission denied");
354+
});
355+
});
356+
319357
it("dedupes repeated suspicious hashes", async () => {
320358
await withSuiteHome(async (home) => {
321359
const { deps, configPath, auditPath } = makeDeps(home);

src/config/io.observe-recovery.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ function createConfigObserveAnomalyAuditAppendParams(
225225
});
226226
}
227227

228-
229228
function hashConfigRaw(raw: string | null): string {
230229
return crypto
231230
.createHash("sha256")
@@ -689,9 +688,9 @@ export async function maybeRecoverSuspiciousConfigRead(params: {
689688
);
690689
} else {
691690
params.deps.logger.warn(
692-
`Config auto-restore from backup failed: ${params.configPath} (${suspicious.join(", ")})${
693-
restoreErrorDetails.message ? `: ${restoreErrorDetails.message}` : ""
694-
}`,
691+
`Config auto-restore from backup failed: ${params.configPath} (${suspicious.join(", ")}${
692+
restoreErrorDetails.message ? `; ${restoreErrorDetails.message}` : ""
693+
})`,
695694
);
696695
}
697696
await appendConfigAuditRecord(
@@ -796,9 +795,9 @@ export function maybeRecoverSuspiciousConfigReadSync(params: {
796795
);
797796
} else {
798797
params.deps.logger.warn(
799-
`Config auto-restore from backup failed: ${params.configPath} (${suspicious.join(", ")})${
800-
restoreErrorDetails.message ? `: ${restoreErrorDetails.message}` : ""
801-
}`,
798+
`Config auto-restore from backup failed: ${params.configPath} (${suspicious.join(", ")}${
799+
restoreErrorDetails.message ? `; ${restoreErrorDetails.message}` : ""
800+
})`,
802801
);
803802
}
804803
appendConfigAuditRecordSync(

0 commit comments

Comments
 (0)