1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/image/test/unit/async_load_tests.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,231 @@ 1.4 +/* 1.5 + * Test to ensure that image loading/decoding notifications are always 1.6 + * delivered async, and in the order we expect. 1.7 + * 1.8 + * Must be included from a file that has a uri of the image to test defined in 1.9 + * var uri. 1.10 + */ 1.11 + 1.12 +const Cc = Components.classes; 1.13 +const Ci = Components.interfaces; 1.14 +const Cu = Components.utils; 1.15 +const Cr = Components.results; 1.16 + 1.17 +Cu.import("resource://testing-common/httpd.js"); 1.18 + 1.19 +var server = new HttpServer(); 1.20 +server.registerDirectory("/", do_get_file('')); 1.21 +server.registerContentType("sjs", "sjs"); 1.22 +server.start(-1); 1.23 + 1.24 + 1.25 +load('image_load_helpers.js'); 1.26 + 1.27 +var requests = []; 1.28 + 1.29 +// Return a closure that holds on to the listener from the original 1.30 +// imgIRequest, and compares its results to the cloned one. 1.31 +function getCloneStopCallback(original_listener) 1.32 +{ 1.33 + return function cloneStop(listener) { 1.34 + do_check_eq(original_listener.state, listener.state); 1.35 + 1.36 + // Sanity check to make sure we didn't accidentally use the same listener 1.37 + // twice. 1.38 + do_check_neq(original_listener, listener); 1.39 + do_test_finished(); 1.40 + } 1.41 +} 1.42 + 1.43 +// Make sure that cloned requests get all the same callbacks as the original, 1.44 +// but they aren't synchronous right now. 1.45 +function checkClone(other_listener, aRequest) 1.46 +{ 1.47 + do_test_pending(); 1.48 + 1.49 + // For as long as clone notification is synchronous, we can't test the clone state reliably. 1.50 + var listener = new ImageListener(null, function(foo, bar) { do_test_finished(); } /*getCloneStopCallback(other_listener)*/); 1.51 + listener.synchronous = false; 1.52 + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) 1.53 + .createScriptedObserver(listener); 1.54 + var clone = aRequest.clone(outer); 1.55 + requests.push(clone); 1.56 +} 1.57 + 1.58 +// Ensure that all the callbacks were called on aRequest. 1.59 +function checkSizeAndLoad(listener, aRequest) 1.60 +{ 1.61 + do_check_neq(listener.state & SIZE_AVAILABLE, 0); 1.62 + do_check_neq(listener.state & LOAD_COMPLETE, 0); 1.63 + 1.64 + do_test_finished(); 1.65 +} 1.66 + 1.67 +function secondLoadDone(oldlistener, aRequest) 1.68 +{ 1.69 + do_test_pending(); 1.70 + 1.71 + try { 1.72 + var staticrequest = aRequest.getStaticRequest(); 1.73 + 1.74 + // For as long as clone notification is synchronous, we can't test the 1.75 + // clone state reliably. 1.76 + var listener = new ImageListener(null, checkSizeAndLoad); 1.77 + listener.synchronous = false; 1.78 + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) 1.79 + .createScriptedObserver(listener); 1.80 + var staticrequestclone = staticrequest.clone(outer); 1.81 + requests.push(staticrequestclone); 1.82 + } catch(e) { 1.83 + // We can't create a static request. Most likely the request we started 1.84 + // with didn't load successfully. 1.85 + do_test_finished(); 1.86 + } 1.87 + 1.88 + run_loadImageWithChannel_tests(); 1.89 + 1.90 + do_test_finished(); 1.91 +} 1.92 + 1.93 +// Load the request a second time. This should come from the image cache, and 1.94 +// therefore would be at most risk of being served synchronously. 1.95 +function checkSecondLoad() 1.96 +{ 1.97 + do_test_pending(); 1.98 + 1.99 + var listener = new ImageListener(checkClone, secondLoadDone); 1.100 + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) 1.101 + .createScriptedObserver(listener); 1.102 + requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, null, null, outer, null, 0, null, null)); 1.103 + listener.synchronous = false; 1.104 +} 1.105 + 1.106 +function firstLoadDone(oldlistener, aRequest) 1.107 +{ 1.108 + checkSecondLoad(uri); 1.109 + 1.110 + do_test_finished(); 1.111 +} 1.112 + 1.113 +// Return a closure that allows us to check the stream listener's status when the 1.114 +// image starts loading. 1.115 +function getChannelLoadImageStartCallback(streamlistener) 1.116 +{ 1.117 + return function channelLoadStart(imglistener, aRequest) { 1.118 + // We must not have received all status before we get this start callback. 1.119 + // If we have, we've broken people's expectations by delaying events from a 1.120 + // channel we were given. 1.121 + do_check_eq(streamlistener.requestStatus & STOP_REQUEST, 0); 1.122 + 1.123 + checkClone(imglistener, aRequest); 1.124 + } 1.125 +} 1.126 + 1.127 +// Return a closure that allows us to check the stream listener's status when the 1.128 +// image finishes loading. 1.129 +function getChannelLoadImageStopCallback(streamlistener, next) 1.130 +{ 1.131 + return function channelLoadStop(imglistener, aRequest) { 1.132 + 1.133 + next(); 1.134 + 1.135 + do_test_finished(); 1.136 + } 1.137 +} 1.138 + 1.139 +// Load the request a second time. This should come from the image cache, and 1.140 +// therefore would be at most risk of being served synchronously. 1.141 +function checkSecondChannelLoad() 1.142 +{ 1.143 + do_test_pending(); 1.144 + 1.145 + var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); 1.146 + var channel = ioService.newChannelFromURI(uri); 1.147 + var channellistener = new ChannelListener(); 1.148 + channel.asyncOpen(channellistener, null); 1.149 + 1.150 + var listener = new ImageListener(getChannelLoadImageStartCallback(channellistener), 1.151 + getChannelLoadImageStopCallback(channellistener, 1.152 + all_done_callback)); 1.153 + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) 1.154 + .createScriptedObserver(listener); 1.155 + var outlistener = {}; 1.156 + requests.push(gCurrentLoader.loadImageWithChannelXPCOM(channel, outer, null, outlistener)); 1.157 + channellistener.outputListener = outlistener.value; 1.158 + 1.159 + listener.synchronous = false; 1.160 +} 1.161 + 1.162 +function run_loadImageWithChannel_tests() 1.163 +{ 1.164 + // To ensure we're testing what we expect to, create a new loader and cache. 1.165 + gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader); 1.166 + 1.167 + do_test_pending(); 1.168 + 1.169 + var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); 1.170 + var channel = ioService.newChannelFromURI(uri); 1.171 + var channellistener = new ChannelListener(); 1.172 + channel.asyncOpen(channellistener, null); 1.173 + 1.174 + var listener = new ImageListener(getChannelLoadImageStartCallback(channellistener), 1.175 + getChannelLoadImageStopCallback(channellistener, 1.176 + checkSecondChannelLoad)); 1.177 + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) 1.178 + .createScriptedObserver(listener); 1.179 + var outlistener = {}; 1.180 + requests.push(gCurrentLoader.loadImageWithChannelXPCOM(channel, outer, null, outlistener)); 1.181 + channellistener.outputListener = outlistener.value; 1.182 + 1.183 + listener.synchronous = false; 1.184 +} 1.185 + 1.186 +function all_done_callback() 1.187 +{ 1.188 + server.stop(function() { do_test_finished(); }); 1.189 +} 1.190 + 1.191 +function startImageCallback(otherCb) 1.192 +{ 1.193 + return function(listener, request) 1.194 + { 1.195 + // Make sure we can load the same image immediately out of the cache. 1.196 + do_test_pending(); 1.197 + var listener2 = new ImageListener(null, function(foo, bar) { do_test_finished(); }); 1.198 + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) 1.199 + .createScriptedObserver(listener2); 1.200 + requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, null, null, outer, null, 0, null, null)); 1.201 + listener2.synchronous = false; 1.202 + 1.203 + // Now that we've started another load, chain to the callback. 1.204 + otherCb(listener, request); 1.205 + } 1.206 +} 1.207 + 1.208 +var gCurrentLoader; 1.209 + 1.210 +function cleanup() 1.211 +{ 1.212 + for (var i = 0; i < requests.length; ++i) { 1.213 + requests[i].cancelAndForgetObserver(0); 1.214 + } 1.215 +} 1.216 + 1.217 +function run_test() 1.218 +{ 1.219 + do_register_cleanup(cleanup); 1.220 + 1.221 + gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader); 1.222 + 1.223 + do_test_pending(); 1.224 + var listener = new ImageListener(startImageCallback(checkClone), firstLoadDone); 1.225 + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) 1.226 + .createScriptedObserver(listener); 1.227 + var req = gCurrentLoader.loadImageXPCOM(uri, null, null, null, null, outer, null, 0, null, null); 1.228 + requests.push(req); 1.229 + 1.230 + // Ensure that we don't cause any mayhem when we lock an image. 1.231 + req.lockImage(); 1.232 + 1.233 + listener.synchronous = false; 1.234 +}