Files

42 lines
1.8 KiB
JavaScript

'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs/promises');
const os = require('node:os');
const path = require('node:path');
const { writeJsonAtomic } = require('../lib/json-file');
test('Windows rename fallback replaces JSON without deleting the old state first', async t => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mc-json-'));
t.after(() => fs.rm(root, { recursive: true, force: true }));
const file = path.join(root, 'queue.json');
await fs.writeFile(file, '{"old":true}\n');
let failedOnce = false;
const io = { ...fs, async rename(from, to) {
if (to === file && !failedOnce) {
failedOnce = true;
const error = new Error('destination busy'); error.code = 'EEXIST'; throw error;
}
return fs.rename(from, to);
} };
await writeJsonAtomic(file, { next: true }, io);
assert.deepEqual(JSON.parse(await fs.readFile(file, 'utf8')), { next: true });
assert.deepEqual(await fs.readdir(root), ['queue.json']);
});
test('failed replacement restores the old JSON', async t => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mc-json-'));
t.after(() => fs.rm(root, { recursive: true, force: true }));
const file = path.join(root, 'queue.json');
await fs.writeFile(file, '{"old":true}\n');
const io = { ...fs, async rename(from, to) {
if (to === file && from.endsWith('.tmp')) {
const error = new Error('replacement blocked'); error.code = 'EEXIST'; throw error;
}
return fs.rename(from, to);
} };
await assert.rejects(writeJsonAtomic(file, { next: true }, io), /replacement blocked/);
assert.deepEqual(JSON.parse(await fs.readFile(file, 'utf8')), { old: true });
assert.deepEqual(await fs.readdir(root), ['queue.json']);
});