blob: 0074060d0900ed57400f9df537e6d12314982496 [file] [log] [blame]
var tape = require('tape')
var through = require('through2')
var concat = require('concat-stream')
var net = require('net')
var duplexify = require('./')
var HELLO_WORLD = (Buffer.from && Buffer.from !== Uint8Array.from)
? Buffer.from('hello world')
: new Buffer('hello world')
tape('passthrough', function(t) {
t.plan(2)
var pt = through()
var dup = duplexify(pt, pt)
dup.end('hello world')
dup.on('finish', function() {
t.ok(true, 'should finish')
})
dup.pipe(concat(function(data) {
t.same(data.toString(), 'hello world', 'same in as out')
}))
})
tape('passthrough + double end', function(t) {
t.plan(2)
var pt = through()
var dup = duplexify(pt, pt)
dup.end('hello world')
dup.end()
dup.on('finish', function() {
t.ok(true, 'should finish')
})
dup.pipe(concat(function(data) {
t.same(data.toString(), 'hello world', 'same in as out')
}))
})
tape('async passthrough + end', function(t) {
t.plan(2)
var pt = through.obj({highWaterMark:1}, function(data, enc, cb) {
setTimeout(function() {
cb(null, data)
}, 100)
})
var dup = duplexify(pt, pt)
dup.write('hello ')
dup.write('world')
dup.end()
dup.on('finish', function() {
t.ok(true, 'should finish')
})
dup.pipe(concat(function(data) {
t.same(data.toString(), 'hello world', 'same in as out')
}))
})
tape('duplex', function(t) {
var readExpected = ['read-a', 'read-b', 'read-c']
var writeExpected = ['write-a', 'write-b', 'write-c']
t.plan(readExpected.length+writeExpected.length+2)
var readable = through.obj()
var writable = through.obj(function(data, enc, cb) {
t.same(data, writeExpected.shift(), 'onwrite should match')
cb()
})
var dup = duplexify.obj(writable, readable)
readExpected.slice().forEach(function(data) {
readable.write(data)
})
readable.end()
writeExpected.slice().forEach(function(data) {
dup.write(data)
})
dup.end()
dup.on('data', function(data) {
t.same(data, readExpected.shift(), 'ondata should match')
})
dup.on('end', function() {
t.ok(true, 'should end')
})
dup.on('finish', function() {
t.ok(true, 'should finish')
})
})
tape('async', function(t) {
var dup = duplexify()
var pt = through()
dup.pipe(concat(function(data) {
t.same(data.toString(), 'i was async', 'same in as out')
t.end()
}))
dup.write('i')
dup.write(' was ')
dup.end('async')
setTimeout(function() {
dup.setWritable(pt)
setTimeout(function() {
dup.setReadable(pt)
}, 50)
}, 50)
})
tape('destroy', function(t) {
t.plan(2)
var write = through()
var read = through()
var dup = duplexify(write, read)
write.destroy = function() {
t.ok(true, 'write destroyed')
}
dup.on('close', function() {
t.ok(true, 'close emitted')
})
dup.destroy()
dup.destroy() // should only work once
})
tape('destroy both', function(t) {
t.plan(3)
var write = through()
var read = through()
var dup = duplexify(write, read)
write.destroy = function() {
t.ok(true, 'write destroyed')
}
read.destroy = function() {
t.ok(true, 'read destroyed')
}
dup.on('close', function() {
t.ok(true, 'close emitted')
})
dup.destroy()
dup.destroy() // should only work once
})
tape('bubble read errors', function(t) {
t.plan(2)
var write = through()
var read = through()
var dup = duplexify(write, read)
dup.on('error', function(err) {
t.same(err.message, 'read-error', 'received read error')
})
dup.on('close', function() {
t.ok(true, 'close emitted')
})
read.emit('error', new Error('read-error'))
write.emit('error', new Error('write-error')) // only emit first error
})
tape('bubble write errors', function(t) {
t.plan(2)
var write = through()
var read = through()
var dup = duplexify(write, read)
dup.on('error', function(err) {
t.same(err.message, 'write-error', 'received write error')
})
dup.on('close', function() {
t.ok(true, 'close emitted')
})
write.emit('error', new Error('write-error'))
read.emit('error', new Error('read-error')) // only emit first error
})
tape('reset writable / readable', function(t) {
t.plan(3)
var toUpperCase = function(data, enc, cb) {
cb(null, data.toString().toUpperCase())
}
var passthrough = through()
var upper = through(toUpperCase)
var dup = duplexify(passthrough, passthrough)
dup.once('data', function(data) {
t.same(data.toString(), 'hello')
dup.setWritable(upper)
dup.setReadable(upper)
dup.once('data', function(data) {
t.same(data.toString(), 'HELLO')
dup.once('data', function(data) {
t.same(data.toString(), 'HI')
t.end()
})
})
dup.write('hello')
dup.write('hi')
})
dup.write('hello')
})
tape('cork', function(t) {
var passthrough = through()
var dup = duplexify(passthrough, passthrough)
var ok = false
dup.on('prefinish', function() {
dup.cork()
setTimeout(function() {
ok = true
dup.uncork()
}, 100)
})
dup.on('finish', function() {
t.ok(ok)
t.end()
})
dup.end()
})
tape('prefinish not twice', function(t) {
var passthrough = through()
var dup = duplexify(passthrough, passthrough)
var prefinished = false
dup.on('prefinish', function() {
t.ok(!prefinished, 'only prefinish once')
prefinished = true
})
dup.on('finish', function() {
t.end()
})
dup.end()
})
tape('close', function(t) {
var passthrough = through()
var dup = duplexify(passthrough, passthrough)
passthrough.emit('close')
dup.on('close', function() {
t.ok(true, 'should forward close')
t.end()
})
})
tape('works with node native streams (net)', function(t) {
t.plan(1)
var server = net.createServer(function(socket) {
var dup = duplexify(socket, socket)
dup.once('data', function(chunk) {
t.same(chunk, HELLO_WORLD)
server.close()
socket.end()
t.end()
})
})
server.listen(0, function () {
var socket = net.connect(server.address().port)
var dup = duplexify(socket, socket)
dup.write(HELLO_WORLD)
})
})