async_load_tests.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Test to ensure that image loading/decoding notifications are always
  3. * delivered async, and in the order we expect.
  4. *
  5. * Must be included from a file that has a uri of the image to test defined in
  6. * var uri.
  7. */
  8. var Cc = Components.classes;
  9. var Ci = Components.interfaces;
  10. var Cu = Components.utils;
  11. var Cr = Components.results;
  12. Cu.import("resource://testing-common/httpd.js");
  13. Cu.import("resource://gre/modules/NetUtil.jsm");
  14. var server = new HttpServer();
  15. server.registerDirectory("/", do_get_file(''));
  16. server.registerContentType("sjs", "sjs");
  17. server.start(-1);
  18. load('image_load_helpers.js');
  19. var requests = [];
  20. // Return a closure that holds on to the listener from the original
  21. // imgIRequest, and compares its results to the cloned one.
  22. function getCloneStopCallback(original_listener)
  23. {
  24. return function cloneStop(listener) {
  25. do_check_eq(original_listener.state, listener.state);
  26. // Sanity check to make sure we didn't accidentally use the same listener
  27. // twice.
  28. do_check_neq(original_listener, listener);
  29. do_test_finished();
  30. }
  31. }
  32. // Make sure that cloned requests get all the same callbacks as the original,
  33. // but they aren't synchronous right now.
  34. function checkClone(other_listener, aRequest)
  35. {
  36. do_test_pending();
  37. // For as long as clone notification is synchronous, we can't test the clone state reliably.
  38. var listener = new ImageListener(null, function(foo, bar) { do_test_finished(); } /*getCloneStopCallback(other_listener)*/);
  39. listener.synchronous = false;
  40. var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
  41. .createScriptedObserver(listener);
  42. var clone = aRequest.clone(outer);
  43. requests.push(clone);
  44. }
  45. // Ensure that all the callbacks were called on aRequest.
  46. function checkSizeAndLoad(listener, aRequest)
  47. {
  48. do_check_neq(listener.state & SIZE_AVAILABLE, 0);
  49. do_check_neq(listener.state & LOAD_COMPLETE, 0);
  50. do_test_finished();
  51. }
  52. function secondLoadDone(oldlistener, aRequest)
  53. {
  54. do_test_pending();
  55. try {
  56. var staticrequest = aRequest.getStaticRequest();
  57. // For as long as clone notification is synchronous, we can't test the
  58. // clone state reliably.
  59. var listener = new ImageListener(null, checkSizeAndLoad);
  60. listener.synchronous = false;
  61. var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
  62. .createScriptedObserver(listener);
  63. var staticrequestclone = staticrequest.clone(outer);
  64. requests.push(staticrequestclone);
  65. } catch(e) {
  66. // We can't create a static request. Most likely the request we started
  67. // with didn't load successfully.
  68. do_test_finished();
  69. }
  70. run_loadImageWithChannel_tests();
  71. do_test_finished();
  72. }
  73. // Load the request a second time. This should come from the image cache, and
  74. // therefore would be at most risk of being served synchronously.
  75. function checkSecondLoad()
  76. {
  77. do_test_pending();
  78. var listener = new ImageListener(checkClone, secondLoadDone);
  79. var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
  80. .createScriptedObserver(listener);
  81. requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, "default", null, null, outer, null, 0, null));
  82. listener.synchronous = false;
  83. }
  84. function firstLoadDone(oldlistener, aRequest)
  85. {
  86. checkSecondLoad(uri);
  87. do_test_finished();
  88. }
  89. // Return a closure that allows us to check the stream listener's status when the
  90. // image finishes loading.
  91. function getChannelLoadImageStopCallback(streamlistener, next)
  92. {
  93. return function channelLoadStop(imglistener, aRequest) {
  94. next();
  95. do_test_finished();
  96. }
  97. }
  98. // Load the request a second time. This should come from the image cache, and
  99. // therefore would be at most risk of being served synchronously.
  100. function checkSecondChannelLoad()
  101. {
  102. do_test_pending();
  103. var channel = NetUtil.newChannel({uri: uri, loadUsingSystemPrincipal: true});
  104. var channellistener = new ChannelListener();
  105. channel.asyncOpen2(channellistener);
  106. var listener = new ImageListener(null,
  107. getChannelLoadImageStopCallback(channellistener,
  108. all_done_callback));
  109. var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
  110. .createScriptedObserver(listener);
  111. var outlistener = {};
  112. requests.push(gCurrentLoader.loadImageWithChannelXPCOM(channel, outer, null, outlistener));
  113. channellistener.outputListener = outlistener.value;
  114. listener.synchronous = false;
  115. }
  116. function run_loadImageWithChannel_tests()
  117. {
  118. // To ensure we're testing what we expect to, create a new loader and cache.
  119. gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
  120. do_test_pending();
  121. var channel = NetUtil.newChannel({uri: uri, loadUsingSystemPrincipal: true});
  122. var channellistener = new ChannelListener();
  123. channel.asyncOpen2(channellistener);
  124. var listener = new ImageListener(null,
  125. getChannelLoadImageStopCallback(channellistener,
  126. checkSecondChannelLoad));
  127. var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
  128. .createScriptedObserver(listener);
  129. var outlistener = {};
  130. requests.push(gCurrentLoader.loadImageWithChannelXPCOM(channel, outer, null, outlistener));
  131. channellistener.outputListener = outlistener.value;
  132. listener.synchronous = false;
  133. }
  134. function all_done_callback()
  135. {
  136. server.stop(function() { do_test_finished(); });
  137. }
  138. function startImageCallback(otherCb)
  139. {
  140. return function(listener, request)
  141. {
  142. // Make sure we can load the same image immediately out of the cache.
  143. do_test_pending();
  144. var listener2 = new ImageListener(null, function(foo, bar) { do_test_finished(); });
  145. var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
  146. .createScriptedObserver(listener2);
  147. requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, "default", null, null, outer, null, 0, null));
  148. listener2.synchronous = false;
  149. // Now that we've started another load, chain to the callback.
  150. otherCb(listener, request);
  151. }
  152. }
  153. var gCurrentLoader;
  154. function cleanup()
  155. {
  156. for (var i = 0; i < requests.length; ++i) {
  157. requests[i].cancelAndForgetObserver(0);
  158. }
  159. }
  160. function run_test()
  161. {
  162. do_register_cleanup(cleanup);
  163. gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
  164. do_test_pending();
  165. var listener = new ImageListener(startImageCallback(checkClone), firstLoadDone);
  166. var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
  167. .createScriptedObserver(listener);
  168. var req = gCurrentLoader.loadImageXPCOM(uri, null, null, "default", null, null, outer, null, 0, null);
  169. requests.push(req);
  170. // Ensure that we don't cause any mayhem when we lock an image.
  171. req.lockImage();
  172. listener.synchronous = false;
  173. }