Skip to content

Commit e87b6f4

Browse files
committed
test: add regression test for repl history leak
This adds a test case to verify that the file handle is properly closed when REPL history initialization fails, preventing resource leaks. Refs: 52e5e2d
1 parent 52e5e2d commit e87b6f4

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
'use strict';
2+
// Flags: --expose-internals
3+
4+
const common = require('../common');
5+
const fs = require('fs');
6+
const path = require('path');
7+
const { ReplHistory } = require('internal/repl/history');
8+
const assert = require('assert');
9+
10+
const tmpdir = require('../common/tmpdir');
11+
tmpdir.refresh();
12+
13+
const historyPath = path.join(tmpdir.path, '.node_repl_history');
14+
15+
fs.writeFileSync(historyPath, 'dummy\n');
16+
17+
const originalOpen = fs.promises.open;
18+
let closeCalled = false;
19+
20+
fs.promises.open = async (filepath, flags, mode) => {
21+
const handle = await originalOpen(filepath, flags, mode);
22+
23+
if (flags === 'r+' && filepath === historyPath) {
24+
handle.truncate = async (len) => {
25+
throw new Error('Mock truncate error');
26+
};
27+
28+
const originalClose = handle.close;
29+
handle.close = async () => {
30+
closeCalled = true;
31+
return originalClose.call(handle);
32+
};
33+
}
34+
35+
return handle;
36+
};
37+
38+
const context = {
39+
historySize: 30,
40+
on: () => {},
41+
once: () => {},
42+
emit: () => {},
43+
pause: () => {},
44+
resume: () => {},
45+
off: () => {},
46+
line: '',
47+
_historyPrev: () => {},
48+
_writeToOutput: () => {}
49+
};
50+
51+
const history = new ReplHistory(context, { filePath: historyPath });
52+
53+
history.initialize(common.mustCall((err) => {
54+
assert.strictEqual(err, null);
55+
assert.strictEqual(closeCalled, true);
56+
}));

0 commit comments

Comments
 (0)