node/test/parallel/test-stream2-writable.js
Rich Trott 082cc8d6d8 test: remove unnecessary assignments
common.js needs to be loaded in all tests so that there is checking
for variable leaks and possibly other things. However, it does not
need to be assigned to a variable if nothing in common.js is referred
to elsewhere in the test.

PR-URL: https://github.com/nodejs/node/pull/4408
Reviewed-By: James M Snell <jasnell@gmail.com>
2015-12-26 18:00:02 -08:00

386 lines
7.7 KiB
JavaScript

'use strict';
require('../common');
var W = require('_stream_writable');
var D = require('_stream_duplex');
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, encoding, 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 = [];
var count = 0;
function test(name, fn) {
count++;
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: function() {
count--;
run();
}
});
}
// ensure all tests have run
process.on('exit', function() {
assert.equal(count, 0);
});
process.nextTick(run);
test('write fast', function(t) {
var tw = new TestWriter({
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({
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({
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();
}
})();
});
test('write bufferize', function(t) {
var tw = new TestWriter({
highWaterMark: 100
});
var encodings =
[ 'hex',
'utf8',
'utf-8',
'ascii',
'binary',
'base64',
'ucs2',
'ucs-2',
'utf16le',
'utf-16le',
undefined ];
tw.on('finish', function() {
t.same(tw.buffer, chunks, 'got the expected chunks');
});
chunks.forEach(function(chunk, i) {
var enc = encodings[ i % encodings.length ];
chunk = new Buffer(chunk);
tw.write(chunk.toString(enc), enc);
});
t.end();
});
test('write no bufferize', function(t) {
var tw = new TestWriter({
highWaterMark: 100,
decodeStrings: false
});
tw._write = function(chunk, encoding, cb) {
assert(typeof chunk === 'string');
chunk = new Buffer(chunk, encoding);
return TestWriter.prototype._write.call(this, chunk, encoding, cb);
};
var encodings =
[ 'hex',
'utf8',
'utf-8',
'ascii',
'binary',
'base64',
'ucs2',
'ucs-2',
'utf16le',
'utf-16le',
undefined ];
tw.on('finish', function() {
t.same(tw.buffer, chunks, 'got the expected chunks');
});
chunks.forEach(function(chunk, i) {
var enc = encodings[ i % encodings.length ];
chunk = new Buffer(chunk);
tw.write(chunk.toString(enc), enc);
});
t.end();
});
test('write callbacks', function(t) {
var callbacks = chunks.map(function(chunk, i) {
return [i, function(er) {
callbacks._called[i] = chunk;
}];
}).reduce(function(set, x) {
set['callback-' + x[0]] = x[1];
return set;
}, {});
callbacks._called = [];
var tw = new TestWriter({
highWaterMark: 100
});
tw.on('finish', function() {
process.nextTick(function() {
t.same(tw.buffer, chunks, 'got chunks in the right order');
t.same(callbacks._called, chunks, 'called all callbacks');
t.end();
});
});
chunks.forEach(function(chunk, i) {
tw.write(chunk, callbacks['callback-' + i]);
});
tw.end();
});
test('end callback', function(t) {
var tw = new TestWriter();
tw.end(function() {
t.end();
});
});
test('end callback with chunk', function(t) {
var tw = new TestWriter();
tw.end(new Buffer('hello world'), function() {
t.end();
});
});
test('end callback with chunk and encoding', function(t) {
var tw = new TestWriter();
tw.end('hello world', 'ascii', function() {
t.end();
});
});
test('end callback after .write() call', function(t) {
var tw = new TestWriter();
tw.write(new Buffer('hello world'));
tw.end(function() {
t.end();
});
});
test('end callback called after write callback', function(t) {
var tw = new TestWriter();
var writeCalledback = false;
tw.write(new Buffer('hello world'), function() {
writeCalledback = true;
});
tw.end(function() {
t.equal(writeCalledback, true);
t.end();
});
});
test('encoding should be ignored for buffers', function(t) {
var tw = new W();
var hex = '018b5e9a8f6236ffe30e31baf80d2cf6eb';
tw._write = function(chunk, encoding, cb) {
t.equal(chunk.toString('hex'), hex);
t.end();
};
var buf = new Buffer(hex, 'hex');
tw.write(buf, 'binary');
});
test('writables are not pipable', function(t) {
var w = new W();
w._write = function() {};
var gotError = false;
w.on('error', function(er) {
gotError = true;
});
w.pipe(process.stdout);
assert(gotError);
t.end();
});
test('duplexes are pipable', function(t) {
var d = new D();
d._read = function() {};
d._write = function() {};
var gotError = false;
d.on('error', function(er) {
gotError = true;
});
d.pipe(process.stdout);
assert(!gotError);
t.end();
});
test('end(chunk) two times is an error', function(t) {
var w = new W();
w._write = function() {};
var gotError = false;
w.on('error', function(er) {
gotError = true;
t.equal(er.message, 'write after end');
});
w.end('this is the end');
w.end('and so is this');
process.nextTick(function() {
assert(gotError);
t.end();
});
});
test('dont end while writing', function(t) {
var w = new W();
var wrote = false;
w._write = function(chunk, e, cb) {
assert(!this.writing);
wrote = true;
this.writing = true;
setTimeout(function() {
this.writing = false;
cb();
});
};
w.on('finish', function() {
assert(wrote);
t.end();
});
w.write(Buffer(0));
w.end();
});
test('finish does not come before write cb', function(t) {
var w = new W();
var writeCb = false;
w._write = function(chunk, e, cb) {
setTimeout(function() {
writeCb = true;
cb();
}, 10);
};
w.on('finish', function() {
assert(writeCb);
t.end();
});
w.write(Buffer(0));
w.end();
});
test('finish does not come before sync _write cb', function(t) {
var w = new W();
var writeCb = false;
w._write = function(chunk, e, cb) {
cb();
};
w.on('finish', function() {
assert(writeCb);
t.end();
});
w.write(Buffer(0), function(er) {
writeCb = true;
});
w.end();
});
test('finish is emitted if last chunk is empty', function(t) {
var w = new W();
w._write = function(chunk, e, cb) {
process.nextTick(cb);
};
w.on('finish', function() {
t.end();
});
w.write(Buffer(1));
w.end(Buffer(0));
});