Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* Notes: |
michael@0 | 2 | - All times are expressed in milliseconds in this test suite. |
michael@0 | 3 | - Test harness code is at the end of this file. |
michael@0 | 4 | - We generate only one request at a time, to avoid overloading the HTTP |
michael@0 | 5 | request handlers. |
michael@0 | 6 | */ |
michael@0 | 7 | |
michael@0 | 8 | var inWorker = false; |
michael@0 | 9 | try { |
michael@0 | 10 | inWorker = !(self instanceof Window); |
michael@0 | 11 | } catch (e) { |
michael@0 | 12 | inWorker = true; |
michael@0 | 13 | } |
michael@0 | 14 | |
michael@0 | 15 | function message(data) { |
michael@0 | 16 | if (inWorker) |
michael@0 | 17 | self.postMessage(data); |
michael@0 | 18 | else |
michael@0 | 19 | self.postMessage(data, "*"); |
michael@0 | 20 | } |
michael@0 | 21 | |
michael@0 | 22 | function is(got, expected, msg) { |
michael@0 | 23 | var obj = {}; |
michael@0 | 24 | obj.type = "is"; |
michael@0 | 25 | obj.got = got; |
michael@0 | 26 | obj.expected = expected; |
michael@0 | 27 | obj.msg = msg; |
michael@0 | 28 | |
michael@0 | 29 | message(obj); |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | function ok(bool, msg) { |
michael@0 | 33 | var obj = {}; |
michael@0 | 34 | obj.type = "ok"; |
michael@0 | 35 | obj.bool = bool; |
michael@0 | 36 | obj.msg = msg; |
michael@0 | 37 | |
michael@0 | 38 | message(obj); |
michael@0 | 39 | } |
michael@0 | 40 | |
michael@0 | 41 | /** |
michael@0 | 42 | * Generate and track results from a XMLHttpRequest with regards to timeouts. |
michael@0 | 43 | * |
michael@0 | 44 | * @param {String} id The test description. |
michael@0 | 45 | * @param {Number} timeLimit The initial setting for the request timeout. |
michael@0 | 46 | * @param {Number} resetAfter (Optional) The time after sending the request, to |
michael@0 | 47 | * reset the timeout. |
michael@0 | 48 | * @param {Number} resetTo (Optional) The delay to reset the timeout to. |
michael@0 | 49 | * |
michael@0 | 50 | * @note The actual testing takes place in handleEvent(event). |
michael@0 | 51 | * The requests are generated in startXHR(). |
michael@0 | 52 | * |
michael@0 | 53 | * @note If resetAfter and resetTo are omitted, only the initial timeout setting |
michael@0 | 54 | * applies. |
michael@0 | 55 | * |
michael@0 | 56 | * @constructor |
michael@0 | 57 | * @implements DOMEventListener |
michael@0 | 58 | */ |
michael@0 | 59 | function RequestTracker(async, id, timeLimit /*[, resetAfter, resetTo]*/) { |
michael@0 | 60 | this.async = async; |
michael@0 | 61 | this.id = id; |
michael@0 | 62 | this.timeLimit = timeLimit; |
michael@0 | 63 | |
michael@0 | 64 | if (arguments.length > 3) { |
michael@0 | 65 | this.mustReset = true; |
michael@0 | 66 | this.resetAfter = arguments[3]; |
michael@0 | 67 | this.resetTo = arguments[4]; |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | this.hasFired = false; |
michael@0 | 71 | } |
michael@0 | 72 | RequestTracker.prototype = { |
michael@0 | 73 | /** |
michael@0 | 74 | * Start the XMLHttpRequest! |
michael@0 | 75 | */ |
michael@0 | 76 | startXHR: function() { |
michael@0 | 77 | var req = new XMLHttpRequest(); |
michael@0 | 78 | this.request = req; |
michael@0 | 79 | req.open("GET", "file_XHR_timeout.sjs", this.async); |
michael@0 | 80 | var me = this; |
michael@0 | 81 | function handleEvent(e) { return me.handleEvent(e); }; |
michael@0 | 82 | req.onerror = handleEvent; |
michael@0 | 83 | req.onload = handleEvent; |
michael@0 | 84 | req.onabort = handleEvent; |
michael@0 | 85 | req.ontimeout = handleEvent; |
michael@0 | 86 | |
michael@0 | 87 | req.timeout = this.timeLimit; |
michael@0 | 88 | |
michael@0 | 89 | if (this.mustReset) { |
michael@0 | 90 | var resetTo = this.resetTo; |
michael@0 | 91 | self.setTimeout(function() { |
michael@0 | 92 | req.timeout = resetTo; |
michael@0 | 93 | }, this.resetAfter); |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | req.send(null); |
michael@0 | 97 | }, |
michael@0 | 98 | |
michael@0 | 99 | /** |
michael@0 | 100 | * Get a message describing this test. |
michael@0 | 101 | * |
michael@0 | 102 | * @returns {String} The test description. |
michael@0 | 103 | */ |
michael@0 | 104 | getMessage: function() { |
michael@0 | 105 | var rv = this.id + ", "; |
michael@0 | 106 | if (this.mustReset) { |
michael@0 | 107 | rv += "original timeout at " + this.timeLimit + ", "; |
michael@0 | 108 | rv += "reset at " + this.resetAfter + " to " + this.resetTo; |
michael@0 | 109 | } |
michael@0 | 110 | else { |
michael@0 | 111 | rv += "timeout scheduled at " + this.timeLimit; |
michael@0 | 112 | } |
michael@0 | 113 | return rv; |
michael@0 | 114 | }, |
michael@0 | 115 | |
michael@0 | 116 | /** |
michael@0 | 117 | * Check the event received, and if it's the right (and only) one we get. |
michael@0 | 118 | * |
michael@0 | 119 | * @param {DOMProgressEvent} evt An event of type "load" or "timeout". |
michael@0 | 120 | */ |
michael@0 | 121 | handleEvent: function(evt) { |
michael@0 | 122 | if (this.hasFired) { |
michael@0 | 123 | ok(false, "Only one event should fire: " + this.getMessage()); |
michael@0 | 124 | return; |
michael@0 | 125 | } |
michael@0 | 126 | this.hasFired = true; |
michael@0 | 127 | |
michael@0 | 128 | var type = evt.type, expectedType; |
michael@0 | 129 | // The XHR responds after 3000 milliseconds with a load event. |
michael@0 | 130 | var timeLimit = this.mustReset && (this.resetAfter < Math.min(3000, this.timeLimit)) ? |
michael@0 | 131 | this.resetTo : |
michael@0 | 132 | this.timeLimit; |
michael@0 | 133 | if ((timeLimit == 0) || (timeLimit >= 3000)) { |
michael@0 | 134 | expectedType = "load"; |
michael@0 | 135 | } |
michael@0 | 136 | else { |
michael@0 | 137 | expectedType = "timeout"; |
michael@0 | 138 | } |
michael@0 | 139 | is(type, expectedType, this.getMessage()); |
michael@0 | 140 | TestCounter.testComplete(); |
michael@0 | 141 | } |
michael@0 | 142 | }; |
michael@0 | 143 | |
michael@0 | 144 | /** |
michael@0 | 145 | * Generate and track XMLHttpRequests which will have abort() called on. |
michael@0 | 146 | * |
michael@0 | 147 | * @param shouldAbort {Boolean} True if we should call abort at all. |
michael@0 | 148 | * @param abortDelay {Number} The time in ms to wait before calling abort(). |
michael@0 | 149 | */ |
michael@0 | 150 | function AbortedRequest(shouldAbort, abortDelay) { |
michael@0 | 151 | this.shouldAbort = shouldAbort; |
michael@0 | 152 | this.abortDelay = abortDelay; |
michael@0 | 153 | this.hasFired = false; |
michael@0 | 154 | } |
michael@0 | 155 | AbortedRequest.prototype = { |
michael@0 | 156 | /** |
michael@0 | 157 | * Start the XMLHttpRequest! |
michael@0 | 158 | */ |
michael@0 | 159 | startXHR: function() { |
michael@0 | 160 | var req = new XMLHttpRequest(); |
michael@0 | 161 | this.request = req; |
michael@0 | 162 | req.open("GET", "file_XHR_timeout.sjs"); |
michael@0 | 163 | var me = this; |
michael@0 | 164 | function handleEvent(e) { return me.handleEvent(e); }; |
michael@0 | 165 | req.onerror = handleEvent; |
michael@0 | 166 | req.onload = handleEvent; |
michael@0 | 167 | req.onabort = handleEvent; |
michael@0 | 168 | req.ontimeout = handleEvent; |
michael@0 | 169 | |
michael@0 | 170 | req.timeout = 2000; |
michael@0 | 171 | var _this = this; |
michael@0 | 172 | |
michael@0 | 173 | function abortReq() { |
michael@0 | 174 | req.abort(); |
michael@0 | 175 | } |
michael@0 | 176 | |
michael@0 | 177 | if (!this.shouldAbort) { |
michael@0 | 178 | self.setTimeout(function() { |
michael@0 | 179 | try { |
michael@0 | 180 | _this.noEventsFired(); |
michael@0 | 181 | } |
michael@0 | 182 | catch (e) { |
michael@0 | 183 | ok(false, "Unexpected error: " + e); |
michael@0 | 184 | TestCounter.testComplete(); |
michael@0 | 185 | } |
michael@0 | 186 | }, 5000); |
michael@0 | 187 | } |
michael@0 | 188 | else { |
michael@0 | 189 | // Abort events can only be triggered on sent requests. |
michael@0 | 190 | req.send(); |
michael@0 | 191 | if (this.abortDelay == -1) { |
michael@0 | 192 | abortReq(); |
michael@0 | 193 | } |
michael@0 | 194 | else { |
michael@0 | 195 | self.setTimeout(abortReq, this.abortDelay); |
michael@0 | 196 | } |
michael@0 | 197 | } |
michael@0 | 198 | }, |
michael@0 | 199 | |
michael@0 | 200 | /** |
michael@0 | 201 | * Ensure that no events fired at all, especially not our timeout event. |
michael@0 | 202 | */ |
michael@0 | 203 | noEventsFired: function() { |
michael@0 | 204 | ok(!this.hasFired, "No events should fire for an unsent, unaborted request"); |
michael@0 | 205 | // We're done; if timeout hasn't fired by now, it never will. |
michael@0 | 206 | TestCounter.testComplete(); |
michael@0 | 207 | }, |
michael@0 | 208 | |
michael@0 | 209 | /** |
michael@0 | 210 | * Get a message describing this test. |
michael@0 | 211 | * |
michael@0 | 212 | * @returns {String} The test description. |
michael@0 | 213 | */ |
michael@0 | 214 | getMessage: function() { |
michael@0 | 215 | return "time to abort is " + this.abortDelay + ", timeout set at 2000"; |
michael@0 | 216 | }, |
michael@0 | 217 | |
michael@0 | 218 | /** |
michael@0 | 219 | * Check the event received, and if it's the right (and only) one we get. |
michael@0 | 220 | * |
michael@0 | 221 | * @param {DOMProgressEvent} evt An event of type "load" or "timeout". |
michael@0 | 222 | */ |
michael@0 | 223 | handleEvent: function(evt) { |
michael@0 | 224 | if (this.hasFired) { |
michael@0 | 225 | ok(false, "Only abort event should fire: " + this.getMessage()); |
michael@0 | 226 | return; |
michael@0 | 227 | } |
michael@0 | 228 | this.hasFired = true; |
michael@0 | 229 | |
michael@0 | 230 | var expectedEvent = (this.abortDelay >= 2000) ? "timeout" : "abort"; |
michael@0 | 231 | is(evt.type, expectedEvent, this.getMessage()); |
michael@0 | 232 | TestCounter.testComplete(); |
michael@0 | 233 | } |
michael@0 | 234 | }; |
michael@0 | 235 | |
michael@0 | 236 | var SyncRequestSettingTimeoutAfterOpen = { |
michael@0 | 237 | startXHR: function() { |
michael@0 | 238 | var pass = false; |
michael@0 | 239 | var req = new XMLHttpRequest(); |
michael@0 | 240 | req.open("GET", "file_XHR_timeout.sjs", false); |
michael@0 | 241 | try { |
michael@0 | 242 | req.timeout = 1000; |
michael@0 | 243 | } |
michael@0 | 244 | catch (e) { |
michael@0 | 245 | pass = true; |
michael@0 | 246 | } |
michael@0 | 247 | ok(pass, "Synchronous XHR must not allow a timeout to be set"); |
michael@0 | 248 | TestCounter.testComplete(); |
michael@0 | 249 | } |
michael@0 | 250 | }; |
michael@0 | 251 | |
michael@0 | 252 | var SyncRequestSettingTimeoutBeforeOpen = { |
michael@0 | 253 | startXHR: function() { |
michael@0 | 254 | var pass = false; |
michael@0 | 255 | var req = new XMLHttpRequest(); |
michael@0 | 256 | req.timeout = 1000; |
michael@0 | 257 | try { |
michael@0 | 258 | req.open("GET", "file_XHR_timeout.sjs", false); |
michael@0 | 259 | } |
michael@0 | 260 | catch (e) { |
michael@0 | 261 | pass = true; |
michael@0 | 262 | } |
michael@0 | 263 | ok(pass, "Synchronous XHR must not allow a timeout to be set"); |
michael@0 | 264 | TestCounter.testComplete(); |
michael@0 | 265 | } |
michael@0 | 266 | }; |
michael@0 | 267 | |
michael@0 | 268 | var TestRequests = [ |
michael@0 | 269 | // Simple timeouts. |
michael@0 | 270 | new RequestTracker(true, "no time out scheduled, load fires normally", 0), |
michael@0 | 271 | new RequestTracker(true, "load fires normally", 5000), |
michael@0 | 272 | new RequestTracker(true, "timeout hit before load", 2000), |
michael@0 | 273 | |
michael@0 | 274 | // Timeouts reset after a certain delay. |
michael@0 | 275 | new RequestTracker(true, "load fires normally with no timeout set, twice", 0, 2000, 0), |
michael@0 | 276 | new RequestTracker(true, "load fires normally with same timeout set twice", 5000, 2000, 5000), |
michael@0 | 277 | new RequestTracker(true, "timeout fires normally with same timeout set twice", 2000, 1000, 2000), |
michael@0 | 278 | |
michael@0 | 279 | new RequestTracker(true, "timeout disabled after initially set", 5000, 2000, 0), |
michael@0 | 280 | new RequestTracker(true, "timeout overrides load after a delay", 5000, 1000, 2000), |
michael@0 | 281 | new RequestTracker(true, "timeout enabled after initially disabled", 0, 2000, 5000), |
michael@0 | 282 | |
michael@0 | 283 | new RequestTracker(true, "timeout set to expiring value after load fires", 5000, 4000, 1000), |
michael@0 | 284 | new RequestTracker(true, "timeout set to expired value before load fires", 5000, 2000, 1000), |
michael@0 | 285 | new RequestTracker(true, "timeout set to non-expiring value after timeout fires", 1000, 2000, 5000), |
michael@0 | 286 | |
michael@0 | 287 | // Aborted requests. |
michael@0 | 288 | new AbortedRequest(false), |
michael@0 | 289 | new AbortedRequest(true, -1), |
michael@0 | 290 | new AbortedRequest(true, 5000), |
michael@0 | 291 | ]; |
michael@0 | 292 | |
michael@0 | 293 | var MainThreadTestRequests = [ |
michael@0 | 294 | new AbortedRequest(true, 0), |
michael@0 | 295 | new AbortedRequest(true, 1000), |
michael@0 | 296 | |
michael@0 | 297 | // Synchronous requests. |
michael@0 | 298 | SyncRequestSettingTimeoutAfterOpen, |
michael@0 | 299 | SyncRequestSettingTimeoutBeforeOpen |
michael@0 | 300 | ]; |
michael@0 | 301 | |
michael@0 | 302 | var WorkerThreadTestRequests = [ |
michael@0 | 303 | // Simple timeouts. |
michael@0 | 304 | new RequestTracker(false, "no time out scheduled, load fires normally", 0), |
michael@0 | 305 | new RequestTracker(false, "load fires normally", 5000), |
michael@0 | 306 | new RequestTracker(false, "timeout hit before load", 2000), |
michael@0 | 307 | |
michael@0 | 308 | // Reset timeouts don't make much sense with a sync request ... |
michael@0 | 309 | ]; |
michael@0 | 310 | |
michael@0 | 311 | if (inWorker) { |
michael@0 | 312 | TestRequests = TestRequests.concat(WorkerThreadTestRequests); |
michael@0 | 313 | } else { |
michael@0 | 314 | TestRequests = TestRequests.concat(MainThreadTestRequests); |
michael@0 | 315 | } |
michael@0 | 316 | |
michael@0 | 317 | // This code controls moving from one test to another. |
michael@0 | 318 | var TestCounter = { |
michael@0 | 319 | testComplete: function() { |
michael@0 | 320 | // Allow for the possibility there are other events coming. |
michael@0 | 321 | self.setTimeout(function() { |
michael@0 | 322 | TestCounter.next(); |
michael@0 | 323 | }, 5000); |
michael@0 | 324 | }, |
michael@0 | 325 | |
michael@0 | 326 | next: function() { |
michael@0 | 327 | var test = TestRequests.shift(); |
michael@0 | 328 | |
michael@0 | 329 | if (test) { |
michael@0 | 330 | test.startXHR(); |
michael@0 | 331 | } |
michael@0 | 332 | else { |
michael@0 | 333 | message("done"); |
michael@0 | 334 | } |
michael@0 | 335 | } |
michael@0 | 336 | }; |
michael@0 | 337 | |
michael@0 | 338 | self.addEventListener("message", function (event) { |
michael@0 | 339 | if (event.data == "start") { |
michael@0 | 340 | TestCounter.next(); |
michael@0 | 341 | } |
michael@0 | 342 | }); |