diff options
Diffstat (limited to 'node_modules/cloneable-readable/test.js')
-rw-r--r-- | node_modules/cloneable-readable/test.js | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/node_modules/cloneable-readable/test.js b/node_modules/cloneable-readable/test.js new file mode 100644 index 000000000..e1d88d4d9 --- /dev/null +++ b/node_modules/cloneable-readable/test.js @@ -0,0 +1,576 @@ +'use strict' + +var test = require('tape').test +var from = require('from2') +var sink = require('flush-write-stream') +var cloneable = require('./') + +test('basic passthrough', function (t) { + t.plan(2) + + var read = false + var source = from(function (size, next) { + if (read) { + this.push(null) + } else { + read = true + this.push('hello world') + } + next() + }) + + var instance = cloneable(source) + t.notOk(read, 'stream not started') + + instance.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches') + cb() + })) +}) + +test('clone sync', function (t) { + t.plan(4) + + var read = false + var source = from(function (size, next) { + if (read) { + this.push(null) + } else { + read = true + this.push('hello world') + } + next() + }) + + var instance = cloneable(source) + t.notOk(read, 'stream not started') + + var cloned = instance.clone() + t.notOk(read, 'stream not started') + + instance.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches') + cb() + })) + + cloned.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches') + cb() + })) +}) + +test('clone async', function (t) { + t.plan(4) + + var read = false + var source = from(function (size, next) { + if (read) { + this.push(null) + } else { + read = true + this.push('hello world') + } + next() + }) + + var instance = cloneable(source) + t.notOk(read, 'stream not started') + + var cloned = instance.clone() + t.notOk(read, 'stream not started') + + instance.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches') + cb() + })) + + setImmediate(function () { + cloned.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches') + cb() + })) + }) +}) + +test('basic passthrough in obj mode', function (t) { + t.plan(2) + + var read = false + var source = from.obj(function (size, next) { + if (read) { + return this.push(null) + } else { + read = true + this.push({ hello: 'world' }) + } + next() + }) + + var instance = cloneable(source) + t.notOk(read, 'stream not started') + + instance.pipe(sink.obj(function (chunk, enc, cb) { + t.deepEqual(chunk, { hello: 'world' }, 'chunk matches') + cb() + })) +}) + +test('multiple clone in object mode', function (t) { + t.plan(4) + + var read = false + var source = from.obj(function (size, next) { + if (read) { + return this.push(null) + } else { + read = true + this.push({ hello: 'world' }) + } + next() + }) + + var instance = cloneable(source) + t.notOk(read, 'stream not started') + + var cloned = instance.clone() + t.notOk(read, 'stream not started') + + instance.pipe(sink.obj(function (chunk, enc, cb) { + t.deepEqual(chunk, { hello: 'world' }, 'chunk matches') + cb() + })) + + setImmediate(function () { + cloned.pipe(sink.obj(function (chunk, enc, cb) { + t.deepEqual(chunk, { hello: 'world' }, 'chunk matches') + cb() + })) + }) +}) + +test('basic passthrough with data event', function (t) { + t.plan(2) + + var read = false + var source = from(function (size, next) { + if (read) { + this.push(null) + } else { + read = true + this.push('hello world') + } + next() + }) + + var instance = cloneable(source) + t.notOk(read, 'stream not started') + + var data = '' + instance.on('data', function (chunk) { + data += chunk.toString() + }) + + instance.on('end', function () { + t.equal(data, 'hello world', 'chunk matches') + }) +}) + +test('basic passthrough with data event on clone', function (t) { + t.plan(3) + + var read = false + var source = from(function (size, next) { + if (read) { + this.push(null) + } else { + read = true + this.push('hello world') + } + next() + }) + + var instance = cloneable(source) + var cloned = instance.clone() + + t.notOk(read, 'stream not started') + + var data = '' + cloned.on('data', function (chunk) { + data += chunk.toString() + }) + + cloned.on('end', function () { + t.equal(data, 'hello world', 'chunk matches in clone') + }) + + instance.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches in instance') + cb() + })) +}) + +test('errors if cloned after start', function (t) { + t.plan(2) + + var source = from(function (size, next) { + this.push('hello world') + this.push(null) + next() + }) + + var instance = cloneable(source) + + instance.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches') + t.throws(function () { + instance.clone() + }, 'throws if cloned after start') + cb() + })) +}) + +test('basic passthrough with readable event', function (t) { + t.plan(2) + + var read = false + var source = from(function (size, next) { + if (read) { + this.push(null) + } else { + read = true + this.push('hello world') + } + next() + }) + + var instance = cloneable(source) + t.notOk(read, 'stream not started') + + var data = '' + instance.on('readable', function () { + var chunk + while ((chunk = this.read()) !== null) { + data += chunk.toString() + } + }) + + instance.on('end', function () { + t.equal(data, 'hello world', 'chunk matches') + }) +}) + +test('basic passthrough with readable event on clone', function (t) { + t.plan(3) + + var read = false + var source = from(function (size, next) { + if (read) { + this.push(null) + } else { + read = true + this.push('hello world') + } + next() + }) + + var instance = cloneable(source) + var cloned = instance.clone() + + t.notOk(read, 'stream not started') + + var data = '' + cloned.on('readable', function () { + var chunk + while ((chunk = this.read()) !== null) { + data += chunk.toString() + } + }) + + cloned.on('end', function () { + t.equal(data, 'hello world', 'chunk matches in clone') + }) + + instance.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches in instance') + cb() + })) +}) + +test('source error destroys all', function (t) { + t.plan(5) + + var source = from() + var instance = cloneable(source) + var clone = instance.clone() + + source.on('error', function (err) { + t.ok(err, 'source errors') + + instance.on('error', function (err2) { + t.ok(err === err2, 'instance receives same error') + }) + + instance.on('close', function () { + t.pass('instance is closed') + }) + + clone.on('error', function (err3) { + t.ok(err === err3, 'clone receives same error') + }) + + clone.on('close', function () { + t.pass('clone is closed') + }) + }) + + source.emit('error', new Error()) +}) + +test('source destroy destroys all', function (t) { + t.plan(2) + + var source = from() + var instance = cloneable(source) + var clone = instance.clone() + + instance.on('close', function () { + t.pass('instance is closed') + }) + + clone.on('close', function () { + t.pass('clone is closed') + }) + + source.destroy() +}) + +test('instance error destroys all but the source', function (t) { + t.plan(4) + + var source = from() + var instance = cloneable(source) + var clone = instance.clone() + + source.on('close', function () { + t.fail('source should not be closed') + }) + + instance.on('error', function (err) { + t.is(err.message, 'beep', 'instance errors') + + instance.on('close', function () { + t.pass('instance is closed') + }) + + clone.on('error', function (err3) { + t.ok(err === err3, 'clone receives same error') + }) + + clone.on('close', function () { + t.pass('clone is closed') + }) + }) + + instance.destroy(new Error('beep')) +}) + +test('instance destroy destroys all but the source', function (t) { + t.plan(2) + + var source = from() + var instance = cloneable(source) + var clone = instance.clone() + + source.on('close', function () { + t.fail('source should not be closed') + }) + + instance.on('close', function () { + t.pass('instance is closed') + }) + + clone.on('close', function () { + t.pass('clone is closed') + }) + + instance.destroy() +}) + +test('clone destroy does not affect other clones, cloneable or source', function (t) { + t.plan(1) + + var source = from() + var instance = cloneable(source) + var clone = instance.clone() + var other = instance.clone() + + source.on('close', function () { + t.fail('source should not be closed') + }) + + instance.on('close', function () { + t.fail('instance should not be closed') + }) + + other.on('close', function () { + t.fail('other clone should not be closed') + }) + + clone.on('close', function () { + t.pass('clone is closed') + }) + + clone.destroy() +}) + +test('clone remains readable if other is destroyed', function (t) { + t.plan(3) + + var read = false + var source = from(function (size, next) { + if (read) { + this.push(null) + } else { + read = true + this.push('hello') + } + next() + }) + + var instance = cloneable(source) + var clone = instance.clone() + var other = instance.clone() + + instance.pipe(sink.obj(function (chunk, enc, cb) { + t.deepEqual(chunk.toString(), 'hello', 'instance chunk matches') + cb() + })) + + clone.pipe(sink.obj(function (chunk, enc, cb) { + t.deepEqual(chunk.toString(), 'hello', 'clone chunk matches') + cb() + })) + + clone.on('close', function () { + t.fail('clone should not be closed') + }) + + instance.on('close', function () { + t.fail('instance should not be closed') + }) + + other.on('close', function () { + t.pass('other is closed') + }) + + other.destroy() +}) + +test('clone of clone', function (t) { + t.plan(6) + + var read = false + var source = from(function (size, next) { + if (read) { + this.push(null) + } else { + read = true + this.push('hello world') + } + next() + }) + + var instance = cloneable(source) + t.notOk(read, 'stream not started') + + var cloned = instance.clone() + t.notOk(read, 'stream not started') + + var replica = cloned.clone() + t.notOk(read, 'stream not started') + + instance.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches') + cb() + })) + + cloned.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches') + cb() + })) + + replica.pipe(sink(function (chunk, enc, cb) { + t.equal(chunk.toString(), 'hello world', 'chunk matches') + cb() + })) +}) + +test('from vinyl', function (t) { + t.plan(3) + + var source = from(['wa', 'dup']) + + var instance = cloneable(source) + var clone = instance.clone() + + var data = '' + var data2 = '' + var ends = 2 + + function latch () { + if (--ends === 0) { + t.equal(data, data2) + } + } + + instance.on('data', function (chunk) { + data += chunk.toString() + }) + + process.nextTick(function () { + t.equal('', data, 'nothing was written yet') + t.equal('', data2, 'nothing was written yet') + + clone.on('data', function (chunk) { + data2 += chunk.toString() + }) + }) + + instance.on('end', latch) + clone.on('end', latch) +}) + +test('waits till all are flowing', function (t) { + t.plan(1) + + var source = from(['wa', 'dup']) + + var instance = cloneable(source) + + // we create a clone + instance.clone() + + instance.on('data', function (chunk) { + t.fail('this should never happen') + }) + + process.nextTick(function () { + t.pass('wait till nextTick') + }) +}) + +test('isCloneable', function (t) { + t.plan(4) + + var source = from(['hello', ' ', 'world']) + t.notOk(cloneable.isCloneable(source), 'a generic readable is not cloneable') + + var instance = cloneable(source) + t.ok(cloneable.isCloneable(instance), 'a cloneable is cloneable') + + var clone = instance.clone() + t.ok(cloneable.isCloneable(clone), 'a clone is cloneable') + + var cloneClone = clone.clone() + t.ok(cloneable.isCloneable(cloneClone), 'a clone of a clone is cloneable') +}) |