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 compressor = require('../lib/compressor');
5 var HeaderTable = compressor.HeaderTable;
6 var HuffmanTable = compressor.HuffmanTable;
7 var HeaderSetCompressor = compressor.HeaderSetCompressor;
8 var HeaderSetDecompressor = compressor.HeaderSetDecompressor;
9 var Compressor = compressor.Compressor;
10 var Decompressor = compressor.Decompressor;
12 var test_integers = [{
13 N: 5,
14 I: 10,
15 buffer: new Buffer([10])
16 }, {
17 N: 0,
18 I: 10,
19 buffer: new Buffer([10])
20 }, {
21 N: 5,
22 I: 1337,
23 buffer: new Buffer([31, 128 + 26, 10])
24 }, {
25 N: 0,
26 I: 1337,
27 buffer: new Buffer([128 + 57, 10])
28 }];
30 var test_strings = [{
31 string: 'www.foo.com',
32 buffer: new Buffer('88db6d898b5a44b74f', 'hex')
33 }, {
34 string: 'éáűőúöüó€',
35 buffer: new Buffer('13C3A9C3A1C5B1C591C3BAC3B6C3BCC3B3E282AC', 'hex')
36 }];
38 test_huffman_request = {
39 'GET': 'f77778ff',
40 'http': 'ce3177',
41 '/': '0f',
42 'www.foo.com': 'db6d898b5a44b74f',
43 'https': 'ce31743f',
44 'www.bar.com': 'db6d897a1e44b74f',
45 'no-cache': '63654a1398ff',
46 '/custom-path.css': '04eb08b7495c88e644c21f',
47 'custom-key': '4eb08b749790fa7f',
48 'custom-value': '4eb08b74979a17a8ff'
49 };
51 test_huffman_response = {
52 '302': '98a7',
53 'private': '73d5cd111f',
54 'Mon, 21 OCt 2013 20:13:21 GMT': 'ef6b3a7a0e6e8fa7647a0e534dd072fb0d37b0e6e8f777f8ff',
55 ': https://www.bar.com': 'f6746718ba1ec00db6d897a1e44b74',
56 '200': '394b',
57 'Mon, 21 OCt 2013 20:13:22 GMT': 'ef6b3a7a0e6e8fa7647a0e534dd072fb0d37b0e7e8f777f8ff',
58 'https://www.bar.com': 'ce31743d801b6db12f43c896e9',
59 'gzip': 'cbd54e',
60 'foo=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
61 AAAAAAAAAAAAAAAAAAAAAAAAAALASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKHQWOEIUAL\
62 QWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKH\
63 QWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEO\
64 IUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOP\
65 IUAXQWEOIUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234ZZZZZZZZZZ\
66 ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ1234 m\
67 ax-age=3600; version=1': 'c5adb77efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7\
68 efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfb\
69 f7efdfbf7efdfbf7efdfbfe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bf\
70 f7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb7\
71 77e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf\
72 5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e3\
73 7fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f3\
74 31e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8d\
75 ffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe\
76 3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf\
77 4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f\
78 1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69ffcff3fcff3\
79 fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcf\
80 f3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3f\
81 cff3fcff3fcff3fcff3fcff3fcff3fcff0c79a7e8d11e72a321b66a4a5eae8e62f82\
82 9acb4d',
83 'foo=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\
84 ZZZZZZZZZZZZZZZZZZZZZZZZZZLASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKHQWOEIUAL\
85 QWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKH\
86 QWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEO\
87 IUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOP\
88 IUAXQWEOIUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234AAAAAAAAAA\
89 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1234 m\
90 ax-age=3600; version=1': 'c5adb7fcff3fcff3fcff3fcff3fcff3fcff3fcff3f\
91 cff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff\
92 3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fc\
93 ff3fcff3e5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f\
94 8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fe\
95 fe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5d\
96 df4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c\
97 3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7\
98 e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fd\
99 bf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeef\
100 a7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6\
101 fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e3\
102 7fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69f7efdfbf7efdfbf7efdfbf7ef\
103 dfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7\
104 efdfbf7efdfbf7efdfbf7efdfbf7efdfbcc79a7e8d11e72a321b66a4a5eae8e62f82\
105 9acb4d'
106 };
108 var test_headers = [{
109 header: {
110 name: 1,
111 value: 'GET',
112 index: true
113 },
114 buffer: new Buffer('02' + '03474554', 'hex')
115 }, {
116 header: {
117 name: 6,
118 value: 'http',
119 index: true
120 },
121 buffer: new Buffer('07' + '83ce3177', 'hex')
122 }, {
123 header: {
124 name: 5,
125 value: '/',
126 index: true
127 },
128 buffer: new Buffer('06' + '012f', 'hex')
129 }, {
130 header: {
131 name: 3,
132 value: 'www.foo.com',
133 index: true
134 },
135 buffer: new Buffer('04' + '88db6d898b5a44b74f', 'hex')
136 }, {
137 header: {
138 name: 2,
139 value: 'https',
140 index: true
141 },
142 buffer: new Buffer('03' + '84ce31743f', 'hex')
143 }, {
144 header: {
145 name: 1,
146 value: 'www.bar.com',
147 index: true
148 },
149 buffer: new Buffer('02' + '88db6d897a1e44b74f', 'hex')
150 }, {
151 header: {
152 name: 28,
153 value: 'no-cache',
154 index: true
155 },
156 buffer: new Buffer('1d' + '8663654a1398ff', 'hex')
157 }, {
158 header: {
159 name: 3,
160 value: 3,
161 index: false
162 },
163 buffer: new Buffer('84', 'hex')
164 }, {
165 header: {
166 name: 5,
167 value: 5,
168 index: false
169 },
170 buffer: new Buffer('86', 'hex')
171 }, {
172 header: {
173 name: 4,
174 value: '/custom-path.css',
175 index: true
176 },
177 buffer: new Buffer('05' + '8b04eb08b7495c88e644c21f', 'hex')
178 }, {
179 header: {
180 name: 'custom-key',
181 value: 'custom-value',
182 index: true
183 },
184 buffer: new Buffer('00' + '884eb08b749790fa7f' + '894eb08b74979a17a8ff', 'hex')
185 }, {
186 header: {
187 name: 2,
188 value: 2,
189 index: false
190 },
191 buffer: new Buffer('83', 'hex')
192 }, {
193 header: {
194 name: 6,
195 value: 6,
196 index: false
197 },
198 buffer: new Buffer('87', 'hex')
199 }, {
200 header: {
201 name: -1,
202 value: -1,
203 index: true
204 },
205 buffer: new Buffer('8080', 'hex')
206 }];
208 var test_header_sets = [{
209 headers: {
210 ':method': 'GET',
211 ':scheme': 'http',
212 ':path': '/',
213 ':authority': 'www.foo.com'
214 },
215 buffer: util.concat(test_headers.slice(0, 4).map(function(test) { return test.buffer; }))
216 }, {
217 headers: {
218 ':method': 'GET',
219 ':scheme': 'https',
220 ':path': '/',
221 ':authority': 'www.bar.com',
222 'cache-control': 'no-cache'
223 },
224 buffer: util.concat(test_headers.slice(4, 9).map(function(test) { return test.buffer; }))
225 }, {
226 headers: {
227 ':method': 'GET',
228 ':scheme': 'https',
229 ':path': '/custom-path.css',
230 ':authority': 'www.bar.com',
231 'custom-key': 'custom-value'
232 },
233 buffer: util.concat(test_headers.slice(9, 13).map(function(test) { return test.buffer; }))
234 }, {
235 headers: {
236 ':method': 'GET',
237 ':scheme': 'https',
238 ':path': '/custom-path.css',
239 ':authority': ['www.foo.com', 'www.bar.com'],
240 'custom-key': 'custom-value'
241 },
242 buffer: test_headers[3].buffer
243 }, {
244 headers: {},
245 buffer: test_headers[13].buffer
246 }, {
247 headers: {
248 ':status': '200',
249 'user-agent': 'my-user-agent',
250 'cookie': 'first; second; third; third; fourth',
251 'multiple': ['first', 'second', 'third', 'third; fourth'],
252 'verylong': (new Buffer(9000)).toString('hex')
253 }
254 }];
256 describe('compressor.js', function() {
257 describe('HeaderTable', function() {
258 });
260 describe('HuffmanTable', function() {
261 describe('method encode(buffer)', function() {
262 it('should return the Huffman encoded version of the input buffer', function() {
263 var table = HuffmanTable.huffmanTable;
264 for (var decoded in test_huffman_request) {
265 var encoded = test_huffman_request[decoded];
266 expect(table.encode(new Buffer(decoded)).toString('hex')).to.equal(encoded);
267 }
268 table = HuffmanTable.huffmanTable;
269 for (decoded in test_huffman_response) {
270 encoded = test_huffman_response[decoded];
271 expect(table.encode(new Buffer(decoded)).toString('hex')).to.equal(encoded);
272 }
273 });
274 })
275 describe('method decode(buffer)', function() {
276 it('should return the Huffman decoded version of the input buffer', function() {
277 var table = HuffmanTable.huffmanTable;
278 for (var decoded in test_huffman_request) {
279 var encoded = test_huffman_request[decoded];
280 expect(table.decode(new Buffer(encoded, 'hex')).toString()).to.equal(decoded)
281 }
282 table = HuffmanTable.huffmanTable;
283 for (decoded in test_huffman_response) {
284 encoded = test_huffman_response[decoded];
285 expect(table.decode(new Buffer(encoded, 'hex')).toString()).to.equal(decoded)
286 }
287 });
288 })
289 });
291 describe('HeaderSetCompressor', function() {
292 describe('static method .integer(I, N)', function() {
293 it('should return an array of buffers that represent the N-prefix coded form of the integer I', function() {
294 for (var i = 0; i < test_integers.length; i++) {
295 var test = test_integers[i];
296 test.buffer.cursor = 0;
297 expect(util.concat(HeaderSetCompressor.integer(test.I, test.N))).to.deep.equal(test.buffer);
298 }
299 });
300 });
301 describe('static method .string(string)', function() {
302 it('should return an array of buffers that represent the encoded form of the string', function() {
303 var table = HuffmanTable.huffmanTable;
304 for (var i = 0; i < test_strings.length; i++) {
305 var test = test_strings[i];
306 expect(util.concat(HeaderSetCompressor.string(test.string, table))).to.deep.equal(test.buffer);
307 }
308 });
309 });
310 describe('static method .header({ name, value, index })', function() {
311 it('should return an array of buffers that represent the encoded form of the header', function() {
312 var table = HuffmanTable.huffmanTable;
313 for (var i = 0; i < test_headers.length; i++) {
314 var test = test_headers[i];
315 expect(util.concat(HeaderSetCompressor.header(test.header, table))).to.deep.equal(test.buffer);
316 }
317 });
318 });
319 });
321 describe('HeaderSetDecompressor', function() {
322 describe('static method .integer(buffer, N)', function() {
323 it('should return the parsed N-prefix coded number and increase the cursor property of buffer', function() {
324 for (var i = 0; i < test_integers.length; i++) {
325 var test = test_integers[i];
326 test.buffer.cursor = 0;
327 expect(HeaderSetDecompressor.integer(test.buffer, test.N)).to.equal(test.I);
328 expect(test.buffer.cursor).to.equal(test.buffer.length);
329 }
330 });
331 });
332 describe('static method .string(buffer)', function() {
333 it('should return the parsed string and increase the cursor property of buffer', function() {
334 var table = HuffmanTable.huffmanTable;
335 for (var i = 0; i < test_strings.length; i++) {
336 var test = test_strings[i];
337 test.buffer.cursor = 0;
338 expect(HeaderSetDecompressor.string(test.buffer, table)).to.equal(test.string);
339 expect(test.buffer.cursor).to.equal(test.buffer.length);
340 }
341 });
342 });
343 describe('static method .header(buffer)', function() {
344 it('should return the parsed header and increase the cursor property of buffer', function() {
345 var table = HuffmanTable.huffmanTable;
346 for (var i = 0; i < test_headers.length; i++) {
347 var test = test_headers[i];
348 test.buffer.cursor = 0;
349 expect(HeaderSetDecompressor.header(test.buffer, table)).to.deep.equal(test.header);
350 expect(test.buffer.cursor).to.equal(test.buffer.length);
351 }
352 });
353 });
354 });
355 describe('Decompressor', function() {
356 describe('method decompress(buffer)', function() {
357 it('should return the parsed header set in { name1: value1, name2: [value2, value3], ... } format', function() {
358 var decompressor = new Decompressor(util.log, 'REQUEST');
359 for (var i = 0; i < 5; i++) {
360 var header_set = test_header_sets[i];
361 expect(decompressor.decompress(header_set.buffer)).to.deep.equal(header_set.headers);
362 }
363 });
364 });
365 describe('transform stream', function() {
366 it('should emit an error event if a series of header frames is interleaved with other frames', function() {
367 var decompressor = new Decompressor(util.log, 'REQUEST');
368 var error_occured = false;
369 decompressor.on('error', function() {
370 error_occured = true;
371 });
372 decompressor.write({
373 type: 'HEADERS',
374 flags: {
375 END_HEADERS: false
376 },
377 data: new Buffer(5)
378 });
379 decompressor.write({
380 type: 'DATA',
381 flags: {},
382 data: new Buffer(5)
383 });
384 expect(error_occured).to.be.equal(true);
385 });
386 });
387 });
389 describe('invariant', function() {
390 describe('decompressor.decompress(compressor.compress(headerset)) === headerset', function() {
391 it('should be true for any header set if the states are synchronized', function() {
392 var compressor = new Compressor(util.log, 'REQUEST');
393 var decompressor = new Decompressor(util.log, 'REQUEST');
394 var n = test_header_sets.length;
395 for (var i = 0; i < 10; i++) {
396 var headers = test_header_sets[i%n].headers;
397 var compressed = compressor.compress(headers);
398 var decompressed = decompressor.decompress(compressed);
399 expect(decompressed).to.deep.equal(headers);
400 expect(compressor._table).to.deep.equal(decompressor._table);
401 }
402 });
403 });
404 describe('source.pipe(compressor).pipe(decompressor).pipe(destination)', function() {
405 it('should behave like source.pipe(destination) for a stream of frames', function(done) {
406 var compressor = new Compressor(util.log, 'RESPONSE');
407 var decompressor = new Decompressor(util.log, 'RESPONSE');
408 var n = test_header_sets.length;
409 compressor.pipe(decompressor);
410 for (var i = 0; i < 10; i++) {
411 compressor.write({
412 type: i%2 ? 'HEADERS' : 'PUSH_PROMISE',
413 flags: {},
414 headers: test_header_sets[i%n].headers
415 });
416 }
417 setTimeout(function() {
418 for (var j = 0; j < 10; j++) {
419 expect(decompressor.read().headers).to.deep.equal(test_header_sets[j%n].headers);
420 }
421 done();
422 }, 10);
423 });
424 });
425 describe('huffmanTable.decompress(huffmanTable.compress(buffer)) === buffer', function() {
426 it('should be true for any buffer', function() {
427 for (var i = 0; i < 10; i++) {
428 var buffer = [];
429 while (Math.random() > 0.1) {
430 buffer.push(Math.floor(Math.random() * 256))
431 }
432 buffer = new Buffer(buffer);
433 var table = HuffmanTable.huffmanTable;
434 var result = table.decode(table.encode(buffer));
435 expect(result).to.deep.equal(buffer);
436 }
437 })
438 })
439 });
440 });