62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
import { retryTransientFilesystemOperation } from '@electron/opencode/filesystem-retry';
|
|
|
|
describe('retryTransientFilesystemOperation', () => {
|
|
it.each(['EIO', 'EPERM', 'EBUSY', 'EACCES'])(
|
|
'retries transient %s failures within the configured bound',
|
|
(code) => {
|
|
const wait = vi.fn();
|
|
let attempts = 0;
|
|
|
|
const result = retryTransientFilesystemOperation(() => {
|
|
attempts += 1;
|
|
if (attempts < 3) {
|
|
throw Object.assign(new Error('temporary filesystem failure'), { code });
|
|
}
|
|
return 'installed';
|
|
}, {
|
|
retryDelaysMs: [0, 0],
|
|
wait,
|
|
});
|
|
|
|
expect(result).toBe('installed');
|
|
expect(attempts).toBe(3);
|
|
expect(wait).toHaveBeenCalledTimes(2);
|
|
},
|
|
);
|
|
|
|
it('does not retry a non-transient filesystem failure', () => {
|
|
const wait = vi.fn();
|
|
let attempts = 0;
|
|
const failure = Object.assign(new Error('missing source'), { code: 'ENOENT' });
|
|
|
|
expect(() => retryTransientFilesystemOperation(() => {
|
|
attempts += 1;
|
|
throw failure;
|
|
}, {
|
|
retryDelaysMs: [0, 0],
|
|
wait,
|
|
})).toThrow(failure);
|
|
|
|
expect(attempts).toBe(1);
|
|
expect(wait).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('stops after the configured retry delays are exhausted', () => {
|
|
const wait = vi.fn();
|
|
let attempts = 0;
|
|
const failure = Object.assign(new Error('persistent filesystem failure'), { code: 'EIO' });
|
|
|
|
expect(() => retryTransientFilesystemOperation(() => {
|
|
attempts += 1;
|
|
throw failure;
|
|
}, {
|
|
retryDelaysMs: [0, 0],
|
|
wait,
|
|
})).toThrow(failure);
|
|
|
|
expect(attempts).toBe(3);
|
|
expect(wait).toHaveBeenCalledTimes(2);
|
|
});
|
|
});
|