|
const test = require('brittle') |
|
const { Readable, Writable, Transform } = require('streamx') |
|
const Composer = require('./') |
|
|
|
test('read and write', function (t) { |
|
t.plan(42) |
|
|
|
const c = new Composer() |
|
|
|
let writes = 0 |
|
let reads = 0 |
|
|
|
const r = new Readable() |
|
const w = new Writable({ |
|
write (data, cb) { |
|
t.is(data, 'write-' + (writes++)) |
|
setTimeout(cb, 0) |
|
} |
|
}) |
|
|
|
c.setReadable(r) |
|
c.setWritable(w) |
|
|
|
let flushed = true |
|
for (let i = 0; i < 20; i++) { |
|
flushed = c.write('write-' + i) |
|
} |
|
|
|
t.not(flushed) |
|
|
|
for (let i = 0; i < 20; i++) { |
|
r.push('read-' + i) |
|
} |
|
|
|
t.ok(Readable.isBackpressured(r)) |
|
|
|
c.on('data', function (data) { |
|
t.is(data, 'read-' + (reads++)) |
|
}) |
|
}) |
|
|
|
test('read and write (twice)', function (t) { |
|
t.plan(42) |
|
|
|
const c = new Composer() |
|
|
|
let writes = 0 |
|
let reads = 0 |
|
|
|
const r = new Readable() |
|
const w = new Writable({ |
|
write (data, cb) { |
|
t.is(data, 'write-' + (writes++)) |
|
setTimeout(cb, 0) |
|
} |
|
}) |
|
|
|
c.setReadable(r) |
|
c.setWritable(w) |
|
|
|
c.setReadable(r) |
|
c.setWritable(w) |
|
|
|
let flushed = true |
|
for (let i = 0; i < 20; i++) { |
|
flushed = c.write('write-' + i) |
|
} |
|
|
|
t.not(flushed) |
|
|
|
for (let i = 0; i < 20; i++) { |
|
r.push('read-' + i) |
|
} |
|
|
|
t.ok(Readable.isBackpressured(r)) |
|
|
|
c.on('data', function (data) { |
|
t.is(data, 'read-' + (reads++)) |
|
}) |
|
}) |
|
|
|
test('no write', function (t) { |
|
t.plan(13) |
|
|
|
const c = new Composer() |
|
|
|
let reads = 0 |
|
|
|
const r = new Readable() |
|
|
|
c.setReadable(r) |
|
c.setWritable(null) |
|
|
|
for (let i = 0; i < 10; i++) { |
|
r.push('read-' + i) |
|
} |
|
|
|
r.push(null) |
|
|
|
c.on('data', function (data) { |
|
t.is(data, 'read-' + (reads++)) |
|
}) |
|
|
|
c.on('end', function () { |
|
t.pass('end') |
|
}) |
|
|
|
c.on('finish', function () { |
|
t.pass('finish') |
|
}) |
|
|
|
c.on('close', function () { |
|
t.pass('closed') |
|
}) |
|
}) |
|
|
|
test('no read', function (t) { |
|
t.plan(12) |
|
|
|
const c = new Composer() |
|
|
|
let writes = 0 |
|
|
|
const w = new Writable({ |
|
write (data, cb) { |
|
t.is(data, 'write-' + (writes++)) |
|
setTimeout(cb, 0) |
|
} |
|
}) |
|
|
|
c.setReadable(null) |
|
c.setWritable(w) |
|
|
|
for (let i = 0; i < 10; i++) { |
|
c.write('write-' + i) |
|
} |
|
|
|
c.end() |
|
|
|
c.on('end', function () { |
|
t.pass('ended') |
|
}) |
|
|
|
c.on('close', function () { |
|
t.pass('closed') |
|
}) |
|
}) |
|
|
|
test('pipeline', function (t) { |
|
t.plan(22) |
|
|
|
const c = new Composer() |
|
|
|
c.setPipeline(new Transform(), new Transform()) |
|
|
|
let reads = 0 |
|
|
|
for (let i = 0; i < 20; i++) { |
|
c.write('hello-' + i) |
|
} |
|
|
|
c.on('finish', function () { |
|
t.pass('finish') |
|
}) |
|
|
|
c.end() |
|
|
|
c.on('data', function (data) { |
|
t.is(data, 'hello-' + (reads++)) |
|
}) |
|
|
|
c.on('end', function () { |
|
t.pass('end') |
|
}) |
|
}) |
|
|
|
test('pipeline, static', function (t) { |
|
t.plan(21) |
|
|
|
const c = Composer.pipeline(new Transform(), new Transform(), new Transform(), new Transform()) |
|
|
|
for (let i = 0; i < 20; i++) { |
|
c.write('hello-' + i) |
|
} |
|
|
|
c.end() |
|
|
|
let reads = 0 |
|
c.on('data', function (data) { |
|
t.is(data, 'hello-' + (reads++)) |
|
}) |
|
|
|
c.on('end', function () { |
|
t.pass('ended') |
|
}) |
|
}) |
|
|
|
test('pipeline destroy', function (t) { |
|
t.plan(4) |
|
|
|
const streams = [new Transform(), new Transform(), new Transform(), new Transform()] |
|
const c = Composer.pipeline(streams) |
|
|
|
for (let i = 0; i < 20; i++) { |
|
c.write('hello-' + i) |
|
} |
|
|
|
c.destroy() |
|
|
|
c.on('close', function () { |
|
for (const stream of streams) { |
|
t.ok(stream.destroying) |
|
} |
|
}) |
|
}) |
|
|
|
test('pipeline destroy inner', function (t) { |
|
t.plan(5) |
|
|
|
const streams = [new Transform(), new Transform(), new Transform(), new Transform()] |
|
const c = Composer.pipeline(streams) |
|
|
|
for (let i = 0; i < 20; i++) { |
|
c.write('hello-' + i) |
|
} |
|
|
|
streams[1].destroy() |
|
|
|
c.on('error', function () { |
|
t.pass('has error') |
|
}) |
|
|
|
c.on('close', function () { |
|
for (const stream of streams) { |
|
t.ok(stream.destroying) |
|
} |
|
}) |
|
}) |
|
|
|
test('pipeline w/ core streams', function (t) { |
|
t.plan(23) |
|
|
|
const coreStream = require('stream') |
|
|
|
const c = Composer.pipeline(new Transform({ |
|
transform (obj, cb) { |
|
setImmediate(function () { |
|
cb(null, obj) |
|
}) |
|
} |
|
}), new Transform({ |
|
transform (obj, cb) { |
|
setImmediate(function () { |
|
cb(null, obj) |
|
}) |
|
} |
|
})) |
|
let reads = 0 |
|
|
|
const data = [] |
|
for (let i = 0; i < 20; i++) { |
|
data.push({ msg: 'hello-' + i }) |
|
} |
|
|
|
c.on('finish', function () { |
|
t.absent(pipelineEnded, 'finish') |
|
}) |
|
|
|
c.on('end', function () { |
|
t.absent(pipelineEnded, 'ended') |
|
}) |
|
|
|
let pipelineEnded = false |
|
|
|
coreStream.pipeline([coreStream.Readable.from(data), c], function (err) { |
|
pipelineEnded = true |
|
t.ok(!err, 'pipeline ended') |
|
}) |
|
|
|
c.on('data', function (data) { |
|
t.alike(data, { msg: 'hello-' + reads++ }, 'got data') |
|
}) |
|
}) |
|
|