1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/test/TestCacheCollisions.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,291 @@ 1.4 +var DEBUG = true; 1.5 + 1.6 +var clientID = "HTTP"; 1.7 +var nsICache = Components.interfaces.nsICache; 1.8 + 1.9 +function getEventQueue() 1.10 +{ 1.11 + var nsIEventQueueService = Components.interfaces.nsIEventQueueService; 1.12 + var CID = Components.classes["@mozilla.org/event-queue-service;1"]; 1.13 + var service = CID.getService(nsIEventQueueService); 1.14 + return service.getSpecialEventQueue(nsIEventQueueService.CURRENT_THREAD_EVENT_QUEUE); 1.15 +} 1.16 + 1.17 +var eventQueue = getEventQueue(); 1.18 + 1.19 +function getCacheService() 1.20 +{ 1.21 + var nsCacheService = Components.classes["@mozilla.org/network/cache-service;1"]; 1.22 + var service = nsCacheService.getService(Components.interfaces.nsICacheService); 1.23 + return service; 1.24 +} 1.25 + 1.26 +function createCacheSession(clientID, storagePolicy, streamable) 1.27 +{ 1.28 + var service = getCacheService(); 1.29 + var session = service.createSession(clientID, storagePolicy, streamable); 1.30 + return session; 1.31 +} 1.32 + 1.33 +function openCacheEntry(url, mode) 1.34 +{ 1.35 + var session = createCacheSession(clientID, nsICache.STORE_ON_DISK, true); 1.36 + var entry = session.openCacheEntry(url, mode); 1.37 + return entry; 1.38 +} 1.39 + 1.40 +function wrapInputStream(input) 1.41 +{ 1.42 + var nsIScriptableInputStream = Components.interfaces.nsIScriptableInputStream; 1.43 + var factory = Components.classes["@mozilla.org/scriptableinputstream;1"]; 1.44 + var wrapper = factory.createInstance(nsIScriptableInputStream); 1.45 + wrapper.init(input); 1.46 + return wrapper; 1.47 +} 1.48 + 1.49 +function download(key) 1.50 +{ 1.51 + var url = new java.net.URL(key); 1.52 + var data = ""; 1.53 + var buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 65536); 1.54 + var stream = url.openStream(); 1.55 + while (true) { 1.56 + var count = stream.read(buffer); 1.57 + if (count <= 0) 1.58 + break; 1.59 + var str = new java.lang.String(buffer, 0, count); 1.60 + data += str; 1.61 + } 1.62 + stream.close(); 1.63 + return data; 1.64 +} 1.65 + 1.66 +function write(url, data) 1.67 +{ 1.68 + var key = url.toString(); 1.69 + var outputEntry = openCacheEntry(key, nsICache.ACCESS_WRITE); 1.70 + var output = outputEntry.transport.openOutputStream(0, -1, 0); 1.71 + var count = output.write(data, data.length); 1.72 + 1.73 + // store some metadata. 1.74 + outputEntry.setMetaDataElement("size", data.length); 1.75 + 1.76 + output.close(); 1.77 + outputEntry.markValid(); 1.78 + outputEntry.close(); 1.79 + 1.80 + return count; 1.81 +} 1.82 + 1.83 +function CacheListener() 1.84 +{ 1.85 + this.done = false; 1.86 +} 1.87 + 1.88 +CacheListener.prototype = { 1.89 + QueryInterface : function(iid) 1.90 + { 1.91 + if (iid.equals(Components.interfaces.nsICacheListener)) 1.92 + return this; 1.93 + throw Components.results.NS_NOINTERFACE; 1.94 + }, 1.95 + 1.96 + onCacheEntryAvailable : function(/* in nsICacheEntryDescriptor */ descriptor, 1.97 + /* in nsCacheAccessMode */ accessGranted, 1.98 + /* in nsresult */ status) 1.99 + { 1.100 + this.descriptor = descriptor; 1.101 + this.status = status; 1.102 + this.done = true; 1.103 + } 1.104 +}; 1.105 + 1.106 +function asyncOpenCacheEntry(url, mode) 1.107 +{ 1.108 + var session = createCacheSession(clientID, nsICache.STORE_ON_DISK, true); 1.109 + var listener = new CacheListener(); 1.110 + session.asyncOpenCacheEntry(url, mode, listener); 1.111 + while (!listener.done) 1.112 + eventQueue.processPendingEvents(); 1.113 + return listener.descriptor; 1.114 +} 1.115 + 1.116 +function asyncWrite(key, data) 1.117 +{ 1.118 + var outputEntry = asyncOpenCacheEntry(key, nsICache.ACCESS_WRITE); 1.119 + 1.120 + var output = outputEntry.transport.openOutputStream(0, -1, 0); 1.121 + var count = output.write(data, data.length); 1.122 + 1.123 + // store some metadata. 1.124 + outputEntry.setMetaDataElement("size", data.length); 1.125 + 1.126 + output.close(); 1.127 + outputEntry.markValid(); 1.128 + outputEntry.close(); 1.129 + 1.130 + return count; 1.131 +} 1.132 + 1.133 +function StreamListener() 1.134 +{ 1.135 + this.done = false; 1.136 + this.data = ""; 1.137 + this.wrapper = null; 1.138 +} 1.139 + 1.140 +StreamListener.prototype = { 1.141 + QueryInterface : function(iid) 1.142 + { 1.143 + if (iid.equals(Components.interfaces.nsIStreamListener) || 1.144 + iid.equals(Components.interfaces.nsIStreamObserver)) 1.145 + return this; 1.146 + throw Components.results.NS_NOINTERFACE; 1.147 + }, 1.148 + 1.149 + onStartRequest : function(request, context) 1.150 + { 1.151 + }, 1.152 + 1.153 + onStopRequest : function(request, context, statusCode, statusText) 1.154 + { 1.155 + this.statusCode = statusCode; 1.156 + this.done = true; 1.157 + }, 1.158 + 1.159 + onDataAvailable : function(request, context, input, offset, count) 1.160 + { 1.161 + if (this.wrapper == null) 1.162 + this.wrapper = wrapInputStream(input); 1.163 + input = this.wrapper; 1.164 + this.data += input.read(count); 1.165 + } 1.166 +}; 1.167 + 1.168 +function asyncRead(key) 1.169 +{ 1.170 + var inputEntry = asyncOpenCacheEntry(key, nsICache.ACCESS_READ); 1.171 + var listener = new StreamListener(); 1.172 + inputEntry.transport.asyncRead(listener, null, 0, inputEntry.dataSize, 0); 1.173 + while (!listener.done) 1.174 + eventQueue.processPendingEvents(); 1.175 + inputEntry.close(); 1.176 + return listener.data; 1.177 +} 1.178 + 1.179 +function read(key) 1.180 +{ 1.181 + var inputEntry = openCacheEntry(key, nsICache.ACCESS_READ); 1.182 + var input = wrapInputStream(inputEntry.transport.openInputStream(0, -1, 0)); 1.183 + var data = input.read(input.available()); 1.184 + input.close(); 1.185 + inputEntry.close(); 1.186 + return data; 1.187 +} 1.188 + 1.189 +function readMetaData(key, element) 1.190 +{ 1.191 + var inputEntry = openCacheEntry(key, nsICache.ACCESS_READ); 1.192 + var metadata = inputEntry.getMetaDataElement(element); 1.193 + inputEntry.close(); 1.194 + return metadata; 1.195 +} 1.196 + 1.197 +function doom(url) 1.198 +{ 1.199 + var key = url.toString(); 1.200 + var doomedEntry = openCacheEntry(key, nsICache.ACCESS_READ_WRITE); 1.201 + doomedEntry.doom(); 1.202 + doomedEntry.close(); 1.203 +} 1.204 + 1.205 +// two keys which are known to collide right now. 1.206 +var key1 = "http://a772.g.akamai.net/7/772/51/7648437e551b56/www.apple.com/t/2001/us/en/i/2.gif"; 1.207 +var key2 = "http://a772.g.akamai.net/7/772/51/70601300d0bde6/www.apple.com/t/2001/us/en/i/1right.gif"; 1.208 + 1.209 +function test() 1.210 +{ 1.211 + // 1. generate a collision, and close the colliding entry first. 1.212 + var entry1 = asyncOpenCacheEntry(key1, nsICache.ACCESS_READ_WRITE); 1.213 + var data1 = key1; 1.214 + entry1.setMetaDataElement("size", data1.length); 1.215 + entry1.markValid(); 1.216 + var output1 = entry1.transport.openOutputStream(0, -1, 0); 1.217 + output1.write(data1, data1.length); 1.218 + 1.219 + var entry2 = asyncOpenCacheEntry(key2, nsICache.ACCESS_READ_WRITE); 1.220 + var data2 = key2; 1.221 + entry2.setMetaDataElement("size", data2.length); 1.222 + entry2.markValid(); 1.223 + var output2 = entry2.transport.openOutputStream(0, -1, 0); 1.224 + output2.write(data2, data2.length); 1.225 + 1.226 + output1.close(); 1.227 + output2.close(); 1.228 + 1.229 + entry1.close(); 1.230 + entry2.close(); 1.231 +} 1.232 + 1.233 +function median(array) 1.234 +{ 1.235 + var cmp = function(x, y) { return x - y; } 1.236 + array.sort(cmp); 1.237 + var middle = Math.floor(array.length / 2); 1.238 + return array[middle]; 1.239 +} 1.240 + 1.241 +function sum(array) 1.242 +{ 1.243 + var s = 0; 1.244 + var len = array.length; 1.245 + for (var i = 0; i < len; ++i) 1.246 + s += array[i]; 1.247 + return s; 1.248 +} 1.249 + 1.250 +function time() 1.251 +{ 1.252 + var N = 50; 1.253 + var System = java.lang.System; 1.254 + var url = new java.net.URL("http://www.mozilla.org"); 1.255 + var key = url.toString(); 1.256 + var downloadTimes = new Array(); 1.257 + for (var i = 0; i < N; ++i) { 1.258 + var begin = System.currentTimeMillis(); 1.259 + download(url); 1.260 + var end = System.currentTimeMillis(); 1.261 + downloadTimes.push(end - begin); 1.262 + } 1.263 + var downloadTotal = sum(downloadTimes); 1.264 + var downloadMean = downloadTotal / N; 1.265 + var downloadMedian = median(downloadTimes); 1.266 + print("" + N + " downloads took " + downloadTotal + " milliseconds."); 1.267 + print("mean = " + downloadMean + " milliseconds."); 1.268 + print("median = " + downloadMedian + " milliseconds."); 1.269 + 1.270 + var readTimes = new Array(); 1.271 + for (var i = 0; i < N; ++i) { 1.272 + var begin = System.currentTimeMillis(); 1.273 + asyncRead(key); 1.274 + var end = System.currentTimeMillis(); 1.275 + readTimes.push(end - begin); 1.276 + } 1.277 + var readTotal = sum(readTimes); 1.278 + var readMean = readTotal / N; 1.279 + var readMedian = median(readTimes); 1.280 + print("" + N + " reads took " + readTotal + " milliseconds."); 1.281 + print("mean = " + readMean + " milliseconds."); 1.282 + print("median = " + readMedian + " milliseconds."); 1.283 +} 1.284 + 1.285 +// load the cache service before doing anything with Java... 1.286 +getCacheService(); 1.287 + 1.288 +if (DEBUG) { 1.289 + print("cache service loaded."); 1.290 +} else { 1.291 + print("running disk cache test."); 1.292 + test(); 1.293 + print("disk cache test complete."); 1.294 +}