Bug 1231565 - Basic test, no r draft
authorHonza Bambas <honzab.moz@firemni.cz>
Tue, 22 Mar 2016 11:42:00 +0100
changeset 368988 8476b6464b2a6ce203709e0e89557d431a4e6044
parent 367249 d0be57e84807ce0853b2406de7ff6abb195ac898
child 368989 77322f9e33722dc5d1508468f1730644cea4d7d7
push id18689
push uservalentin.gosu@gmail.com
push dateFri, 20 May 2016 00:56:51 +0000
bugs1231565
milestone49.0a1
Bug 1231565 - Basic test, no r MozReview-Commit-ID: 7uBCMfJ7kT5
netwerk/cache2/CacheStorageService.cpp
netwerk/cache2/nsICacheTesting.idl
netwerk/test/unit/test_alt-data_simple.js
netwerk/test/unit/xpcshell.ini
netwerk/test/unit_ipc/test_alt-data_simple.js_wrap.js
netwerk/test/unit_ipc/xpcshell.ini
--- a/netwerk/cache2/CacheStorageService.cpp
+++ b/netwerk/cache2/CacheStorageService.cpp
@@ -2209,10 +2209,37 @@ CacheStorageService::ResumeCacheIOThread
   MOZ_ASSERT(mActiveIOSuspender);
 
   RefPtr<IOThreadSuspender> suspender;
   suspender.swap(mActiveIOSuspender);
   suspender->Notify();
   return NS_OK;
 }
 
+NS_IMETHODIMP
+CacheStorageService::Flush(nsIObserver* aObserver)
+{
+  RefPtr<CacheIOThread> thread = CacheFileIOManager::IOThread();
+  if (!thread) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  nsCOMPtr<nsIObserverService> observerService =
+    mozilla::services::GetObserverService();
+  if (!observerService) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  // Adding as weak, the consumer is responsible to keep the reference
+  // until notified.
+  observerService->AddObserver(aObserver, "cacheservice:purge-memory-pools", false);
+
+  // This runnable will do the purging and when done, notifies the above observer.
+  // We dispatch it to the CLOSE level, so all data writes scheduled up to this time
+  // will be done before this purging happens.
+  RefPtr<CacheStorageService::PurgeFromMemoryRunnable> r =
+    new CacheStorageService::PurgeFromMemoryRunnable(this, CacheEntry::PURGE_WHOLE);
+
+  return thread->Dispatch(r, CacheIOThread::CLOSE);
+}
+
 } // namespace net
 } // namespace mozilla
--- a/netwerk/cache2/nsICacheTesting.idl
+++ b/netwerk/cache2/nsICacheTesting.idl
@@ -1,17 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #include "nsISupports.idl"
 
+interface nsIObserver;
+
 /**
  * This is an internal interface used only for testing purposes.
  *
  * THIS IS NOT AN API TO BE USED BY EXTENSIONS! ONLY USED BY MOZILLA TESTS.
  */
 [scriptable, builtinclass, uuid(4e8ba935-92e1-4a74-944b-b1a2f02a7480)]
 interface nsICacheTesting : nsISupports
 {
   void suspendCacheIOThread(in uint32_t aLevel);
   void resumeCacheIOThread();
+  void flush(in nsIObserver aObserver);
 };
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_alt-data_simple.js
@@ -0,0 +1,105 @@
+/**
+ * Test for the "alternative data stream" stored withing a cache entry.
+ *
+ * - we load a URL with preference for an alt data (check what we get is the raw data,
+ *   since there was nothing previously cached)
+ * - we store the alt data along the channel (to the cache entry)
+ * - we flush the HTTP cache
+ * - we reload the same URL using a new channel, again prefering the alt data be loaded
+ * - this time the alt data must arive
+ */
+
+Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "URL", function() {
+  return "http://localhost:" + httpServer.identity.primaryPort + "/content";
+});
+
+var httpServer = null;
+var cacheFlushObserver; // needs to be rooted
+
+function make_channel(url, callback, ctx) {
+  return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
+}
+
+const responseContent = "response body";
+const altContent = "!@#$%^&*()";
+const altContentType = "text/binary";
+
+var servedNotModified = false;
+
+function contentHandler(metadata, response)
+{
+  response.setHeader("Content-Type", "text/plain");
+  response.setHeader("Cache-Control", "no-cache");
+  response.setHeader("ETag", "test-etag1");
+
+  try {
+    var etag = metadata.getHeader("If-None-Match");
+  } catch(ex) {
+    var etag = "";
+  }
+
+  if (etag == "test-etag1") {
+    response.setStatusLine(metadata.httpVersion, 304, "Not Modified");
+    servedNotModified = true;
+  } else {
+    response.bodyOutputStream.write(responseContent, responseContent.length);
+  }
+}
+
+function run_test()
+{
+  httpServer = new HttpServer();
+  httpServer.registerPathHandler("/content", contentHandler);
+  httpServer.start(-1);
+
+
+  var chan = make_channel(URL);
+
+  var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
+  cc.preferAlternativeDataType(altContentType);
+
+  chan.asyncOpen2(new ChannelListener(readServerContent, null));
+  do_test_pending();
+}
+
+function readServerContent(request, buffer)
+{
+  var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
+
+  do_check_eq(buffer, responseContent);
+  do_check_eq(cc.alternativeDataType, "");
+
+  var os = cc.openAlternativeOutputStream(altContentType);
+  os.write(altContent, altContent.length);
+  os.close();
+
+  cacheFlushObserver = { observe: function() {
+    cacheFlushObserver = null;
+
+    var chan = make_channel(URL);
+    var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
+    cc.preferAlternativeDataType(altContentType);
+
+    chan.asyncOpen2(new ChannelListener(readAltContent, null));
+  }};
+
+  // we may need some gc() calls first here...
+  // check one of test_cache2-26-no-outputstream-open.js or test_cache2-30c-pinning-deferred-doom.js
+  // but the entry is inside the channel, so probably no need to...
+  do_execute_soon(() => Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver));
+}
+
+function readAltContent(request, buffer)
+{
+  var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
+
+  do_check_eq(servedNotModified, true);
+  do_check_eq(cc.alternativeDataType, altContentType);
+  do_check_eq(buffer, altContent);
+
+  httpServer.stop(do_test_finished);
+}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -348,9 +348,10 @@ firefox-appdir = browser
 [test_dns_disable_ipv6.js]
 [test_packaged_app_service_paths.js]
 [test_bug1195415.js]
 [test_cookie_blacklist.js]
 [test_getHost.js]
 [test_packaged_app_bug1214079.js]
 [test_bug412457.js]
 [test_bug464591.js]
+[test_alt-data_simple.js]
 
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit_ipc/test_alt-data_simple.js_wrap.js
@@ -0,0 +1,3 @@
+function run_test() {
+  run_test_in_child("../unit/test_alt-data_simple.js.js");
+}
--- a/netwerk/test/unit_ipc/xpcshell.ini
+++ b/netwerk/test/unit_ipc/xpcshell.ini
@@ -87,10 +87,11 @@ skip-if = true
 [test_simple_wrap.js]
 [test_synthesized_response_wrap.js]
 [test_xmlhttprequest_wrap.js]
 [test_XHR_redirects.js]
 [test_redirect_history_wrap.js]
 [test_reply_without_content_type_wrap.js]
 [test_app_offline_http.js]
 [test_getHost_wrap.js]
+[test_alt-data_simple.js_wrap.js]
 [test_app_offline_notifications.js]
 [test_original_sent_received_head_wrap.js]