1'use strict';
2
3const common = require('../common');
4const { Writable, Readable, Duplex } = require('stream');
5const assert = require('assert');
6
7{
8  // Multiple callback.
9  new Writable({
10    construct: common.mustCall((callback) => {
11      callback();
12      callback();
13    })
14  }).on('error', common.expectsError({
15    name: 'Error',
16    code: 'ERR_MULTIPLE_CALLBACK'
17  }));
18}
19
20{
21  // Multiple callback.
22  new Readable({
23    construct: common.mustCall((callback) => {
24      callback();
25      callback();
26    })
27  }).on('error', common.expectsError({
28    name: 'Error',
29    code: 'ERR_MULTIPLE_CALLBACK'
30  }));
31}
32
33{
34  // Synchronous error.
35
36  new Writable({
37    construct: common.mustCall((callback) => {
38      callback(new Error('test'));
39    })
40  }).on('error', common.expectsError({
41    name: 'Error',
42    message: 'test'
43  }));
44}
45
46{
47  // Synchronous error.
48
49  new Readable({
50    construct: common.mustCall((callback) => {
51      callback(new Error('test'));
52    })
53  }).on('error', common.expectsError({
54    name: 'Error',
55    message: 'test'
56  }));
57}
58
59{
60  // Asynchronous error.
61
62  new Writable({
63    construct: common.mustCall((callback) => {
64      process.nextTick(callback, new Error('test'));
65    })
66  }).on('error', common.expectsError({
67    name: 'Error',
68    message: 'test'
69  }));
70}
71
72{
73  // Asynchronous error.
74
75  new Readable({
76    construct: common.mustCall((callback) => {
77      process.nextTick(callback, new Error('test'));
78    })
79  }).on('error', common.expectsError({
80    name: 'Error',
81    message: 'test'
82  }));
83}
84
85function testDestroy(factory) {
86  {
87    let constructed = false;
88    const s = factory({
89      construct: common.mustCall((cb) => {
90        constructed = true;
91        process.nextTick(cb);
92      })
93    });
94    s.on('close', common.mustCall(() => {
95      assert.strictEqual(constructed, true);
96    }));
97    s.destroy();
98  }
99
100  {
101    let constructed = false;
102    const s = factory({
103      construct: common.mustCall((cb) => {
104        constructed = true;
105        process.nextTick(cb);
106      })
107    });
108    s.on('close', common.mustCall(() => {
109      assert.strictEqual(constructed, true);
110    }));
111    s.destroy(null, () => {
112      assert.strictEqual(constructed, true);
113    });
114  }
115
116  {
117    let constructed = false;
118    const s = factory({
119      construct: common.mustCall((cb) => {
120        constructed = true;
121        process.nextTick(cb);
122      })
123    });
124    s.on('close', common.mustCall(() => {
125      assert.strictEqual(constructed, true);
126    }));
127    s.destroy();
128  }
129
130
131  {
132    let constructed = false;
133    const s = factory({
134      construct: common.mustCall((cb) => {
135        constructed = true;
136        process.nextTick(cb);
137      })
138    });
139    s.on('close', common.mustCall(() => {
140      assert.strictEqual(constructed, true);
141    }));
142    s.on('error', common.mustCall((err) => {
143      assert.strictEqual(err.message, 'kaboom');
144    }));
145    s.destroy(new Error('kaboom'), (err) => {
146      assert.strictEqual(err.message, 'kaboom');
147      assert.strictEqual(constructed, true);
148    });
149  }
150
151  {
152    let constructed = false;
153    const s = factory({
154      construct: common.mustCall((cb) => {
155        constructed = true;
156        process.nextTick(cb);
157      })
158    });
159    s.on('error', common.mustCall(() => {
160      assert.strictEqual(constructed, true);
161    }));
162    s.on('close', common.mustCall(() => {
163      assert.strictEqual(constructed, true);
164    }));
165    s.destroy(new Error());
166  }
167}
168testDestroy((opts) => new Readable({
169  read: common.mustNotCall(),
170  ...opts
171}));
172testDestroy((opts) => new Writable({
173  write: common.mustNotCall(),
174  final: common.mustNotCall(),
175  ...opts
176}));
177
178{
179  let constructed = false;
180  const r = new Readable({
181    autoDestroy: true,
182    construct: common.mustCall((cb) => {
183      constructed = true;
184      process.nextTick(cb);
185    }),
186    read: common.mustCall(() => {
187      assert.strictEqual(constructed, true);
188      r.push(null);
189    })
190  });
191  r.on('close', common.mustCall(() => {
192    assert.strictEqual(constructed, true);
193  }));
194  r.on('data', common.mustNotCall());
195}
196
197{
198  let constructed = false;
199  const w = new Writable({
200    autoDestroy: true,
201    construct: common.mustCall((cb) => {
202      constructed = true;
203      process.nextTick(cb);
204    }),
205    write: common.mustCall((chunk, encoding, cb) => {
206      assert.strictEqual(constructed, true);
207      process.nextTick(cb);
208    }),
209    final: common.mustCall((cb) => {
210      assert.strictEqual(constructed, true);
211      process.nextTick(cb);
212    })
213  });
214  w.on('close', common.mustCall(() => {
215    assert.strictEqual(constructed, true);
216  }));
217  w.end('data');
218}
219
220{
221  let constructed = false;
222  const w = new Writable({
223    autoDestroy: true,
224    construct: common.mustCall((cb) => {
225      constructed = true;
226      process.nextTick(cb);
227    }),
228    write: common.mustNotCall(),
229    final: common.mustCall((cb) => {
230      assert.strictEqual(constructed, true);
231      process.nextTick(cb);
232    })
233  });
234  w.on('close', common.mustCall(() => {
235    assert.strictEqual(constructed, true);
236  }));
237  w.end();
238}
239
240{
241  new Duplex({
242    construct: common.mustCall()
243  });
244}
245
246{
247  // https://github.com/nodejs/node/issues/34448
248
249  let constructed = false;
250  const d = new Duplex({
251    readable: false,
252    construct: common.mustCall((callback) => {
253      setImmediate(common.mustCall(() => {
254        constructed = true;
255        callback();
256      }));
257    }),
258    write(chunk, encoding, callback) {
259      callback();
260    },
261    read() {
262      this.push(null);
263    }
264  });
265  d.resume();
266  d.end('foo');
267  d.on('close', common.mustCall(() => {
268    assert.strictEqual(constructed, true);
269  }));
270}
271
272{
273  // Construct should not cause stream to read.
274  new Readable({
275    construct: common.mustCall((callback) => {
276      callback();
277    }),
278    read: common.mustNotCall()
279  });
280}
281