11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci'use strict';
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciconst common = require('../common');
251cb0ef41Sopenharmony_ciconst { Readable: R, Writable: W } = require('stream');
261cb0ef41Sopenharmony_ciconst assert = require('assert');
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciconst EE = require('events').EventEmitter;
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciclass TestReader extends R {
311cb0ef41Sopenharmony_ci  constructor(n) {
321cb0ef41Sopenharmony_ci    super();
331cb0ef41Sopenharmony_ci    this._buffer = Buffer.alloc(n || 100, 'x');
341cb0ef41Sopenharmony_ci    this._pos = 0;
351cb0ef41Sopenharmony_ci    this._bufs = 10;
361cb0ef41Sopenharmony_ci  }
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  _read(n) {
391cb0ef41Sopenharmony_ci    const max = this._buffer.length - this._pos;
401cb0ef41Sopenharmony_ci    n = Math.max(n, 0);
411cb0ef41Sopenharmony_ci    const toRead = Math.min(n, max);
421cb0ef41Sopenharmony_ci    if (toRead === 0) {
431cb0ef41Sopenharmony_ci      // Simulate the read buffer filling up with some more bytes some time
441cb0ef41Sopenharmony_ci      // in the future.
451cb0ef41Sopenharmony_ci      setTimeout(() => {
461cb0ef41Sopenharmony_ci        this._pos = 0;
471cb0ef41Sopenharmony_ci        this._bufs -= 1;
481cb0ef41Sopenharmony_ci        if (this._bufs <= 0) {
491cb0ef41Sopenharmony_ci          // read them all!
501cb0ef41Sopenharmony_ci          if (!this.ended)
511cb0ef41Sopenharmony_ci            this.push(null);
521cb0ef41Sopenharmony_ci        } else {
531cb0ef41Sopenharmony_ci          // now we have more.
541cb0ef41Sopenharmony_ci          // kinda cheating by calling _read, but whatever,
551cb0ef41Sopenharmony_ci          // it's just fake anyway.
561cb0ef41Sopenharmony_ci          this._read(n);
571cb0ef41Sopenharmony_ci        }
581cb0ef41Sopenharmony_ci      }, 10);
591cb0ef41Sopenharmony_ci      return;
601cb0ef41Sopenharmony_ci    }
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci    const ret = this._buffer.slice(this._pos, this._pos + toRead);
631cb0ef41Sopenharmony_ci    this._pos += toRead;
641cb0ef41Sopenharmony_ci    this.push(ret);
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ciclass TestWriter extends EE {
691cb0ef41Sopenharmony_ci  constructor() {
701cb0ef41Sopenharmony_ci    super();
711cb0ef41Sopenharmony_ci    this.received = [];
721cb0ef41Sopenharmony_ci    this.flush = false;
731cb0ef41Sopenharmony_ci  }
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  write(c) {
761cb0ef41Sopenharmony_ci    this.received.push(c.toString());
771cb0ef41Sopenharmony_ci    this.emit('write', c);
781cb0ef41Sopenharmony_ci    return true;
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  end(c) {
821cb0ef41Sopenharmony_ci    if (c) this.write(c);
831cb0ef41Sopenharmony_ci    this.emit('end', this.received);
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci{
881cb0ef41Sopenharmony_ci  // Test basic functionality
891cb0ef41Sopenharmony_ci  const r = new TestReader(20);
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  const reads = [];
921cb0ef41Sopenharmony_ci  const expect = [ 'x',
931cb0ef41Sopenharmony_ci                   'xx',
941cb0ef41Sopenharmony_ci                   'xxx',
951cb0ef41Sopenharmony_ci                   'xxxx',
961cb0ef41Sopenharmony_ci                   'xxxxx',
971cb0ef41Sopenharmony_ci                   'xxxxxxxxx',
981cb0ef41Sopenharmony_ci                   'xxxxxxxxxx',
991cb0ef41Sopenharmony_ci                   'xxxxxxxxxxxx',
1001cb0ef41Sopenharmony_ci                   'xxxxxxxxxxxxx',
1011cb0ef41Sopenharmony_ci                   'xxxxxxxxxxxxxxx',
1021cb0ef41Sopenharmony_ci                   'xxxxxxxxxxxxxxxxx',
1031cb0ef41Sopenharmony_ci                   'xxxxxxxxxxxxxxxxxxx',
1041cb0ef41Sopenharmony_ci                   'xxxxxxxxxxxxxxxxxxxxx',
1051cb0ef41Sopenharmony_ci                   'xxxxxxxxxxxxxxxxxxxxxxx',
1061cb0ef41Sopenharmony_ci                   'xxxxxxxxxxxxxxxxxxxxxxxxx',
1071cb0ef41Sopenharmony_ci                   'xxxxxxxxxxxxxxxxxxxxx' ];
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  r.on('end', common.mustCall(function() {
1101cb0ef41Sopenharmony_ci    assert.deepStrictEqual(reads, expect);
1111cb0ef41Sopenharmony_ci  }));
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci  let readSize = 1;
1141cb0ef41Sopenharmony_ci  function flow() {
1151cb0ef41Sopenharmony_ci    let res;
1161cb0ef41Sopenharmony_ci    while (null !== (res = r.read(readSize++))) {
1171cb0ef41Sopenharmony_ci      reads.push(res.toString());
1181cb0ef41Sopenharmony_ci    }
1191cb0ef41Sopenharmony_ci    r.once('readable', flow);
1201cb0ef41Sopenharmony_ci  }
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  flow();
1231cb0ef41Sopenharmony_ci}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci{
1261cb0ef41Sopenharmony_ci  // Verify pipe
1271cb0ef41Sopenharmony_ci  const r = new TestReader(5);
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  const expect = [ 'xxxxx',
1301cb0ef41Sopenharmony_ci                   'xxxxx',
1311cb0ef41Sopenharmony_ci                   'xxxxx',
1321cb0ef41Sopenharmony_ci                   'xxxxx',
1331cb0ef41Sopenharmony_ci                   'xxxxx',
1341cb0ef41Sopenharmony_ci                   'xxxxx',
1351cb0ef41Sopenharmony_ci                   'xxxxx',
1361cb0ef41Sopenharmony_ci                   'xxxxx',
1371cb0ef41Sopenharmony_ci                   'xxxxx',
1381cb0ef41Sopenharmony_ci                   'xxxxx' ];
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  const w = new TestWriter();
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  w.on('end', common.mustCall(function(received) {
1431cb0ef41Sopenharmony_ci    assert.deepStrictEqual(received, expect);
1441cb0ef41Sopenharmony_ci  }));
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  r.pipe(w);
1471cb0ef41Sopenharmony_ci}
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci[1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(function(SPLIT) {
1511cb0ef41Sopenharmony_ci  // Verify unpipe
1521cb0ef41Sopenharmony_ci  const r = new TestReader(5);
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  // Unpipe after 3 writes, then write to another stream instead.
1551cb0ef41Sopenharmony_ci  let expect = [ 'xxxxx',
1561cb0ef41Sopenharmony_ci                 'xxxxx',
1571cb0ef41Sopenharmony_ci                 'xxxxx',
1581cb0ef41Sopenharmony_ci                 'xxxxx',
1591cb0ef41Sopenharmony_ci                 'xxxxx',
1601cb0ef41Sopenharmony_ci                 'xxxxx',
1611cb0ef41Sopenharmony_ci                 'xxxxx',
1621cb0ef41Sopenharmony_ci                 'xxxxx',
1631cb0ef41Sopenharmony_ci                 'xxxxx',
1641cb0ef41Sopenharmony_ci                 'xxxxx' ];
1651cb0ef41Sopenharmony_ci  expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  const w = [ new TestWriter(), new TestWriter() ];
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  let writes = SPLIT;
1701cb0ef41Sopenharmony_ci  w[0].on('write', function() {
1711cb0ef41Sopenharmony_ci    if (--writes === 0) {
1721cb0ef41Sopenharmony_ci      r.unpipe();
1731cb0ef41Sopenharmony_ci      assert.deepStrictEqual(r._readableState.pipes, []);
1741cb0ef41Sopenharmony_ci      w[0].end();
1751cb0ef41Sopenharmony_ci      r.pipe(w[1]);
1761cb0ef41Sopenharmony_ci      assert.deepStrictEqual(r._readableState.pipes, [w[1]]);
1771cb0ef41Sopenharmony_ci    }
1781cb0ef41Sopenharmony_ci  });
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  let ended = 0;
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  w[0].on('end', common.mustCall(function(results) {
1831cb0ef41Sopenharmony_ci    ended++;
1841cb0ef41Sopenharmony_ci    assert.strictEqual(ended, 1);
1851cb0ef41Sopenharmony_ci    assert.deepStrictEqual(results, expect[0]);
1861cb0ef41Sopenharmony_ci  }));
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  w[1].on('end', common.mustCall(function(results) {
1891cb0ef41Sopenharmony_ci    ended++;
1901cb0ef41Sopenharmony_ci    assert.strictEqual(ended, 2);
1911cb0ef41Sopenharmony_ci    assert.deepStrictEqual(results, expect[1]);
1921cb0ef41Sopenharmony_ci  }));
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  r.pipe(w[0]);
1951cb0ef41Sopenharmony_ci});
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci{
1991cb0ef41Sopenharmony_ci  // Verify both writers get the same data when piping to destinations
2001cb0ef41Sopenharmony_ci  const r = new TestReader(5);
2011cb0ef41Sopenharmony_ci  const w = [ new TestWriter(), new TestWriter() ];
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  const expect = [ 'xxxxx',
2041cb0ef41Sopenharmony_ci                   'xxxxx',
2051cb0ef41Sopenharmony_ci                   'xxxxx',
2061cb0ef41Sopenharmony_ci                   'xxxxx',
2071cb0ef41Sopenharmony_ci                   'xxxxx',
2081cb0ef41Sopenharmony_ci                   'xxxxx',
2091cb0ef41Sopenharmony_ci                   'xxxxx',
2101cb0ef41Sopenharmony_ci                   'xxxxx',
2111cb0ef41Sopenharmony_ci                   'xxxxx',
2121cb0ef41Sopenharmony_ci                   'xxxxx' ];
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci  w[0].on('end', common.mustCall(function(received) {
2151cb0ef41Sopenharmony_ci    assert.deepStrictEqual(received, expect);
2161cb0ef41Sopenharmony_ci  }));
2171cb0ef41Sopenharmony_ci  w[1].on('end', common.mustCall(function(received) {
2181cb0ef41Sopenharmony_ci    assert.deepStrictEqual(received, expect);
2191cb0ef41Sopenharmony_ci  }));
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  r.pipe(w[0]);
2221cb0ef41Sopenharmony_ci  r.pipe(w[1]);
2231cb0ef41Sopenharmony_ci}
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci[1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(function(SPLIT) {
2271cb0ef41Sopenharmony_ci  // Verify multi-unpipe
2281cb0ef41Sopenharmony_ci  const r = new TestReader(5);
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  // Unpipe after 3 writes, then write to another stream instead.
2311cb0ef41Sopenharmony_ci  let expect = [ 'xxxxx',
2321cb0ef41Sopenharmony_ci                 'xxxxx',
2331cb0ef41Sopenharmony_ci                 'xxxxx',
2341cb0ef41Sopenharmony_ci                 'xxxxx',
2351cb0ef41Sopenharmony_ci                 'xxxxx',
2361cb0ef41Sopenharmony_ci                 'xxxxx',
2371cb0ef41Sopenharmony_ci                 'xxxxx',
2381cb0ef41Sopenharmony_ci                 'xxxxx',
2391cb0ef41Sopenharmony_ci                 'xxxxx',
2401cb0ef41Sopenharmony_ci                 'xxxxx' ];
2411cb0ef41Sopenharmony_ci  expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  const w = [ new TestWriter(), new TestWriter(), new TestWriter() ];
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  let writes = SPLIT;
2461cb0ef41Sopenharmony_ci  w[0].on('write', function() {
2471cb0ef41Sopenharmony_ci    if (--writes === 0) {
2481cb0ef41Sopenharmony_ci      r.unpipe();
2491cb0ef41Sopenharmony_ci      w[0].end();
2501cb0ef41Sopenharmony_ci      r.pipe(w[1]);
2511cb0ef41Sopenharmony_ci    }
2521cb0ef41Sopenharmony_ci  });
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  let ended = 0;
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci  w[0].on('end', common.mustCall(function(results) {
2571cb0ef41Sopenharmony_ci    ended++;
2581cb0ef41Sopenharmony_ci    assert.strictEqual(ended, 1);
2591cb0ef41Sopenharmony_ci    assert.deepStrictEqual(results, expect[0]);
2601cb0ef41Sopenharmony_ci  }));
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci  w[1].on('end', common.mustCall(function(results) {
2631cb0ef41Sopenharmony_ci    ended++;
2641cb0ef41Sopenharmony_ci    assert.strictEqual(ended, 2);
2651cb0ef41Sopenharmony_ci    assert.deepStrictEqual(results, expect[1]);
2661cb0ef41Sopenharmony_ci  }));
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci  r.pipe(w[0]);
2691cb0ef41Sopenharmony_ci  r.pipe(w[2]);
2701cb0ef41Sopenharmony_ci});
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci{
2731cb0ef41Sopenharmony_ci  // Verify that back pressure is respected
2741cb0ef41Sopenharmony_ci  const r = new R({ objectMode: true });
2751cb0ef41Sopenharmony_ci  r._read = common.mustNotCall();
2761cb0ef41Sopenharmony_ci  let counter = 0;
2771cb0ef41Sopenharmony_ci  r.push(['one']);
2781cb0ef41Sopenharmony_ci  r.push(['two']);
2791cb0ef41Sopenharmony_ci  r.push(['three']);
2801cb0ef41Sopenharmony_ci  r.push(['four']);
2811cb0ef41Sopenharmony_ci  r.push(null);
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci  const w1 = new R();
2841cb0ef41Sopenharmony_ci  w1.write = function(chunk) {
2851cb0ef41Sopenharmony_ci    assert.strictEqual(chunk[0], 'one');
2861cb0ef41Sopenharmony_ci    w1.emit('close');
2871cb0ef41Sopenharmony_ci    process.nextTick(function() {
2881cb0ef41Sopenharmony_ci      r.pipe(w2);
2891cb0ef41Sopenharmony_ci      r.pipe(w3);
2901cb0ef41Sopenharmony_ci    });
2911cb0ef41Sopenharmony_ci  };
2921cb0ef41Sopenharmony_ci  w1.end = common.mustNotCall();
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_ci  r.pipe(w1);
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci  const expected = ['two', 'two', 'three', 'three', 'four', 'four'];
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci  const w2 = new R();
2991cb0ef41Sopenharmony_ci  w2.write = function(chunk) {
3001cb0ef41Sopenharmony_ci    assert.strictEqual(chunk[0], expected.shift());
3011cb0ef41Sopenharmony_ci    assert.strictEqual(counter, 0);
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci    counter++;
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci    if (chunk[0] === 'four') {
3061cb0ef41Sopenharmony_ci      return true;
3071cb0ef41Sopenharmony_ci    }
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci    setTimeout(function() {
3101cb0ef41Sopenharmony_ci      counter--;
3111cb0ef41Sopenharmony_ci      w2.emit('drain');
3121cb0ef41Sopenharmony_ci    }, 10);
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci    return false;
3151cb0ef41Sopenharmony_ci  };
3161cb0ef41Sopenharmony_ci  w2.end = common.mustCall();
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci  const w3 = new R();
3191cb0ef41Sopenharmony_ci  w3.write = function(chunk) {
3201cb0ef41Sopenharmony_ci    assert.strictEqual(chunk[0], expected.shift());
3211cb0ef41Sopenharmony_ci    assert.strictEqual(counter, 1);
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci    counter++;
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci    if (chunk[0] === 'four') {
3261cb0ef41Sopenharmony_ci      return true;
3271cb0ef41Sopenharmony_ci    }
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci    setTimeout(function() {
3301cb0ef41Sopenharmony_ci      counter--;
3311cb0ef41Sopenharmony_ci      w3.emit('drain');
3321cb0ef41Sopenharmony_ci    }, 50);
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci    return false;
3351cb0ef41Sopenharmony_ci  };
3361cb0ef41Sopenharmony_ci  w3.end = common.mustCall(function() {
3371cb0ef41Sopenharmony_ci    assert.strictEqual(counter, 2);
3381cb0ef41Sopenharmony_ci    assert.strictEqual(expected.length, 0);
3391cb0ef41Sopenharmony_ci  });
3401cb0ef41Sopenharmony_ci}
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci{
3431cb0ef41Sopenharmony_ci  // Verify read(0) behavior for ended streams
3441cb0ef41Sopenharmony_ci  const r = new R();
3451cb0ef41Sopenharmony_ci  let written = false;
3461cb0ef41Sopenharmony_ci  let ended = false;
3471cb0ef41Sopenharmony_ci  r._read = common.mustNotCall();
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci  r.push(Buffer.from('foo'));
3501cb0ef41Sopenharmony_ci  r.push(null);
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci  const v = r.read(0);
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  assert.strictEqual(v, null);
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci  const w = new R();
3571cb0ef41Sopenharmony_ci  w.write = function(buffer) {
3581cb0ef41Sopenharmony_ci    written = true;
3591cb0ef41Sopenharmony_ci    assert.strictEqual(ended, false);
3601cb0ef41Sopenharmony_ci    assert.strictEqual(buffer.toString(), 'foo');
3611cb0ef41Sopenharmony_ci  };
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci  w.end = common.mustCall(function() {
3641cb0ef41Sopenharmony_ci    ended = true;
3651cb0ef41Sopenharmony_ci    assert.strictEqual(written, true);
3661cb0ef41Sopenharmony_ci  });
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_ci  r.pipe(w);
3691cb0ef41Sopenharmony_ci}
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_ci{
3721cb0ef41Sopenharmony_ci  // Verify synchronous _read ending
3731cb0ef41Sopenharmony_ci  const r = new R();
3741cb0ef41Sopenharmony_ci  let called = false;
3751cb0ef41Sopenharmony_ci  r._read = function(n) {
3761cb0ef41Sopenharmony_ci    r.push(null);
3771cb0ef41Sopenharmony_ci  };
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  r.once('end', function() {
3801cb0ef41Sopenharmony_ci    // Verify that this is called before the next tick
3811cb0ef41Sopenharmony_ci    called = true;
3821cb0ef41Sopenharmony_ci  });
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  r.read();
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci  process.nextTick(function() {
3871cb0ef41Sopenharmony_ci    assert.strictEqual(called, true);
3881cb0ef41Sopenharmony_ci  });
3891cb0ef41Sopenharmony_ci}
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci{
3921cb0ef41Sopenharmony_ci  // Verify that adding readable listeners trigger data flow
3931cb0ef41Sopenharmony_ci  const r = new R({ highWaterMark: 5 });
3941cb0ef41Sopenharmony_ci  let onReadable = false;
3951cb0ef41Sopenharmony_ci  let readCalled = 0;
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci  r._read = function(n) {
3981cb0ef41Sopenharmony_ci    if (readCalled++ === 2)
3991cb0ef41Sopenharmony_ci      r.push(null);
4001cb0ef41Sopenharmony_ci    else
4011cb0ef41Sopenharmony_ci      r.push(Buffer.from('asdf'));
4021cb0ef41Sopenharmony_ci  };
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci  r.on('readable', function() {
4051cb0ef41Sopenharmony_ci    onReadable = true;
4061cb0ef41Sopenharmony_ci    r.read();
4071cb0ef41Sopenharmony_ci  });
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  r.on('end', common.mustCall(function() {
4101cb0ef41Sopenharmony_ci    assert.strictEqual(readCalled, 3);
4111cb0ef41Sopenharmony_ci    assert.ok(onReadable);
4121cb0ef41Sopenharmony_ci  }));
4131cb0ef41Sopenharmony_ci}
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci{
4161cb0ef41Sopenharmony_ci  // Verify that streams are chainable
4171cb0ef41Sopenharmony_ci  const r = new R();
4181cb0ef41Sopenharmony_ci  r._read = common.mustCall();
4191cb0ef41Sopenharmony_ci  const r2 = r.setEncoding('utf8').pause().resume().pause();
4201cb0ef41Sopenharmony_ci  assert.strictEqual(r, r2);
4211cb0ef41Sopenharmony_ci}
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci{
4241cb0ef41Sopenharmony_ci  // Verify readableEncoding property
4251cb0ef41Sopenharmony_ci  assert(Object.hasOwn(R.prototype, 'readableEncoding'));
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci  const r = new R({ encoding: 'utf8' });
4281cb0ef41Sopenharmony_ci  assert.strictEqual(r.readableEncoding, 'utf8');
4291cb0ef41Sopenharmony_ci}
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci{
4321cb0ef41Sopenharmony_ci  // Verify readableObjectMode property
4331cb0ef41Sopenharmony_ci  assert(Object.hasOwn(R.prototype, 'readableObjectMode'));
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_ci  const r = new R({ objectMode: true });
4361cb0ef41Sopenharmony_ci  assert.strictEqual(r.readableObjectMode, true);
4371cb0ef41Sopenharmony_ci}
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_ci{
4401cb0ef41Sopenharmony_ci  // Verify writableObjectMode property
4411cb0ef41Sopenharmony_ci  assert(Object.hasOwn(W.prototype, 'writableObjectMode'));
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_ci  const w = new W({ objectMode: true });
4441cb0ef41Sopenharmony_ci  assert.strictEqual(w.writableObjectMode, true);
4451cb0ef41Sopenharmony_ci}
446