Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 var expect = require('chai').expect;
2 var util = require('./util');
4 var Connection = require('../lib/connection').Connection;
6 var settings = {
7 SETTINGS_MAX_CONCURRENT_STREAMS: 100,
8 SETTINGS_INITIAL_WINDOW_SIZE: 100000
9 };
11 var MAX_PRIORITY = Math.pow(2, 31) - 1;
12 var MAX_RANDOM_PRIORITY = 10;
14 function randomPriority() {
15 return Math.floor(Math.random() * (MAX_RANDOM_PRIORITY + 1));
16 }
18 function expectPriorityOrder(priorities) {
19 priorities.forEach(function(bucket, priority) {
20 bucket.forEach(function(stream) {
21 expect(stream._priority).to.be.equal(priority);
22 });
23 });
24 }
26 describe('connection.js', function() {
27 describe('Connection class', function() {
28 describe('method ._insert(stream)', function() {
29 it('should insert the stream in _streamPriorities in a place determined by stream._priority', function() {
30 var streams = [];
31 var connection = Object.create(Connection.prototype, { _streamPriorities: { value: streams }});
32 var streamCount = 10;
34 for (var i = 0; i < streamCount; i++) {
35 var stream = { _priority: randomPriority() };
36 connection._insert(stream, stream._priority);
37 expect(connection._streamPriorities[stream._priority]).to.include(stream);
38 }
40 expectPriorityOrder(connection._streamPriorities);
41 });
42 });
43 describe('method ._reprioritize(stream)', function() {
44 it('should eject and then insert the stream in _streamPriorities in a place determined by stream._priority', function() {
45 var streams = [];
46 var connection = Object.create(Connection.prototype, { _streamPriorities: { value: streams }});
47 var streamCount = 10;
48 var oldPriority, newPriority, stream;
50 for (var i = 0; i < streamCount; i++) {
51 oldPriority = randomPriority();
52 while ((newPriority = randomPriority()) === oldPriority);
53 stream = { _priority: oldPriority };
54 connection._insert(stream, oldPriority);
55 connection._reprioritize(stream, newPriority);
56 stream._priority = newPriority;
58 expect(connection._streamPriorities[newPriority]).to.include(stream);
59 expect(connection._streamPriorities[oldPriority] || []).to.not.include(stream);
60 }
62 expectPriorityOrder(streams);
63 });
64 });
65 describe('invalid operation', function() {
66 describe('unsolicited ping answer', function() {
67 it('should be ignored', function() {
68 var connection = new Connection(util.log, 1, settings);
70 connection._receivePing({
71 stream: 0,
72 type: 'PING',
73 flags: {
74 'PONG': true
75 },
76 data: new Buffer(8)
77 });
78 });
79 });
80 });
81 });
82 describe('test scenario', function() {
83 var c, s;
84 beforeEach(function() {
85 c = new Connection(util.log.child({ role: 'client' }), 1, settings);
86 s = new Connection(util.log.child({ role: 'client' }), 2, settings);
87 c.pipe(s).pipe(c);
88 });
90 describe('connection setup', function() {
91 it('should work as expected', function(done) {
92 setTimeout(function() {
93 // If there are no exception until this, then we're done
94 done();
95 }, 10);
96 });
97 });
98 describe('sending/receiving a request', function() {
99 it('should work as expected', function(done) {
100 // Request and response data
101 var request_headers = {
102 ':method': 'GET',
103 ':path': '/'
104 };
105 var request_data = new Buffer(0);
106 var response_headers = {
107 ':status': '200'
108 };
109 var response_data = new Buffer('12345678', 'hex');
111 // Setting up server
112 s.on('stream', function(server_stream) {
113 server_stream.on('headers', function(headers) {
114 expect(headers).to.deep.equal(request_headers);
115 server_stream.headers(response_headers);
116 server_stream.end(response_data);
117 });
118 });
120 // Sending request
121 var client_stream = c.createStream();
122 client_stream.headers(request_headers);
123 client_stream.end(request_data);
125 // Waiting for answer
126 done = util.callNTimes(2, done);
127 client_stream.on('headers', function(headers) {
128 expect(headers).to.deep.equal(response_headers);
129 done();
130 });
131 client_stream.on('readable', function() {
132 expect(client_stream.read()).to.deep.equal(response_data);
133 done();
134 });
135 });
136 });
137 describe('server push', function() {
138 it('should work as expected', function(done) {
139 var request_headers = { ':method': 'get', ':path': '/' };
140 var response_headers = { ':status': '200' };
141 var push_request_headers = { ':method': 'get', ':path': '/x' };
142 var push_response_headers = { ':status': '200' };
143 var response_content = new Buffer(10);
144 var push_content = new Buffer(10);
146 done = util.callNTimes(5, done);
148 s.on('stream', function(response) {
149 response.headers(response_headers);
151 var pushed = response.promise(push_request_headers);
152 pushed.headers(push_response_headers);
153 pushed.end(push_content);
155 response.end(response_content);
156 });
158 var request = c.createStream();
159 request.headers(request_headers);
160 request.end();
161 request.on('headers', function(headers) {
162 expect(headers).to.deep.equal(response_headers);
163 done();
164 });
165 request.on('readable', function() {
166 expect(request.read()).to.deep.equal(response_content);
167 done();
168 });
169 request.on('promise', function(pushed, headers) {
170 expect(headers).to.deep.equal(push_request_headers);
171 pushed.on('headers', function(headers) {
172 expect(headers).to.deep.equal(response_headers);
173 done();
174 });
175 pushed.on('readable', function() {
176 expect(pushed.read()).to.deep.equal(push_content);
177 done();
178 });
179 pushed.on('end', function() {
180 done();
181 });
182 });
183 });
184 });
185 describe('ping from client', function() {
186 it('should work as expected', function(done) {
187 c.ping(function() {
188 done();
189 });
190 });
191 });
192 describe('ping from server', function() {
193 it('should work as expected', function(done) {
194 s.ping(function() {
195 done();
196 });
197 });
198 });
199 describe('creating two streams and then using them in reverse order', function() {
200 it('should not result in non-monotonous local ID ordering', function() {
201 var s1 = c.createStream();
202 var s2 = c.createStream();
203 s2.headers({ ':method': 'get', ':path': '/' });
204 s1.headers({ ':method': 'get', ':path': '/' });
205 });
206 });
207 describe('creating two promises and then using them in reverse order', function() {
208 it('should not result in non-monotonous local ID ordering', function(done) {
209 s.on('stream', function(response) {
210 response.headers({ ':status': '200' });
212 var p1 = s.createStream();
213 var p2 = s.createStream();
214 response.promise(p2, { ':method': 'get', ':path': '/p2' });
215 response.promise(p1, { ':method': 'get', ':path': '/p1' });
216 p2.headers({ ':status': '200' });
217 p1.headers({ ':status': '200' });
218 });
220 var request = c.createStream();
221 request.headers({ ':method': 'get', ':path': '/' });
223 done = util.callNTimes(2, done);
224 request.on('promise', function() {
225 done();
226 });
227 });
228 });
229 describe('closing the connection on one end', function() {
230 it('should result in closed streams on both ends', function(done) {
231 done = util.callNTimes(2, done);
232 c.on('end', done);
233 s.on('end', done);
235 c.close();
236 });
237 });
238 });
239 });