forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtest-stream-iter-pipeto-writev.js
More file actions
178 lines (163 loc) · 5.54 KB
/
Copy pathtest-stream-iter-pipeto-writev.js
File metadata and controls
178 lines (163 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Flags: --experimental-stream-iter
'use strict';
// Tests for pipeTo writev/writevSync paths and writeBatchAsyncFallback.
const common = require('../common');
const assert = require('assert');
const { setImmediate: setImmediatePromise } = require('timers/promises');
const { pipeTo, pipeToSync, push, text } = require('stream/iter');
// Multi-chunk batch with writevSync (sync success path)
async function testWritevSyncSuccess() {
const batches = [];
const writer = {
write(chunk) {},
writevSync(chunks) { batches.push(chunks); return true; },
writev(chunks) { batches.push(chunks); },
writeSync(chunk) { return true; },
endSync() { return 0; },
};
// Source that yields multi-chunk batches
async function* source() {
yield [new Uint8Array([1]), new Uint8Array([2]), new Uint8Array([3])];
yield [new Uint8Array([4]), new Uint8Array([5])];
}
const total = await pipeTo(source(), writer);
assert.ok(batches.length > 0);
// writevSync was used for multi-chunk batches
assert.ok(batches.some((b) => b.length > 1));
assert.strictEqual(total, 5);
}
// Multi-chunk batch with writev async (no writevSync)
async function testWritevAsyncFallback() {
const batches = [];
const writer = {
async writev(chunks) { batches.push(chunks); },
async write(chunk) { batches.push([chunk]); },
async end() {},
};
async function* source() {
yield [new Uint8Array([1]), new Uint8Array([2]), new Uint8Array([3])];
}
await pipeTo(source(), writer);
assert.ok(batches.length > 0);
assert.ok(batches.some((b) => b.length > 1));
}
// writevSync returns false — falls through to async writev
async function testWritevSyncFails() {
const asyncCalls = [];
const writer = {
write() {},
writevSync() { return false; },
async writev(chunks) { asyncCalls.push(chunks); },
writeSync() { return true; },
endSync() { return 0; },
};
async function* source() {
yield [new Uint8Array([1]), new Uint8Array([2])];
}
await pipeTo(source(), writer);
assert.strictEqual(asyncCalls.length, 1);
assert.strictEqual(asyncCalls[0].length, 2);
}
// writeSync fails mid-batch — triggers writeBatchAsyncFallback
async function testWriteSyncFailsMidBatch() {
const asyncWrites = [];
const writer = {
writeSync(chunk) {
// Fail for chunk value 2 — always, including retries
if (chunk[0] === 2) return false;
return true;
},
async write(chunk) { asyncWrites.push(chunk); },
async end() {},
};
// Single batch with 3 chunks
async function* source() {
yield [new Uint8Array([1]), new Uint8Array([2]), new Uint8Array([3])];
}
const total = await pipeTo(source(), writer);
// Chunk 1: writeSync succeeds
// Chunk 2: writeSync fails → writeBatchAsyncFallback → write() called
// Chunk 3: writeBatchAsyncFallback retries writeSync → succeeds
assert.ok(asyncWrites.length >= 1);
assert.deepStrictEqual(asyncWrites[0], new Uint8Array([2]));
assert.strictEqual(total, 3);
}
// writeSync always fails — all chunks go through async
async function testWriteSyncAlwaysFails() {
const asyncWrites = [];
const writer = {
writeSync() { return false; },
async write(chunk) { asyncWrites.push(chunk); },
async end() {},
};
async function* source() {
yield [new Uint8Array([10]), new Uint8Array([20])];
}
const total = await pipeTo(source(), writer);
assert.strictEqual(asyncWrites.length, 2);
assert.strictEqual(total, 2);
}
// PushWriter block mode accepts sync writes even when returning false for
// backpressure. pipeTo must wait for drain, not retry the same write.
async function assertPushWriterBlockPipeTo(source, expected, expectedTotal) {
const { writer, readable } = push({
highWaterMark: 1,
backpressure: 'block',
});
const pipe = pipeTo(source, writer);
await setImmediatePromise();
const data = await text(readable);
const total = await pipe;
assert.strictEqual(data, expected);
assert.strictEqual(total, expectedTotal);
}
async function testPushWriterBlockSyncFalseAccepted() {
await assertPushWriterBlockPipeTo((async function*() {
yield [new Uint8Array([97])];
yield [new Uint8Array([98])];
})(), 'ab', 2);
await assertPushWriterBlockPipeTo((async function*() {
yield [new Uint8Array([97, 98])];
yield [new Uint8Array([99]), new Uint8Array([100])];
})(), 'abcd', 4);
}
// pipeToSync with writevSync
async function testPipeToSyncWritev() {
const batches = [];
const writer = {
writevSync(chunks) { batches.push(chunks); },
writeSync(chunk) { return true; },
endSync() { return 0; },
};
function* source() {
yield [new Uint8Array([1]), new Uint8Array([2]), new Uint8Array([3])];
yield [new Uint8Array([4])];
}
pipeToSync(source(), writer);
// Multi-chunk batch should have used writevSync
assert.ok(batches.some((b) => b.length > 1));
}
// pipeToSync with writer that has write() and writeSync() — writeSync preferred
async function testPipeToSyncWriteFallback() {
const syncWrites = [];
const writer = {
writeSync(chunk) { syncWrites.push(chunk); return true; },
write(chunk) { /* should not be called */ },
endSync() { return 0; },
};
function* source() {
yield [new Uint8Array([1]), new Uint8Array([2])];
}
pipeToSync(source(), writer);
assert.strictEqual(syncWrites.length, 2);
}
Promise.all([
testWritevSyncSuccess(),
testWritevAsyncFallback(),
testWritevSyncFails(),
testWriteSyncFailsMidBatch(),
testWriteSyncAlwaysFails(),
testPushWriterBlockSyncFalseAccepted(),
testPipeToSyncWritev(),
testPipeToSyncWriteFallback(),
]).then(common.mustCall());