Skip to content

Commit 030514c

Browse files
committed
test: rewrite fastutf8stream tests to use node:test
Rewrite test/parallel/test-fastutf8stream-sync.js and test/parallel/test-fastutf8stream-flush-mocks.js to use node:test with individual test functions and proper stream cleanup. Key changes: - Convert from block-based tests to individual test() functions - Use once() from node:events for proper stream close event handling - Ensure streams emit 'close' event before test completion for Windows compatibility - Fix fsync mocking in flush tests to allow proper stream closure - Each test runs independently with proper resource cleanup
1 parent ebd2da6 commit 030514c

2 files changed

Lines changed: 350 additions & 142 deletions

File tree

Lines changed: 197 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

3-
const common = require('../common');
3+
require('../common');
4+
const { test } = require('node:test');
45
const tmpdir = require('../common/tmpdir');
56
const {
67
ok,
@@ -11,10 +12,12 @@ const {
1112
fsyncSync,
1213
writeSync,
1314
write,
15+
mkdirSync,
1416
} = require('node:fs');
1517
const { join } = require('node:path');
1618
const { Utf8Stream } = require('node:fs');
1719
const { isMainThread } = require('node:worker_threads');
20+
const { once } = require('node:events');
1821

1922
tmpdir.refresh();
2023
if (isMainThread) {
@@ -24,82 +27,212 @@ if (isMainThread) {
2427
let fileCounter = 0;
2528

2629
function getTempFile() {
27-
return join(tmpdir.path, `fastutf8stream-${process.pid}-${Date.now()}-${fileCounter++}.log`);
30+
const testDir = join(tmpdir.path, `test-${process.pid}-${process.hrtime.bigint()}`);
31+
mkdirSync(testDir, { recursive: true });
32+
return join(testDir, `fastutf8stream-${fileCounter++}.log`);
33+
}
34+
35+
function createClosePromise(stream) {
36+
return once(stream, 'close');
2837
}
2938

30-
runTests(false);
31-
runTests(true);
32-
33-
function runTests(sync) {
34-
35-
{
36-
const dest = getTempFile();
37-
const fd = openSync(dest, 'w');
38-
39-
const fsOverride = {
40-
fsync: common.mustNotCall(),
41-
fsyncSync: common.mustCall(() => fsyncSync(fd)),
42-
};
43-
if (sync) {
44-
fsOverride.writeSync = common.mustCall((...args) => writeSync(...args));
45-
fsOverride.write = common.mustNotCall();
46-
} else {
47-
fsOverride.write = common.mustCall((...args) => write(...args));
48-
fsOverride.writeSync = common.mustNotCall();
49-
}
50-
51-
const stream = new Utf8Stream({
52-
fd,
53-
sync,
54-
fsync: true,
55-
minLength: 4096,
56-
fs: fsOverride,
57-
});
5839

59-
stream.on('ready', common.mustCall(() => {
40+
test('Utf8Stream sync flush with fsync success', async (t) => {
41+
const dest = getTempFile();
42+
const fd = openSync(dest, 'w');
43+
44+
let fsyncSyncCalled = false;
45+
let writeSyncCalled = false;
46+
47+
const fsOverride = {
48+
fsync: (fd, cb) => process.nextTick(cb),
49+
fsyncSync: () => {
50+
fsyncSyncCalled = true;
51+
return fsyncSync(fd);
52+
},
53+
writeSync: (...args) => {
54+
writeSyncCalled = true;
55+
return writeSync(...args);
56+
},
57+
write: t.assert.fail,
58+
close: (fd, cb) => process.nextTick(cb),
59+
};
60+
61+
const stream = new Utf8Stream({
62+
fd,
63+
sync: true,
64+
fsync: true,
65+
minLength: 4096,
66+
fs: fsOverride,
67+
});
68+
69+
const closePromise = createClosePromise(stream);
70+
71+
await new Promise((resolve) => {
72+
stream.on('ready', () => {
6073
ok(stream.write('hello world\n'));
6174

62-
stream.flush(common.mustSucceed(() => stream.end()));
63-
}));
64-
}
75+
stream.flush((err) => {
76+
t.assert.ifError(err);
77+
stream.end();
78+
resolve();
79+
});
80+
});
81+
});
82+
83+
ok(fsyncSyncCalled, 'fsyncSync should have been called');
84+
ok(writeSyncCalled, 'writeSync should have been called');
85+
86+
await closePromise;
87+
88+
});
89+
90+
test('Utf8Stream async flush with fsync success', async (t) => {
91+
const dest = getTempFile();
92+
const fd = openSync(dest, 'w');
93+
94+
let fsyncSyncCalled = false;
95+
let writeCalled = false;
96+
97+
const fsOverride = {
98+
fsync: (fd, cb) => process.nextTick(cb),
99+
fsyncSync: () => {
100+
fsyncSyncCalled = true;
101+
return fsyncSync(fd);
102+
},
103+
write: (...args) => {
104+
writeCalled = true;
105+
return write(...args);
106+
},
107+
writeSync: t.assert.fail,
108+
close: (fd, cb) => process.nextTick(cb),
109+
};
110+
111+
const stream = new Utf8Stream({
112+
fd,
113+
sync: false,
114+
fsync: true,
115+
minLength: 4096,
116+
fs: fsOverride,
117+
});
118+
119+
const closePromise = createClosePromise(stream);
120+
121+
await new Promise((resolve) => {
122+
stream.on('ready', () => {
123+
ok(stream.write('hello world\n'));
65124

66-
{
67-
const dest = getTempFile();
68-
const fd = openSync(dest, 'w');
125+
stream.flush((err) => {
126+
t.assert.ifError(err);
127+
stream.end();
128+
resolve();
129+
});
130+
});
131+
});
69132

70-
const testError = new Error('fsync failed');
71-
testError.code = 'ETEST';
133+
ok(fsyncSyncCalled, 'fsyncSync should have been called');
134+
ok(writeCalled, 'write should have been called');
72135

73-
const fsOverride = {
74-
fsync: common.mustCall((fd, cb) => {
75-
process.nextTick(() => cb(testError));
76-
}, 2),
77-
};
136+
await closePromise;
78137

79-
if (sync) {
80-
fsOverride.writeSync = common.mustCall((...args) => {
81-
return writeSync(...args);
82-
});
83-
} else {
84-
fsOverride.write = common.mustCall((...args) => {
85-
return write(...args);
86-
});
87-
}
138+
});
139+
140+
test('Utf8Stream sync flush with fsync error', async (t) => {
141+
const dest = getTempFile();
142+
const fd = openSync(dest, 'w');
143+
144+
const testError = new Error('fsync failed');
145+
testError.code = 'ETEST';
146+
147+
let fsyncCallCount = 0;
148+
let writeSyncCalled = false;
88149

89-
const stream = new Utf8Stream({
90-
fd,
91-
sync,
92-
minLength: 4096,
93-
fs: fsOverride,
150+
const fsOverride = {
151+
fsync: (fd, cb) => {
152+
fsyncCallCount++;
153+
process.nextTick(() => cb(testError));
154+
},
155+
writeSync: (...args) => {
156+
writeSyncCalled = true;
157+
return writeSync(...args);
158+
},
159+
close: (fd, cb) => process.nextTick(cb),
160+
};
161+
162+
const stream = new Utf8Stream({
163+
fd,
164+
sync: true,
165+
minLength: 4096,
166+
fs: fsOverride,
167+
});
168+
169+
const closePromise = createClosePromise(stream);
170+
171+
await new Promise((resolve) => {
172+
stream.on('ready', () => {
173+
ok(stream.write('hello world\n'));
174+
stream.flush((err) => {
175+
ok(err, 'flush should return an error');
176+
strictEqual(err.code, 'ETEST');
177+
stream.end();
178+
resolve();
179+
});
94180
});
181+
});
182+
183+
strictEqual(fsyncCallCount, 2, 'fsync should have been called twice');
184+
ok(writeSyncCalled, 'writeSync should have been called');
185+
186+
await closePromise;
187+
188+
});
189+
190+
test('Utf8Stream async flush with fsync error', async (t) => {
191+
const dest = getTempFile();
192+
const fd = openSync(dest, 'w');
193+
194+
const testError = new Error('fsync failed');
195+
testError.code = 'ETEST';
196+
197+
let fsyncCallCount = 0;
198+
let writeCalled = false;
95199

96-
stream.on('ready', common.mustCall(() => {
200+
const fsOverride = {
201+
fsync: (fd, cb) => {
202+
fsyncCallCount++;
203+
process.nextTick(() => cb(testError));
204+
},
205+
write: (...args) => {
206+
writeCalled = true;
207+
return write(...args);
208+
},
209+
close: (fd, cb) => process.nextTick(cb),
210+
};
211+
212+
const stream = new Utf8Stream({
213+
fd,
214+
sync: false,
215+
minLength: 4096,
216+
fs: fsOverride,
217+
});
218+
219+
const closePromise = createClosePromise(stream);
220+
221+
await new Promise((resolve) => {
222+
stream.on('ready', () => {
97223
ok(stream.write('hello world\n'));
98-
stream.flush(common.mustCall((err) => {
224+
stream.flush((err) => {
99225
ok(err, 'flush should return an error');
100226
strictEqual(err.code, 'ETEST');
101227
stream.end();
102-
}));
103-
}));
104-
}
105-
}
228+
resolve();
229+
});
230+
});
231+
});
232+
233+
strictEqual(fsyncCallCount, 2, 'fsync should have been called twice');
234+
ok(writeCalled, 'write should have been called');
235+
236+
await closePromise;
237+
238+
});

0 commit comments

Comments
 (0)