/** * Module dependencies. */ var assert = require('assert'); var Parser = require('../'); var Transform = require('stream').Transform; // for node v0.6.x-v0.8.x support if (!Transform) Transform = require('readable-stream/transform'); describe('Transform stream', function () { it('should have the `_bytes()` function', function () { var t = new Transform(); Parser(t); assert.equal('function', typeof t._bytes); }); it('should have the `_skipBytes()` function', function () { var t = new Transform(); Parser(t); assert.equal('function', typeof t._skipBytes); }); it('should have the `_passthrough()` function', function () { var t = new Transform(); Parser(t); assert.equal('function', typeof t._passthrough); }); it('should read 2 bytes, pass through 2 bytes', function (done) { var t = new Transform(); Parser(t); var gotBytes = false; var gotPassthrough = false; var gotData = false; // read 2 bytes t._bytes(2, read); function read (chunk, output) { assert.equal(2, chunk.length); assert.equal(0, chunk[0]); assert.equal(1, chunk[1]); gotBytes = true; t._passthrough(2, passthrough); } function passthrough (output) { gotPassthrough = true; } t.on('data', function (data) { assert.equal(2, data.length); assert.equal(2, data[0]); assert.equal(3, data[1]); gotData = true; }); t.on('end', function () { assert(gotBytes); assert(gotPassthrough); assert(gotData); done(); }); t.end(new Buffer([ 0, 1, 2, 3 ])); }); it('should allow you to pass through Infinity bytes', function (done) { var t = new Transform(); Parser(t); t._passthrough(Infinity); var out = []; t.on('data', function (data) { out.push(data); }); t.on('end', function () { assert.equal('hello world', Buffer.concat(out).toString()); done(); }); t.end('hello world'); }); it('should *not* allow you to buffer Infinity bytes', function () { // buffering to Infinity would just be silly... var t = new Transform(); Parser(t); assert.throws(function () { t._bytes(Infinity); }); }); it('should not cause stack overflow', function (done) { // this one does an admirable amount of CPU work... this.test.slow(500); this.test.timeout(1000); var t = new Transform(); Parser(t); var bytes = 65536; t._bytes(1, read); function read() { // Any downstream pipe consumer (writable) which doesn't do any async actions. // e.g. console.log, or simply capturing data into an in-memory data-structure. if (--bytes) { t._bytes(1, read); } else { done(); } } var b = new Buffer(bytes); b.fill('h'); t.end(b); }); describe('async', function () { it('should accept a callback function for `_passthrough()`', function (done) { var t = new Transform(); var data = 'test', _data; Parser(t); t._passthrough(data.length, function (output, fn) { setTimeout(fn, 25); }); t.on('data', function (data) { _data = data; }); t.on('end', function () { assert.equal(data, _data); done(); }); t.end(data); t.resume(); }); it('should accept a callback function for `_bytes()`', function (done) { var t = new Transform(); var data = 'test'; Parser(t); t._bytes(data.length, function (chunk, output, fn) { setTimeout(fn, 25); }); t.on('end', function () { done(); }); t.end(data); t.resume(); }); it('should work switching between async and sync callbacks', function (done) { var firstCalled, secondCalled, thirdCalled; // create a 6 byte Buffer. The first 4 will be the int // `1337`. The last 2 will be whatever... var val = 1337; var buf = new Buffer(6); buf.writeUInt32LE(val, 0); var t = new Transform(); Parser(t); // first read 4 bytes, with an async callback function first (chunk, output, fn) { firstCalled = true; assert.equal(chunk.length, 4); assert.equal(val, chunk.readUInt32LE(0)); t._bytes(1, second); setTimeout(fn, 10); } // second read 1 byte, sync callback function second (chunk) { secondCalled = true; assert.equal(chunk.length, 1); t._bytes(1, third); } // third read 1 byte, async callback function third (chunk, output, fn) { thirdCalled = true; assert.equal(chunk.length, 1); setTimeout(fn, 10); } t.on('finish', function () { assert(firstCalled); assert(secondCalled); assert(thirdCalled); done(); }); t._bytes(4, first); t.write(buf); t.end(); }); }); });