123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- var expect = require('chai').expect;
- var util = require('./util');
- var framer = require('../lib/protocol/framer');
- var Serializer = framer.Serializer;
- var Deserializer = framer.Deserializer;
- var frame_types = {
- DATA: ['data'],
- HEADERS: ['priority_information', 'data'],
- PRIORITY: ['priority_information'],
- RST_STREAM: ['error'],
- SETTINGS: ['settings'],
- PUSH_PROMISE: ['promised_stream', 'data'],
- PING: ['data'],
- GOAWAY: ['last_stream', 'error'],
- WINDOW_UPDATE: ['window_size'],
- CONTINUATION: ['data'],
- ALTSVC: ['protocolID', 'host', 'port', 'origin', 'maxAge']
- };
- var test_frames = [{
- frame: {
- type: 'DATA',
- flags: { END_STREAM: false, RESERVED2: false, RESERVED4: false,
- PADDED: false },
- stream: 10,
- data: new Buffer('12345678', 'hex')
- },
- // length + type + flags + stream + content
- buffer: new Buffer('000004' + '00' + '00' + '0000000A' + '12345678', 'hex')
- }, {
- frame: {
- type: 'HEADERS',
- flags: { END_STREAM: false, RESERVED2: false, END_HEADERS: false,
- PADDED: false, RESERVED5: false, PRIORITY: false },
- stream: 15,
- data: new Buffer('12345678', 'hex')
- },
- buffer: new Buffer('000004' + '01' + '00' + '0000000F' + '12345678', 'hex')
- }, {
- frame: {
- type: 'HEADERS',
- flags: { END_STREAM: false, RESERVED2: false, END_HEADERS: false,
- PADDED: false, RESERVED5: false, PRIORITY: true },
- stream: 15,
- priorityDependency: 10,
- priorityWeight: 5,
- exclusiveDependency: false,
- data: new Buffer('12345678', 'hex')
- },
- buffer: new Buffer('000009' + '01' + '20' + '0000000F' + '0000000A' + '05' + '12345678', 'hex')
- }, {
- frame: {
- type: 'HEADERS',
- flags: { END_STREAM: false, RESERVED2: false, END_HEADERS: false,
- PADDED: false, RESERVED5: false, PRIORITY: true },
- stream: 15,
- priorityDependency: 10,
- priorityWeight: 5,
- exclusiveDependency: true,
- data: new Buffer('12345678', 'hex')
- },
- buffer: new Buffer('000009' + '01' + '20' + '0000000F' + '8000000A' + '05' + '12345678', 'hex')
- }, {
- frame: {
- type: 'PRIORITY',
- flags: { },
- stream: 10,
- priorityDependency: 9,
- priorityWeight: 5,
- exclusiveDependency: false
- },
- buffer: new Buffer('000005' + '02' + '00' + '0000000A' + '00000009' + '05', 'hex')
- }, {
- frame: {
- type: 'PRIORITY',
- flags: { },
- stream: 10,
- priorityDependency: 9,
- priorityWeight: 5,
- exclusiveDependency: true
- },
- buffer: new Buffer('000005' + '02' + '00' + '0000000A' + '80000009' + '05', 'hex')
- }, {
- frame: {
- type: 'RST_STREAM',
- flags: { },
- stream: 10,
- error: 'INTERNAL_ERROR'
- },
- buffer: new Buffer('000004' + '03' + '00' + '0000000A' + '00000002', 'hex')
- }, {
- frame: {
- type: 'SETTINGS',
- flags: { ACK: false },
- stream: 10,
- settings: {
- SETTINGS_HEADER_TABLE_SIZE: 0x12345678,
- SETTINGS_ENABLE_PUSH: true,
- SETTINGS_MAX_CONCURRENT_STREAMS: 0x01234567,
- SETTINGS_INITIAL_WINDOW_SIZE: 0x89ABCDEF,
- SETTINGS_MAX_FRAME_SIZE: 0x00010000
- }
- },
- buffer: new Buffer('00001E' + '04' + '00' + '0000000A' + '0001' + '12345678' +
- '0002' + '00000001' +
- '0003' + '01234567' +
- '0004' + '89ABCDEF' +
- '0005' + '00010000', 'hex')
- }, {
- frame: {
- type: 'PUSH_PROMISE',
- flags: { RESERVED1: false, RESERVED2: false, END_PUSH_PROMISE: false,
- PADDED: false },
- stream: 15,
- promised_stream: 3,
- data: new Buffer('12345678', 'hex')
- },
- buffer: new Buffer('000008' + '05' + '00' + '0000000F' + '00000003' + '12345678', 'hex')
- }, {
- frame: {
- type: 'PING',
- flags: { ACK: false },
- stream: 15,
- data: new Buffer('1234567887654321', 'hex')
- },
- buffer: new Buffer('000008' + '06' + '00' + '0000000F' + '1234567887654321', 'hex')
- }, {
- frame: {
- type: 'GOAWAY',
- flags: { },
- stream: 10,
- last_stream: 0x12345678,
- error: 'PROTOCOL_ERROR'
- },
- buffer: new Buffer('000008' + '07' + '00' + '0000000A' + '12345678' + '00000001', 'hex')
- }, {
- frame: {
- type: 'WINDOW_UPDATE',
- flags: { },
- stream: 10,
- window_size: 0x12345678
- },
- buffer: new Buffer('000004' + '08' + '00' + '0000000A' + '12345678', 'hex')
- }, {
- frame: {
- type: 'CONTINUATION',
- flags: { RESERVED1: false, RESERVED2: false, END_HEADERS: true },
- stream: 10,
- data: new Buffer('12345678', 'hex')
- },
- // length + type + flags + stream + content
- buffer: new Buffer('000004' + '09' + '04' + '0000000A' + '12345678', 'hex')
- }, {
- frame: {
- type: 'ALTSVC',
- flags: { },
- stream: 0,
- maxAge: 31536000,
- port: 4443,
- protocolID: "h2",
- host: "altsvc.example.com",
- origin: ""
- },
- buffer: new Buffer(new Buffer('00002B' + '0A' + '00' + '00000000' + '0000', 'hex') + new Buffer('h2="altsvc.example.com:4443"; ma=31536000', 'ascii'))
- }, {
- frame: {
- type: 'ALTSVC',
- flags: { },
- stream: 0,
- maxAge: 31536000,
- port: 4443,
- protocolID: "h2",
- host: "altsvc.example.com",
- origin: "https://onlyme.example.com"
- },
- buffer: new Buffer(new Buffer('000045' + '0A' + '00' + '00000000' + '001A', 'hex') + new Buffer('https://onlyme.example.comh2="altsvc.example.com:4443"; ma=31536000', 'ascii'))
- }, {
- frame: {
- type: 'BLOCKED',
- flags: { },
- stream: 10
- },
- buffer: new Buffer('000000' + '0B' + '00' + '0000000A', 'hex')
- }];
- var deserializer_test_frames = test_frames.slice(0);
- var padded_test_frames = [{
- frame: {
- type: 'DATA',
- flags: { END_STREAM: false, RESERVED2: false, RESERVED4: false,
- PADDED: true },
- stream: 10,
- data: new Buffer('12345678', 'hex')
- },
- // length + type + flags + stream + pad length + content + padding
- buffer: new Buffer('00000B' + '00' + '08' + '0000000A' + '06' + '12345678' + '000000000000', 'hex')
- }, {
- frame: {
- type: 'HEADERS',
- flags: { END_STREAM: false, RESERVED2: false, END_HEADERS: false,
- PADDED: true, RESERVED5: false, PRIORITY: false },
- stream: 15,
- data: new Buffer('12345678', 'hex')
- },
- // length + type + flags + stream + pad length + data + padding
- buffer: new Buffer('00000B' + '01' + '08' + '0000000F' + '06' + '12345678' + '000000000000', 'hex')
- }, {
- frame: {
- type: 'HEADERS',
- flags: { END_STREAM: false, RESERVED2: false, END_HEADERS: false,
- PADDED: true, RESERVED5: false, PRIORITY: true },
- stream: 15,
- priorityDependency: 10,
- priorityWeight: 5,
- exclusiveDependency: false,
- data: new Buffer('12345678', 'hex')
- },
- // length + type + flags + stream + pad length + priority dependency + priority weight + data + padding
- buffer: new Buffer('000010' + '01' + '28' + '0000000F' + '06' + '0000000A' + '05' + '12345678' + '000000000000', 'hex')
- }, {
- frame: {
- type: 'HEADERS',
- flags: { END_STREAM: false, RESERVED2: false, END_HEADERS: false,
- PADDED: true, RESERVED5: false, PRIORITY: true },
- stream: 15,
- priorityDependency: 10,
- priorityWeight: 5,
- exclusiveDependency: true,
- data: new Buffer('12345678', 'hex')
- },
- // length + type + flags + stream + pad length + priority dependency + priority weight + data + padding
- buffer: new Buffer('000010' + '01' + '28' + '0000000F' + '06' + '8000000A' + '05' + '12345678' + '000000000000', 'hex')
- }, {
- frame: {
- type: 'PUSH_PROMISE',
- flags: { RESERVED1: false, RESERVED2: false, END_PUSH_PROMISE: false,
- PADDED: true },
- stream: 15,
- promised_stream: 3,
- data: new Buffer('12345678', 'hex')
- },
- // length + type + flags + stream + pad length + promised stream + data + padding
- buffer: new Buffer('00000F' + '05' + '08' + '0000000F' + '06' + '00000003' + '12345678' + '000000000000', 'hex')
- }];
- for (var idx = 0; idx < padded_test_frames.length; idx++) {
- deserializer_test_frames.push(padded_test_frames[idx]);
- }
- describe('framer.js', function() {
- describe('Serializer', function() {
- describe('static method .commonHeader({ type, flags, stream }, buffer_array)', function() {
- it('should add the appropriate 9 byte header buffer in front of the others', function() {
- for (var i = 0; i < test_frames.length; i++) {
- var test = test_frames[i];
- var buffers = [test.buffer.slice(9)];
- var header_buffer = test.buffer.slice(0,9);
- Serializer.commonHeader(test.frame, buffers);
- expect(buffers[0]).to.deep.equal(header_buffer);
- }
- });
- });
- Object.keys(frame_types).forEach(function(type) {
- var tests = test_frames.filter(function(test) { return test.frame.type === type; });
- var frame_shape = '{ ' + frame_types[type].join(', ') + ' }';
- describe('static method .' + type + '(' + frame_shape + ', buffer_array)', function() {
- it('should push buffers to the array that make up a ' + type + ' type payload', function() {
- for (var i = 0; i < tests.length; i++) {
- var test = tests[i];
- var buffers = [];
- Serializer[type](test.frame, buffers);
- expect(util.concat(buffers)).to.deep.equal(test.buffer.slice(9));
- }
- });
- });
- });
- describe('transform stream', function() {
- it('should transform frame objects to appropriate buffers', function() {
- var stream = new Serializer(util.log);
- for (var i = 0; i < test_frames.length; i++) {
- var test = test_frames[i];
- stream.write(test.frame);
- var chunk, buffer = new Buffer(0);
- while (chunk = stream.read()) {
- buffer = util.concat([buffer, chunk]);
- }
- expect(buffer).to.be.deep.equal(test.buffer);
- }
- });
- });
- });
- describe('Deserializer', function() {
- describe('static method .commonHeader(header_buffer, frame)', function() {
- it('should augment the frame object with these properties: { type, flags, stream })', function() {
- for (var i = 0; i < deserializer_test_frames.length; i++) {
- var test = deserializer_test_frames[i], frame = {};
- Deserializer.commonHeader(test.buffer.slice(0,9), frame);
- expect(frame).to.deep.equal({
- type: test.frame.type,
- flags: test.frame.flags,
- stream: test.frame.stream
- });
- }
- });
- });
- Object.keys(frame_types).forEach(function(type) {
- var tests = deserializer_test_frames.filter(function(test) { return test.frame.type === type; });
- var frame_shape = '{ ' + frame_types[type].join(', ') + ' }';
- describe('static method .' + type + '(payload_buffer, frame)', function() {
- it('should augment the frame object with these properties: ' + frame_shape, function() {
- for (var i = 0; i < tests.length; i++) {
- var test = tests[i];
- var frame = {
- type: test.frame.type,
- flags: test.frame.flags,
- stream: test.frame.stream
- };
- Deserializer[type](test.buffer.slice(9), frame);
- expect(frame).to.deep.equal(test.frame);
- }
- });
- });
- });
- describe('transform stream', function() {
- it('should transform buffers to appropriate frame object', function() {
- var stream = new Deserializer(util.log);
- var shuffled = util.shuffleBuffers(deserializer_test_frames.map(function(test) { return test.buffer; }));
- shuffled.forEach(stream.write.bind(stream));
- for (var j = 0; j < deserializer_test_frames.length; j++) {
- expect(stream.read()).to.be.deep.equal(deserializer_test_frames[j].frame);
- }
- });
- });
- });
- describe('bunyan formatter', function() {
- describe('`frame`', function() {
- var format = framer.serializers.frame;
- it('should assign a unique ID to each frame', function() {
- var frame1 = { type: 'DATA', data: new Buffer(10) };
- var frame2 = { type: 'PRIORITY', priority: 1 };
- expect(format(frame1).id).to.be.equal(format(frame1));
- expect(format(frame2).id).to.be.equal(format(frame2));
- expect(format(frame1)).to.not.be.equal(format(frame2));
- });
- });
- });
- });
|