mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	Differential Revision: https://phabricator.services.mozilla.com/D46260 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			237 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var expect = require('chai').expect;
 | 
						|
var util = require('./util');
 | 
						|
 | 
						|
var Connection = require('../lib/protocol/connection').Connection;
 | 
						|
 | 
						|
var settings = {
 | 
						|
  SETTINGS_MAX_CONCURRENT_STREAMS: 100,
 | 
						|
  SETTINGS_INITIAL_WINDOW_SIZE: 100000
 | 
						|
};
 | 
						|
 | 
						|
var MAX_PRIORITY = Math.pow(2, 31) - 1;
 | 
						|
var MAX_RANDOM_PRIORITY = 10;
 | 
						|
 | 
						|
function randomPriority() {
 | 
						|
  return Math.floor(Math.random() * (MAX_RANDOM_PRIORITY + 1));
 | 
						|
}
 | 
						|
 | 
						|
function expectPriorityOrder(priorities) {
 | 
						|
  priorities.forEach(function(bucket, priority) {
 | 
						|
    bucket.forEach(function(stream) {
 | 
						|
      expect(stream._priority).to.be.equal(priority);
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
describe('connection.js', function() {
 | 
						|
  describe('Connection class', function() {
 | 
						|
    describe('method ._insert(stream)', function() {
 | 
						|
      it('should insert the stream in _streamPriorities in a place determined by stream._priority', function() {
 | 
						|
        var streams = [];
 | 
						|
        var connection = Object.create(Connection.prototype, { _streamPriorities: { value: streams }});
 | 
						|
        var streamCount = 10;
 | 
						|
 | 
						|
        for (var i = 0; i < streamCount; i++) {
 | 
						|
          var stream = { _priority: randomPriority() };
 | 
						|
          connection._insert(stream, stream._priority);
 | 
						|
          expect(connection._streamPriorities[stream._priority]).to.include(stream);
 | 
						|
        }
 | 
						|
 | 
						|
        expectPriorityOrder(connection._streamPriorities);
 | 
						|
      });
 | 
						|
    });
 | 
						|
    describe('method ._reprioritize(stream)', function() {
 | 
						|
      it('should eject and then insert the stream in _streamPriorities in a place determined by stream._priority', function() {
 | 
						|
        var streams = [];
 | 
						|
        var connection = Object.create(Connection.prototype, { _streamPriorities: { value: streams }});
 | 
						|
        var streamCount = 10;
 | 
						|
        var oldPriority, newPriority, stream;
 | 
						|
 | 
						|
        for (var i = 0; i < streamCount; i++) {
 | 
						|
          oldPriority = randomPriority();
 | 
						|
          while ((newPriority = randomPriority()) === oldPriority);
 | 
						|
          stream = { _priority: oldPriority };
 | 
						|
          connection._insert(stream, oldPriority);
 | 
						|
          connection._reprioritize(stream, newPriority);
 | 
						|
          stream._priority = newPriority;
 | 
						|
 | 
						|
          expect(connection._streamPriorities[newPriority]).to.include(stream);
 | 
						|
          expect(connection._streamPriorities[oldPriority] || []).to.not.include(stream);
 | 
						|
        }
 | 
						|
 | 
						|
        expectPriorityOrder(streams);
 | 
						|
      });
 | 
						|
    });
 | 
						|
    describe('invalid operation', function() {
 | 
						|
      describe('unsolicited ping answer', function() {
 | 
						|
        it('should be ignored', function() {
 | 
						|
          var connection = new Connection(util.log, 1, settings);
 | 
						|
 | 
						|
          connection._receivePing({
 | 
						|
            stream: 0,
 | 
						|
            type: 'PING',
 | 
						|
            flags: {
 | 
						|
              'PONG': true
 | 
						|
            },
 | 
						|
            data: Buffer.alloc(8)
 | 
						|
          });
 | 
						|
        });
 | 
						|
      });
 | 
						|
    });
 | 
						|
  });
 | 
						|
  describe('test scenario', function() {
 | 
						|
    var c, s;
 | 
						|
    beforeEach(function() {
 | 
						|
      c = new Connection(util.log.child({ role: 'client' }), 1, settings);
 | 
						|
      s = new Connection(util.log.child({ role: 'client' }), 2, settings);
 | 
						|
      c.pipe(s).pipe(c);
 | 
						|
    });
 | 
						|
 | 
						|
    describe('connection setup', function() {
 | 
						|
      it('should work as expected', function(done) {
 | 
						|
        setTimeout(function() {
 | 
						|
          // If there are no exception until this, then we're done
 | 
						|
          done();
 | 
						|
        }, 10);
 | 
						|
      });
 | 
						|
    });
 | 
						|
    describe('sending/receiving a request', function() {
 | 
						|
      it('should work as expected', function(done) {
 | 
						|
        // Request and response data
 | 
						|
        var request_headers = {
 | 
						|
          ':method': 'GET',
 | 
						|
          ':path': '/'
 | 
						|
        };
 | 
						|
        var request_data = Buffer.alloc(0);
 | 
						|
        var response_headers = {
 | 
						|
          ':status': '200'
 | 
						|
        };
 | 
						|
        var response_data = Buffer.from('12345678', 'hex');
 | 
						|
 | 
						|
        // Setting up server
 | 
						|
        s.on('stream', function(server_stream) {
 | 
						|
          server_stream.on('headers', function(headers) {
 | 
						|
            expect(headers).to.deep.equal(request_headers);
 | 
						|
            server_stream.headers(response_headers);
 | 
						|
            server_stream.end(response_data);
 | 
						|
          });
 | 
						|
        });
 | 
						|
 | 
						|
        // Sending request
 | 
						|
        var client_stream = c.createStream();
 | 
						|
        client_stream.headers(request_headers);
 | 
						|
        client_stream.end(request_data);
 | 
						|
 | 
						|
        // Waiting for answer
 | 
						|
        done = util.callNTimes(2, done);
 | 
						|
        client_stream.on('headers', function(headers) {
 | 
						|
          expect(headers).to.deep.equal(response_headers);
 | 
						|
          done();
 | 
						|
        });
 | 
						|
        client_stream.on('data', function(data) {
 | 
						|
          expect(data).to.deep.equal(response_data);
 | 
						|
          done();
 | 
						|
        });
 | 
						|
      });
 | 
						|
    });
 | 
						|
    describe('server push', function() {
 | 
						|
      it('should work as expected', function(done) {
 | 
						|
        var request_headers = { ':method': 'get', ':path': '/' };
 | 
						|
        var response_headers = { ':status': '200' };
 | 
						|
        var push_request_headers = { ':method': 'get', ':path': '/x' };
 | 
						|
        var push_response_headers = { ':status': '200' };
 | 
						|
        var response_content = Buffer.alloc(10);
 | 
						|
        var push_content = Buffer.alloc(10);
 | 
						|
 | 
						|
        done = util.callNTimes(5, done);
 | 
						|
 | 
						|
        s.on('stream', function(response) {
 | 
						|
          response.headers(response_headers);
 | 
						|
 | 
						|
          var pushed = response.promise(push_request_headers);
 | 
						|
          pushed.headers(push_response_headers);
 | 
						|
          pushed.end(push_content);
 | 
						|
 | 
						|
          response.end(response_content);
 | 
						|
        });
 | 
						|
 | 
						|
        var request = c.createStream();
 | 
						|
        request.headers(request_headers);
 | 
						|
        request.end();
 | 
						|
        request.on('headers', function(headers) {
 | 
						|
          expect(headers).to.deep.equal(response_headers);
 | 
						|
          done();
 | 
						|
        });
 | 
						|
        request.on('data', function(data) {
 | 
						|
          expect(data).to.deep.equal(response_content);
 | 
						|
          done();
 | 
						|
        });
 | 
						|
        request.on('promise', function(pushed, headers) {
 | 
						|
          expect(headers).to.deep.equal(push_request_headers);
 | 
						|
          pushed.on('headers', function(headers) {
 | 
						|
            expect(headers).to.deep.equal(response_headers);
 | 
						|
            done();
 | 
						|
          });
 | 
						|
          pushed.on('data', function(data) {
 | 
						|
            expect(data).to.deep.equal(push_content);
 | 
						|
            done();
 | 
						|
          });
 | 
						|
          pushed.on('end', done);
 | 
						|
        });
 | 
						|
      });
 | 
						|
    });
 | 
						|
    describe('ping from client', function() {
 | 
						|
      it('should work as expected', function(done) {
 | 
						|
        c.ping(function() {
 | 
						|
          done();
 | 
						|
        });
 | 
						|
      });
 | 
						|
    });
 | 
						|
    describe('ping from server', function() {
 | 
						|
      it('should work as expected', function(done) {
 | 
						|
        s.ping(function() {
 | 
						|
          done();
 | 
						|
        });
 | 
						|
      });
 | 
						|
    });
 | 
						|
    describe('creating two streams and then using them in reverse order', function() {
 | 
						|
      it('should not result in non-monotonous local ID ordering', function() {
 | 
						|
        var s1 = c.createStream();
 | 
						|
        var s2 = c.createStream();
 | 
						|
        s2.headers({ ':method': 'get', ':path': '/' });
 | 
						|
        s1.headers({ ':method': 'get', ':path': '/' });
 | 
						|
      });
 | 
						|
    });
 | 
						|
    describe('creating two promises and then using them in reverse order', function() {
 | 
						|
      it('should not result in non-monotonous local ID ordering', function(done) {
 | 
						|
        s.on('stream', function(response) {
 | 
						|
          response.headers({ ':status': '200' });
 | 
						|
 | 
						|
          var p1 = s.createStream();
 | 
						|
          var p2 = s.createStream();
 | 
						|
          response.promise(p2, { ':method': 'get', ':path': '/p2' });
 | 
						|
          response.promise(p1, { ':method': 'get', ':path': '/p1' });
 | 
						|
          p2.headers({ ':status': '200' });
 | 
						|
          p1.headers({ ':status': '200' });
 | 
						|
        });
 | 
						|
 | 
						|
        var request = c.createStream();
 | 
						|
        request.headers({ ':method': 'get', ':path': '/' });
 | 
						|
 | 
						|
        done = util.callNTimes(2, done);
 | 
						|
        request.on('promise', function() {
 | 
						|
          done();
 | 
						|
        });
 | 
						|
      });
 | 
						|
    });
 | 
						|
    describe('closing the connection on one end', function() {
 | 
						|
      it('should result in closed streams on both ends', function(done) {
 | 
						|
        done = util.callNTimes(2, done);
 | 
						|
        c.on('end', done);
 | 
						|
        s.on('end', done);
 | 
						|
 | 
						|
        c.close();
 | 
						|
      });
 | 
						|
    });
 | 
						|
  });
 | 
						|
});
 |