1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/test/unit/test_bug767025.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,280 @@ 1.4 +/* -*- Mode: Javasript; indent-tab-mode: nil; js-indent-level: 2 -*- */ 1.5 + 1.6 +Cu.import("resource://testing-common/httpd.js"); 1.7 + 1.8 +/** 1.9 + * This is testcase do following steps to make sure bug767025 removing 1.10 + * files as expection. 1.11 + * 1.12 + * STEPS: 1.13 + * - Schedule a offline cache update for app.manifest. 1.14 + * - pages/foo1, pages/foo2, pages/foo3, and pages/foo4 are cached. 1.15 + * - Activate pages/foo1 1.16 + * - Doom pages/foo1, and pages/foo2. 1.17 + * - pages/foo1 should keep alive while pages/foo2 was gone. 1.18 + * - Activate pages/foo3 1.19 + * - Evict all documents. 1.20 + * - all documents except pages/foo1 are gone since pages/foo1 & pages/foo3 1.21 + * are activated. 1.22 + */ 1.23 + 1.24 +Cu.import("resource://gre/modules/Services.jsm"); 1.25 + 1.26 +const kNS_OFFLINECACHEUPDATESERVICE_CONTRACTID = 1.27 + "@mozilla.org/offlinecacheupdate-service;1"; 1.28 +const kNS_CACHESERVICE_CONTRACTID = 1.29 + "@mozilla.org/network/cache-service;1"; 1.30 +const kNS_APPLICATIONCACHESERVICE_CONTRACTID = 1.31 + "@mozilla.org/network/application-cache-service;1"; 1.32 + 1.33 +const kManifest = "CACHE MANIFEST\n" + 1.34 + "/pages/foo1\n" + 1.35 + "/pages/foo2\n" + 1.36 + "/pages/foo3\n" + 1.37 + "/pages/foo4\n"; 1.38 + 1.39 +const kDataFileSize = 1024; // file size for each content page 1.40 +const kHttpLocation = "http://localhost:4444/"; 1.41 + 1.42 +function manifest_handler(metadata, response) { 1.43 + do_print("manifest\n"); 1.44 + response.setHeader("content-type", "text/cache-manifest"); 1.45 + 1.46 + response.write(kManifest); 1.47 +} 1.48 + 1.49 +function datafile_handler(metadata, response) { 1.50 + do_print("datafile_handler\n"); 1.51 + let data = ""; 1.52 + 1.53 + while(data.length < kDataFileSize) { 1.54 + data = data + Math.random().toString(36).substring(2, 15); 1.55 + } 1.56 + 1.57 + response.setHeader("content-type", "text/plain"); 1.58 + response.write(data.substring(0, kDataFileSize)); 1.59 +} 1.60 + 1.61 +function app_handler(metadata, response) { 1.62 + do_print("app_handler\n"); 1.63 + response.setHeader("content-type", "text/html"); 1.64 + 1.65 + response.write("<html></html>"); 1.66 +} 1.67 + 1.68 +var httpServer; 1.69 + 1.70 +function init_profile() { 1.71 + var ps = Cc["@mozilla.org/preferences-service;1"] 1.72 + .getService(Ci.nsIPrefBranch); 1.73 + dump(ps.getBoolPref("browser.cache.offline.enable")); 1.74 + ps.setBoolPref("browser.cache.offline.enable", true); 1.75 + ps.setComplexValue("browser.cache.offline.parent_directory", 1.76 + Ci.nsILocalFile, do_get_profile()); 1.77 + do_print("profile " + do_get_profile()); 1.78 +} 1.79 + 1.80 +function init_http_server() { 1.81 + httpServer = new HttpServer(); 1.82 + httpServer.registerPathHandler("/app.appcache", manifest_handler); 1.83 + httpServer.registerPathHandler("/app", app_handler); 1.84 + for (i = 1; i <= 4; i++) { 1.85 + httpServer.registerPathHandler("/pages/foo" + i, datafile_handler); 1.86 + } 1.87 + httpServer.start(4444); 1.88 +} 1.89 + 1.90 +function clean_app_cache() { 1.91 + let cache_service = Cc[kNS_CACHESERVICE_CONTRACTID]. 1.92 + getService(Ci.nsICacheService); 1.93 + cache_service.evictEntries(Ci.nsICache.STORE_OFFLINE); 1.94 +} 1.95 + 1.96 +function do_app_cache(manifestURL, pageURL) { 1.97 + let update_service = Cc[kNS_OFFLINECACHEUPDATESERVICE_CONTRACTID]. 1.98 + getService(Ci.nsIOfflineCacheUpdateService); 1.99 + 1.100 + Services.perms.add(manifestURL, 1.101 + "offline-app", 1.102 + Ci.nsIPermissionManager.ALLOW_ACTION); 1.103 + 1.104 + let update = 1.105 + update_service.scheduleUpdate(manifestURL, 1.106 + pageURL, 1.107 + null); /* no window */ 1.108 + 1.109 + return update; 1.110 +} 1.111 + 1.112 +function watch_update(update, stateChangeHandler, cacheAvailHandler) { 1.113 + let observer = { 1.114 + QueryInterface: function QueryInterface(iftype) { 1.115 + return this; 1.116 + }, 1.117 + 1.118 + updateStateChanged: stateChangeHandler, 1.119 + applicationCacheAvailable: cacheAvailHandler 1.120 + };~ 1.121 + update.addObserver(observer, false); 1.122 + 1.123 + return update; 1.124 +} 1.125 + 1.126 +function start_and_watch_app_cache(manifestURL, 1.127 + pageURL, 1.128 + stateChangeHandler, 1.129 + cacheAvailHandler) { 1.130 + let ioService = Cc["@mozilla.org/network/io-service;1"]. 1.131 + getService(Ci.nsIIOService); 1.132 + let update = do_app_cache(ioService.newURI(manifestURL, null, null), 1.133 + ioService.newURI(pageURL, null, null)); 1.134 + watch_update(update, stateChangeHandler, cacheAvailHandler); 1.135 + return update; 1.136 +} 1.137 + 1.138 +const {STATE_FINISHED: STATE_FINISHED, 1.139 + STATE_CHECKING: STATE_CHECKING, 1.140 + STATE_ERROR: STATE_ERROR } = Ci.nsIOfflineCacheUpdateObserver; 1.141 + 1.142 +/* 1.143 + * Start caching app1 as a non-pinned app. 1.144 + */ 1.145 +function start_cache_nonpinned_app() { 1.146 + do_print("Start non-pinned App1"); 1.147 + start_and_watch_app_cache(kHttpLocation + "app.appcache", 1.148 + kHttpLocation + "app", 1.149 + function (update, state) { 1.150 + switch(state) { 1.151 + case STATE_FINISHED: 1.152 + check_bug(); 1.153 + break; 1.154 + 1.155 + case STATE_ERROR: 1.156 + do_throw("App cache state = " + state); 1.157 + break; 1.158 + } 1.159 + }, 1.160 + function (appcahe) { 1.161 + do_print("app avail " + appcache + "\n"); 1.162 + }); 1.163 +} 1.164 + 1.165 +var hold_entry_foo1 = null; 1.166 + 1.167 +function check_bug() { 1.168 + // activate foo1 1.169 + asyncOpenCacheEntry( 1.170 + kHttpLocation + "pages/foo1", 1.171 + "appcache", Ci.nsICacheStorage.OPEN_READONLY, null, 1.172 + function(status, entry, appcache) { 1.173 + let storage = get_cache_service().appCacheStorage(LoadContextInfo.default, appcache); 1.174 + 1.175 + // Doom foo1 & foo2 1.176 + storage.asyncDoomURI(createURI(kHttpLocation + "pages/foo1"), "", { onCacheEntryDoomed: function() { 1.177 + storage.asyncDoomURI(createURI(kHttpLocation + "pages/foo2"), "", { onCacheEntryDoomed: function() { 1.178 + check_evict_cache(appcache); 1.179 + }}); 1.180 + }}); 1.181 + 1.182 + hold_entry_foo1 = entry; 1.183 + }); 1.184 +} 1.185 + 1.186 +function check_evict_cache(appcache) { 1.187 + // Only foo2 should be removed. 1.188 + let file = do_get_profile().clone(); 1.189 + file.append("OfflineCache"); 1.190 + file.append("5"); 1.191 + file.append("9"); 1.192 + file.append("8379C6596B8CA4-0"); 1.193 + do_check_eq(file.exists(), true); 1.194 + 1.195 + file = do_get_profile().clone(); 1.196 + file.append("OfflineCache"); 1.197 + file.append("C"); 1.198 + file.append("2"); 1.199 + file.append("5F356A168B5E3B-0"); 1.200 + do_check_eq(file.exists(), false); 1.201 + 1.202 + // activate foo3 1.203 + asyncOpenCacheEntry( 1.204 + kHttpLocation + "pages/foo3", 1.205 + "appcache", Ci.nsICacheStorage.OPEN_READONLY, null, 1.206 + function(status, entry, appcache) { 1.207 + hold_entry_foo3 = entry; 1.208 + 1.209 + // evict all documents. 1.210 + let storage = get_cache_service().appCacheStorage(LoadContextInfo.default, appcache); 1.211 + storage.asyncEvictStorage(null); 1.212 + 1.213 + // All documents are removed except foo1 & foo3. 1.214 + syncWithCacheIOThread(function () { 1.215 + // foo1 1.216 + let file = do_get_profile().clone(); 1.217 + file.append("OfflineCache"); 1.218 + file.append("5"); 1.219 + file.append("9"); 1.220 + file.append("8379C6596B8CA4-0"); 1.221 + do_check_eq(file.exists(), true); 1.222 + 1.223 + file = do_get_profile().clone(); 1.224 + file.append("OfflineCache"); 1.225 + file.append("0"); 1.226 + file.append("0"); 1.227 + file.append("61FEE819921D39-0"); 1.228 + do_check_eq(file.exists(), false); 1.229 + 1.230 + file = do_get_profile().clone(); 1.231 + file.append("OfflineCache"); 1.232 + file.append("3"); 1.233 + file.append("9"); 1.234 + file.append("0D8759F1DE5452-0"); 1.235 + do_check_eq(file.exists(), false); 1.236 + 1.237 + file = do_get_profile().clone(); 1.238 + file.append("OfflineCache"); 1.239 + file.append("C"); 1.240 + file.append("2"); 1.241 + file.append("5F356A168B5E3B-0"); 1.242 + do_check_eq(file.exists(), false); 1.243 + 1.244 + // foo3 1.245 + file = do_get_profile().clone(); 1.246 + file.append("OfflineCache"); 1.247 + file.append("D"); 1.248 + file.append("C"); 1.249 + file.append("1ADCCC843B5C00-0"); 1.250 + do_check_eq(file.exists(), true); 1.251 + 1.252 + file = do_get_profile().clone(); 1.253 + file.append("OfflineCache"); 1.254 + file.append("F"); 1.255 + file.append("0"); 1.256 + file.append("FC3E6D6C1164E9-0"); 1.257 + do_check_eq(file.exists(), false); 1.258 + 1.259 + httpServer.stop(do_test_finished); 1.260 + }); 1.261 + }, 1.262 + appcache 1.263 + ); 1.264 +} 1.265 + 1.266 +function run_test() { 1.267 + if (newCacheBackEndUsed()) { 1.268 + // times out on storage.asyncDoomURI @ check_bug because that method is not implemented for appcache 1.269 + // either revert the test changes or implement the method (former seems more reasonable) 1.270 + do_check_true(true, "This test doesn't run with the new cache backend, the test or the cache needs to be fixed"); 1.271 + return; 1.272 + } 1.273 + 1.274 + if (typeof _XPCSHELL_PROCESS == "undefined" || 1.275 + _XPCSHELL_PROCESS != "child") { 1.276 + init_profile(); 1.277 + clean_app_cache(); 1.278 + } 1.279 + 1.280 + init_http_server(); 1.281 + start_cache_nonpinned_app(); 1.282 + do_test_pending(); 1.283 +}