image/test/unit/async_load_tests.js

branch
TOR_BUG_9701
changeset 14
925c144e1f1f
equal deleted inserted replaced
-1:000000000000 0:8105fc9f1a80
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
9 const Cc = Components.classes;
10 const Ci = Components.interfaces;
11 const Cu = Components.utils;
12 const Cr = Components.results;
13
14 Cu.import("resource://testing-common/httpd.js");
15
16 var server = new HttpServer();
17 server.registerDirectory("/", do_get_file(''));
18 server.registerContentType("sjs", "sjs");
19 server.start(-1);
20
21
22 load('image_load_helpers.js');
23
24 var requests = [];
25
26 // Return a closure that holds on to the listener from the original
27 // imgIRequest, and compares its results to the cloned one.
28 function getCloneStopCallback(original_listener)
29 {
30 return function cloneStop(listener) {
31 do_check_eq(original_listener.state, listener.state);
32
33 // Sanity check to make sure we didn't accidentally use the same listener
34 // twice.
35 do_check_neq(original_listener, listener);
36 do_test_finished();
37 }
38 }
39
40 // Make sure that cloned requests get all the same callbacks as the original,
41 // but they aren't synchronous right now.
42 function checkClone(other_listener, aRequest)
43 {
44 do_test_pending();
45
46 // For as long as clone notification is synchronous, we can't test the clone state reliably.
47 var listener = new ImageListener(null, function(foo, bar) { do_test_finished(); } /*getCloneStopCallback(other_listener)*/);
48 listener.synchronous = false;
49 var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
50 .createScriptedObserver(listener);
51 var clone = aRequest.clone(outer);
52 requests.push(clone);
53 }
54
55 // Ensure that all the callbacks were called on aRequest.
56 function checkSizeAndLoad(listener, aRequest)
57 {
58 do_check_neq(listener.state & SIZE_AVAILABLE, 0);
59 do_check_neq(listener.state & LOAD_COMPLETE, 0);
60
61 do_test_finished();
62 }
63
64 function secondLoadDone(oldlistener, aRequest)
65 {
66 do_test_pending();
67
68 try {
69 var staticrequest = aRequest.getStaticRequest();
70
71 // For as long as clone notification is synchronous, we can't test the
72 // clone state reliably.
73 var listener = new ImageListener(null, checkSizeAndLoad);
74 listener.synchronous = false;
75 var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
76 .createScriptedObserver(listener);
77 var staticrequestclone = staticrequest.clone(outer);
78 requests.push(staticrequestclone);
79 } catch(e) {
80 // We can't create a static request. Most likely the request we started
81 // with didn't load successfully.
82 do_test_finished();
83 }
84
85 run_loadImageWithChannel_tests();
86
87 do_test_finished();
88 }
89
90 // Load the request a second time. This should come from the image cache, and
91 // therefore would be at most risk of being served synchronously.
92 function checkSecondLoad()
93 {
94 do_test_pending();
95
96 var listener = new ImageListener(checkClone, secondLoadDone);
97 var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
98 .createScriptedObserver(listener);
99 requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, null, null, outer, null, 0, null, null));
100 listener.synchronous = false;
101 }
102
103 function firstLoadDone(oldlistener, aRequest)
104 {
105 checkSecondLoad(uri);
106
107 do_test_finished();
108 }
109
110 // Return a closure that allows us to check the stream listener's status when the
111 // image starts loading.
112 function getChannelLoadImageStartCallback(streamlistener)
113 {
114 return function channelLoadStart(imglistener, aRequest) {
115 // We must not have received all status before we get this start callback.
116 // If we have, we've broken people's expectations by delaying events from a
117 // channel we were given.
118 do_check_eq(streamlistener.requestStatus & STOP_REQUEST, 0);
119
120 checkClone(imglistener, aRequest);
121 }
122 }
123
124 // Return a closure that allows us to check the stream listener's status when the
125 // image finishes loading.
126 function getChannelLoadImageStopCallback(streamlistener, next)
127 {
128 return function channelLoadStop(imglistener, aRequest) {
129
130 next();
131
132 do_test_finished();
133 }
134 }
135
136 // Load the request a second time. This should come from the image cache, and
137 // therefore would be at most risk of being served synchronously.
138 function checkSecondChannelLoad()
139 {
140 do_test_pending();
141
142 var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
143 var channel = ioService.newChannelFromURI(uri);
144 var channellistener = new ChannelListener();
145 channel.asyncOpen(channellistener, null);
146
147 var listener = new ImageListener(getChannelLoadImageStartCallback(channellistener),
148 getChannelLoadImageStopCallback(channellistener,
149 all_done_callback));
150 var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
151 .createScriptedObserver(listener);
152 var outlistener = {};
153 requests.push(gCurrentLoader.loadImageWithChannelXPCOM(channel, outer, null, outlistener));
154 channellistener.outputListener = outlistener.value;
155
156 listener.synchronous = false;
157 }
158
159 function run_loadImageWithChannel_tests()
160 {
161 // To ensure we're testing what we expect to, create a new loader and cache.
162 gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
163
164 do_test_pending();
165
166 var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
167 var channel = ioService.newChannelFromURI(uri);
168 var channellistener = new ChannelListener();
169 channel.asyncOpen(channellistener, null);
170
171 var listener = new ImageListener(getChannelLoadImageStartCallback(channellistener),
172 getChannelLoadImageStopCallback(channellistener,
173 checkSecondChannelLoad));
174 var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
175 .createScriptedObserver(listener);
176 var outlistener = {};
177 requests.push(gCurrentLoader.loadImageWithChannelXPCOM(channel, outer, null, outlistener));
178 channellistener.outputListener = outlistener.value;
179
180 listener.synchronous = false;
181 }
182
183 function all_done_callback()
184 {
185 server.stop(function() { do_test_finished(); });
186 }
187
188 function startImageCallback(otherCb)
189 {
190 return function(listener, request)
191 {
192 // Make sure we can load the same image immediately out of the cache.
193 do_test_pending();
194 var listener2 = new ImageListener(null, function(foo, bar) { do_test_finished(); });
195 var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
196 .createScriptedObserver(listener2);
197 requests.push(gCurrentLoader.loadImageXPCOM(uri, null, null, null, null, outer, null, 0, null, null));
198 listener2.synchronous = false;
199
200 // Now that we've started another load, chain to the callback.
201 otherCb(listener, request);
202 }
203 }
204
205 var gCurrentLoader;
206
207 function cleanup()
208 {
209 for (var i = 0; i < requests.length; ++i) {
210 requests[i].cancelAndForgetObserver(0);
211 }
212 }
213
214 function run_test()
215 {
216 do_register_cleanup(cleanup);
217
218 gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
219
220 do_test_pending();
221 var listener = new ImageListener(startImageCallback(checkClone), firstLoadDone);
222 var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
223 .createScriptedObserver(listener);
224 var req = gCurrentLoader.loadImageXPCOM(uri, null, null, null, null, outer, null, 0, null, null);
225 requests.push(req);
226
227 // Ensure that we don't cause any mayhem when we lock an image.
228 req.lockImage();
229
230 listener.synchronous = false;
231 }

mercurial