1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/test/compressor.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,440 @@ 1.4 +var expect = require('chai').expect; 1.5 +var util = require('./util'); 1.6 + 1.7 +var compressor = require('../lib/compressor'); 1.8 +var HeaderTable = compressor.HeaderTable; 1.9 +var HuffmanTable = compressor.HuffmanTable; 1.10 +var HeaderSetCompressor = compressor.HeaderSetCompressor; 1.11 +var HeaderSetDecompressor = compressor.HeaderSetDecompressor; 1.12 +var Compressor = compressor.Compressor; 1.13 +var Decompressor = compressor.Decompressor; 1.14 + 1.15 +var test_integers = [{ 1.16 + N: 5, 1.17 + I: 10, 1.18 + buffer: new Buffer([10]) 1.19 +}, { 1.20 + N: 0, 1.21 + I: 10, 1.22 + buffer: new Buffer([10]) 1.23 +}, { 1.24 + N: 5, 1.25 + I: 1337, 1.26 + buffer: new Buffer([31, 128 + 26, 10]) 1.27 +}, { 1.28 + N: 0, 1.29 + I: 1337, 1.30 + buffer: new Buffer([128 + 57, 10]) 1.31 +}]; 1.32 + 1.33 +var test_strings = [{ 1.34 + string: 'www.foo.com', 1.35 + buffer: new Buffer('88db6d898b5a44b74f', 'hex') 1.36 +}, { 1.37 + string: 'éáűőúöüó€', 1.38 + buffer: new Buffer('13C3A9C3A1C5B1C591C3BAC3B6C3BCC3B3E282AC', 'hex') 1.39 +}]; 1.40 + 1.41 +test_huffman_request = { 1.42 + 'GET': 'f77778ff', 1.43 + 'http': 'ce3177', 1.44 + '/': '0f', 1.45 + 'www.foo.com': 'db6d898b5a44b74f', 1.46 + 'https': 'ce31743f', 1.47 + 'www.bar.com': 'db6d897a1e44b74f', 1.48 + 'no-cache': '63654a1398ff', 1.49 + '/custom-path.css': '04eb08b7495c88e644c21f', 1.50 + 'custom-key': '4eb08b749790fa7f', 1.51 + 'custom-value': '4eb08b74979a17a8ff' 1.52 +}; 1.53 + 1.54 +test_huffman_response = { 1.55 + '302': '98a7', 1.56 + 'private': '73d5cd111f', 1.57 + 'Mon, 21 OCt 2013 20:13:21 GMT': 'ef6b3a7a0e6e8fa7647a0e534dd072fb0d37b0e6e8f777f8ff', 1.58 + ': https://www.bar.com': 'f6746718ba1ec00db6d897a1e44b74', 1.59 + '200': '394b', 1.60 + 'Mon, 21 OCt 2013 20:13:22 GMT': 'ef6b3a7a0e6e8fa7647a0e534dd072fb0d37b0e7e8f777f8ff', 1.61 + 'https://www.bar.com': 'ce31743d801b6db12f43c896e9', 1.62 + 'gzip': 'cbd54e', 1.63 + 'foo=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ 1.64 +AAAAAAAAAAAAAAAAAAAAAAAAAALASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKHQWOEIUAL\ 1.65 +QWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKH\ 1.66 +QWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEO\ 1.67 +IUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOP\ 1.68 +IUAXQWEOIUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234ZZZZZZZZZZ\ 1.69 +ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ1234 m\ 1.70 +ax-age=3600; version=1': 'c5adb77efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7\ 1.71 +efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfb\ 1.72 +f7efdfbf7efdfbf7efdfbfe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bf\ 1.73 +f7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb7\ 1.74 +77e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf\ 1.75 +5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e3\ 1.76 +7fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f3\ 1.77 +31e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8d\ 1.78 +ffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe\ 1.79 +3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf\ 1.80 +4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f\ 1.81 +1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69ffcff3fcff3\ 1.82 +fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcf\ 1.83 +f3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3f\ 1.84 +cff3fcff3fcff3fcff3fcff3fcff3fcff0c79a7e8d11e72a321b66a4a5eae8e62f82\ 1.85 +9acb4d', 1.86 + 'foo=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\ 1.87 +ZZZZZZZZZZZZZZZZZZZZZZZZZZLASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKHQWOEIUAL\ 1.88 +QWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKH\ 1.89 +QWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEO\ 1.90 +IUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOP\ 1.91 +IUAXQWEOIUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234AAAAAAAAAA\ 1.92 +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1234 m\ 1.93 +ax-age=3600; version=1': 'c5adb7fcff3fcff3fcff3fcff3fcff3fcff3fcff3f\ 1.94 +cff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff\ 1.95 +3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fc\ 1.96 +ff3fcff3e5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f\ 1.97 +8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fe\ 1.98 +fe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5d\ 1.99 +df4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c\ 1.100 +3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7\ 1.101 +e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fd\ 1.102 +bf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeef\ 1.103 +a7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6\ 1.104 +fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e3\ 1.105 +7fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69f7efdfbf7efdfbf7efdfbf7ef\ 1.106 +dfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7\ 1.107 +efdfbf7efdfbf7efdfbf7efdfbf7efdfbcc79a7e8d11e72a321b66a4a5eae8e62f82\ 1.108 +9acb4d' 1.109 +}; 1.110 + 1.111 +var test_headers = [{ 1.112 + header: { 1.113 + name: 1, 1.114 + value: 'GET', 1.115 + index: true 1.116 + }, 1.117 + buffer: new Buffer('02' + '03474554', 'hex') 1.118 +}, { 1.119 + header: { 1.120 + name: 6, 1.121 + value: 'http', 1.122 + index: true 1.123 + }, 1.124 + buffer: new Buffer('07' + '83ce3177', 'hex') 1.125 +}, { 1.126 + header: { 1.127 + name: 5, 1.128 + value: '/', 1.129 + index: true 1.130 + }, 1.131 + buffer: new Buffer('06' + '012f', 'hex') 1.132 +}, { 1.133 + header: { 1.134 + name: 3, 1.135 + value: 'www.foo.com', 1.136 + index: true 1.137 + }, 1.138 + buffer: new Buffer('04' + '88db6d898b5a44b74f', 'hex') 1.139 +}, { 1.140 + header: { 1.141 + name: 2, 1.142 + value: 'https', 1.143 + index: true 1.144 + }, 1.145 + buffer: new Buffer('03' + '84ce31743f', 'hex') 1.146 +}, { 1.147 + header: { 1.148 + name: 1, 1.149 + value: 'www.bar.com', 1.150 + index: true 1.151 + }, 1.152 + buffer: new Buffer('02' + '88db6d897a1e44b74f', 'hex') 1.153 +}, { 1.154 + header: { 1.155 + name: 28, 1.156 + value: 'no-cache', 1.157 + index: true 1.158 + }, 1.159 + buffer: new Buffer('1d' + '8663654a1398ff', 'hex') 1.160 +}, { 1.161 + header: { 1.162 + name: 3, 1.163 + value: 3, 1.164 + index: false 1.165 + }, 1.166 + buffer: new Buffer('84', 'hex') 1.167 +}, { 1.168 + header: { 1.169 + name: 5, 1.170 + value: 5, 1.171 + index: false 1.172 + }, 1.173 + buffer: new Buffer('86', 'hex') 1.174 +}, { 1.175 + header: { 1.176 + name: 4, 1.177 + value: '/custom-path.css', 1.178 + index: true 1.179 + }, 1.180 + buffer: new Buffer('05' + '8b04eb08b7495c88e644c21f', 'hex') 1.181 +}, { 1.182 + header: { 1.183 + name: 'custom-key', 1.184 + value: 'custom-value', 1.185 + index: true 1.186 + }, 1.187 + buffer: new Buffer('00' + '884eb08b749790fa7f' + '894eb08b74979a17a8ff', 'hex') 1.188 +}, { 1.189 + header: { 1.190 + name: 2, 1.191 + value: 2, 1.192 + index: false 1.193 + }, 1.194 + buffer: new Buffer('83', 'hex') 1.195 +}, { 1.196 + header: { 1.197 + name: 6, 1.198 + value: 6, 1.199 + index: false 1.200 + }, 1.201 + buffer: new Buffer('87', 'hex') 1.202 +}, { 1.203 + header: { 1.204 + name: -1, 1.205 + value: -1, 1.206 + index: true 1.207 + }, 1.208 + buffer: new Buffer('8080', 'hex') 1.209 +}]; 1.210 + 1.211 +var test_header_sets = [{ 1.212 + headers: { 1.213 + ':method': 'GET', 1.214 + ':scheme': 'http', 1.215 + ':path': '/', 1.216 + ':authority': 'www.foo.com' 1.217 + }, 1.218 + buffer: util.concat(test_headers.slice(0, 4).map(function(test) { return test.buffer; })) 1.219 +}, { 1.220 + headers: { 1.221 + ':method': 'GET', 1.222 + ':scheme': 'https', 1.223 + ':path': '/', 1.224 + ':authority': 'www.bar.com', 1.225 + 'cache-control': 'no-cache' 1.226 + }, 1.227 + buffer: util.concat(test_headers.slice(4, 9).map(function(test) { return test.buffer; })) 1.228 +}, { 1.229 + headers: { 1.230 + ':method': 'GET', 1.231 + ':scheme': 'https', 1.232 + ':path': '/custom-path.css', 1.233 + ':authority': 'www.bar.com', 1.234 + 'custom-key': 'custom-value' 1.235 + }, 1.236 + buffer: util.concat(test_headers.slice(9, 13).map(function(test) { return test.buffer; })) 1.237 +}, { 1.238 + headers: { 1.239 + ':method': 'GET', 1.240 + ':scheme': 'https', 1.241 + ':path': '/custom-path.css', 1.242 + ':authority': ['www.foo.com', 'www.bar.com'], 1.243 + 'custom-key': 'custom-value' 1.244 + }, 1.245 + buffer: test_headers[3].buffer 1.246 +}, { 1.247 + headers: {}, 1.248 + buffer: test_headers[13].buffer 1.249 +}, { 1.250 + headers: { 1.251 + ':status': '200', 1.252 + 'user-agent': 'my-user-agent', 1.253 + 'cookie': 'first; second; third; third; fourth', 1.254 + 'multiple': ['first', 'second', 'third', 'third; fourth'], 1.255 + 'verylong': (new Buffer(9000)).toString('hex') 1.256 + } 1.257 +}]; 1.258 + 1.259 +describe('compressor.js', function() { 1.260 + describe('HeaderTable', function() { 1.261 + }); 1.262 + 1.263 + describe('HuffmanTable', function() { 1.264 + describe('method encode(buffer)', function() { 1.265 + it('should return the Huffman encoded version of the input buffer', function() { 1.266 + var table = HuffmanTable.huffmanTable; 1.267 + for (var decoded in test_huffman_request) { 1.268 + var encoded = test_huffman_request[decoded]; 1.269 + expect(table.encode(new Buffer(decoded)).toString('hex')).to.equal(encoded); 1.270 + } 1.271 + table = HuffmanTable.huffmanTable; 1.272 + for (decoded in test_huffman_response) { 1.273 + encoded = test_huffman_response[decoded]; 1.274 + expect(table.encode(new Buffer(decoded)).toString('hex')).to.equal(encoded); 1.275 + } 1.276 + }); 1.277 + }) 1.278 + describe('method decode(buffer)', function() { 1.279 + it('should return the Huffman decoded version of the input buffer', function() { 1.280 + var table = HuffmanTable.huffmanTable; 1.281 + for (var decoded in test_huffman_request) { 1.282 + var encoded = test_huffman_request[decoded]; 1.283 + expect(table.decode(new Buffer(encoded, 'hex')).toString()).to.equal(decoded) 1.284 + } 1.285 + table = HuffmanTable.huffmanTable; 1.286 + for (decoded in test_huffman_response) { 1.287 + encoded = test_huffman_response[decoded]; 1.288 + expect(table.decode(new Buffer(encoded, 'hex')).toString()).to.equal(decoded) 1.289 + } 1.290 + }); 1.291 + }) 1.292 + }); 1.293 + 1.294 + describe('HeaderSetCompressor', function() { 1.295 + describe('static method .integer(I, N)', function() { 1.296 + it('should return an array of buffers that represent the N-prefix coded form of the integer I', function() { 1.297 + for (var i = 0; i < test_integers.length; i++) { 1.298 + var test = test_integers[i]; 1.299 + test.buffer.cursor = 0; 1.300 + expect(util.concat(HeaderSetCompressor.integer(test.I, test.N))).to.deep.equal(test.buffer); 1.301 + } 1.302 + }); 1.303 + }); 1.304 + describe('static method .string(string)', function() { 1.305 + it('should return an array of buffers that represent the encoded form of the string', function() { 1.306 + var table = HuffmanTable.huffmanTable; 1.307 + for (var i = 0; i < test_strings.length; i++) { 1.308 + var test = test_strings[i]; 1.309 + expect(util.concat(HeaderSetCompressor.string(test.string, table))).to.deep.equal(test.buffer); 1.310 + } 1.311 + }); 1.312 + }); 1.313 + describe('static method .header({ name, value, index })', function() { 1.314 + it('should return an array of buffers that represent the encoded form of the header', function() { 1.315 + var table = HuffmanTable.huffmanTable; 1.316 + for (var i = 0; i < test_headers.length; i++) { 1.317 + var test = test_headers[i]; 1.318 + expect(util.concat(HeaderSetCompressor.header(test.header, table))).to.deep.equal(test.buffer); 1.319 + } 1.320 + }); 1.321 + }); 1.322 + }); 1.323 + 1.324 + describe('HeaderSetDecompressor', function() { 1.325 + describe('static method .integer(buffer, N)', function() { 1.326 + it('should return the parsed N-prefix coded number and increase the cursor property of buffer', function() { 1.327 + for (var i = 0; i < test_integers.length; i++) { 1.328 + var test = test_integers[i]; 1.329 + test.buffer.cursor = 0; 1.330 + expect(HeaderSetDecompressor.integer(test.buffer, test.N)).to.equal(test.I); 1.331 + expect(test.buffer.cursor).to.equal(test.buffer.length); 1.332 + } 1.333 + }); 1.334 + }); 1.335 + describe('static method .string(buffer)', function() { 1.336 + it('should return the parsed string and increase the cursor property of buffer', function() { 1.337 + var table = HuffmanTable.huffmanTable; 1.338 + for (var i = 0; i < test_strings.length; i++) { 1.339 + var test = test_strings[i]; 1.340 + test.buffer.cursor = 0; 1.341 + expect(HeaderSetDecompressor.string(test.buffer, table)).to.equal(test.string); 1.342 + expect(test.buffer.cursor).to.equal(test.buffer.length); 1.343 + } 1.344 + }); 1.345 + }); 1.346 + describe('static method .header(buffer)', function() { 1.347 + it('should return the parsed header and increase the cursor property of buffer', function() { 1.348 + var table = HuffmanTable.huffmanTable; 1.349 + for (var i = 0; i < test_headers.length; i++) { 1.350 + var test = test_headers[i]; 1.351 + test.buffer.cursor = 0; 1.352 + expect(HeaderSetDecompressor.header(test.buffer, table)).to.deep.equal(test.header); 1.353 + expect(test.buffer.cursor).to.equal(test.buffer.length); 1.354 + } 1.355 + }); 1.356 + }); 1.357 + }); 1.358 + describe('Decompressor', function() { 1.359 + describe('method decompress(buffer)', function() { 1.360 + it('should return the parsed header set in { name1: value1, name2: [value2, value3], ... } format', function() { 1.361 + var decompressor = new Decompressor(util.log, 'REQUEST'); 1.362 + for (var i = 0; i < 5; i++) { 1.363 + var header_set = test_header_sets[i]; 1.364 + expect(decompressor.decompress(header_set.buffer)).to.deep.equal(header_set.headers); 1.365 + } 1.366 + }); 1.367 + }); 1.368 + describe('transform stream', function() { 1.369 + it('should emit an error event if a series of header frames is interleaved with other frames', function() { 1.370 + var decompressor = new Decompressor(util.log, 'REQUEST'); 1.371 + var error_occured = false; 1.372 + decompressor.on('error', function() { 1.373 + error_occured = true; 1.374 + }); 1.375 + decompressor.write({ 1.376 + type: 'HEADERS', 1.377 + flags: { 1.378 + END_HEADERS: false 1.379 + }, 1.380 + data: new Buffer(5) 1.381 + }); 1.382 + decompressor.write({ 1.383 + type: 'DATA', 1.384 + flags: {}, 1.385 + data: new Buffer(5) 1.386 + }); 1.387 + expect(error_occured).to.be.equal(true); 1.388 + }); 1.389 + }); 1.390 + }); 1.391 + 1.392 + describe('invariant', function() { 1.393 + describe('decompressor.decompress(compressor.compress(headerset)) === headerset', function() { 1.394 + it('should be true for any header set if the states are synchronized', function() { 1.395 + var compressor = new Compressor(util.log, 'REQUEST'); 1.396 + var decompressor = new Decompressor(util.log, 'REQUEST'); 1.397 + var n = test_header_sets.length; 1.398 + for (var i = 0; i < 10; i++) { 1.399 + var headers = test_header_sets[i%n].headers; 1.400 + var compressed = compressor.compress(headers); 1.401 + var decompressed = decompressor.decompress(compressed); 1.402 + expect(decompressed).to.deep.equal(headers); 1.403 + expect(compressor._table).to.deep.equal(decompressor._table); 1.404 + } 1.405 + }); 1.406 + }); 1.407 + describe('source.pipe(compressor).pipe(decompressor).pipe(destination)', function() { 1.408 + it('should behave like source.pipe(destination) for a stream of frames', function(done) { 1.409 + var compressor = new Compressor(util.log, 'RESPONSE'); 1.410 + var decompressor = new Decompressor(util.log, 'RESPONSE'); 1.411 + var n = test_header_sets.length; 1.412 + compressor.pipe(decompressor); 1.413 + for (var i = 0; i < 10; i++) { 1.414 + compressor.write({ 1.415 + type: i%2 ? 'HEADERS' : 'PUSH_PROMISE', 1.416 + flags: {}, 1.417 + headers: test_header_sets[i%n].headers 1.418 + }); 1.419 + } 1.420 + setTimeout(function() { 1.421 + for (var j = 0; j < 10; j++) { 1.422 + expect(decompressor.read().headers).to.deep.equal(test_header_sets[j%n].headers); 1.423 + } 1.424 + done(); 1.425 + }, 10); 1.426 + }); 1.427 + }); 1.428 + describe('huffmanTable.decompress(huffmanTable.compress(buffer)) === buffer', function() { 1.429 + it('should be true for any buffer', function() { 1.430 + for (var i = 0; i < 10; i++) { 1.431 + var buffer = []; 1.432 + while (Math.random() > 0.1) { 1.433 + buffer.push(Math.floor(Math.random() * 256)) 1.434 + } 1.435 + buffer = new Buffer(buffer); 1.436 + var table = HuffmanTable.huffmanTable; 1.437 + var result = table.decode(table.encode(buffer)); 1.438 + expect(result).to.deep.equal(buffer); 1.439 + } 1.440 + }) 1.441 + }) 1.442 + }); 1.443 +});