netwerk/test/TestCacheCollisions.js

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     1 var DEBUG = true;
     3 var clientID = "HTTP";
     4 var nsICache = Components.interfaces.nsICache;
     6 function getEventQueue()
     7 {
     8     var nsIEventQueueService = Components.interfaces.nsIEventQueueService;
     9     var CID = Components.classes["@mozilla.org/event-queue-service;1"];
    10     var service = CID.getService(nsIEventQueueService);
    11     return service.getSpecialEventQueue(nsIEventQueueService.CURRENT_THREAD_EVENT_QUEUE);
    12 }
    14 var eventQueue = getEventQueue();
    16 function getCacheService()
    17 {
    18     var nsCacheService = Components.classes["@mozilla.org/network/cache-service;1"];
    19     var service = nsCacheService.getService(Components.interfaces.nsICacheService);
    20     return service;
    21 }
    23 function createCacheSession(clientID, storagePolicy, streamable)
    24 {
    25     var service = getCacheService();
    26     var session = service.createSession(clientID, storagePolicy, streamable);
    27     return session;
    28 }
    30 function openCacheEntry(url, mode)
    31 {
    32     var session = createCacheSession(clientID, nsICache.STORE_ON_DISK, true);
    33     var entry = session.openCacheEntry(url, mode);
    34     return entry;
    35 }
    37 function wrapInputStream(input)
    38 {
    39     var nsIScriptableInputStream = Components.interfaces.nsIScriptableInputStream;
    40     var factory = Components.classes["@mozilla.org/scriptableinputstream;1"];
    41     var wrapper = factory.createInstance(nsIScriptableInputStream);
    42     wrapper.init(input);
    43     return wrapper;
    44 }
    46 function download(key)
    47 {
    48     var url = new java.net.URL(key);
    49     var data = "";
    50     var buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 65536);
    51     var stream = url.openStream();
    52     while (true) {
    53         var count = stream.read(buffer);
    54         if (count <= 0)
    55             break;
    56         var str = new java.lang.String(buffer, 0, count);
    57         data += str;
    58     }
    59     stream.close();
    60     return data;
    61 }
    63 function write(url, data)
    64 {
    65     var key = url.toString();
    66     var outputEntry = openCacheEntry(key, nsICache.ACCESS_WRITE);
    67     var output = outputEntry.transport.openOutputStream(0, -1, 0);
    68     var count = output.write(data, data.length);
    70     // store some metadata.
    71     outputEntry.setMetaDataElement("size", data.length);
    73     output.close();
    74     outputEntry.markValid();
    75     outputEntry.close();
    77     return count;
    78 }
    80 function CacheListener()
    81 {
    82     this.done = false;
    83 }
    85 CacheListener.prototype = {
    86     QueryInterface : function(iid)
    87     {
    88         if (iid.equals(Components.interfaces.nsICacheListener))
    89             return this;
    90         throw Components.results.NS_NOINTERFACE;
    91     },
    93     onCacheEntryAvailable : function(/* in nsICacheEntryDescriptor */   descriptor,
    94                                      /* in nsCacheAccessMode */         accessGranted,
    95                                      /* in nsresult */                  status)
    96     {
    97         this.descriptor = descriptor;
    98         this.status = status;
    99         this.done = true;
   100     }
   101 };
   103 function asyncOpenCacheEntry(url, mode)
   104 {
   105     var session = createCacheSession(clientID, nsICache.STORE_ON_DISK, true);
   106     var listener = new CacheListener();
   107     session.asyncOpenCacheEntry(url, mode, listener);
   108     while (!listener.done)
   109         eventQueue.processPendingEvents();
   110     return listener.descriptor;
   111 }
   113 function asyncWrite(key, data)
   114 {
   115     var outputEntry = asyncOpenCacheEntry(key, nsICache.ACCESS_WRITE);
   117     var output = outputEntry.transport.openOutputStream(0, -1, 0);
   118     var count = output.write(data, data.length);
   120     // store some metadata.
   121     outputEntry.setMetaDataElement("size", data.length);
   123     output.close();
   124     outputEntry.markValid();
   125     outputEntry.close();
   127     return count;
   128 }
   130 function StreamListener()
   131 {
   132     this.done = false;
   133     this.data = "";
   134     this.wrapper = null;
   135 }
   137 StreamListener.prototype = {
   138     QueryInterface : function(iid)
   139     {
   140         if (iid.equals(Components.interfaces.nsIStreamListener) ||
   141             iid.equals(Components.interfaces.nsIStreamObserver))
   142             return this;
   143         throw Components.results.NS_NOINTERFACE;
   144     },
   146     onStartRequest : function(request, context)
   147     {
   148     },
   150     onStopRequest : function(request, context, statusCode, statusText)
   151     {
   152         this.statusCode = statusCode;
   153         this.done = true;
   154     },
   156     onDataAvailable : function(request, context, input, offset, count)
   157     {
   158         if (this.wrapper == null)
   159             this.wrapper = wrapInputStream(input);
   160         input = this.wrapper;
   161         this.data += input.read(count);
   162     }
   163 };
   165 function asyncRead(key)
   166 {
   167     var inputEntry = asyncOpenCacheEntry(key, nsICache.ACCESS_READ);
   168     var listener = new StreamListener();
   169     inputEntry.transport.asyncRead(listener, null, 0, inputEntry.dataSize, 0);
   170     while (!listener.done)
   171         eventQueue.processPendingEvents();
   172     inputEntry.close();
   173     return listener.data;
   174 }
   176 function read(key)
   177 {
   178     var inputEntry = openCacheEntry(key, nsICache.ACCESS_READ);
   179     var input = wrapInputStream(inputEntry.transport.openInputStream(0, -1, 0));
   180     var data = input.read(input.available());
   181     input.close();
   182     inputEntry.close();
   183     return data;
   184 }
   186 function readMetaData(key, element)
   187 {
   188     var inputEntry = openCacheEntry(key, nsICache.ACCESS_READ);
   189     var metadata = inputEntry.getMetaDataElement(element);
   190     inputEntry.close();
   191     return metadata;
   192 }
   194 function doom(url)
   195 {
   196     var key = url.toString();
   197     var doomedEntry = openCacheEntry(key, nsICache.ACCESS_READ_WRITE);
   198     doomedEntry.doom();
   199     doomedEntry.close();
   200 }
   202 // two keys which are known to collide right now.
   203 var key1 = "http://a772.g.akamai.net/7/772/51/7648437e551b56/www.apple.com/t/2001/us/en/i/2.gif";
   204 var key2 = "http://a772.g.akamai.net/7/772/51/70601300d0bde6/www.apple.com/t/2001/us/en/i/1right.gif";
   206 function test()
   207 {
   208     // 1. generate a collision, and close the colliding entry first.
   209     var entry1 = asyncOpenCacheEntry(key1, nsICache.ACCESS_READ_WRITE);
   210     var data1 = key1;
   211     entry1.setMetaDataElement("size", data1.length);
   212     entry1.markValid();
   213     var output1 = entry1.transport.openOutputStream(0, -1, 0);
   214     output1.write(data1, data1.length);
   216     var entry2 = asyncOpenCacheEntry(key2, nsICache.ACCESS_READ_WRITE);
   217     var data2 = key2;
   218     entry2.setMetaDataElement("size", data2.length);
   219     entry2.markValid();
   220     var output2 = entry2.transport.openOutputStream(0, -1, 0);
   221     output2.write(data2, data2.length);
   223     output1.close();
   224     output2.close();
   226     entry1.close();
   227     entry2.close();
   228 }
   230 function median(array)
   231 {
   232     var cmp = function(x, y) { return x - y; }
   233     array.sort(cmp);
   234     var middle = Math.floor(array.length / 2);
   235     return array[middle];
   236 }
   238 function sum(array)
   239 {
   240     var s = 0;
   241     var len = array.length;
   242     for (var i = 0; i < len; ++i)
   243         s += array[i];
   244     return s;
   245 }
   247 function time()
   248 {
   249     var N = 50;
   250     var System = java.lang.System;
   251     var url = new java.net.URL("http://www.mozilla.org");
   252     var key = url.toString();
   253     var downloadTimes = new Array();
   254     for (var i = 0; i < N; ++i) {
   255         var begin = System.currentTimeMillis();
   256         download(url);
   257         var end = System.currentTimeMillis();
   258         downloadTimes.push(end - begin);
   259     }
   260     var downloadTotal = sum(downloadTimes);
   261     var downloadMean = downloadTotal / N;
   262     var downloadMedian = median(downloadTimes);
   263     print("" + N + " downloads took " + downloadTotal + " milliseconds.");
   264     print("mean = " + downloadMean + " milliseconds.");
   265     print("median = " + downloadMedian + " milliseconds.");
   267     var readTimes = new Array();
   268     for (var i = 0; i < N; ++i) {
   269         var begin = System.currentTimeMillis();
   270         asyncRead(key);
   271         var end = System.currentTimeMillis();
   272         readTimes.push(end - begin);
   273     }
   274     var readTotal = sum(readTimes);
   275     var readMean = readTotal / N;
   276     var readMedian = median(readTimes);
   277     print("" + N + " reads took " + readTotal + " milliseconds.");
   278     print("mean = " + readMean + " milliseconds.");
   279     print("median = " + readMedian + " milliseconds.");
   280 }
   282 // load the cache service before doing anything with Java...
   283 getCacheService();
   285 if (DEBUG) {
   286     print("cache service loaded.");
   287 } else {
   288     print("running disk cache test.");
   289     test();
   290     print("disk cache test complete.");
   291 }

mercurial