11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciconst {
51cb0ef41Sopenharmony_ci  Writable,
61cb0ef41Sopenharmony_ci  Readable,
71cb0ef41Sopenharmony_ci  Transform,
81cb0ef41Sopenharmony_ci  finished,
91cb0ef41Sopenharmony_ci  Duplex,
101cb0ef41Sopenharmony_ci  PassThrough,
111cb0ef41Sopenharmony_ci  Stream,
121cb0ef41Sopenharmony_ci} = require('stream');
131cb0ef41Sopenharmony_ciconst assert = require('assert');
141cb0ef41Sopenharmony_ciconst EE = require('events');
151cb0ef41Sopenharmony_ciconst fs = require('fs');
161cb0ef41Sopenharmony_ciconst { promisify } = require('util');
171cb0ef41Sopenharmony_ciconst http = require('http');
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci{
201cb0ef41Sopenharmony_ci  const rs = new Readable({
211cb0ef41Sopenharmony_ci    read() {}
221cb0ef41Sopenharmony_ci  });
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci  finished(rs, common.mustSucceed());
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  rs.push(null);
271cb0ef41Sopenharmony_ci  rs.resume();
281cb0ef41Sopenharmony_ci}
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci{
311cb0ef41Sopenharmony_ci  const ws = new Writable({
321cb0ef41Sopenharmony_ci    write(data, enc, cb) {
331cb0ef41Sopenharmony_ci      cb();
341cb0ef41Sopenharmony_ci    }
351cb0ef41Sopenharmony_ci  });
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  finished(ws, common.mustSucceed());
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  ws.end();
401cb0ef41Sopenharmony_ci}
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci{
431cb0ef41Sopenharmony_ci  const tr = new Transform({
441cb0ef41Sopenharmony_ci    transform(data, enc, cb) {
451cb0ef41Sopenharmony_ci      cb();
461cb0ef41Sopenharmony_ci    }
471cb0ef41Sopenharmony_ci  });
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  let finish = false;
501cb0ef41Sopenharmony_ci  let ended = false;
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  tr.on('end', () => {
531cb0ef41Sopenharmony_ci    ended = true;
541cb0ef41Sopenharmony_ci  });
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  tr.on('finish', () => {
571cb0ef41Sopenharmony_ci    finish = true;
581cb0ef41Sopenharmony_ci  });
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  finished(tr, common.mustSucceed(() => {
611cb0ef41Sopenharmony_ci    assert(finish);
621cb0ef41Sopenharmony_ci    assert(ended);
631cb0ef41Sopenharmony_ci  }));
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  tr.end();
661cb0ef41Sopenharmony_ci  tr.resume();
671cb0ef41Sopenharmony_ci}
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci{
701cb0ef41Sopenharmony_ci  const rs = fs.createReadStream(__filename);
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  rs.resume();
731cb0ef41Sopenharmony_ci  finished(rs, common.mustCall());
741cb0ef41Sopenharmony_ci}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci{
771cb0ef41Sopenharmony_ci  const finishedPromise = promisify(finished);
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  async function run() {
801cb0ef41Sopenharmony_ci    const rs = fs.createReadStream(__filename);
811cb0ef41Sopenharmony_ci    const done = common.mustCall();
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci    let ended = false;
841cb0ef41Sopenharmony_ci    rs.resume();
851cb0ef41Sopenharmony_ci    rs.on('end', () => {
861cb0ef41Sopenharmony_ci      ended = true;
871cb0ef41Sopenharmony_ci    });
881cb0ef41Sopenharmony_ci    await finishedPromise(rs);
891cb0ef41Sopenharmony_ci    assert(ended);
901cb0ef41Sopenharmony_ci    done();
911cb0ef41Sopenharmony_ci  }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  run();
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci{
971cb0ef41Sopenharmony_ci  // Check pre-cancelled
981cb0ef41Sopenharmony_ci  const signal = new EventTarget();
991cb0ef41Sopenharmony_ci  signal.aborted = true;
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  const rs = Readable.from((function* () {})());
1021cb0ef41Sopenharmony_ci  finished(rs, { signal }, common.mustCall((err) => {
1031cb0ef41Sopenharmony_ci    assert.strictEqual(err.name, 'AbortError');
1041cb0ef41Sopenharmony_ci  }));
1051cb0ef41Sopenharmony_ci}
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci{
1081cb0ef41Sopenharmony_ci  // Check cancelled before the stream ends sync.
1091cb0ef41Sopenharmony_ci  const ac = new AbortController();
1101cb0ef41Sopenharmony_ci  const { signal } = ac;
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  const rs = Readable.from((function* () {})());
1131cb0ef41Sopenharmony_ci  finished(rs, { signal }, common.mustCall((err) => {
1141cb0ef41Sopenharmony_ci    assert.strictEqual(err.name, 'AbortError');
1151cb0ef41Sopenharmony_ci  }));
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  ac.abort();
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci{
1211cb0ef41Sopenharmony_ci  // Check cancelled before the stream ends async.
1221cb0ef41Sopenharmony_ci  const ac = new AbortController();
1231cb0ef41Sopenharmony_ci  const { signal } = ac;
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  const rs = Readable.from((function* () {})());
1261cb0ef41Sopenharmony_ci  setTimeout(() => ac.abort(), 1);
1271cb0ef41Sopenharmony_ci  finished(rs, { signal }, common.mustCall((err) => {
1281cb0ef41Sopenharmony_ci    assert.strictEqual(err.name, 'AbortError');
1291cb0ef41Sopenharmony_ci  }));
1301cb0ef41Sopenharmony_ci}
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci{
1331cb0ef41Sopenharmony_ci  // Check cancelled after doesn't throw.
1341cb0ef41Sopenharmony_ci  const ac = new AbortController();
1351cb0ef41Sopenharmony_ci  const { signal } = ac;
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  const rs = Readable.from((function* () {
1381cb0ef41Sopenharmony_ci    yield 5;
1391cb0ef41Sopenharmony_ci    setImmediate(() => ac.abort());
1401cb0ef41Sopenharmony_ci  })());
1411cb0ef41Sopenharmony_ci  rs.resume();
1421cb0ef41Sopenharmony_ci  finished(rs, { signal }, common.mustSucceed());
1431cb0ef41Sopenharmony_ci}
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci{
1461cb0ef41Sopenharmony_ci  // Promisified abort works
1471cb0ef41Sopenharmony_ci  const finishedPromise = promisify(finished);
1481cb0ef41Sopenharmony_ci  async function run() {
1491cb0ef41Sopenharmony_ci    const ac = new AbortController();
1501cb0ef41Sopenharmony_ci    const { signal } = ac;
1511cb0ef41Sopenharmony_ci    const rs = Readable.from((function* () {})());
1521cb0ef41Sopenharmony_ci    setImmediate(() => ac.abort());
1531cb0ef41Sopenharmony_ci    await finishedPromise(rs, { signal });
1541cb0ef41Sopenharmony_ci  }
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  assert.rejects(run, { name: 'AbortError' }).then(common.mustCall());
1571cb0ef41Sopenharmony_ci}
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci{
1601cb0ef41Sopenharmony_ci  // Promisified pre-aborted works
1611cb0ef41Sopenharmony_ci  const finishedPromise = promisify(finished);
1621cb0ef41Sopenharmony_ci  async function run() {
1631cb0ef41Sopenharmony_ci    const signal = new EventTarget();
1641cb0ef41Sopenharmony_ci    signal.aborted = true;
1651cb0ef41Sopenharmony_ci    const rs = Readable.from((function* () {})());
1661cb0ef41Sopenharmony_ci    await finishedPromise(rs, { signal });
1671cb0ef41Sopenharmony_ci  }
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  assert.rejects(run, { name: 'AbortError' }).then(common.mustCall());
1701cb0ef41Sopenharmony_ci}
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci{
1741cb0ef41Sopenharmony_ci  const rs = fs.createReadStream('file-does-not-exist');
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci  finished(rs, common.expectsError({
1771cb0ef41Sopenharmony_ci    code: 'ENOENT'
1781cb0ef41Sopenharmony_ci  }));
1791cb0ef41Sopenharmony_ci}
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci{
1821cb0ef41Sopenharmony_ci  const rs = new Readable();
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  finished(rs, common.mustSucceed());
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  rs.push(null);
1871cb0ef41Sopenharmony_ci  rs.emit('close'); // Should not trigger an error
1881cb0ef41Sopenharmony_ci  rs.resume();
1891cb0ef41Sopenharmony_ci}
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci{
1921cb0ef41Sopenharmony_ci  const rs = new Readable();
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  finished(rs, common.mustCall((err) => {
1951cb0ef41Sopenharmony_ci    assert(err, 'premature close error');
1961cb0ef41Sopenharmony_ci  }));
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci  rs.emit('close'); // Should trigger error
1991cb0ef41Sopenharmony_ci  rs.push(null);
2001cb0ef41Sopenharmony_ci  rs.resume();
2011cb0ef41Sopenharmony_ci}
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci// Test faulty input values and options.
2041cb0ef41Sopenharmony_ci{
2051cb0ef41Sopenharmony_ci  const rs = new Readable({
2061cb0ef41Sopenharmony_ci    read() {}
2071cb0ef41Sopenharmony_ci  });
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci  assert.throws(
2101cb0ef41Sopenharmony_ci    () => finished(rs, 'foo'),
2111cb0ef41Sopenharmony_ci    {
2121cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
2131cb0ef41Sopenharmony_ci      message: /callback/
2141cb0ef41Sopenharmony_ci    }
2151cb0ef41Sopenharmony_ci  );
2161cb0ef41Sopenharmony_ci  assert.throws(
2171cb0ef41Sopenharmony_ci    () => finished(rs, 'foo', () => {}),
2181cb0ef41Sopenharmony_ci    {
2191cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
2201cb0ef41Sopenharmony_ci      message: /options/
2211cb0ef41Sopenharmony_ci    }
2221cb0ef41Sopenharmony_ci  );
2231cb0ef41Sopenharmony_ci  assert.throws(
2241cb0ef41Sopenharmony_ci    () => finished(rs, {}, 'foo'),
2251cb0ef41Sopenharmony_ci    {
2261cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
2271cb0ef41Sopenharmony_ci      message: /callback/
2281cb0ef41Sopenharmony_ci    }
2291cb0ef41Sopenharmony_ci  );
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci  finished(rs, null, common.mustCall());
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci  rs.push(null);
2341cb0ef41Sopenharmony_ci  rs.resume();
2351cb0ef41Sopenharmony_ci}
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci// Test that calling returned function removes listeners
2381cb0ef41Sopenharmony_ci{
2391cb0ef41Sopenharmony_ci  const ws = new Writable({
2401cb0ef41Sopenharmony_ci    write(data, env, cb) {
2411cb0ef41Sopenharmony_ci      cb();
2421cb0ef41Sopenharmony_ci    }
2431cb0ef41Sopenharmony_ci  });
2441cb0ef41Sopenharmony_ci  const removeListener = finished(ws, common.mustNotCall());
2451cb0ef41Sopenharmony_ci  removeListener();
2461cb0ef41Sopenharmony_ci  ws.end();
2471cb0ef41Sopenharmony_ci}
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ci{
2501cb0ef41Sopenharmony_ci  const rs = new Readable();
2511cb0ef41Sopenharmony_ci  const removeListeners = finished(rs, common.mustNotCall());
2521cb0ef41Sopenharmony_ci  removeListeners();
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  rs.emit('close');
2551cb0ef41Sopenharmony_ci  rs.push(null);
2561cb0ef41Sopenharmony_ci  rs.resume();
2571cb0ef41Sopenharmony_ci}
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci{
2601cb0ef41Sopenharmony_ci  const streamLike = new EE();
2611cb0ef41Sopenharmony_ci  streamLike.readableEnded = true;
2621cb0ef41Sopenharmony_ci  streamLike.readable = true;
2631cb0ef41Sopenharmony_ci  assert.throws(
2641cb0ef41Sopenharmony_ci    () => {
2651cb0ef41Sopenharmony_ci      finished(streamLike, () => {});
2661cb0ef41Sopenharmony_ci    },
2671cb0ef41Sopenharmony_ci    { code: 'ERR_INVALID_ARG_TYPE' }
2681cb0ef41Sopenharmony_ci  );
2691cb0ef41Sopenharmony_ci  streamLike.emit('close');
2701cb0ef41Sopenharmony_ci}
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci{
2731cb0ef41Sopenharmony_ci  const writable = new Writable({ write() {} });
2741cb0ef41Sopenharmony_ci  writable.writable = false;
2751cb0ef41Sopenharmony_ci  writable.destroy();
2761cb0ef41Sopenharmony_ci  finished(writable, common.mustCall((err) => {
2771cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE');
2781cb0ef41Sopenharmony_ci  }));
2791cb0ef41Sopenharmony_ci}
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci{
2821cb0ef41Sopenharmony_ci  const readable = new Readable();
2831cb0ef41Sopenharmony_ci  readable.readable = false;
2841cb0ef41Sopenharmony_ci  readable.destroy();
2851cb0ef41Sopenharmony_ci  finished(readable, common.mustCall((err) => {
2861cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE');
2871cb0ef41Sopenharmony_ci  }));
2881cb0ef41Sopenharmony_ci}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci{
2911cb0ef41Sopenharmony_ci  const w = new Writable({
2921cb0ef41Sopenharmony_ci    write(chunk, encoding, callback) {
2931cb0ef41Sopenharmony_ci      setImmediate(callback);
2941cb0ef41Sopenharmony_ci    }
2951cb0ef41Sopenharmony_ci  });
2961cb0ef41Sopenharmony_ci  finished(w, common.mustCall((err) => {
2971cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE');
2981cb0ef41Sopenharmony_ci  }));
2991cb0ef41Sopenharmony_ci  w.end('asd');
3001cb0ef41Sopenharmony_ci  w.destroy();
3011cb0ef41Sopenharmony_ci}
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_cifunction testClosed(factory) {
3041cb0ef41Sopenharmony_ci  {
3051cb0ef41Sopenharmony_ci    // If already destroyed but finished is cancelled in same tick
3061cb0ef41Sopenharmony_ci    // don't invoke the callback,
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci    const s = factory();
3091cb0ef41Sopenharmony_ci    s.destroy();
3101cb0ef41Sopenharmony_ci    const dispose = finished(s, common.mustNotCall());
3111cb0ef41Sopenharmony_ci    dispose();
3121cb0ef41Sopenharmony_ci  }
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci  {
3151cb0ef41Sopenharmony_ci    // If already destroyed invoked callback.
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci    const s = factory();
3181cb0ef41Sopenharmony_ci    s.destroy();
3191cb0ef41Sopenharmony_ci    finished(s, common.mustCall());
3201cb0ef41Sopenharmony_ci  }
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci  {
3231cb0ef41Sopenharmony_ci    // Don't invoke until destroy has completed.
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci    let destroyed = false;
3261cb0ef41Sopenharmony_ci    const s = factory({
3271cb0ef41Sopenharmony_ci      destroy(err, cb) {
3281cb0ef41Sopenharmony_ci        setImmediate(() => {
3291cb0ef41Sopenharmony_ci          destroyed = true;
3301cb0ef41Sopenharmony_ci          cb();
3311cb0ef41Sopenharmony_ci        });
3321cb0ef41Sopenharmony_ci      }
3331cb0ef41Sopenharmony_ci    });
3341cb0ef41Sopenharmony_ci    s.destroy();
3351cb0ef41Sopenharmony_ci    finished(s, common.mustCall(() => {
3361cb0ef41Sopenharmony_ci      assert.strictEqual(destroyed, true);
3371cb0ef41Sopenharmony_ci    }));
3381cb0ef41Sopenharmony_ci  }
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci  {
3411cb0ef41Sopenharmony_ci    // Invoke callback even if close is inhibited.
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci    const s = factory({
3441cb0ef41Sopenharmony_ci      emitClose: false,
3451cb0ef41Sopenharmony_ci      destroy(err, cb) {
3461cb0ef41Sopenharmony_ci        cb();
3471cb0ef41Sopenharmony_ci        finished(s, common.mustCall());
3481cb0ef41Sopenharmony_ci      }
3491cb0ef41Sopenharmony_ci    });
3501cb0ef41Sopenharmony_ci    s.destroy();
3511cb0ef41Sopenharmony_ci  }
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci  {
3541cb0ef41Sopenharmony_ci    // Invoke with deep async.
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci    const s = factory({
3571cb0ef41Sopenharmony_ci      destroy(err, cb) {
3581cb0ef41Sopenharmony_ci        setImmediate(() => {
3591cb0ef41Sopenharmony_ci          cb();
3601cb0ef41Sopenharmony_ci          setImmediate(() => {
3611cb0ef41Sopenharmony_ci            finished(s, common.mustCall());
3621cb0ef41Sopenharmony_ci          });
3631cb0ef41Sopenharmony_ci        });
3641cb0ef41Sopenharmony_ci      }
3651cb0ef41Sopenharmony_ci    });
3661cb0ef41Sopenharmony_ci    s.destroy();
3671cb0ef41Sopenharmony_ci  }
3681cb0ef41Sopenharmony_ci}
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_citestClosed((opts) => new Readable({ ...opts }));
3711cb0ef41Sopenharmony_citestClosed((opts) => new Writable({ write() {}, ...opts }));
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci{
3741cb0ef41Sopenharmony_ci  const w = new Writable({
3751cb0ef41Sopenharmony_ci    write(chunk, encoding, cb) {
3761cb0ef41Sopenharmony_ci      cb();
3771cb0ef41Sopenharmony_ci    },
3781cb0ef41Sopenharmony_ci    autoDestroy: false
3791cb0ef41Sopenharmony_ci  });
3801cb0ef41Sopenharmony_ci  w.end('asd');
3811cb0ef41Sopenharmony_ci  process.nextTick(() => {
3821cb0ef41Sopenharmony_ci    finished(w, common.mustCall());
3831cb0ef41Sopenharmony_ci  });
3841cb0ef41Sopenharmony_ci}
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci{
3871cb0ef41Sopenharmony_ci  const w = new Writable({
3881cb0ef41Sopenharmony_ci    write(chunk, encoding, cb) {
3891cb0ef41Sopenharmony_ci      cb(new Error());
3901cb0ef41Sopenharmony_ci    },
3911cb0ef41Sopenharmony_ci    autoDestroy: false
3921cb0ef41Sopenharmony_ci  });
3931cb0ef41Sopenharmony_ci  w.write('asd');
3941cb0ef41Sopenharmony_ci  w.on('error', common.mustCall(() => {
3951cb0ef41Sopenharmony_ci    finished(w, common.mustCall());
3961cb0ef41Sopenharmony_ci  }));
3971cb0ef41Sopenharmony_ci}
3981cb0ef41Sopenharmony_ci
3991cb0ef41Sopenharmony_ci{
4001cb0ef41Sopenharmony_ci  const r = new Readable({
4011cb0ef41Sopenharmony_ci    autoDestroy: false
4021cb0ef41Sopenharmony_ci  });
4031cb0ef41Sopenharmony_ci  r.push(null);
4041cb0ef41Sopenharmony_ci  r.resume();
4051cb0ef41Sopenharmony_ci  r.on('end', common.mustCall(() => {
4061cb0ef41Sopenharmony_ci    finished(r, common.mustCall());
4071cb0ef41Sopenharmony_ci  }));
4081cb0ef41Sopenharmony_ci}
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ci{
4111cb0ef41Sopenharmony_ci  const rs = fs.createReadStream(__filename, { autoClose: false });
4121cb0ef41Sopenharmony_ci  rs.resume();
4131cb0ef41Sopenharmony_ci  rs.on('close', common.mustNotCall());
4141cb0ef41Sopenharmony_ci  rs.on('end', common.mustCall(() => {
4151cb0ef41Sopenharmony_ci    finished(rs, common.mustCall());
4161cb0ef41Sopenharmony_ci  }));
4171cb0ef41Sopenharmony_ci}
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci{
4201cb0ef41Sopenharmony_ci  const d = new EE();
4211cb0ef41Sopenharmony_ci  d._writableState = {};
4221cb0ef41Sopenharmony_ci  d._writableState.finished = true;
4231cb0ef41Sopenharmony_ci  finished(d, { readable: false, writable: true }, common.mustCall((err) => {
4241cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE');
4251cb0ef41Sopenharmony_ci  }));
4261cb0ef41Sopenharmony_ci  d._writableState.errored = true;
4271cb0ef41Sopenharmony_ci  d.emit('close');
4281cb0ef41Sopenharmony_ci}
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci{
4311cb0ef41Sopenharmony_ci  const r = new Readable();
4321cb0ef41Sopenharmony_ci  finished(r, common.mustCall((err) => {
4331cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE');
4341cb0ef41Sopenharmony_ci  }));
4351cb0ef41Sopenharmony_ci  r.push('asd');
4361cb0ef41Sopenharmony_ci  r.push(null);
4371cb0ef41Sopenharmony_ci  r.destroy();
4381cb0ef41Sopenharmony_ci}
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci{
4411cb0ef41Sopenharmony_ci  const d = new Duplex({
4421cb0ef41Sopenharmony_ci    final(cb) { }, // Never close writable side for test purpose
4431cb0ef41Sopenharmony_ci    read() {
4441cb0ef41Sopenharmony_ci      this.push(null);
4451cb0ef41Sopenharmony_ci    }
4461cb0ef41Sopenharmony_ci  });
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  d.on('end', common.mustCall());
4491cb0ef41Sopenharmony_ci
4501cb0ef41Sopenharmony_ci  finished(d, { readable: true, writable: false }, common.mustCall());
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ci  d.end();
4531cb0ef41Sopenharmony_ci  d.resume();
4541cb0ef41Sopenharmony_ci}
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci{
4571cb0ef41Sopenharmony_ci  const d = new Duplex({
4581cb0ef41Sopenharmony_ci    final(cb) { }, // Never close writable side for test purpose
4591cb0ef41Sopenharmony_ci    read() {
4601cb0ef41Sopenharmony_ci      this.push(null);
4611cb0ef41Sopenharmony_ci    }
4621cb0ef41Sopenharmony_ci  });
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci  d.on('end', common.mustCall());
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci  d.end();
4671cb0ef41Sopenharmony_ci  finished(d, { readable: true, writable: false }, common.mustCall());
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci  d.resume();
4701cb0ef41Sopenharmony_ci}
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci{
4731cb0ef41Sopenharmony_ci  // Test for compat for e.g. fd-slicer which implements
4741cb0ef41Sopenharmony_ci  // non standard destroy behavior which might not emit
4751cb0ef41Sopenharmony_ci  // 'close'.
4761cb0ef41Sopenharmony_ci  const r = new Readable();
4771cb0ef41Sopenharmony_ci  finished(r, common.mustCall());
4781cb0ef41Sopenharmony_ci  r.resume();
4791cb0ef41Sopenharmony_ci  r.push('asd');
4801cb0ef41Sopenharmony_ci  r.destroyed = true;
4811cb0ef41Sopenharmony_ci  r.push(null);
4821cb0ef41Sopenharmony_ci}
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci{
4851cb0ef41Sopenharmony_ci  // Regression https://github.com/nodejs/node/issues/33130
4861cb0ef41Sopenharmony_ci  const response = new PassThrough();
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ci  class HelloWorld extends Duplex {
4891cb0ef41Sopenharmony_ci    constructor(response) {
4901cb0ef41Sopenharmony_ci      super({
4911cb0ef41Sopenharmony_ci        autoDestroy: false
4921cb0ef41Sopenharmony_ci      });
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci      this.response = response;
4951cb0ef41Sopenharmony_ci      this.readMore = false;
4961cb0ef41Sopenharmony_ci
4971cb0ef41Sopenharmony_ci      response.once('end', () => {
4981cb0ef41Sopenharmony_ci        this.push(null);
4991cb0ef41Sopenharmony_ci      });
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci      response.on('readable', () => {
5021cb0ef41Sopenharmony_ci        if (this.readMore) {
5031cb0ef41Sopenharmony_ci          this._read();
5041cb0ef41Sopenharmony_ci        }
5051cb0ef41Sopenharmony_ci      });
5061cb0ef41Sopenharmony_ci    }
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_ci    _read() {
5091cb0ef41Sopenharmony_ci      const { response } = this;
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci      this.readMore = true;
5121cb0ef41Sopenharmony_ci
5131cb0ef41Sopenharmony_ci      if (response.readableLength) {
5141cb0ef41Sopenharmony_ci        this.readMore = false;
5151cb0ef41Sopenharmony_ci      }
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_ci      let data;
5181cb0ef41Sopenharmony_ci      while ((data = response.read()) !== null) {
5191cb0ef41Sopenharmony_ci        this.push(data);
5201cb0ef41Sopenharmony_ci      }
5211cb0ef41Sopenharmony_ci    }
5221cb0ef41Sopenharmony_ci  }
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci  const instance = new HelloWorld(response);
5251cb0ef41Sopenharmony_ci  instance.setEncoding('utf8');
5261cb0ef41Sopenharmony_ci  instance.end();
5271cb0ef41Sopenharmony_ci
5281cb0ef41Sopenharmony_ci  (async () => {
5291cb0ef41Sopenharmony_ci    await EE.once(instance, 'finish');
5301cb0ef41Sopenharmony_ci
5311cb0ef41Sopenharmony_ci    setImmediate(() => {
5321cb0ef41Sopenharmony_ci      response.write('chunk 1');
5331cb0ef41Sopenharmony_ci      response.write('chunk 2');
5341cb0ef41Sopenharmony_ci      response.write('chunk 3');
5351cb0ef41Sopenharmony_ci      response.end();
5361cb0ef41Sopenharmony_ci    });
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci    let res = '';
5391cb0ef41Sopenharmony_ci    for await (const data of instance) {
5401cb0ef41Sopenharmony_ci      res += data;
5411cb0ef41Sopenharmony_ci    }
5421cb0ef41Sopenharmony_ci
5431cb0ef41Sopenharmony_ci    assert.strictEqual(res, 'chunk 1chunk 2chunk 3');
5441cb0ef41Sopenharmony_ci  })().then(common.mustCall());
5451cb0ef41Sopenharmony_ci}
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_ci{
5481cb0ef41Sopenharmony_ci  const p = new PassThrough();
5491cb0ef41Sopenharmony_ci  p.end();
5501cb0ef41Sopenharmony_ci  finished(p, common.mustNotCall());
5511cb0ef41Sopenharmony_ci}
5521cb0ef41Sopenharmony_ci
5531cb0ef41Sopenharmony_ci{
5541cb0ef41Sopenharmony_ci  const p = new PassThrough();
5551cb0ef41Sopenharmony_ci  p.end();
5561cb0ef41Sopenharmony_ci  p.on('finish', common.mustCall(() => {
5571cb0ef41Sopenharmony_ci    finished(p, common.mustNotCall());
5581cb0ef41Sopenharmony_ci  }));
5591cb0ef41Sopenharmony_ci}
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci{
5621cb0ef41Sopenharmony_ci  const server = http.createServer(common.mustCall((req, res) => {
5631cb0ef41Sopenharmony_ci    res.on('close', common.mustCall(() => {
5641cb0ef41Sopenharmony_ci      finished(res, common.mustCall(() => {
5651cb0ef41Sopenharmony_ci        server.close();
5661cb0ef41Sopenharmony_ci      }));
5671cb0ef41Sopenharmony_ci    }));
5681cb0ef41Sopenharmony_ci    res.end();
5691cb0ef41Sopenharmony_ci  }))
5701cb0ef41Sopenharmony_ci  .listen(0, function() {
5711cb0ef41Sopenharmony_ci    http.request({
5721cb0ef41Sopenharmony_ci      method: 'GET',
5731cb0ef41Sopenharmony_ci      port: this.address().port
5741cb0ef41Sopenharmony_ci    }).end()
5751cb0ef41Sopenharmony_ci      .on('response', common.mustCall());
5761cb0ef41Sopenharmony_ci  });
5771cb0ef41Sopenharmony_ci}
5781cb0ef41Sopenharmony_ci
5791cb0ef41Sopenharmony_ci{
5801cb0ef41Sopenharmony_ci  const server = http.createServer(common.mustCall((req, res) => {
5811cb0ef41Sopenharmony_ci    req.on('close', common.mustCall(() => {
5821cb0ef41Sopenharmony_ci      finished(req, common.mustCall(() => {
5831cb0ef41Sopenharmony_ci        server.close();
5841cb0ef41Sopenharmony_ci      }));
5851cb0ef41Sopenharmony_ci    }));
5861cb0ef41Sopenharmony_ci    req.destroy();
5871cb0ef41Sopenharmony_ci  })).listen(0, function() {
5881cb0ef41Sopenharmony_ci    http.request({
5891cb0ef41Sopenharmony_ci      method: 'GET',
5901cb0ef41Sopenharmony_ci      port: this.address().port
5911cb0ef41Sopenharmony_ci    }).end().on('error', common.mustCall());
5921cb0ef41Sopenharmony_ci  });
5931cb0ef41Sopenharmony_ci}
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_ci{
5961cb0ef41Sopenharmony_ci  const w = new Writable({
5971cb0ef41Sopenharmony_ci    write(chunk, encoding, callback) {
5981cb0ef41Sopenharmony_ci      process.nextTick(callback);
5991cb0ef41Sopenharmony_ci    }
6001cb0ef41Sopenharmony_ci  });
6011cb0ef41Sopenharmony_ci  w.aborted = false;
6021cb0ef41Sopenharmony_ci  w.end();
6031cb0ef41Sopenharmony_ci  let closed = false;
6041cb0ef41Sopenharmony_ci  w.on('finish', () => {
6051cb0ef41Sopenharmony_ci    assert.strictEqual(closed, false);
6061cb0ef41Sopenharmony_ci    w.emit('aborted');
6071cb0ef41Sopenharmony_ci  });
6081cb0ef41Sopenharmony_ci  w.on('close', common.mustCall(() => {
6091cb0ef41Sopenharmony_ci    closed = true;
6101cb0ef41Sopenharmony_ci  }));
6111cb0ef41Sopenharmony_ci
6121cb0ef41Sopenharmony_ci  finished(w, common.mustCall(() => {
6131cb0ef41Sopenharmony_ci    assert.strictEqual(closed, true);
6141cb0ef41Sopenharmony_ci  }));
6151cb0ef41Sopenharmony_ci}
6161cb0ef41Sopenharmony_ci
6171cb0ef41Sopenharmony_ci{
6181cb0ef41Sopenharmony_ci  const w = new Writable();
6191cb0ef41Sopenharmony_ci  const _err = new Error();
6201cb0ef41Sopenharmony_ci  w.destroy(_err);
6211cb0ef41Sopenharmony_ci  assert.strictEqual(w.errored, _err);
6221cb0ef41Sopenharmony_ci  finished(w, common.mustCall((err) => {
6231cb0ef41Sopenharmony_ci    assert.strictEqual(_err, err);
6241cb0ef41Sopenharmony_ci    assert.strictEqual(w.closed, true);
6251cb0ef41Sopenharmony_ci    finished(w, common.mustCall((err) => {
6261cb0ef41Sopenharmony_ci      assert.strictEqual(_err, err);
6271cb0ef41Sopenharmony_ci    }));
6281cb0ef41Sopenharmony_ci  }));
6291cb0ef41Sopenharmony_ci}
6301cb0ef41Sopenharmony_ci
6311cb0ef41Sopenharmony_ci{
6321cb0ef41Sopenharmony_ci  const w = new Writable();
6331cb0ef41Sopenharmony_ci  w.destroy();
6341cb0ef41Sopenharmony_ci  assert.strictEqual(w.errored, null);
6351cb0ef41Sopenharmony_ci  finished(w, common.mustCall((err) => {
6361cb0ef41Sopenharmony_ci    assert.strictEqual(w.closed, true);
6371cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE');
6381cb0ef41Sopenharmony_ci    finished(w, common.mustCall((err) => {
6391cb0ef41Sopenharmony_ci      assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE');
6401cb0ef41Sopenharmony_ci    }));
6411cb0ef41Sopenharmony_ci  }));
6421cb0ef41Sopenharmony_ci}
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_ci{
6451cb0ef41Sopenharmony_ci  // Legacy Streams do not inherit from Readable or Writable.
6461cb0ef41Sopenharmony_ci  // We cannot really assume anything about them, so we cannot close them
6471cb0ef41Sopenharmony_ci  // automatically.
6481cb0ef41Sopenharmony_ci  const s = new Stream();
6491cb0ef41Sopenharmony_ci  finished(s, common.mustNotCall());
6501cb0ef41Sopenharmony_ci}
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ci{
6531cb0ef41Sopenharmony_ci  const server = http.createServer(common.mustCall(function(req, res) {
6541cb0ef41Sopenharmony_ci    fs.createReadStream(__filename).pipe(res);
6551cb0ef41Sopenharmony_ci    finished(res, common.mustCall(function(err) {
6561cb0ef41Sopenharmony_ci      assert.strictEqual(err, undefined);
6571cb0ef41Sopenharmony_ci    }));
6581cb0ef41Sopenharmony_ci  })).listen(0, function() {
6591cb0ef41Sopenharmony_ci    http.request(
6601cb0ef41Sopenharmony_ci      { method: 'GET', port: this.address().port },
6611cb0ef41Sopenharmony_ci      common.mustCall(function(res) {
6621cb0ef41Sopenharmony_ci        res.resume();
6631cb0ef41Sopenharmony_ci        finished(res, common.mustCall(() => {
6641cb0ef41Sopenharmony_ci          server.close();
6651cb0ef41Sopenharmony_ci        }));
6661cb0ef41Sopenharmony_ci      })
6671cb0ef41Sopenharmony_ci    ).end();
6681cb0ef41Sopenharmony_ci  });
6691cb0ef41Sopenharmony_ci}
6701cb0ef41Sopenharmony_ci
6711cb0ef41Sopenharmony_ci{
6721cb0ef41Sopenharmony_ci  const stream = new Duplex({
6731cb0ef41Sopenharmony_ci    write(chunk, enc, cb) {
6741cb0ef41Sopenharmony_ci      setImmediate(cb);
6751cb0ef41Sopenharmony_ci    }
6761cb0ef41Sopenharmony_ci  });
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_ci  stream.end('foo');
6791cb0ef41Sopenharmony_ci
6801cb0ef41Sopenharmony_ci  finished(stream, { readable: false }, common.mustCall((err) => {
6811cb0ef41Sopenharmony_ci    assert(!err);
6821cb0ef41Sopenharmony_ci  }));
6831cb0ef41Sopenharmony_ci}
684