michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: michael@0: const VALUE_HDR_NAME = "X-HTTP-VALUE-HEADER"; michael@0: const VARY_HDR_NAME = "X-HTTP-VARY-HEADER"; michael@0: const CACHECTRL_HDR_NAME = "X-CACHE-CONTROL-HEADER"; michael@0: michael@0: var httpserver = null; michael@0: michael@0: function make_channel(flags, vary, value) { michael@0: var ios = Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: var chan = ios.newChannel("http://localhost:" + michael@0: httpserver.identity.primaryPort + michael@0: "/bug633743", null, null); michael@0: return chan.QueryInterface(Ci.nsIHttpChannel); michael@0: } michael@0: michael@0: function Test(flags, varyHdr, sendValue, expectValue, cacheHdr) { michael@0: this._flags = flags; michael@0: this._varyHdr = varyHdr; michael@0: this._sendVal = sendValue; michael@0: this._expectVal = expectValue; michael@0: this._cacheHdr = cacheHdr; michael@0: } michael@0: michael@0: Test.prototype = { michael@0: _buffer: "", michael@0: _flags: null, michael@0: _varyHdr: null, michael@0: _sendVal: null, michael@0: _expectVal: null, michael@0: _cacheHdr: null, michael@0: michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsIStreamListener) || michael@0: iid.equals(Ci.nsIRequestObserver) || michael@0: iid.equals(Ci.nsISupports)) michael@0: return this; michael@0: throw Cr.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: onStartRequest: function(request, context) { }, michael@0: michael@0: onDataAvailable: function(request, context, stream, offset, count) { michael@0: this._buffer = this._buffer.concat(read_stream(stream, count)); michael@0: }, michael@0: michael@0: onStopRequest: function(request, context, status) { michael@0: do_check_eq(this._buffer, this._expectVal); michael@0: do_timeout(0, run_next_test); michael@0: }, michael@0: michael@0: run: function() { michael@0: var channel = make_channel(); michael@0: channel.loadFlags = this._flags; michael@0: channel.setRequestHeader(VALUE_HDR_NAME, this._sendVal, false); michael@0: channel.setRequestHeader(VARY_HDR_NAME, this._varyHdr, false); michael@0: if (this._cacheHdr) michael@0: channel.setRequestHeader(CACHECTRL_HDR_NAME, this._cacheHdr, false); michael@0: michael@0: channel.asyncOpen(this, null); michael@0: } michael@0: }; michael@0: michael@0: var gTests = [ michael@0: // Test LOAD_FROM_CACHE: Load cache-entry michael@0: new Test(Ci.nsIRequest.LOAD_NORMAL, michael@0: "entity-initial", // hdr-value used to vary michael@0: "request1", // echoed by handler michael@0: "request1" // value expected to receive in channel michael@0: ), michael@0: // Verify that it was cached michael@0: new Test(Ci.nsIRequest.LOAD_NORMAL, michael@0: "entity-initial", // hdr-value used to vary michael@0: "fresh value with LOAD_NORMAL", // echoed by handler michael@0: "request1" // value expected to receive in channel michael@0: ), michael@0: // Load same entity with LOAD_FROM_CACHE-flag michael@0: new Test(Ci.nsIRequest.LOAD_FROM_CACHE, michael@0: "entity-initial", // hdr-value used to vary michael@0: "fresh value with LOAD_FROM_CACHE", // echoed by handler michael@0: "request1" // value expected to receive in channel michael@0: ), michael@0: // Load different entity with LOAD_FROM_CACHE-flag michael@0: new Test(Ci.nsIRequest.LOAD_FROM_CACHE, michael@0: "entity-l-f-c", // hdr-value used to vary michael@0: "request2", // echoed by handler michael@0: "request2" // value expected to receive in channel michael@0: ), michael@0: // Verify that new value was cached michael@0: new Test(Ci.nsIRequest.LOAD_NORMAL, michael@0: "entity-l-f-c", // hdr-value used to vary michael@0: "fresh value with LOAD_NORMAL", // echoed by handler michael@0: "request2" // value expected to receive in channel michael@0: ), michael@0: michael@0: // Test VALIDATE_NEVER: Note previous cache-entry michael@0: new Test(Ci.nsIRequest.VALIDATE_NEVER, michael@0: "entity-v-n", // hdr-value used to vary michael@0: "request3", // echoed by handler michael@0: "request3" // value expected to receive in channel michael@0: ), michael@0: // Verify that cache-entry was replaced michael@0: new Test(Ci.nsIRequest.LOAD_NORMAL, michael@0: "entity-v-n", // hdr-value used to vary michael@0: "fresh value with LOAD_NORMAL", // echoed by handler michael@0: "request3" // value expected to receive in channel michael@0: ), michael@0: michael@0: // Test combination VALIDATE_NEVER && no-store: Load new cache-entry michael@0: new Test(Ci.nsIRequest.LOAD_NORMAL, michael@0: "entity-2",// hdr-value used to vary michael@0: "request4", // echoed by handler michael@0: "request4", // value expected to receive in channel michael@0: "no-store" // set no-store on response michael@0: ), michael@0: // Ensure we validate without IMS header in this case (verified in handler) michael@0: new Test(Ci.nsIRequest.VALIDATE_NEVER, michael@0: "entity-2-v-n",// hdr-value used to vary michael@0: "request5", // echoed by handler michael@0: "request5" // value expected to receive in channel michael@0: ), michael@0: michael@0: // Test VALIDATE-ALWAYS: Load new entity michael@0: new Test(Ci.nsIRequest.LOAD_NORMAL, michael@0: "entity-3",// hdr-value used to vary michael@0: "request6", // echoed by handler michael@0: "request6", // value expected to receive in channel michael@0: "no-cache" // set no-cache on response michael@0: ), michael@0: // Ensure we don't send IMS header also in this case (verified in handler) michael@0: new Test(Ci.nsIRequest.VALIDATE_ALWAYS, michael@0: "entity-3-v-a",// hdr-value used to vary michael@0: "request7", // echoed by handler michael@0: "request7" // value expected to receive in channel michael@0: ), michael@0: ]; michael@0: michael@0: function run_next_test() michael@0: { michael@0: if (gTests.length == 0) { michael@0: httpserver.stop(do_test_finished); michael@0: return; michael@0: } michael@0: michael@0: var test = gTests.shift(); michael@0: test.run(); michael@0: } michael@0: michael@0: function handler(metadata, response) { michael@0: michael@0: // None of the tests above should send an IMS michael@0: do_check_false(metadata.hasHeader("If-Modified-Since")); michael@0: michael@0: // Pick up requested value to echo michael@0: var hdr = "default value"; michael@0: try { michael@0: hdr = metadata.getHeader(VALUE_HDR_NAME); michael@0: } catch(ex) { } michael@0: michael@0: // Pick up requested cache-control header-value michael@0: var cctrlVal = "max-age=10000"; michael@0: try { michael@0: cctrlVal = metadata.getHeader(CACHECTRL_HDR_NAME); michael@0: } catch(ex) { } michael@0: michael@0: response.setStatusLine(metadata.httpVersion, 200, "OK"); michael@0: response.setHeader("Content-Type", "text/plain", false); michael@0: response.setHeader("Cache-Control", cctrlVal, false); michael@0: response.setHeader("Vary", VARY_HDR_NAME, false); michael@0: response.setHeader("Last-Modified", "Tue, 15 Nov 1994 12:45:26 GMT", false); michael@0: response.bodyOutputStream.write(hdr, hdr.length); michael@0: } michael@0: michael@0: function run_test() { michael@0: michael@0: // clear the cache michael@0: evict_cache_entries(); michael@0: michael@0: httpserver = new HttpServer(); michael@0: httpserver.registerPathHandler("/bug633743", handler); michael@0: httpserver.start(-1); michael@0: michael@0: run_next_test(); michael@0: do_test_pending(); michael@0: }