Bug 961616 - simple HTTP2 Cookie crumbling unit tests
authorGábor Molnár <gabor@molnar.es>
Mon, 24 Feb 2014 11:42:15 -0800
changeset 170573 45d6553188138262082fbc8bf2ca0d68497d73a5
parent 170572 afbf1c788adad3bab396fc6e6ac92f0cff101747
child 170574 1f7c3b10f48252cb66eeaf6ef95bfb6e8edf0451
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
bugs961616
milestone30.0a1
Bug 961616 - simple HTTP2 Cookie crumbling unit tests
netwerk/test/unit/test_http2.js
testing/xpcshell/moz-http2/moz-http2.js
--- a/netwerk/test/unit/test_http2.js
+++ b/netwerk/test/unit/test_http2.js
@@ -110,27 +110,30 @@ Http2MultiplexListener.prototype.onStopR
   do_check_true(this.isHttp2Connection);
   do_check_true(this.buffer == multiplexContent);
   
   // This is what does most of the hard work for us
   register_completed_channel(this);
 };
 
 // Does the appropriate checks for header gatewaying
-var Http2HeaderListener = function(value) {
-  this.value = value
+var Http2HeaderListener = function(name, callback) {
+  this.name = name;
+  this.callback = callback;
 };
 
 Http2HeaderListener.prototype = new Http2CheckListener();
 Http2HeaderListener.prototype.value = "";
 
 Http2HeaderListener.prototype.onDataAvailable = function(request, ctx, stream, off, cnt) {
   this.onDataAvailableFired = true;
   this.isHttp2Connection = checkIsHttp2(request);
-  do_check_eq(request.getResponseHeader("X-Received-Test-Header"), this.value);
+  var hvalue = request.getResponseHeader(this.name);
+  do_check_neq(hvalue, "");
+  this.callback(hvalue);
   read_stream(stream, cnt);
 };
 
 var Http2PushListener = function() {};
 
 Http2PushListener.prototype = new Http2CheckListener();
 
 Http2PushListener.prototype.onDataAvailable = function(request, ctx, stream, off, cnt) {
@@ -230,18 +233,39 @@ function test_http2_multiplex() {
   chan1.asyncOpen(listener1, null);
   chan2.asyncOpen(listener2, null);
 }
 
 // Test to make sure we gateway non-standard headers properly
 function test_http2_header() {
   var chan = makeChan("https://localhost:6944/header");
   var hvalue = "Headers are fun";
-  var listener = new Http2HeaderListener(hvalue);
   chan.setRequestHeader("X-Test-Header", hvalue, false);
+  var listener = new Http2HeaderListener("X-Received-Test-Header", function(received_hvalue) {
+    do_check_eq(received_hvalue, hvalue);
+  });
+  chan.asyncOpen(listener, null);
+}
+
+// Test to make sure cookies are split into separate fields before compression
+function test_http2_cookie_crumbling() {
+  var chan = makeChan("https://localhost:6944/cookie_crumbling");
+  var cookiesSent = ['a=b', 'c=d', 'e=f'].sort();
+  chan.setRequestHeader("Cookie", cookiesSent.join('; '), false);
+  var listener = new Http2HeaderListener("X-Received-Header-Pairs", function(pairsReceived) {
+    var cookiesReceived = JSON.parse(pairsReceived).filter(function(pair) {
+      return pair[0] == 'cookie';
+    }).map(function(pair) {
+      return pair[1];
+    }).sort();
+    do_check_eq(cookiesReceived.length, cookiesSent.length);
+    cookiesReceived.forEach(function(cookieReceived, index) {
+      do_check_eq(cookiesSent[index], cookieReceived)
+    });
+  });
   chan.asyncOpen(listener, null);
 }
 
 function test_http2_push1() {
   var chan = makeChan("https://localhost:6944/push");
   chan.loadGroup = loadGroup;
   var listener = new Http2PushListener();
   chan.asyncOpen(listener, chan);
@@ -311,16 +335,17 @@ function test_http2_post_big() {
 var tests = [ test_http2_post_big
             , test_http2_basic
             , test_http2_push1
             , test_http2_push2
             , test_http2_push3
             , test_http2_push4
             , test_http2_xhr
             , test_http2_header
+            , test_http2_cookie_crumbling
             , test_http2_multiplex
             , test_http2_big
             , test_http2_post
             ];
 var current_test = 0;
 
 function run_next_test() {
   if (current_test < tests.length) {
--- a/testing/xpcshell/moz-http2/moz-http2.js
+++ b/testing/xpcshell/moz-http2/moz-http2.js
@@ -2,16 +2,34 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var http2 = require('../node-http2');
 var fs = require('fs');
 var url = require('url');
 var crypto = require('crypto');
 
+// Hook into the decompression code to log the decompressed name-value pairs
+var http2_compression = require('../node-http2/node_modules/http2-protocol/lib/compressor');
+var HeaderSetDecompressor = http2_compression.HeaderSetDecompressor;
+var originalRead = HeaderSetDecompressor.prototype.read;
+var lastDecompressor;
+var decompressedPairs;
+HeaderSetDecompressor.prototype.read = function() {
+  if (this != lastDecompressor) {
+    lastDecompressor = this;
+    decompressedPairs = [];
+  }
+  var pair = originalRead.apply(this, arguments);
+  if (pair) {
+    decompressedPairs.push(pair);
+  }
+  return pair;
+}
+
 function getHttpContent(path) {
   var content = '<!doctype html>' +
                 '<html>' +
                 '<head><title>HOORAY!</title></head>' +
                 '<body>You Win! (by requesting' + path + ')</body>' +
                 '</html>';
   return content;
 }
@@ -91,16 +109,20 @@ function handleRequest(req, res) {
 
   else if (u.pathname === "/header") {
     var val = req.headers["x-test-header"];
     if (val) {
       res.setHeader("X-Received-Test-Header", val);
     }
   }
 
+  else if (u.pathname === "/cookie_crumbling") {
+    res.setHeader("X-Received-Header-Pairs", JSON.stringify(decompressedPairs));
+  }
+
   else if (u.pathname === "/push") {
     push = res.push('/push.js');
     push.writeHead(200, {
       'content-type': 'application/javascript',
       'pushed' : 'yes',
       'content-length' : 11,
       'X-Connection-Http2': 'yes'
     });