diff options
author | Rich Trott <rtrott@gmail.com> | 2017-05-21 14:43:09 -0700 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2017-05-24 13:45:21 +0200 |
commit | 1aad4ba2841120d04661681cd7a60b7124912d42 (patch) | |
tree | ec2ff8c85279d947fcfefd2b57691b68517dd562 /test/parallel/test-stream2-basic.js | |
parent | 7bb9fd203522cb37424629dad777f966a81dd03d (diff) | |
download | android-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.js | 475 |
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(); +}); |