test_cache2-30d-pinning-WasEvicted-API.js (4128B)
1 /* 2 3 This test exercises the CacheFileContextEvictor::WasEvicted API and code using it. 4 5 - We store 10+10 (pinned and non-pinned) entries to the cache, wait for them being written. 6 - Then we purge the memory pools. 7 - Now the IO thread is suspended on the EVICT (7) level to prevent actual deletion of the files. 8 - Index is disabled. 9 - We do clear() of the cache, this creates the "ce_*" file and posts to the EVICT level 10 the eviction loop mechanics. 11 - We open again those 10+10 entries previously stored. 12 - IO is resumed 13 - We expect to get all the pinned and 14 loose all the non-pinned (common) entries. 15 16 */ 17 18 "use strict"; 19 20 const kENTRYCOUNT = 10; 21 22 function log_(msg) { 23 if (true) { 24 dump(">>>>>>>>>>>>> " + msg + "\n"); 25 } 26 } 27 28 function run_test() { 29 do_get_profile(); 30 31 var lci = Services.loadContextInfo.default; 32 var testingInterface = Services.cache2.QueryInterface(Ci.nsICacheTesting); 33 Assert.ok(testingInterface); 34 35 var mc = new MultipleCallbacks( 36 1, 37 function () { 38 // (2) 39 40 mc = new MultipleCallbacks(1, finish_cache2_test); 41 // Release all references to cache entries so that they can be purged 42 // Calling gc() four times is needed to force it to actually release 43 // entries that are obviously unreferenced. Yeah, I know, this is wacky... 44 gc(); 45 gc(); 46 executeSoon(() => { 47 gc(); 48 gc(); 49 log_("purging"); 50 51 // Invokes cacheservice:purge-memory-pools when done. 52 Services.cache2.purgeFromMemory( 53 Ci.nsICacheStorageService.PURGE_EVERYTHING 54 ); // goes to (3) 55 }); 56 }, 57 true 58 ); 59 60 // (1), here we start 61 62 log_("first set of opens"); 63 var i; 64 for (i = 0; i < kENTRYCOUNT; ++i) { 65 // Callbacks 1-20 66 mc.add(); 67 asyncOpenCacheEntry( 68 "http://pinned" + i + "/", 69 "pin", 70 Ci.nsICacheStorage.OPEN_TRUNCATE, 71 lci, 72 new OpenCallback(NEW | WAITFORWRITE, "m" + i, "p" + i, function () { 73 mc.fired(); 74 }) 75 ); 76 77 mc.add(); 78 asyncOpenCacheEntry( 79 "http://common" + i + "/", 80 "disk", 81 Ci.nsICacheStorage.OPEN_TRUNCATE, 82 lci, 83 new OpenCallback(NEW | WAITFORWRITE, "m" + i, "d" + i, function () { 84 mc.fired(); 85 }) 86 ); 87 } 88 89 mc.fired(); // Goes to (2) 90 91 Services.obs.addObserver( 92 { 93 observe() { 94 // (3) 95 96 log_("after purge"); 97 // Prevent the I/O thread from evicting physically the data. We first want to re-open the entries. 98 // This deterministically emulates a slow hard drive. 99 testingInterface.suspendCacheIOThread(7); 100 101 log_("clearing"); 102 // Now clear everything except pinned. Stores the "ce_*" file and schedules background eviction. 103 Services.cache2.clear(); 104 log_("cleared"); 105 106 log_("second set of opens"); 107 // Now open again. Pinned entries should be there, disk entries should be the renewed entries. 108 // Callbacks 21-40 109 for (i = 0; i < kENTRYCOUNT; ++i) { 110 mc.add(); 111 asyncOpenCacheEntry( 112 "http://pinned" + i + "/", 113 "disk", 114 Ci.nsICacheStorage.OPEN_NORMALLY, 115 lci, 116 new OpenCallback(NORMAL, "m" + i, "p" + i, function () { 117 mc.fired(); 118 }) 119 ); 120 121 mc.add(); 122 asyncOpenCacheEntry( 123 "http://common" + i + "/", 124 "disk", 125 Ci.nsICacheStorage.OPEN_NORMALLY, 126 lci, 127 new OpenCallback(NEW, "m2" + i, "d2" + i, function () { 128 mc.fired(); 129 }) 130 ); 131 } 132 133 // Resume IO, this will just pop-off the CacheFileContextEvictor::EvictEntries() because of 134 // an early check on CacheIOThread::YieldAndRerun() in that method. 135 // CacheFileIOManager::OpenFileInternal should now run and CacheFileContextEvictor::WasEvicted 136 // should be checked on. 137 log_("resuming"); 138 testingInterface.resumeCacheIOThread(); 139 log_("resumed"); 140 141 mc.fired(); // Finishes this test 142 }, 143 }, 144 "cacheservice:purge-memory-pools" 145 ); 146 147 do_test_pending(); 148 }