testing/xpcshell/node-http2/node_modules/http2-protocol/test/flow.js

Thu, 15 Jan 2015 21:13:52 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:13:52 +0100
branch
TOR_BUG_9701
changeset 12
7540298fafa1
permissions
-rw-r--r--

Remove forgotten relic of ABI crash risk averse overloaded method change.

michael@0 1 var expect = require('chai').expect;
michael@0 2 var util = require('./util');
michael@0 3
michael@0 4 var Flow = require('../lib/flow').Flow;
michael@0 5
michael@0 6 function createFlow(log) {
michael@0 7 var flowControlId = util.random(10, 100);
michael@0 8 var flow = new Flow(flowControlId);
michael@0 9 flow._log = util.log.child(log || {});
michael@0 10 return flow;
michael@0 11 }
michael@0 12
michael@0 13 describe('flow.js', function() {
michael@0 14 describe('Flow class', function() {
michael@0 15 var flow;
michael@0 16 beforeEach(function() {
michael@0 17 flow = createFlow();
michael@0 18 });
michael@0 19
michael@0 20 describe('._receive(frame, callback) method', function() {
michael@0 21 it('is called when there\'s a frame in the input buffer to be consumed', function(done) {
michael@0 22 var frame = { type: 'PRIORITY', flags: {}, priority: 1 };
michael@0 23 flow._receive = function _receive(receivedFrame, callback) {
michael@0 24 expect(receivedFrame).to.equal(frame);
michael@0 25 callback();
michael@0 26 };
michael@0 27 flow.write(frame, done);
michael@0 28 });
michael@0 29 it('has to be overridden by the child class, otherwise it throws', function() {
michael@0 30 expect(flow._receive.bind(flow)).to.throw(Error);
michael@0 31 });
michael@0 32 });
michael@0 33 describe('._send() method', function() {
michael@0 34 it('is called when the output buffer should be filled with more frames and the flow' +
michael@0 35 'control queue is empty', function() {
michael@0 36 var sendCalled = 0;
michael@0 37 var notFlowControlledFrame = { type: 'PRIORITY', flags: {}, priority: 1 };
michael@0 38 flow._send = function _send() {
michael@0 39 sendCalled += 1;
michael@0 40 this.push(notFlowControlledFrame);
michael@0 41 };
michael@0 42 expect(flow.read()).to.equal(notFlowControlledFrame);
michael@0 43
michael@0 44 flow._window = 0;
michael@0 45 flow._queue.push({ type: 'DATA', flags: {}, data: { length: 1 } });
michael@0 46 expect(flow.read()).to.equal(null);
michael@0 47
michael@0 48 expect(sendCalled).to.equal(1);
michael@0 49 });
michael@0 50 it('has to be overridden by the child class, otherwise it throws', function() {
michael@0 51 expect(flow._send.bind(flow)).to.throw(Error);
michael@0 52 });
michael@0 53 });
michael@0 54 describe('._increaseWindow(size) method', function() {
michael@0 55 it('should increase `this._window` by `size`', function() {
michael@0 56 flow._send = util.noop;
michael@0 57 flow._window = 0;
michael@0 58
michael@0 59 var increase1 = util.random(0,100);
michael@0 60 var increase2 = util.random(0,100);
michael@0 61 flow._increaseWindow(increase1);
michael@0 62 flow._increaseWindow(increase2);
michael@0 63 expect(flow._window).to.equal(increase1 + increase2);
michael@0 64
michael@0 65 flow._increaseWindow(Infinity);
michael@0 66 expect(flow._window).to.equal(Infinity);
michael@0 67 });
michael@0 68 it('should emit error when increasing with a finite `size` when `_window` is infinite', function() {
michael@0 69 flow._send = util.noop;
michael@0 70 flow._increaseWindow(Infinity);
michael@0 71 var increase = util.random(1,100);
michael@0 72
michael@0 73 expect(flow._increaseWindow.bind(flow, increase)).to.throw('Uncaught, unspecified "error" event.');
michael@0 74 });
michael@0 75 it('should emit error when `_window` grows over the window limit', function() {
michael@0 76 var WINDOW_SIZE_LIMIT = Math.pow(2, 31) - 1;
michael@0 77 flow._send = util.noop;
michael@0 78 flow._window = 0;
michael@0 79
michael@0 80 flow._increaseWindow(WINDOW_SIZE_LIMIT);
michael@0 81 expect(flow._increaseWindow.bind(flow, 1)).to.throw('Uncaught, unspecified "error" event.');
michael@0 82
michael@0 83 });
michael@0 84 });
michael@0 85 describe('.read() method', function() {
michael@0 86 describe('when the flow control queue is not empty', function() {
michael@0 87 it('should return the first item in the queue if the window is enough', function() {
michael@0 88 var priorityFrame = { type: 'PRIORITY', flags: {}, priority: 1 };
michael@0 89 var dataFrame = { type: 'DATA', flags: {}, data: { length: 10 } };
michael@0 90 flow._send = util.noop;
michael@0 91 flow._window = 10;
michael@0 92 flow._queue = [priorityFrame, dataFrame];
michael@0 93
michael@0 94 expect(flow.read()).to.equal(priorityFrame);
michael@0 95 expect(flow.read()).to.equal(dataFrame);
michael@0 96 });
michael@0 97 it('should also split DATA frames when needed', function() {
michael@0 98 var buffer = new Buffer(10);
michael@0 99 var dataFrame = { type: 'DATA', flags: {}, stream: util.random(0, 100), data: buffer };
michael@0 100 flow._send = util.noop;
michael@0 101 flow._window = 5;
michael@0 102 flow._queue = [dataFrame];
michael@0 103
michael@0 104 var expectedFragment = { flags: {}, type: 'DATA', stream: dataFrame.stream, data: buffer.slice(0,5) };
michael@0 105 expect(flow.read()).to.deep.equal(expectedFragment);
michael@0 106 expect(dataFrame.data).to.deep.equal(buffer.slice(5));
michael@0 107 });
michael@0 108 });
michael@0 109 });
michael@0 110 describe('.push(frame) method', function() {
michael@0 111 it('should push `frame` into the output queue or the flow control queue', function() {
michael@0 112 var priorityFrame = { type: 'PRIORITY', flags: {}, priority: 1 };
michael@0 113 var dataFrame = { type: 'DATA', flags: {}, data: { length: 10 } };
michael@0 114 flow._window = 10;
michael@0 115
michael@0 116 flow.push(dataFrame); // output queue
michael@0 117 flow.push(dataFrame); // flow control queue, because of depleted window
michael@0 118 flow.push(priorityFrame); // flow control queue, because it's not empty
michael@0 119
michael@0 120 expect(flow.read()).to.be.equal(dataFrame);
michael@0 121 expect(flow._queue[0]).to.be.equal(dataFrame);
michael@0 122 expect(flow._queue[1]).to.be.equal(priorityFrame);
michael@0 123 });
michael@0 124 });
michael@0 125 describe('.write() method', function() {
michael@0 126 it('call with a DATA frame should trigger sending WINDOW_UPDATE if remote flow control is not' +
michael@0 127 'disabled', function(done) {
michael@0 128 flow._window = 100;
michael@0 129 flow._send = util.noop;
michael@0 130 flow._receive = function(frame, callback) {
michael@0 131 callback();
michael@0 132 };
michael@0 133
michael@0 134 var buffer = new Buffer(util.random(10, 100));
michael@0 135 flow.write({ type: 'DATA', flags: {}, data: buffer });
michael@0 136 flow.once('readable', function() {
michael@0 137 expect(flow.read()).to.be.deep.equal({
michael@0 138 type: 'WINDOW_UPDATE',
michael@0 139 flags: {},
michael@0 140 stream: flow._flowControlId,
michael@0 141 window_size: buffer.length
michael@0 142 });
michael@0 143 done();
michael@0 144 });
michael@0 145 });
michael@0 146 });
michael@0 147 });
michael@0 148 describe('test scenario', function() {
michael@0 149 var flow1, flow2;
michael@0 150 beforeEach(function() {
michael@0 151 flow1 = createFlow({ flow: 1 });
michael@0 152 flow2 = createFlow({ flow: 2 });
michael@0 153 flow1._flowControlId = flow2._flowControlId;
michael@0 154 flow1._send = flow2._send = util.noop;
michael@0 155 flow1._receive = flow2._receive = function(frame, callback) { callback(); };
michael@0 156 });
michael@0 157
michael@0 158 describe('sending a large data stream', function() {
michael@0 159 it('should work as expected', function(done) {
michael@0 160 // Sender side
michael@0 161 var frameNumber = util.random(5, 8);
michael@0 162 var input = [];
michael@0 163 flow1._send = function _send() {
michael@0 164 if (input.length >= frameNumber) {
michael@0 165 this.push({ type: 'DATA', flags: { END_STREAM: true }, data: new Buffer(0) });
michael@0 166 this.push(null);
michael@0 167 } else {
michael@0 168 var buffer = new Buffer(util.random(1000, 100000));
michael@0 169 input.push(buffer);
michael@0 170 this.push({ type: 'DATA', flags: {}, data: buffer });
michael@0 171 }
michael@0 172 };
michael@0 173
michael@0 174 // Receiver side
michael@0 175 var output = [];
michael@0 176 flow2._receive = function _receive(frame, callback) {
michael@0 177 if (frame.type === 'DATA') {
michael@0 178 output.push(frame.data);
michael@0 179 }
michael@0 180 if (frame.flags.END_STREAM) {
michael@0 181 this.emit('end_stream');
michael@0 182 }
michael@0 183 callback();
michael@0 184 };
michael@0 185
michael@0 186 // Checking results
michael@0 187 flow2.on('end_stream', function() {
michael@0 188 input = util.concat(input);
michael@0 189 output = util.concat(output);
michael@0 190
michael@0 191 expect(input).to.deep.equal(output);
michael@0 192
michael@0 193 done();
michael@0 194 });
michael@0 195
michael@0 196 // Start piping
michael@0 197 flow1.pipe(flow2).pipe(flow1);
michael@0 198 });
michael@0 199 });
michael@0 200 });
michael@0 201 });

mercurial