42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import { describe, it, expect, afterEach } from 'vitest';
|
|
import nodePath from 'node:path';
|
|
import os from 'node:os';
|
|
import { promises as fs } from 'node:fs';
|
|
import { writeFileAtomic, withFileLock } from '../../apps/desktop/src/main/safe/atomic-write';
|
|
|
|
const dir = nodePath.join(os.tmpdir(), 'dsh-atomic-test');
|
|
afterEach(async () => { await fs.rm(dir, { recursive: true, force: true }); });
|
|
|
|
describe('writeFileAtomic (FR-S5)', () => {
|
|
it('写入内容并回读一致', async () => {
|
|
const p = nodePath.join(dir, 'a.md');
|
|
await writeFileAtomic(p, '# 标题\n内容');
|
|
expect(await fs.readFile(p, 'utf8')).toBe('# 标题\n内容');
|
|
});
|
|
it('不残留临时文件', async () => {
|
|
const p = nodePath.join(dir, 'b.md');
|
|
await writeFileAtomic(p, 'x');
|
|
const files = await fs.readdir(dir);
|
|
expect(files).toEqual(['b.md']);
|
|
});
|
|
it('覆盖已有文件', async () => {
|
|
const p = nodePath.join(dir, 'c.md');
|
|
await writeFileAtomic(p, 'old');
|
|
await writeFileAtomic(p, 'new');
|
|
expect(await fs.readFile(p, 'utf8')).toBe('new');
|
|
});
|
|
});
|
|
|
|
describe('withFileLock 并发安全', () => {
|
|
it('同文件请求串行执行', async () => {
|
|
const p = nodePath.join(dir, 'lock.md');
|
|
const order: number[] = [];
|
|
const t = (id: number, delay: number) => withFileLock(p, async () => {
|
|
order.push(id);
|
|
await new Promise(r => setTimeout(r, delay));
|
|
});
|
|
await Promise.all([t(1, 20), t(2, 1), t(3, 1)]);
|
|
expect(order).toEqual([1, 2, 3]);
|
|
});
|
|
});
|