11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// Ensure that subscribing the 'data' event will not make the stream flow.
61cb0ef41Sopenharmony_ci// The 'data' event will require calling read() by hand.
71cb0ef41Sopenharmony_ci//
81cb0ef41Sopenharmony_ci// The test is written for the (somewhat rare) highWaterMark: 0 streams to
91cb0ef41Sopenharmony_ci// specifically catch any regressions that might occur with these streams.
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciconst assert = require('assert');
121cb0ef41Sopenharmony_ciconst { Readable } = require('stream');
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciconst streamData = [ 'a', null ];
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// Track the calls so we can assert their order later.
171cb0ef41Sopenharmony_ciconst calls = [];
181cb0ef41Sopenharmony_ciconst r = new Readable({
191cb0ef41Sopenharmony_ci  read: common.mustCall(() => {
201cb0ef41Sopenharmony_ci    calls.push('_read:' + streamData[0]);
211cb0ef41Sopenharmony_ci    process.nextTick(() => {
221cb0ef41Sopenharmony_ci      calls.push('push:' + streamData[0]);
231cb0ef41Sopenharmony_ci      r.push(streamData.shift());
241cb0ef41Sopenharmony_ci    });
251cb0ef41Sopenharmony_ci  }, streamData.length),
261cb0ef41Sopenharmony_ci  highWaterMark: 0,
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  // Object mode is used here just for testing convenience. It really
291cb0ef41Sopenharmony_ci  // shouldn't affect the order of events. Just the data and its format.
301cb0ef41Sopenharmony_ci  objectMode: true,
311cb0ef41Sopenharmony_ci});
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciassert.strictEqual(r.readableFlowing, null);
341cb0ef41Sopenharmony_cir.on('readable', common.mustCall(() => {
351cb0ef41Sopenharmony_ci  calls.push('readable');
361cb0ef41Sopenharmony_ci}, 2));
371cb0ef41Sopenharmony_ciassert.strictEqual(r.readableFlowing, false);
381cb0ef41Sopenharmony_cir.on('data', common.mustCall((data) => {
391cb0ef41Sopenharmony_ci  calls.push('data:' + data);
401cb0ef41Sopenharmony_ci}, 1));
411cb0ef41Sopenharmony_cir.on('end', common.mustCall(() => {
421cb0ef41Sopenharmony_ci  calls.push('end');
431cb0ef41Sopenharmony_ci}));
441cb0ef41Sopenharmony_ciassert.strictEqual(r.readableFlowing, false);
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci// The stream emits the events asynchronously but that's not guaranteed to
471cb0ef41Sopenharmony_ci// happen on the next tick (especially since the _read implementation above
481cb0ef41Sopenharmony_ci// uses process.nextTick).
491cb0ef41Sopenharmony_ci//
501cb0ef41Sopenharmony_ci// We use setImmediate here to give the stream enough time to emit all the
511cb0ef41Sopenharmony_ci// events it's about to emit.
521cb0ef41Sopenharmony_cisetImmediate(() => {
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  // Only the _read, push, readable calls have happened. No data must be
551cb0ef41Sopenharmony_ci  // emitted yet.
561cb0ef41Sopenharmony_ci  assert.deepStrictEqual(calls, ['_read:a', 'push:a', 'readable']);
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  // Calling 'r.read()' should trigger the data event.
591cb0ef41Sopenharmony_ci  assert.strictEqual(r.read(), 'a');
601cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
611cb0ef41Sopenharmony_ci    calls,
621cb0ef41Sopenharmony_ci    ['_read:a', 'push:a', 'readable', 'data:a']);
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  // The next 'read()' will return null because hwm: 0 does not buffer any
651cb0ef41Sopenharmony_ci  // data and the _read implementation above does the push() asynchronously.
661cb0ef41Sopenharmony_ci  //
671cb0ef41Sopenharmony_ci  // Note: This 'null' signals "no data available". It isn't the end-of-stream
681cb0ef41Sopenharmony_ci  // null value as the stream doesn't know yet that it is about to reach the
691cb0ef41Sopenharmony_ci  // end.
701cb0ef41Sopenharmony_ci  //
711cb0ef41Sopenharmony_ci  // Using setImmediate again to give the stream enough time to emit all the
721cb0ef41Sopenharmony_ci  // events it wants to emit.
731cb0ef41Sopenharmony_ci  assert.strictEqual(r.read(), null);
741cb0ef41Sopenharmony_ci  setImmediate(() => {
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci    // There's a new 'readable' event after the data has been pushed.
771cb0ef41Sopenharmony_ci    // The 'end' event will be emitted only after a 'read()'.
781cb0ef41Sopenharmony_ci    //
791cb0ef41Sopenharmony_ci    // This is somewhat special for the case where the '_read' implementation
801cb0ef41Sopenharmony_ci    // calls 'push' asynchronously. If 'push' was synchronous, the 'end' event
811cb0ef41Sopenharmony_ci    // would be emitted here _before_ we call read().
821cb0ef41Sopenharmony_ci    assert.deepStrictEqual(
831cb0ef41Sopenharmony_ci      calls,
841cb0ef41Sopenharmony_ci      ['_read:a', 'push:a', 'readable', 'data:a',
851cb0ef41Sopenharmony_ci       '_read:null', 'push:null', 'readable']);
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci    assert.strictEqual(r.read(), null);
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci    // While it isn't really specified whether the 'end' event should happen
901cb0ef41Sopenharmony_ci    // synchronously with read() or not, we'll assert the current behavior
911cb0ef41Sopenharmony_ci    // ('end' event happening on the next tick after read()) so any changes
921cb0ef41Sopenharmony_ci    // to it are noted and acknowledged in the future.
931cb0ef41Sopenharmony_ci    assert.deepStrictEqual(
941cb0ef41Sopenharmony_ci      calls,
951cb0ef41Sopenharmony_ci      ['_read:a', 'push:a', 'readable', 'data:a',
961cb0ef41Sopenharmony_ci       '_read:null', 'push:null', 'readable']);
971cb0ef41Sopenharmony_ci    process.nextTick(() => {
981cb0ef41Sopenharmony_ci      assert.deepStrictEqual(
991cb0ef41Sopenharmony_ci        calls,
1001cb0ef41Sopenharmony_ci        ['_read:a', 'push:a', 'readable', 'data:a',
1011cb0ef41Sopenharmony_ci         '_read:null', 'push:null', 'readable', 'end']);
1021cb0ef41Sopenharmony_ci    });
1031cb0ef41Sopenharmony_ci  });
1041cb0ef41Sopenharmony_ci});
105