mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:40:43 +00:00
test(commands): share atomic backup setup
This commit is contained in:
@@ -45,33 +45,48 @@ describe("backupCreateCommand atomic archive write", () => {
|
||||
await tempHome.restore();
|
||||
});
|
||||
|
||||
it("does not leave a partial final archive behind when tar creation fails", async () => {
|
||||
async function prepareAtomicBackupScenario(params: {
|
||||
archivePrefix: string;
|
||||
outputName?: string;
|
||||
}) {
|
||||
const stateDir = path.join(tempHome.home, ".openclaw");
|
||||
const archiveDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-backup-failure-"));
|
||||
const archiveDir = await fs.mkdtemp(path.join(os.tmpdir(), params.archivePrefix));
|
||||
await fs.writeFile(path.join(stateDir, "openclaw.json"), JSON.stringify({}), "utf8");
|
||||
await fs.writeFile(path.join(stateDir, "state.txt"), "state\n", "utf8");
|
||||
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
const outputPath = path.join(archiveDir, params.outputName ?? "backup.tar.gz");
|
||||
|
||||
vi.spyOn(backupShared, "resolveBackupPlanFromDisk").mockResolvedValue(
|
||||
await resolveBackupPlanFromPaths({
|
||||
stateDir,
|
||||
configPath: path.join(stateDir, "openclaw.json"),
|
||||
oauthDir: path.join(stateDir, "credentials"),
|
||||
includeWorkspace: false,
|
||||
configInsideState: true,
|
||||
oauthInsideState: true,
|
||||
nowMs: 123,
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
archiveDir,
|
||||
outputPath,
|
||||
runtime,
|
||||
};
|
||||
}
|
||||
|
||||
it("does not leave a partial final archive behind when tar creation fails", async () => {
|
||||
const { archiveDir, outputPath, runtime } = await prepareAtomicBackupScenario({
|
||||
archivePrefix: "openclaw-backup-failure-",
|
||||
});
|
||||
try {
|
||||
await fs.writeFile(path.join(stateDir, "openclaw.json"), JSON.stringify({}), "utf8");
|
||||
await fs.writeFile(path.join(stateDir, "state.txt"), "state\n", "utf8");
|
||||
|
||||
tarCreateMock.mockRejectedValueOnce(new Error("disk full"));
|
||||
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
const outputPath = path.join(archiveDir, "backup.tar.gz");
|
||||
vi.spyOn(backupShared, "resolveBackupPlanFromDisk").mockResolvedValue(
|
||||
await resolveBackupPlanFromPaths({
|
||||
stateDir,
|
||||
configPath: path.join(stateDir, "openclaw.json"),
|
||||
oauthDir: path.join(stateDir, "credentials"),
|
||||
includeWorkspace: false,
|
||||
configInsideState: true,
|
||||
oauthInsideState: true,
|
||||
nowMs: 123,
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(
|
||||
backupCreateCommand(runtime, {
|
||||
output: outputPath,
|
||||
@@ -87,14 +102,12 @@ describe("backupCreateCommand atomic archive write", () => {
|
||||
});
|
||||
|
||||
it("does not overwrite an archive created after readiness checks complete", async () => {
|
||||
const stateDir = path.join(tempHome.home, ".openclaw");
|
||||
const archiveDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-backup-race-"));
|
||||
const { archiveDir, outputPath, runtime } = await prepareAtomicBackupScenario({
|
||||
archivePrefix: "openclaw-backup-race-",
|
||||
});
|
||||
const realLink = fs.link.bind(fs);
|
||||
const linkSpy = vi.spyOn(fs, "link");
|
||||
try {
|
||||
await fs.writeFile(path.join(stateDir, "openclaw.json"), JSON.stringify({}), "utf8");
|
||||
await fs.writeFile(path.join(stateDir, "state.txt"), "state\n", "utf8");
|
||||
|
||||
tarCreateMock.mockImplementationOnce(async ({ file }: { file: string }) => {
|
||||
await fs.writeFile(file, "archive-bytes", "utf8");
|
||||
});
|
||||
@@ -103,24 +116,6 @@ describe("backupCreateCommand atomic archive write", () => {
|
||||
return await realLink(existingPath, newPath);
|
||||
});
|
||||
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
const outputPath = path.join(archiveDir, "backup.tar.gz");
|
||||
vi.spyOn(backupShared, "resolveBackupPlanFromDisk").mockResolvedValue(
|
||||
await resolveBackupPlanFromPaths({
|
||||
stateDir,
|
||||
configPath: path.join(stateDir, "openclaw.json"),
|
||||
oauthDir: path.join(stateDir, "credentials"),
|
||||
includeWorkspace: false,
|
||||
configInsideState: true,
|
||||
oauthInsideState: true,
|
||||
nowMs: 123,
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(
|
||||
backupCreateCommand(runtime, {
|
||||
output: outputPath,
|
||||
@@ -135,13 +130,11 @@ describe("backupCreateCommand atomic archive write", () => {
|
||||
});
|
||||
|
||||
it("falls back to exclusive copy when hard-link publication is unsupported", async () => {
|
||||
const stateDir = path.join(tempHome.home, ".openclaw");
|
||||
const archiveDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-backup-copy-fallback-"));
|
||||
const { archiveDir, outputPath, runtime } = await prepareAtomicBackupScenario({
|
||||
archivePrefix: "openclaw-backup-copy-fallback-",
|
||||
});
|
||||
const linkSpy = vi.spyOn(fs, "link");
|
||||
try {
|
||||
await fs.writeFile(path.join(stateDir, "openclaw.json"), JSON.stringify({}), "utf8");
|
||||
await fs.writeFile(path.join(stateDir, "state.txt"), "state\n", "utf8");
|
||||
|
||||
tarCreateMock.mockImplementationOnce(async ({ file }: { file: string }) => {
|
||||
await fs.writeFile(file, "archive-bytes", "utf8");
|
||||
});
|
||||
@@ -149,24 +142,6 @@ describe("backupCreateCommand atomic archive write", () => {
|
||||
Object.assign(new Error("hard links not supported"), { code: "EOPNOTSUPP" }),
|
||||
);
|
||||
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
const outputPath = path.join(archiveDir, "backup.tar.gz");
|
||||
vi.spyOn(backupShared, "resolveBackupPlanFromDisk").mockResolvedValue(
|
||||
await resolveBackupPlanFromPaths({
|
||||
stateDir,
|
||||
configPath: path.join(stateDir, "openclaw.json"),
|
||||
oauthDir: path.join(stateDir, "credentials"),
|
||||
includeWorkspace: false,
|
||||
configInsideState: true,
|
||||
oauthInsideState: true,
|
||||
nowMs: 123,
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await backupCreateCommand(runtime, {
|
||||
output: outputPath,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user