test_cache-entry-id.js (5466B)
1 /** 2 * Test for the "CacheEntryId" under several cases. 3 */ 4 5 "use strict"; 6 7 const { HttpServer } = ChromeUtils.importESModule( 8 "resource://testing-common/httpd.sys.mjs" 9 ); 10 11 ChromeUtils.defineLazyGetter(this, "URL", function () { 12 return "http://localhost:" + httpServer.identity.primaryPort + "/content"; 13 }); 14 15 var httpServer = null; 16 17 const responseContent = "response body"; 18 const responseContent2 = "response body 2"; 19 const altContent = "!@#$%^&*()"; 20 const altContentType = "text/binary"; 21 22 function isParentProcess() { 23 let appInfo = Cc["@mozilla.org/xre/app-info;1"]; 24 return ( 25 !appInfo || 26 Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT 27 ); 28 } 29 30 var handlers = [ 31 (m, r) => { 32 r.bodyOutputStream.write(responseContent, responseContent.length); 33 }, 34 (m, r) => { 35 r.setStatusLine(m.httpVersion, 304, "Not Modified"); 36 }, 37 (m, r) => { 38 r.setStatusLine(m.httpVersion, 304, "Not Modified"); 39 }, 40 (m, r) => { 41 r.setStatusLine(m.httpVersion, 304, "Not Modified"); 42 }, 43 (m, r) => { 44 r.setStatusLine(m.httpVersion, 304, "Not Modified"); 45 }, 46 (m, r) => { 47 r.bodyOutputStream.write(responseContent2, responseContent2.length); 48 }, 49 (m, r) => { 50 r.setStatusLine(m.httpVersion, 304, "Not Modified"); 51 }, 52 ]; 53 54 function contentHandler(metadata, response) { 55 response.setHeader("Content-Type", "text/plain"); 56 response.setHeader("Cache-Control", "no-cache"); 57 58 var handler = handlers.shift(); 59 if (handler) { 60 handler(metadata, response); 61 return; 62 } 63 64 Assert.ok(false, "Should not reach here."); 65 } 66 67 function fetch(preferredDataType = null) { 68 return new Promise(resolve => { 69 var chan = NetUtil.newChannel({ uri: URL, loadUsingSystemPrincipal: true }); 70 71 if (preferredDataType) { 72 var cc = chan.QueryInterface(Ci.nsICacheInfoChannel); 73 cc.preferAlternativeDataType( 74 altContentType, 75 "", 76 Ci.nsICacheInfoChannel.ASYNC 77 ); 78 } 79 80 chan.asyncOpen( 81 new ChannelListener((request, buffer, ctx, isFromCache, cacheEntryId) => { 82 resolve({ request, buffer, isFromCache, cacheEntryId }); 83 }, null) 84 ); 85 }); 86 } 87 88 function check( 89 response, 90 content, 91 preferredDataType, 92 isFromCache, 93 cacheEntryIdChecker 94 ) { 95 var cc = response.request.QueryInterface(Ci.nsICacheInfoChannel); 96 97 Assert.equal(response.buffer, content); 98 Assert.equal(cc.alternativeDataType, preferredDataType); 99 Assert.equal(response.isFromCache, isFromCache); 100 Assert.ok(!cacheEntryIdChecker || cacheEntryIdChecker(response.cacheEntryId)); 101 102 return response; 103 } 104 105 function writeAltData(request) { 106 var cc = request.QueryInterface(Ci.nsICacheInfoChannel); 107 var os = cc.openAlternativeOutputStream(altContentType, altContent.length); 108 os.write(altContent, altContent.length); 109 os.close(); 110 gc(); // We need to do a GC pass to ensure the cache entry has been freed. 111 112 return new Promise(resolve => { 113 if (isParentProcess()) { 114 Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(resolve); 115 } else { 116 do_send_remote_message("flush"); 117 do_await_remote_message("flushed").then(resolve); 118 } 119 }); 120 } 121 122 function run_test() { 123 do_get_profile(); 124 httpServer = new HttpServer(); 125 httpServer.registerPathHandler("/content", contentHandler); 126 httpServer.start(-1); 127 do_test_pending(); 128 129 var targetCacheEntryId = null; 130 var secondCacheEntryId = null; 131 132 return ( 133 Promise.resolve() 134 // Setup testing environment: Placing alternative data into HTTP cache. 135 .then(_ => fetch(altContentType)) 136 .then(r => 137 check( 138 r, 139 responseContent, 140 "", 141 false, 142 cacheEntryId => cacheEntryId !== undefined 143 ) 144 ) 145 .then(r => { 146 targetCacheEntryId = r.cacheEntryId; 147 writeAltData(r.request); 148 }) 149 150 // Start testing. 151 .then(_ => fetch(altContentType)) 152 .then(r => 153 check( 154 r, 155 altContent, 156 altContentType, 157 true, 158 cacheEntryId => cacheEntryId !== undefined 159 ) 160 ) 161 162 .then(_ => fetch()) 163 .then(r => 164 check( 165 r, 166 responseContent, 167 "", 168 true, 169 cacheEntryId => cacheEntryId === targetCacheEntryId 170 ) 171 ) 172 173 .then(_ => fetch(altContentType)) 174 .then(r => 175 check( 176 r, 177 altContent, 178 altContentType, 179 true, 180 cacheEntryId => cacheEntryId === targetCacheEntryId 181 ) 182 ) 183 184 .then(_ => fetch()) 185 .then(r => 186 check( 187 r, 188 responseContent, 189 "", 190 true, 191 cacheEntryId => cacheEntryId === targetCacheEntryId 192 ) 193 ) 194 195 .then(_ => fetch()) // The response is changed here. 196 .then(r => 197 check( 198 r, 199 responseContent2, 200 "", 201 false, 202 cacheEntryId => 203 cacheEntryId !== undefined && cacheEntryId !== targetCacheEntryId 204 ) 205 ) 206 .then(r => { 207 secondCacheEntryId = r.cacheEntryId; 208 }) 209 210 .then(_ => fetch()) 211 .then(r => 212 check( 213 r, 214 responseContent2, 215 "", 216 true, 217 cacheEntryId => cacheEntryId === secondCacheEntryId 218 ) 219 ) 220 221 // Tear down. 222 .catch(e => Assert.ok(false, "Unexpected exception: " + e)) 223 .then(_ => Assert.equal(handlers.length, 0)) 224 .then(_ => httpServer.stop(do_test_finished)) 225 ); 226 }