michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: var httpserver = new HttpServer(); michael@0: michael@0: var ios; michael@0: michael@0: // Test the handling of a cache revalidation with mismatching last-modified michael@0: // headers. If we get such a revalidation the cache entry should be purged. michael@0: // see bug 717350 michael@0: michael@0: // In this test the wrong data is from 11-16-1994 with a value of 'A', michael@0: // and the right data is from 11-15-1994 with a value of 'B'. michael@0: michael@0: // the same URL is requested 3 times. the first time the wrong data comes michael@0: // back, the second time that wrong data is revalidated with a 304 but michael@0: // a L-M header of the right data (this triggers a cache purge), and michael@0: // the third time the right data is returned. michael@0: michael@0: var listener_3 = { michael@0: // this listener is used to process the the request made after michael@0: // the cache invalidation. it expects to see the 'right data' michael@0: michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Components.interfaces.nsIStreamListener) || michael@0: iid.equals(Components.interfaces.nsIRequestObserver) || michael@0: iid.equals(Components.interfaces.nsISupports)) michael@0: return this; michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: onStartRequest: function test_onStartR(request, ctx) {}, michael@0: michael@0: onDataAvailable: function test_ODA(request, cx, inputStream, michael@0: offset, count) { michael@0: var data = new BinaryInputStream(inputStream).readByteArray(count); michael@0: michael@0: do_check_eq(data[0], "B".charCodeAt(0)); michael@0: }, michael@0: michael@0: onStopRequest: function test_onStopR(request, ctx, status) { michael@0: httpserver.stop(do_test_finished); michael@0: } michael@0: }; michael@0: michael@0: XPCOMUtils.defineLazyGetter(this, "listener_2", function() { michael@0: return { michael@0: // this listener is used to process the revalidation of the michael@0: // corrupted cache entry. its revalidation prompts it to be cleaned michael@0: michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Components.interfaces.nsIStreamListener) || michael@0: iid.equals(Components.interfaces.nsIRequestObserver) || michael@0: iid.equals(Components.interfaces.nsISupports)) michael@0: return this; michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: onStartRequest: function test_onStartR(request, ctx) {}, michael@0: michael@0: onDataAvailable: function test_ODA(request, cx, inputStream, michael@0: offset, count) { michael@0: var data = new BinaryInputStream(inputStream).readByteArray(count); michael@0: michael@0: // This is 'A' from a cache revalidation, but that reval will clean the cache michael@0: // because of mismatched last-modified response headers michael@0: michael@0: do_check_eq(data[0], "A".charCodeAt(0)); michael@0: }, michael@0: michael@0: onStopRequest: function test_onStopR(request, ctx, status) { michael@0: var channel = request.QueryInterface(Ci.nsIHttpChannel); michael@0: michael@0: var chan = ios.newChannel("http://localhost:" + michael@0: httpserver.identity.primaryPort + michael@0: "/test1", "", null); michael@0: chan.asyncOpen(listener_3, null); michael@0: } michael@0: }; michael@0: }); michael@0: michael@0: XPCOMUtils.defineLazyGetter(this, "listener_1", function() { michael@0: return { michael@0: // this listener processes the initial request from a empty cache. michael@0: // the server responds with the wrong data ('A') michael@0: michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Components.interfaces.nsIStreamListener) || michael@0: iid.equals(Components.interfaces.nsIRequestObserver) || michael@0: iid.equals(Components.interfaces.nsISupports)) michael@0: return this; michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: onStartRequest: function test_onStartR(request, ctx) {}, michael@0: michael@0: onDataAvailable: function test_ODA(request, cx, inputStream, michael@0: offset, count) { michael@0: var data = new BinaryInputStream(inputStream).readByteArray(count); michael@0: do_check_eq(data[0], "A".charCodeAt(0)); michael@0: }, michael@0: michael@0: onStopRequest: function test_onStopR(request, ctx, status) { michael@0: var channel = request.QueryInterface(Ci.nsIHttpChannel); michael@0: michael@0: var chan = ios.newChannel("http://localhost:" + michael@0: httpserver.identity.primaryPort + michael@0: "/test1", "", null); michael@0: chan.asyncOpen(listener_2, null); michael@0: } michael@0: }; michael@0: }); michael@0: michael@0: function run_test() { michael@0: do_get_profile(); michael@0: ios = Cc["@mozilla.org/network/io-service;1"] michael@0: .getService(Ci.nsIIOService); michael@0: michael@0: evict_cache_entries(); michael@0: michael@0: httpserver.registerPathHandler("/test1", handler); michael@0: httpserver.start(-1); michael@0: michael@0: var port = httpserver.identity.primaryPort; michael@0: michael@0: var chan = ios.newChannel("http://localhost:" + port + "/test1", "", null); michael@0: chan.asyncOpen(listener_1, null); michael@0: michael@0: do_test_pending(); michael@0: } michael@0: michael@0: var iter=0; michael@0: function handler(metadata, response) { michael@0: iter++; michael@0: if (metadata.hasHeader("If-Modified-Since")) { michael@0: response.setStatusLine(metadata.httpVersion, 304, "Not Modified"); michael@0: response.setHeader("Last-Modified", "Tue, 15 Nov 1994 12:45:26 GMT", false); michael@0: } michael@0: else { michael@0: response.setStatusLine(metadata.httpVersion, 200, "OK"); michael@0: response.setHeader("Cache-Control", "max-age=0", false) michael@0: if (iter == 1) { michael@0: // simulated wrong response michael@0: response.setHeader("Last-Modified", "Wed, 16 Nov 1994 00:00:00 GMT", false); michael@0: response.bodyOutputStream.write("A", 1); michael@0: } michael@0: if (iter == 3) { michael@0: // 'correct' response michael@0: response.setHeader("Last-Modified", "Tue, 15 Nov 1994 12:45:26 GMT", false); michael@0: response.bodyOutputStream.write("B", 1); michael@0: } michael@0: } michael@0: }