summaryrefslogtreecommitdiffstats
path: root/testing/xpcshell/node-http2/test/connection.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--testing/xpcshell/node-http2/test/connection.js237
1 files changed, 237 insertions, 0 deletions
diff --git a/testing/xpcshell/node-http2/test/connection.js b/testing/xpcshell/node-http2/test/connection.js
new file mode 100644
index 0000000000..21785d620a
--- /dev/null
+++ b/testing/xpcshell/node-http2/test/connection.js
@@ -0,0 +1,237 @@
+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();
+ });
+ });
+ });
+});