streams2: Tests of new interfaces
This commit is contained in:
Родитель
8acb416ad0
Коммит
9b1b85490b
|
@ -0,0 +1,312 @@
|
|||
// 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.
|
||||
|
||||
|
||||
var common = require('../common.js');
|
||||
var R = require('_stream_readable');
|
||||
var assert = require('assert');
|
||||
|
||||
var util = require('util');
|
||||
var EE = require('events').EventEmitter;
|
||||
|
||||
function TestReader(n) {
|
||||
R.apply(this);
|
||||
this._buffer = new Buffer(n || 100);
|
||||
this._buffer.fill('x');
|
||||
this._pos = 0;
|
||||
this._bufs = 10;
|
||||
}
|
||||
|
||||
util.inherits(TestReader, R);
|
||||
|
||||
TestReader.prototype.read = function(n) {
|
||||
var max = this._buffer.length - this._pos;
|
||||
n = n || max;
|
||||
n = Math.max(n, 0);
|
||||
var 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.emit('end');
|
||||
this.ended = true;
|
||||
}
|
||||
} else {
|
||||
this.emit('readable');
|
||||
}
|
||||
}.bind(this), 10);
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = this._buffer.slice(this._pos, this._pos + toRead);
|
||||
this._pos += toRead;
|
||||
return 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;
|
||||
|
||||
// flip back and forth between immediate acceptance and not.
|
||||
this.flush = !this.flush;
|
||||
if (!this.flush) setTimeout(this.emit.bind(this, 'drain'), 10);
|
||||
return this.flush;
|
||||
};
|
||||
|
||||
TestWriter.prototype.end = function(c) {
|
||||
if (c) this.write(c);
|
||||
this.emit('end', this.received);
|
||||
};
|
||||
|
||||
////////
|
||||
|
||||
// tiny node-tap lookalike.
|
||||
var tests = [];
|
||||
function test(name, fn) {
|
||||
tests.push([name, fn]);
|
||||
}
|
||||
|
||||
function run() {
|
||||
var next = tests.shift();
|
||||
if (!next)
|
||||
return console.error('ok');
|
||||
|
||||
var name = next[0];
|
||||
var fn = next[1];
|
||||
console.log('# %s', name);
|
||||
fn({
|
||||
same: assert.deepEqual,
|
||||
equal: assert.equal,
|
||||
end: run
|
||||
});
|
||||
}
|
||||
|
||||
process.nextTick(run);
|
||||
|
||||
|
||||
test('a most basic test', function(t) {
|
||||
var r = new TestReader(20);
|
||||
|
||||
var reads = [];
|
||||
var expect = [ 'x',
|
||||
'xx',
|
||||
'xxx',
|
||||
'xxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxxxxx',
|
||||
'xxxxxxxxx',
|
||||
'xxx',
|
||||
'xxxxxxxxxxxx',
|
||||
'xxxxxxxx',
|
||||
'xxxxxxxxxxxxxxx',
|
||||
'xxxxx',
|
||||
'xxxxxxxxxxxxxxxxxx',
|
||||
'xx',
|
||||
'xxxxxxxxxxxxxxxxxxxx',
|
||||
'xxxxxxxxxxxxxxxxxxxx',
|
||||
'xxxxxxxxxxxxxxxxxxxx',
|
||||
'xxxxxxxxxxxxxxxxxxxx',
|
||||
'xxxxxxxxxxxxxxxxxxxx' ];
|
||||
|
||||
r.on('end', function() {
|
||||
t.same(reads, expect);
|
||||
t.end();
|
||||
});
|
||||
|
||||
var readSize = 1;
|
||||
function flow() {
|
||||
var res;
|
||||
while (null !== (res = r.read(readSize++))) {
|
||||
reads.push(res.toString());
|
||||
}
|
||||
r.once('readable', flow);
|
||||
}
|
||||
|
||||
flow();
|
||||
});
|
||||
|
||||
test('pipe', function(t) {
|
||||
var r = new TestReader(5);
|
||||
|
||||
var expect = [ 'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx' ]
|
||||
|
||||
var w = new TestWriter;
|
||||
var flush = true;
|
||||
w.on('end', function(received) {
|
||||
t.same(received, expect);
|
||||
t.end();
|
||||
});
|
||||
|
||||
r.pipe(w);
|
||||
});
|
||||
|
||||
|
||||
|
||||
[1,2,3,4,5,6,7,8,9].forEach(function(SPLIT) {
|
||||
test('unpipe', function(t) {
|
||||
var r = new TestReader(5);
|
||||
|
||||
// unpipe after 3 writes, then write to another stream instead.
|
||||
var expect = [ 'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx' ];
|
||||
expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
|
||||
|
||||
var w = [ new TestWriter(), new TestWriter() ];
|
||||
|
||||
var writes = SPLIT;
|
||||
w[0].on('write', function() {
|
||||
if (--writes === 0) {
|
||||
r.unpipe();
|
||||
w[0].end();
|
||||
r.pipe(w[1]);
|
||||
}
|
||||
});
|
||||
|
||||
var ended = 0;
|
||||
|
||||
w[0].on('end', function(results) {
|
||||
ended++;
|
||||
t.same(results, expect[0]);
|
||||
});
|
||||
|
||||
w[1].on('end', function(results) {
|
||||
ended++;
|
||||
t.equal(ended, 2);
|
||||
t.same(results, expect[1]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
r.pipe(w[0]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// both writers should get the same exact data.
|
||||
test('multipipe', function(t) {
|
||||
var r = new TestReader(5);
|
||||
var w = [ new TestWriter, new TestWriter ];
|
||||
|
||||
var expect = [ 'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx' ];
|
||||
|
||||
var c = 2;
|
||||
w[0].on('end', function(received) {
|
||||
t.same(received, expect, 'first');
|
||||
if (--c === 0) t.end();
|
||||
});
|
||||
w[1].on('end', function(received) {
|
||||
t.same(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) {
|
||||
var r = new TestReader(5);
|
||||
|
||||
// unpipe after 3 writes, then write to another stream instead.
|
||||
var expect = [ 'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx',
|
||||
'xxxxx' ];
|
||||
expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
|
||||
|
||||
var w = [ new TestWriter(), new TestWriter(), new TestWriter() ];
|
||||
|
||||
var writes = SPLIT;
|
||||
w[0].on('write', function() {
|
||||
if (--writes === 0) {
|
||||
r.unpipe();
|
||||
w[0].end();
|
||||
r.pipe(w[1]);
|
||||
}
|
||||
});
|
||||
|
||||
var ended = 0;
|
||||
|
||||
w[0].on('end', function(results) {
|
||||
ended++;
|
||||
t.same(results, expect[0]);
|
||||
});
|
||||
|
||||
w[1].on('end', function(results) {
|
||||
ended++;
|
||||
t.equal(ended, 2);
|
||||
t.same(results, expect[1]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
r.pipe(w[0]);
|
||||
r.pipe(w[2]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,76 @@
|
|||
// 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.
|
||||
|
||||
|
||||
var common = require('../common.js');
|
||||
var R = require('_stream_readable');
|
||||
var assert = require('assert');
|
||||
|
||||
var fs = require('fs');
|
||||
var FSReadable = fs.ReadStream;
|
||||
|
||||
var path = require('path');
|
||||
var file = path.resolve(common.fixturesDir, 'x1024.txt');
|
||||
|
||||
var size = fs.statSync(file).size;
|
||||
|
||||
// expect to see chunks no more than 10 bytes each.
|
||||
var expectLengths = [];
|
||||
for (var i = size; i > 0; i -= 10) {
|
||||
expectLengths.push(Math.min(i, 10));
|
||||
}
|
||||
|
||||
var util = require('util');
|
||||
var Stream = require('stream');
|
||||
|
||||
util.inherits(TestWriter, Stream);
|
||||
|
||||
function TestWriter() {
|
||||
Stream.apply(this);
|
||||
this.buffer = [];
|
||||
this.length = 0;
|
||||
}
|
||||
|
||||
TestWriter.prototype.write = function(c) {
|
||||
this.buffer.push(c.toString());
|
||||
this.length += c.length;
|
||||
return true;
|
||||
};
|
||||
|
||||
TestWriter.prototype.end = function(c) {
|
||||
if (c) this.buffer.push(c.toString());
|
||||
this.emit('results', this.buffer);
|
||||
}
|
||||
|
||||
var r = new FSReadable(file, { bufferSize: 10 });
|
||||
var w = new TestWriter();
|
||||
|
||||
w.on('results', function(res) {
|
||||
console.error(res, w.length);
|
||||
assert.equal(w.length, size);
|
||||
var l = 0;
|
||||
assert.deepEqual(res.map(function (c) {
|
||||
return c.length;
|
||||
}), expectLengths);
|
||||
console.log('ok');
|
||||
});
|
||||
|
||||
r.pipe(w, { chunkSize: 10 });
|
|
@ -0,0 +1,109 @@
|
|||
// 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.
|
||||
|
||||
var assert = require('assert');
|
||||
var common = require('../common.js');
|
||||
var fromList = require('_stream_readable')._fromList;
|
||||
|
||||
// tiny node-tap lookalike.
|
||||
var tests = [];
|
||||
function test(name, fn) {
|
||||
tests.push([name, fn]);
|
||||
}
|
||||
|
||||
function run() {
|
||||
var next = tests.shift();
|
||||
if (!next)
|
||||
return console.error('ok');
|
||||
|
||||
var name = next[0];
|
||||
var fn = next[1];
|
||||
console.log('# %s', name);
|
||||
fn({
|
||||
same: assert.deepEqual,
|
||||
equal: assert.equal,
|
||||
end: run
|
||||
});
|
||||
}
|
||||
|
||||
process.nextTick(run);
|
||||
|
||||
|
||||
|
||||
test('buffers', function(t) {
|
||||
// have a length
|
||||
var len = 16;
|
||||
var list = [ new Buffer('foog'),
|
||||
new Buffer('bark'),
|
||||
new Buffer('bazy'),
|
||||
new Buffer('kuel') ];
|
||||
|
||||
// read more than the first element.
|
||||
var ret = fromList(6, list, 16);
|
||||
t.equal(ret.toString(), 'foogba');
|
||||
|
||||
// read exactly the first element.
|
||||
ret = fromList(2, list, 10);
|
||||
t.equal(ret.toString(), 'rk');
|
||||
|
||||
// read less than the first element.
|
||||
ret = fromList(2, list, 8);
|
||||
t.equal(ret.toString(), 'ba');
|
||||
|
||||
// read more than we have.
|
||||
ret = fromList(100, list, 6);
|
||||
t.equal(ret.toString(), 'zykuel');
|
||||
|
||||
// all consumed.
|
||||
t.same(list, []);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('strings', function(t) {
|
||||
// have a length
|
||||
var len = 16;
|
||||
var list = [ 'foog',
|
||||
'bark',
|
||||
'bazy',
|
||||
'kuel' ];
|
||||
|
||||
// read more than the first element.
|
||||
var ret = fromList(6, list, 16, true);
|
||||
t.equal(ret, 'foogba');
|
||||
|
||||
// read exactly the first element.
|
||||
ret = fromList(2, list, 10, true);
|
||||
t.equal(ret, 'rk');
|
||||
|
||||
// read less than the first element.
|
||||
ret = fromList(2, list, 8, true);
|
||||
t.equal(ret, 'ba');
|
||||
|
||||
// read more than we have.
|
||||
ret = fromList(100, list, 6, true);
|
||||
t.equal(ret, 'zykuel');
|
||||
|
||||
// all consumed.
|
||||
t.same(list, []);
|
||||
|
||||
t.end();
|
||||
});
|
|
@ -0,0 +1,299 @@
|
|||
// 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.
|
||||
|
||||
|
||||
var common = require('../common.js');
|
||||
var assert = require('assert');
|
||||
var R = require('_stream_readable');
|
||||
var util = require('util');
|
||||
|
||||
// tiny node-tap lookalike.
|
||||
var tests = [];
|
||||
function test(name, fn) {
|
||||
tests.push([name, fn]);
|
||||
}
|
||||
|
||||
function run() {
|
||||
var next = tests.shift();
|
||||
if (!next)
|
||||
return console.error('ok');
|
||||
|
||||
var name = next[0];
|
||||
var fn = next[1];
|
||||
console.log('# %s', name);
|
||||
fn({
|
||||
same: assert.deepEqual,
|
||||
equal: assert.equal,
|
||||
end: run
|
||||
});
|
||||
}
|
||||
|
||||
process.nextTick(run);
|
||||
|
||||
/////
|
||||
|
||||
util.inherits(TestReader, R);
|
||||
|
||||
function TestReader(n, opts) {
|
||||
R.call(this, util._extend({
|
||||
bufferSize: 5
|
||||
}, opts));
|
||||
|
||||
this.pos = 0;
|
||||
this.len = n || 100;
|
||||
}
|
||||
|
||||
TestReader.prototype._read = function(n, cb) {
|
||||
setTimeout(function() {
|
||||
|
||||
if (this.pos >= this.len) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
n = Math.min(n, this.len - this.pos);
|
||||
if (n <= 0) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
this.pos += n;
|
||||
var ret = new Buffer(n);
|
||||
ret.fill('a');
|
||||
|
||||
return cb(null, ret);
|
||||
}.bind(this), 1);
|
||||
};
|
||||
|
||||
test('setEncoding utf8', function(t) {
|
||||
var tr = new TestReader(100);
|
||||
tr.setEncoding('utf8');
|
||||
var out = [];
|
||||
var expect =
|
||||
[ 'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa' ];
|
||||
|
||||
tr.on('readable', function flow() {
|
||||
var chunk;
|
||||
while (null !== (chunk = tr.read(10)))
|
||||
out.push(chunk);
|
||||
});
|
||||
|
||||
tr.on('end', function() {
|
||||
t.same(out, expect);
|
||||
t.end();
|
||||
});
|
||||
|
||||
// just kick it off.
|
||||
tr.emit('readable');
|
||||
});
|
||||
|
||||
|
||||
test('setEncoding hex', function(t) {
|
||||
var tr = new TestReader(100);
|
||||
tr.setEncoding('hex');
|
||||
var out = [];
|
||||
var expect =
|
||||
[ '6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161' ];
|
||||
|
||||
tr.on('readable', function flow() {
|
||||
var chunk;
|
||||
while (null !== (chunk = tr.read(10)))
|
||||
out.push(chunk);
|
||||
});
|
||||
|
||||
tr.on('end', function() {
|
||||
t.same(out, expect);
|
||||
t.end();
|
||||
});
|
||||
|
||||
// just kick it off.
|
||||
tr.emit('readable');
|
||||
});
|
||||
|
||||
test('setEncoding hex with read(13)', function(t) {
|
||||
var tr = new TestReader(100);
|
||||
tr.setEncoding('hex');
|
||||
var out = [];
|
||||
var expect =
|
||||
[ "6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"16161" ];
|
||||
|
||||
tr.on('readable', function flow() {
|
||||
var chunk;
|
||||
while (null !== (chunk = tr.read(13)))
|
||||
out.push(chunk);
|
||||
});
|
||||
|
||||
tr.on('end', function() {
|
||||
t.same(out, expect);
|
||||
t.end();
|
||||
});
|
||||
|
||||
// just kick it off.
|
||||
tr.emit('readable');
|
||||
});
|
||||
|
||||
test('encoding: utf8', function(t) {
|
||||
var tr = new TestReader(100, { encoding: 'utf8' });
|
||||
var out = [];
|
||||
var expect =
|
||||
[ 'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa',
|
||||
'aaaaaaaaaa' ];
|
||||
|
||||
tr.on('readable', function flow() {
|
||||
var chunk;
|
||||
while (null !== (chunk = tr.read(10)))
|
||||
out.push(chunk);
|
||||
});
|
||||
|
||||
tr.on('end', function() {
|
||||
t.same(out, expect);
|
||||
t.end();
|
||||
});
|
||||
|
||||
// just kick it off.
|
||||
tr.emit('readable');
|
||||
});
|
||||
|
||||
|
||||
test('encoding: hex', function(t) {
|
||||
var tr = new TestReader(100, { encoding: 'hex' });
|
||||
var out = [];
|
||||
var expect =
|
||||
[ '6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161',
|
||||
'6161616161' ];
|
||||
|
||||
tr.on('readable', function flow() {
|
||||
var chunk;
|
||||
while (null !== (chunk = tr.read(10)))
|
||||
out.push(chunk);
|
||||
});
|
||||
|
||||
tr.on('end', function() {
|
||||
t.same(out, expect);
|
||||
t.end();
|
||||
});
|
||||
|
||||
// just kick it off.
|
||||
tr.emit('readable');
|
||||
});
|
||||
|
||||
test('encoding: hex with read(13)', function(t) {
|
||||
var tr = new TestReader(100, { encoding: 'hex' });
|
||||
var out = [];
|
||||
var expect =
|
||||
[ "6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"1616161616161",
|
||||
"6161616161616",
|
||||
"16161" ];
|
||||
|
||||
tr.on('readable', function flow() {
|
||||
var chunk;
|
||||
while (null !== (chunk = tr.read(13)))
|
||||
out.push(chunk);
|
||||
});
|
||||
|
||||
tr.on('end', function() {
|
||||
t.same(out, expect);
|
||||
t.end();
|
||||
});
|
||||
|
||||
// just kick it off.
|
||||
tr.emit('readable');
|
||||
});
|
|
@ -0,0 +1,309 @@
|
|||
// 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.
|
||||
|
||||
var assert = require('assert');
|
||||
var common = require('../common.js');
|
||||
var PassThrough = require('_stream_passthrough');
|
||||
var Transform = require('_stream_transform');
|
||||
|
||||
// tiny node-tap lookalike.
|
||||
var tests = [];
|
||||
function test(name, fn) {
|
||||
tests.push([name, fn]);
|
||||
}
|
||||
|
||||
function run() {
|
||||
var next = tests.shift();
|
||||
if (!next)
|
||||
return console.error('ok');
|
||||
|
||||
var name = next[0];
|
||||
var fn = next[1];
|
||||
console.log('# %s', name);
|
||||
fn({
|
||||
same: assert.deepEqual,
|
||||
equal: assert.equal,
|
||||
end: run
|
||||
});
|
||||
}
|
||||
|
||||
process.nextTick(run);
|
||||
|
||||
/////
|
||||
|
||||
test('passthrough', function(t) {
|
||||
var pt = new PassThrough();
|
||||
|
||||
pt.write(new Buffer('foog'));
|
||||
pt.write(new Buffer('bark'));
|
||||
pt.write(new Buffer('bazy'));
|
||||
pt.write(new Buffer('kuel'));
|
||||
pt.end();
|
||||
|
||||
t.equal(pt.read(5).toString(), 'foogb');
|
||||
t.equal(pt.read(5).toString(), 'arkba');
|
||||
t.equal(pt.read(5).toString(), 'zykue');
|
||||
t.equal(pt.read(5).toString(), 'l');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('simple transform', function(t) {
|
||||
var pt = new Transform;
|
||||
pt._transform = function(c, output, cb) {
|
||||
var ret = new Buffer(c.length);
|
||||
ret.fill('x');
|
||||
output(ret);
|
||||
cb();
|
||||
};
|
||||
|
||||
pt.write(new Buffer('foog'));
|
||||
pt.write(new Buffer('bark'));
|
||||
pt.write(new Buffer('bazy'));
|
||||
pt.write(new Buffer('kuel'));
|
||||
pt.end();
|
||||
|
||||
t.equal(pt.read(5).toString(), 'xxxxx');
|
||||
t.equal(pt.read(5).toString(), 'xxxxx');
|
||||
t.equal(pt.read(5).toString(), 'xxxxx');
|
||||
t.equal(pt.read(5).toString(), 'x');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('async passthrough', function(t) {
|
||||
var pt = new Transform;
|
||||
pt._transform = function(chunk, output, cb) {
|
||||
setTimeout(function() {
|
||||
output(chunk);
|
||||
cb();
|
||||
}, 10);
|
||||
};
|
||||
|
||||
pt.write(new Buffer('foog'));
|
||||
pt.write(new Buffer('bark'));
|
||||
pt.write(new Buffer('bazy'));
|
||||
pt.write(new Buffer('kuel'));
|
||||
pt.end();
|
||||
|
||||
setTimeout(function() {
|
||||
t.equal(pt.read(5).toString(), 'foogb');
|
||||
t.equal(pt.read(5).toString(), 'arkba');
|
||||
t.equal(pt.read(5).toString(), 'zykue');
|
||||
t.equal(pt.read(5).toString(), 'l');
|
||||
t.end();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
test('assymetric transform (expand)', function(t) {
|
||||
var pt = new Transform;
|
||||
|
||||
// emit each chunk 2 times.
|
||||
pt._transform = function(chunk, output, cb) {
|
||||
setTimeout(function() {
|
||||
output(chunk);
|
||||
setTimeout(function() {
|
||||
output(chunk);
|
||||
cb();
|
||||
}, 10)
|
||||
}, 10);
|
||||
};
|
||||
|
||||
pt.write(new Buffer('foog'));
|
||||
pt.write(new Buffer('bark'));
|
||||
pt.write(new Buffer('bazy'));
|
||||
pt.write(new Buffer('kuel'));
|
||||
pt.end();
|
||||
|
||||
setTimeout(function() {
|
||||
t.equal(pt.read(5).toString(), 'foogf');
|
||||
t.equal(pt.read(5).toString(), 'oogba');
|
||||
t.equal(pt.read(5).toString(), 'rkbar');
|
||||
t.equal(pt.read(5).toString(), 'kbazy');
|
||||
t.equal(pt.read(5).toString(), 'bazyk');
|
||||
t.equal(pt.read(5).toString(), 'uelku');
|
||||
t.equal(pt.read(5).toString(), 'el');
|
||||
t.end();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
test('assymetric transform (compress)', function(t) {
|
||||
var pt = new Transform;
|
||||
|
||||
// each output is the first char of 3 consecutive chunks,
|
||||
// or whatever's left.
|
||||
pt.state = '';
|
||||
|
||||
pt._transform = function(chunk, output, cb) {
|
||||
if (!chunk)
|
||||
chunk = '';
|
||||
var s = chunk.toString();
|
||||
setTimeout(function() {
|
||||
this.state += s.charAt(0);
|
||||
if (this.state.length === 3) {
|
||||
output(new Buffer(this.state));
|
||||
this.state = '';
|
||||
}
|
||||
cb();
|
||||
}.bind(this), 10);
|
||||
};
|
||||
|
||||
pt._flush = function(output, cb) {
|
||||
// just output whatever we have.
|
||||
setTimeout(function() {
|
||||
output(new Buffer(this.state));
|
||||
this.state = '';
|
||||
cb();
|
||||
}.bind(this), 10);
|
||||
};
|
||||
|
||||
pt._writableState.lowWaterMark = 3;
|
||||
|
||||
pt.write(new Buffer('aaaa'));
|
||||
pt.write(new Buffer('bbbb'));
|
||||
pt.write(new Buffer('cccc'));
|
||||
pt.write(new Buffer('dddd'));
|
||||
pt.write(new Buffer('eeee'));
|
||||
pt.write(new Buffer('aaaa'));
|
||||
pt.write(new Buffer('bbbb'));
|
||||
pt.write(new Buffer('cccc'));
|
||||
pt.write(new Buffer('dddd'));
|
||||
pt.write(new Buffer('eeee'));
|
||||
pt.write(new Buffer('aaaa'));
|
||||
pt.write(new Buffer('bbbb'));
|
||||
pt.write(new Buffer('cccc'));
|
||||
pt.write(new Buffer('dddd'));
|
||||
pt.end();
|
||||
|
||||
// 'abcdeabcdeabcd'
|
||||
setTimeout(function() {
|
||||
t.equal(pt.read(5).toString(), 'abcde');
|
||||
t.equal(pt.read(5).toString(), 'abcde');
|
||||
t.equal(pt.read(5).toString(), 'abcd');
|
||||
t.end();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
|
||||
test('passthrough event emission', function(t) {
|
||||
var pt = new PassThrough({
|
||||
lowWaterMark: 0
|
||||
});
|
||||
var emits = 0;
|
||||
pt.on('readable', function() {
|
||||
var state = pt._readableState;
|
||||
console.error('>>> emit readable %d', emits);
|
||||
emits++;
|
||||
});
|
||||
|
||||
var i = 0;
|
||||
|
||||
pt.write(new Buffer('foog'));
|
||||
pt.write(new Buffer('bark'));
|
||||
|
||||
t.equal(pt.read(5).toString(), 'foogb');
|
||||
t.equal(pt.read(5) + '', 'null');
|
||||
|
||||
console.error('need emit 0');
|
||||
|
||||
pt.write(new Buffer('bazy'));
|
||||
pt.write(new Buffer('kuel'));
|
||||
|
||||
console.error('should have emitted readable now');
|
||||
t.equal(emits, 1);
|
||||
|
||||
t.equal(pt.read(5).toString(), 'arkba');
|
||||
t.equal(pt.read(5).toString(), 'zykue');
|
||||
t.equal(pt.read(5), null);
|
||||
|
||||
console.error('need emit 1');
|
||||
|
||||
pt.end();
|
||||
|
||||
t.equal(emits, 2);
|
||||
|
||||
t.equal(pt.read(5).toString(), 'l');
|
||||
t.equal(pt.read(5), null);
|
||||
|
||||
console.error('should not have emitted again');
|
||||
t.equal(emits, 2);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('passthrough event emission reordered', function(t) {
|
||||
var pt = new PassThrough;
|
||||
var emits = 0;
|
||||
pt.on('readable', function() {
|
||||
console.error('emit readable', emits)
|
||||
emits++;
|
||||
});
|
||||
|
||||
pt.write(new Buffer('foog'));
|
||||
pt.write(new Buffer('bark'));
|
||||
|
||||
t.equal(pt.read(5).toString(), 'foogb');
|
||||
t.equal(pt.read(5), null);
|
||||
|
||||
console.error('need emit 0');
|
||||
pt.once('readable', function() {
|
||||
t.equal(pt.read(5).toString(), 'arkba');
|
||||
t.equal(pt.read(5).toString(), 'zykue');
|
||||
t.equal(pt.read(5), null);
|
||||
|
||||
console.error('need emit 1');
|
||||
pt.once('readable', function() {
|
||||
t.equal(pt.read(5).toString(), 'l');
|
||||
t.equal(pt.read(5), null);
|
||||
|
||||
t.equal(emits, 2);
|
||||
t.end();
|
||||
});
|
||||
pt.end();
|
||||
});
|
||||
pt.write(new Buffer('bazy'));
|
||||
pt.write(new Buffer('kuel'));
|
||||
});
|
||||
|
||||
test('passthrough facaded', function(t) {
|
||||
console.error('passthrough facaded');
|
||||
var pt = new PassThrough;
|
||||
var datas = [];
|
||||
pt.on('data', function(chunk) {
|
||||
datas.push(chunk.toString());
|
||||
});
|
||||
|
||||
pt.on('end', function() {
|
||||
t.same(datas, ['foog', 'bark', 'bazy', 'kuel']);
|
||||
t.end();
|
||||
});
|
||||
|
||||
pt.write(new Buffer('foog'));
|
||||
setTimeout(function() {
|
||||
pt.write(new Buffer('bark'));
|
||||
setTimeout(function() {
|
||||
pt.write(new Buffer('bazy'));
|
||||
setTimeout(function() {
|
||||
pt.write(new Buffer('kuel'));
|
||||
setTimeout(function() {
|
||||
pt.end();
|
||||
}, 10);
|
||||
}, 10);
|
||||
}, 10);
|
||||
}, 10);
|
||||
});
|
|
@ -0,0 +1,142 @@
|
|||
// 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.
|
||||
|
||||
var common = require('../common.js');
|
||||
var W = require('_stream_writable');
|
||||
var assert = require('assert');
|
||||
|
||||
var util = require('util');
|
||||
util.inherits(TestWriter, W);
|
||||
|
||||
function TestWriter() {
|
||||
W.apply(this, arguments);
|
||||
this.buffer = [];
|
||||
this.written = 0;
|
||||
}
|
||||
|
||||
TestWriter.prototype._write = function(chunk, cb) {
|
||||
// simulate a small unpredictable latency
|
||||
setTimeout(function() {
|
||||
this.buffer.push(chunk.toString());
|
||||
this.written += chunk.length;
|
||||
cb();
|
||||
}.bind(this), Math.floor(Math.random() * 10));
|
||||
};
|
||||
|
||||
var chunks = new Array(50);
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
chunks[i] = new Array(i + 1).join('x');
|
||||
}
|
||||
|
||||
// tiny node-tap lookalike.
|
||||
var tests = [];
|
||||
function test(name, fn) {
|
||||
tests.push([name, fn]);
|
||||
}
|
||||
|
||||
function run() {
|
||||
var next = tests.shift();
|
||||
if (!next)
|
||||
return console.log('ok');
|
||||
|
||||
var name = next[0];
|
||||
var fn = next[1];
|
||||
console.log('# %s', name);
|
||||
fn({
|
||||
same: assert.deepEqual,
|
||||
equal: assert.equal,
|
||||
end: run
|
||||
});
|
||||
}
|
||||
|
||||
process.nextTick(run);
|
||||
|
||||
test('write fast', function(t) {
|
||||
var tw = new TestWriter({
|
||||
lowWaterMark: 5,
|
||||
highWaterMark: 100
|
||||
});
|
||||
|
||||
tw.on('finish', function() {
|
||||
t.same(tw.buffer, chunks, 'got chunks in the right order');
|
||||
t.end();
|
||||
});
|
||||
|
||||
chunks.forEach(function(chunk) {
|
||||
// screw backpressure. Just buffer it all up.
|
||||
tw.write(chunk);
|
||||
});
|
||||
tw.end();
|
||||
});
|
||||
|
||||
test('write slow', function(t) {
|
||||
var tw = new TestWriter({
|
||||
lowWaterMark: 5,
|
||||
highWaterMark: 100
|
||||
});
|
||||
|
||||
tw.on('finish', function() {
|
||||
t.same(tw.buffer, chunks, 'got chunks in the right order');
|
||||
t.end();
|
||||
});
|
||||
|
||||
var i = 0;
|
||||
(function W() {
|
||||
tw.write(chunks[i++]);
|
||||
if (i < chunks.length)
|
||||
setTimeout(W, 10);
|
||||
else
|
||||
tw.end();
|
||||
})();
|
||||
});
|
||||
|
||||
test('write backpressure', function(t) {
|
||||
var tw = new TestWriter({
|
||||
lowWaterMark: 5,
|
||||
highWaterMark: 50
|
||||
});
|
||||
|
||||
var drains = 0;
|
||||
|
||||
tw.on('finish', function() {
|
||||
t.same(tw.buffer, chunks, 'got chunks in the right order');
|
||||
t.equal(drains, 17);
|
||||
t.end();
|
||||
});
|
||||
|
||||
tw.on('drain', function() {
|
||||
drains++;
|
||||
});
|
||||
|
||||
var i = 0;
|
||||
(function W() {
|
||||
do {
|
||||
var ret = tw.write(chunks[i++]);
|
||||
} while (ret !== false && i < chunks.length);
|
||||
|
||||
if (i < chunks.length) {
|
||||
assert(tw._writableState.length >= 50);
|
||||
tw.once('drain', W);
|
||||
} else {
|
||||
tw.end();
|
||||
}
|
||||
})();
|
||||
});
|
Загрузка…
Ссылка в новой задаче