summaryrefslogtreecommitdiff
path: root/test/parallel/test-stream2-basic.js
diff options
context:
space:
mode:
authorRich Trott <rtrott@gmail.com>2017-05-21 14:43:09 -0700
committerAnna Henningsen <anna@addaleax.net>2017-05-24 13:45:21 +0200
commit1aad4ba2841120d04661681cd7a60b7124912d42 (patch)
treeec2ff8c85279d947fcfefd2b57691b68517dd562 /test/parallel/test-stream2-basic.js
parent7bb9fd203522cb37424629dad777f966a81dd03d (diff)
downloadandroid-node-v8-1aad4ba2841120d04661681cd7a60b7124912d42.tar.gz
android-node-v8-1aad4ba2841120d04661681cd7a60b7124912d42.tar.bz2
android-node-v8-1aad4ba2841120d04661681cd7a60b7124912d42.zip
test: move stream2 test from pummel to parallel
test-stream2-basic runs in a few seconds. It can be moved to parallel. PR-URL: https://github.com/nodejs/node/pull/13146 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'test/parallel/test-stream2-basic.js')
-rw-r--r--test/parallel/test-stream2-basic.js475
1 files changed, 475 insertions, 0 deletions
diff --git a/test/parallel/test-stream2-basic.js b/test/parallel/test-stream2-basic.js
new file mode 100644
index 0000000000..cb017a1706
--- /dev/null
+++ b/test/parallel/test-stream2-basic.js
@@ -0,0 +1,475 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+'use strict';
+
+const common = require('../common');
+const R = require('_stream_readable');
+const assert = require('assert');
+
+const util = require('util');
+const EE = require('events').EventEmitter;
+
+function TestReader(n) {
+ R.apply(this);
+ this._buffer = Buffer.alloc(n || 100, 'x');
+ this._pos = 0;
+ this._bufs = 10;
+}
+
+util.inherits(TestReader, R);
+
+TestReader.prototype._read = function(n) {
+ const max = this._buffer.length - this._pos;
+ n = Math.max(n, 0);
+ const toRead = Math.min(n, max);
+ if (toRead === 0) {
+ // simulate the read buffer filling up with some more bytes some time
+ // in the future.
+ setTimeout(function() {
+ this._pos = 0;
+ this._bufs -= 1;
+ if (this._bufs <= 0) {
+ // read them all!
+ if (!this.ended)
+ this.push(null);
+ } else {
+ // now we have more.
+ // kinda cheating by calling _read, but whatever,
+ // it's just fake anyway.
+ this._read(n);
+ }
+ }.bind(this), 10);
+ return;
+ }
+
+ const ret = this._buffer.slice(this._pos, this._pos + toRead);
+ this._pos += toRead;
+ this.push(ret);
+};
+
+/////
+
+function TestWriter() {
+ EE.apply(this);
+ this.received = [];
+ this.flush = false;
+}
+
+util.inherits(TestWriter, EE);
+
+TestWriter.prototype.write = function(c) {
+ this.received.push(c.toString());
+ this.emit('write', c);
+ return true;
+};
+
+TestWriter.prototype.end = function(c) {
+ if (c) this.write(c);
+ this.emit('end', this.received);
+};
+
+////////
+
+// tiny node-tap lookalike.
+const tests = [];
+let count = 0;
+
+function test(name, fn) {
+ count++;
+ tests.push([name, fn]);
+}
+
+function run() {
+ const next = tests.shift();
+ if (!next)
+ return console.error('ok');
+
+ const name = next[0];
+ const fn = next[1];
+ console.log('# %s', name);
+ fn({
+ end: function() {
+ count--;
+ run();
+ }
+ });
+}
+
+// ensure all tests have run
+process.on('exit', function() {
+ assert.strictEqual(count, 0);
+});
+
+process.nextTick(run);
+
+
+test('a most basic test', function(t) {
+ const r = new TestReader(20);
+
+ const reads = [];
+ const expect = [ 'x',
+ 'xx',
+ 'xxx',
+ 'xxxx',
+ 'xxxxx',
+ 'xxxxxxxxx',
+ 'xxxxxxxxxx',
+ 'xxxxxxxxxxxx',
+ 'xxxxxxxxxxxxx',
+ 'xxxxxxxxxxxxxxx',
+ 'xxxxxxxxxxxxxxxxx',
+ 'xxxxxxxxxxxxxxxxxxx',
+ 'xxxxxxxxxxxxxxxxxxxxx',
+ 'xxxxxxxxxxxxxxxxxxxxxxx',
+ 'xxxxxxxxxxxxxxxxxxxxxxxxx',
+ 'xxxxxxxxxxxxxxxxxxxxx' ];
+
+ r.on('end', function() {
+ assert.deepStrictEqual(reads, expect);
+ t.end();
+ });
+
+ let readSize = 1;
+ function flow() {
+ let res;
+ while (null !== (res = r.read(readSize++))) {
+ reads.push(res.toString());
+ }
+ r.once('readable', flow);
+ }
+
+ flow();
+});
+
+test('pipe', function(t) {
+ const r = new TestReader(5);
+
+ const expect = [ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx' ];
+
+ const w = new TestWriter();
+
+ w.on('end', function(received) {
+ assert.deepStrictEqual(received, expect);
+ t.end();
+ });
+
+ r.pipe(w);
+});
+
+
+[1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(function(SPLIT) {
+ test('unpipe', function(t) {
+ const r = new TestReader(5);
+
+ // unpipe after 3 writes, then write to another stream instead.
+ let expect = [ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx' ];
+ expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
+
+ const w = [ new TestWriter(), new TestWriter() ];
+
+ let writes = SPLIT;
+ w[0].on('write', function() {
+ if (--writes === 0) {
+ r.unpipe();
+ assert.strictEqual(r._readableState.pipes, null);
+ w[0].end();
+ r.pipe(w[1]);
+ assert.strictEqual(r._readableState.pipes, w[1]);
+ }
+ });
+
+ let ended = 0;
+
+ let ended0 = false;
+ let ended1 = false;
+ w[0].on('end', function(results) {
+ assert.strictEqual(ended0, false);
+ ended0 = true;
+ ended++;
+ assert.deepStrictEqual(results, expect[0]);
+ });
+
+ w[1].on('end', function(results) {
+ assert.strictEqual(ended1, false);
+ ended1 = true;
+ ended++;
+ assert.strictEqual(ended, 2);
+ assert.deepStrictEqual(results, expect[1]);
+ t.end();
+ });
+
+ r.pipe(w[0]);
+ });
+});
+
+
+// both writers should get the same exact data.
+test('multipipe', function(t) {
+ const r = new TestReader(5);
+ const w = [ new TestWriter(), new TestWriter() ];
+
+ const expect = [ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx' ];
+
+ let c = 2;
+ w[0].on('end', function(received) {
+ assert.deepStrictEqual(received, expect, 'first');
+ if (--c === 0) t.end();
+ });
+ w[1].on('end', function(received) {
+ assert.deepStrictEqual(received, expect, 'second');
+ if (--c === 0) t.end();
+ });
+
+ r.pipe(w[0]);
+ r.pipe(w[1]);
+});
+
+
+[1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(function(SPLIT) {
+ test('multi-unpipe', function(t) {
+ const r = new TestReader(5);
+
+ // unpipe after 3 writes, then write to another stream instead.
+ let expect = [ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx' ];
+ expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
+
+ const w = [ new TestWriter(), new TestWriter(), new TestWriter() ];
+
+ let writes = SPLIT;
+ w[0].on('write', function() {
+ if (--writes === 0) {
+ r.unpipe();
+ w[0].end();
+ r.pipe(w[1]);
+ }
+ });
+
+ let ended = 0;
+
+ w[0].on('end', function(results) {
+ ended++;
+ assert.deepStrictEqual(results, expect[0]);
+ });
+
+ w[1].on('end', function(results) {
+ ended++;
+ assert.strictEqual(ended, 2);
+ assert.deepStrictEqual(results, expect[1]);
+ t.end();
+ });
+
+ r.pipe(w[0]);
+ r.pipe(w[2]);
+ });
+});
+
+test('back pressure respected', function(t) {
+ const r = new R({ objectMode: true });
+ r._read = common.mustNotCall();
+ let counter = 0;
+ r.push(['one']);
+ r.push(['two']);
+ r.push(['three']);
+ r.push(['four']);
+ r.push(null);
+
+ const w1 = new R();
+ w1.write = function(chunk) {
+ console.error('w1.emit("close")');
+ assert.strictEqual(chunk[0], 'one');
+ w1.emit('close');
+ process.nextTick(function() {
+ r.pipe(w2);
+ r.pipe(w3);
+ });
+ };
+ w1.end = common.mustNotCall();
+
+ r.pipe(w1);
+
+ const expected = ['two', 'two', 'three', 'three', 'four', 'four'];
+
+ const w2 = new R();
+ w2.write = function(chunk) {
+ console.error('w2 write', chunk, counter);
+ assert.strictEqual(chunk[0], expected.shift());
+ assert.strictEqual(counter, 0);
+
+ counter++;
+
+ if (chunk[0] === 'four') {
+ return true;
+ }
+
+ setTimeout(function() {
+ counter--;
+ console.error('w2 drain');
+ w2.emit('drain');
+ }, 10);
+
+ return false;
+ };
+ w2.end = common.mustCall();
+
+ const w3 = new R();
+ w3.write = function(chunk) {
+ console.error('w3 write', chunk, counter);
+ assert.strictEqual(chunk[0], expected.shift());
+ assert.strictEqual(counter, 1);
+
+ counter++;
+
+ if (chunk[0] === 'four') {
+ return true;
+ }
+
+ setTimeout(function() {
+ counter--;
+ console.error('w3 drain');
+ w3.emit('drain');
+ }, 50);
+
+ return false;
+ };
+ w3.end = function() {
+ assert.strictEqual(counter, 2);
+ assert.strictEqual(expected.length, 0);
+ t.end();
+ };
+});
+
+test('read(0) for ended streams', function(t) {
+ const r = new R();
+ let written = false;
+ let ended = false;
+ r._read = common.mustNotCall();
+
+ r.push(Buffer.from('foo'));
+ r.push(null);
+
+ const v = r.read(0);
+
+ assert.strictEqual(v, null);
+
+ const w = new R();
+
+ w.write = function(buffer) {
+ written = true;
+ assert.strictEqual(ended, false);
+ assert.strictEqual(buffer.toString(), 'foo');
+ };
+
+ w.end = function() {
+ ended = true;
+ assert.strictEqual(written, true);
+ t.end();
+ };
+
+ r.pipe(w);
+});
+
+test('sync _read ending', function(t) {
+ const r = new R();
+ let called = false;
+ r._read = function(n) {
+ r.push(null);
+ };
+
+ r.once('end', function() {
+ called = true;
+ });
+
+ r.read();
+
+ process.nextTick(function() {
+ assert.strictEqual(called, true);
+ t.end();
+ });
+});
+
+test('adding readable triggers data flow', function(t) {
+ const r = new R({ highWaterMark: 5 });
+ let onReadable = false;
+ let readCalled = 0;
+
+ r._read = function(n) {
+ if (readCalled++ === 2)
+ r.push(null);
+ else
+ r.push(Buffer.from('asdf'));
+ };
+
+ r.on('readable', function() {
+ onReadable = true;
+ r.read();
+ });
+
+ r.on('end', function() {
+ assert.strictEqual(readCalled, 3);
+ assert.ok(onReadable);
+ t.end();
+ });
+});
+
+test('chainable', function(t) {
+ const r = new R();
+ r._read = common.mustCall();
+ const r2 = r.setEncoding('utf8').pause().resume().pause();
+ assert.strictEqual(r, r2);
+ t.end();
+});