content/base/test/test_xhr_progressevents.html

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 <!DOCTYPE HTML>
michael@0 2 <html>
michael@0 3 <head>
michael@0 4 <title>Test for XMLHttpRequest Progress Events</title>
michael@0 5 <script type="text/javascript" src="/MochiKit/packed.js"></script>
michael@0 6 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
michael@0 7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
michael@0 8 </head>
michael@0 9 <body onload="gen.next();">
michael@0 10 <pre id=l></pre>
michael@0 11 <script type="application/javascript;version=1.7">
michael@0 12 SimpleTest.waitForExplicitFinish();
michael@0 13
michael@0 14 var gen = runTests();
michael@0 15
michael@0 16 function log(s) {
michael@0 17 // Uncomment these to get debugging information
michael@0 18 /*
michael@0 19 document.getElementById("l").textContent += s + "\n";
michael@0 20 dump(s + "\n");
michael@0 21 */
michael@0 22 }
michael@0 23
michael@0 24 function getEvent(e) {
michael@0 25 log("got event: " + e.type + " (" + e.target.readyState + ")");
michael@0 26 gen.send(e);
michael@0 27 }
michael@0 28
michael@0 29 function startsWith(a, b) {
michael@0 30 return a.substr(0, b.length) === b;
michael@0 31 }
michael@0 32
michael@0 33 function updateProgress(e, data, testName) {
michael@0 34 var test = " while running " + testName;
michael@0 35 is(e.type, "progress", "event type" + test);
michael@0 36
michael@0 37 let response;
michael@0 38 if (data.nodata) {
michael@0 39 is(e.target.response, null, "response should be null" + test);
michael@0 40 response = null;
michael@0 41 }
michael@0 42 else if (data.text) {
michael@0 43 is(typeof e.target.response, "string", "response should be a string" + test);
michael@0 44 response = e.target.response;
michael@0 45 }
michael@0 46 else if (data.blob) {
michael@0 47 ok(e.target.response instanceof Blob, "response should be a Blob" + test);
michael@0 48 response = e.target.response;
michael@0 49 }
michael@0 50 else {
michael@0 51 ok(e.target.response instanceof ArrayBuffer, "response should be an ArrayBuffer" + test);
michael@0 52 response = bufferToString(e.target.response);
michael@0 53 }
michael@0 54 is(e.target.response, e.target.response, "reflexivity should hold" + test);
michael@0 55
michael@0 56 if (!data.nodata && !data.encoded) {
michael@0 57 if (data.blob) {
michael@0 58 is(e.loaded, response.size, "event.loaded matches response size" + test);
michael@0 59 }
michael@0 60 else if (!data.chunked) {
michael@0 61 is(e.loaded, response.length, "event.loaded matches response size" + test);
michael@0 62 }
michael@0 63 else {
michael@0 64 is(e.loaded - data.receivedBytes, response.length,
michael@0 65 "event.loaded grew by response size" + test);
michael@0 66 }
michael@0 67 }
michael@0 68 ok(e.loaded > data.receivedBytes, "event.loaded increased" + test);
michael@0 69 ok(e.loaded - data.receivedBytes <= data.pendingBytes,
michael@0 70 "event.loaded didn't increase too much" + test);
michael@0 71
michael@0 72 if (!data.nodata && !data.blob) {
michael@0 73 var newData;
michael@0 74 ok(startsWith(response, data.receivedResult),
michael@0 75 "response strictly grew" + test);
michael@0 76 newData = response.substr(data.receivedResult.length);
michael@0 77
michael@0 78 if (!data.encoded) {
michael@0 79 ok(newData.length > 0, "sanity check for progress" + test);
michael@0 80 }
michael@0 81 ok(startsWith(data.pendingResult, newData), "new data matches expected" + test);
michael@0 82 }
michael@0 83
michael@0 84 is(e.lengthComputable, "total" in data, "lengthComputable" + test);
michael@0 85 if ("total" in data) {
michael@0 86 is(e.total, data.total, "total" + test);
michael@0 87 }
michael@0 88
michael@0 89 if (!data.nodata && !data.blob) {
michael@0 90 data.pendingResult = data.pendingResult.substr(newData.length);
michael@0 91 }
michael@0 92 data.pendingBytes -= e.loaded - data.receivedBytes;
michael@0 93 data.receivedResult = response;
michael@0 94 data.receivedBytes = e.loaded;
michael@0 95 }
michael@0 96
michael@0 97 function sendData(s) {
michael@0 98 var xhr = new XMLHttpRequest();
michael@0 99 xhr.open("POST", "progressserver.sjs?send");
michael@0 100 xhr.sendAsBinary(s);
michael@0 101 }
michael@0 102
michael@0 103 function closeConn() {
michael@0 104 log("in closeConn");
michael@0 105 var xhr = new XMLHttpRequest();
michael@0 106 xhr.open("POST", "progressserver.sjs?close");
michael@0 107 xhr.send();
michael@0 108 return xhr;
michael@0 109 }
michael@0 110
michael@0 111 var longString = "long";
michael@0 112 while(longString.length < 65536)
michael@0 113 longString += longString;
michael@0 114
michael@0 115 function utf8encode(s) {
michael@0 116 return unescape(encodeURIComponent(s));
michael@0 117 }
michael@0 118
michael@0 119 function bufferToString(buffer) {
michael@0 120 return String.fromCharCode.apply(String, new Uint8Array(buffer));
michael@0 121 }
michael@0 122
michael@0 123 function runTests() {
michael@0 124 var xhr = new XMLHttpRequest();
michael@0 125 xhr.onprogress = xhr.onload = xhr.onerror = xhr.onreadystatechange = xhr.onloadend = getEvent;
michael@0 126
michael@0 127 var responseTypes = [{ type: "text", text: true },
michael@0 128 { type: "arraybuffer", text: false, nodata: true },
michael@0 129 { type: "blob", text: false, nodata: true, blob: true },
michael@0 130 { type: "moz-blob", text: false, nodata: false, blob: true },
michael@0 131 { type: "document", text: true, nodata: true },
michael@0 132 { type: "json", text: true, nodata: true },
michael@0 133 { type: "", text: true },
michael@0 134 { type: "moz-chunked-text", text: true, chunked: true },
michael@0 135 { type: "moz-chunked-arraybuffer", text: false, chunked: true },
michael@0 136 ];
michael@0 137 var responseType;
michael@0 138 var fileExpectedResult = "";
michael@0 139 for (var i = 0; i < 65536; i++) {
michael@0 140 fileExpectedResult += String.fromCharCode(i & 255);
michael@0 141 }
michael@0 142 while (responseType = responseTypes.shift()) {
michael@0 143 let tests = [{ open: "Content-Type=text/plain", name: "simple test" },
michael@0 144 { data: "hello world" },
michael@0 145 { data: "\u0000\u0001\u0002\u0003" },
michael@0 146 { data: longString },
michael@0 147 { data: "x" },
michael@0 148 { close: true },
michael@0 149 { open: "Content-Type=text/plain&Content-Length=20", name: "with length", total: 20 },
michael@0 150 // 5 bytes from the "ready" in the open step
michael@0 151 { data: "abcde" },
michael@0 152 { data: "0123456789" },
michael@0 153 { close: true },
michael@0 154 { open: "Content-Type=application/xml", name: "without length, as xml" },
michael@0 155 { data: "<out>" },
michael@0 156 { data: "text" },
michael@0 157 { data: "</foo>invalid" },
michael@0 158 { close: true },
michael@0 159 { open: "Content-Type=text/plain;charset%3dutf-8", name: "utf8 data", encoded: true },
michael@0 160 { data: utf8encode("räksmörgås"), utf16: "räksmörgås" },
michael@0 161 { data: utf8encode("Å").substr(0,1), utf16: "" },
michael@0 162 { data: utf8encode("Å").substr(1), utf16: "Å" },
michael@0 163 { data: utf8encode("aöb").substr(0,2), utf16: "a" },
michael@0 164 { data: utf8encode("aöb").substr(2), utf16: "öb" },
michael@0 165 { data: utf8encode("a\u867Eb").substr(0,3), utf16: "a" },
michael@0 166 { data: utf8encode("a\u867Eb").substr(3,1), utf16: "\u867E" },
michael@0 167 { data: utf8encode("a\u867Eb").substr(4), utf16: "b" },
michael@0 168 { close: true },
michael@0 169 ];
michael@0 170 if (responseType.blob) {
michael@0 171 tests.push({ file: "file_XHR_binary2.bin", name: "cacheable data", total: 65536 },
michael@0 172 { close: true },
michael@0 173 { file: "file_XHR_binary2.bin", name: "cached data", total: 65536 },
michael@0 174 { close: true });
michael@0 175 }
michael@0 176 let testState = { index: 0 };
michael@0 177
michael@0 178 for (let i = 0; i < tests.length; ++i) {
michael@0 179 let test = tests[i];
michael@0 180 testState.index++;
michael@0 181 if ("open" in test || "file" in test) {
michael@0 182 log("opening " + testState.name);
michael@0 183 testState = { name: test.name + " for " + responseType.type,
michael@0 184 index: 0,
michael@0 185 pendingResult: "ready",
michael@0 186 pendingBytes: 5,
michael@0 187 receivedResult: "",
michael@0 188 receivedBytes: 0,
michael@0 189 total: test.total,
michael@0 190 encoded: test.encoded,
michael@0 191 nodata: responseType.nodata,
michael@0 192 chunked: responseType.chunked,
michael@0 193 text: responseType.text,
michael@0 194 blob: responseType.blob,
michael@0 195 file: test.file };
michael@0 196
michael@0 197 xhr.onreadystatechange = null;
michael@0 198 if (testState.file)
michael@0 199 xhr.open("GET", test.file);
michael@0 200 else
michael@0 201 xhr.open("POST", "progressserver.sjs?open&" + test.open);
michael@0 202 xhr.responseType = responseType.type;
michael@0 203 xhr.send("ready");
michael@0 204 xhr.onreadystatechange = getEvent;
michael@0 205
michael@0 206 let e = yield undefined;
michael@0 207 is(e.type, "readystatechange", "should readystate to headers-received starting " + testState.name);
michael@0 208 is(xhr.readyState, xhr.HEADERS_RECEIVED, "should be in state HEADERS_RECEIVED starting " + testState.name);
michael@0 209
michael@0 210 e = yield undefined;
michael@0 211 is(e.type, "readystatechange", "should readystate to loading starting " + testState.name);
michael@0 212 is(xhr.readyState, xhr.LOADING, "should be in state LOADING starting " + testState.name);
michael@0 213 if (typeof testState.total == "undefined")
michael@0 214 delete testState.total;
michael@0 215 }
michael@0 216 if ("file" in test) {
michael@0 217 testState.pendingBytes = testState.total;
michael@0 218 testState.pendingResult = fileExpectedResult;
michael@0 219 }
michael@0 220 if ("close" in test) {
michael@0 221 log("closing");
michael@0 222 let xhrClose;
michael@0 223 if (!testState.file)
michael@0 224 xhrClose = closeConn();
michael@0 225
michael@0 226 e = yield undefined;
michael@0 227 is(e.type, "readystatechange", "should readystate to done closing " + testState.name);
michael@0 228 is(xhr.readyState, xhr.DONE, "should be in state DONE closing " + testState.name);
michael@0 229 log("readystate to 4");
michael@0 230
michael@0 231 if (responseType.chunked) {
michael@0 232 xhr.responseType;
michael@0 233 is(xhr.response, null, "chunked data has null response for " + testState.name);
michael@0 234 }
michael@0 235
michael@0 236 e = yield undefined;
michael@0 237 is(e.type, "load", "should fire load closing " + testState.name);
michael@0 238 is(e.lengthComputable, true, "length should be computable during load closing " + testState.name);
michael@0 239 log("got load");
michael@0 240
michael@0 241 if (responseType.chunked) {
michael@0 242 is(xhr.response, null, "chunked data has null response for " + testState.name);
michael@0 243 }
michael@0 244
michael@0 245 e = yield undefined;
michael@0 246 is(e.type, "loadend", "should fire loadend closing " + testState.name);
michael@0 247 is(e.lengthComputable, true, "length should be computable during loadend closing " + testState.name);
michael@0 248 log("got loadend");
michael@0 249
michael@0 250 // if we closed the connection using an explicit request, make sure that goes through before
michael@0 251 // running the next test in order to avoid reordered requests from closing the wrong
michael@0 252 // connection.
michael@0 253 if (xhrClose && xhrClose.readyState != xhrClose.DONE) {
michael@0 254 log("wait for closeConn to finish");
michael@0 255 xhrClose.onloadend = getEvent;
michael@0 256 yield undefined;
michael@0 257 is(xhrClose.readyState, xhrClose.DONE, "closeConn finished");
michael@0 258 }
michael@0 259
michael@0 260 if (responseType.chunked) {
michael@0 261 is(xhr.response, null, "chunked data has null response for " + testState.name);
michael@0 262 }
michael@0 263
michael@0 264 if (!testState.nodata && !responseType.blob || responseType.chunked) {
michael@0 265 // This branch intentionally left blank
michael@0 266 // Under these conditions we check the response during updateProgress
michael@0 267 }
michael@0 268 else if (responseType.type === "arraybuffer") {
michael@0 269 is(bufferToString(xhr.response), testState.pendingResult,
michael@0 270 "full response for " + testState.name);
michael@0 271 }
michael@0 272 else if (responseType.blob) {
michael@0 273 let reader = new FileReader;
michael@0 274 reader.readAsBinaryString(xhr.response);
michael@0 275 reader.onloadend = getEvent;
michael@0 276 yield undefined;
michael@0 277
michael@0 278 is(reader.result, testState.pendingResult,
michael@0 279 "full response in blob for " + testState.name);
michael@0 280 }
michael@0 281
michael@0 282 testState.name = "";
michael@0 283 }
michael@0 284 if ("data" in test) {
michael@0 285 log("sending");
michael@0 286 if (responseType.text) {
michael@0 287 testState.pendingResult += "utf16" in test ? test.utf16 : test.data;
michael@0 288 }
michael@0 289 else {
michael@0 290 testState.pendingResult += test.data;
michael@0 291 }
michael@0 292 testState.pendingBytes = test.data.length;
michael@0 293 sendData(test.data);
michael@0 294 }
michael@0 295
michael@0 296 while(testState.pendingBytes) {
michael@0 297 log("waiting for more bytes: " + testState.pendingBytes);
michael@0 298 e = yield undefined;
michael@0 299 // Readystate can fire several times between each progress event.
michael@0 300 if (e.type === "readystatechange")
michael@0 301 continue;
michael@0 302
michael@0 303 updateProgress(e, testState, "data for " + testState.name + "[" + testState.index + "]");
michael@0 304 if (responseType.chunked) {
michael@0 305 testState.receivedResult = "";
michael@0 306 }
michael@0 307 }
michael@0 308
michael@0 309 if (!testState.nodata && !testState.blob) {
michael@0 310 is(testState.pendingResult, "",
michael@0 311 "should have consumed the expected result");
michael@0 312 }
michael@0 313
michael@0 314 log("done with this test");
michael@0 315 }
michael@0 316
michael@0 317 is(testState.name, "", "forgot to close last test");
michael@0 318 }
michael@0 319
michael@0 320 SimpleTest.finish();
michael@0 321 yield undefined;
michael@0 322 }
michael@0 323
michael@0 324 </script>
michael@0 325
michael@0 326 </body>
michael@0 327 </html>

mercurial