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 | <!DOCTYPE HTML> |
michael@0 | 2 | <html> |
michael@0 | 3 | <head> |
michael@0 | 4 | <title>Test for XMLHttpRequest</title> |
michael@0 | 5 | <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
michael@0 | 6 | <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> |
michael@0 | 7 | </head> |
michael@0 | 8 | <body onload="gen.next();"> |
michael@0 | 9 | <p id="display"></p> |
michael@0 | 10 | <div id="content" style="display: none"> |
michael@0 | 11 | |
michael@0 | 12 | </div> |
michael@0 | 13 | <pre id="test"> |
michael@0 | 14 | <script class="testbody" type="application/javascript;version=1.7"> |
michael@0 | 15 | "use strict"; |
michael@0 | 16 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 17 | |
michael@0 | 18 | var gen = runTests(); |
michael@0 | 19 | function continueTest() { gen.next(); } |
michael@0 | 20 | |
michael@0 | 21 | function runTests() { |
michael@0 | 22 | |
michael@0 | 23 | var path = "/tests/content/base/test/"; |
michael@0 | 24 | |
michael@0 | 25 | var passFiles = [['file_XHR_pass1.xml', 'GET', 200, 'text/xml'], |
michael@0 | 26 | ['file_XHR_pass2.txt', 'GET', 200, 'text/plain'], |
michael@0 | 27 | ['file_XHR_pass3.txt', 'GET', 200, 'text/plain'], |
michael@0 | 28 | ['data:text/xml,%3Cres%3Ehello%3C/res%3E%0A', 'GET', 0, 'text/xml'], |
michael@0 | 29 | ['data:text/plain,hello%20pass%0A', 'GET', 0, 'text/plain'], |
michael@0 | 30 | ['data:,foo', 'GET', 0, 'text/plain;charset=US-ASCII', 'foo'], |
michael@0 | 31 | ['data:text/plain;base64,Zm9v', 'GET', 0, 'text/plain', 'foo'], |
michael@0 | 32 | ['data:text/plain,foo#bar', 'GET', 0, 'text/plain', 'foo'], |
michael@0 | 33 | ['data:text/plain,foo%23bar', 'GET', 0, 'text/plain', 'foo#bar'], |
michael@0 | 34 | ]; |
michael@0 | 35 | |
michael@0 | 36 | var failFiles = [['//example.com' + path + 'file_XHR_pass1.xml', 'GET'], |
michael@0 | 37 | ['ftp://localhost' + path + 'file_XHR_pass1.xml', 'GET'], |
michael@0 | 38 | ['file_XHR_fail1.txt', 'GET'], |
michael@0 | 39 | ]; |
michael@0 | 40 | |
michael@0 | 41 | for (i = 0; i < passFiles.length; ++i) { |
michael@0 | 42 | xhr = new XMLHttpRequest(); |
michael@0 | 43 | is(xhr.getResponseHeader("Content-Type"), null, "should be null"); |
michael@0 | 44 | is(xhr.getAllResponseHeaders(), "", "should be empty string"); |
michael@0 | 45 | is(xhr.responseType, "", "wrong initial responseType"); |
michael@0 | 46 | xhr.open(passFiles[i][1], passFiles[i][0], false); |
michael@0 | 47 | xhr.send(null); |
michael@0 | 48 | is(xhr.status, passFiles[i][2], "wrong status"); |
michael@0 | 49 | is(xhr.getResponseHeader("Content-Type"), passFiles[i][3], "wrong content type"); |
michael@0 | 50 | var headers = xhr.getAllResponseHeaders(); |
michael@0 | 51 | ok(/(?:^|\n)Content-Type:\s*([^\r\n]*)\r\n/i.test(headers) && |
michael@0 | 52 | RegExp.$1 === passFiles[i][3], "wrong response headers"); |
michael@0 | 53 | if (xhr.responseXML) { |
michael@0 | 54 | is((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement), |
michael@0 | 55 | passFiles[i][4] || "<res>hello</res>", "wrong responseXML"); |
michael@0 | 56 | is(xhr.response, passFiles[i][4] || "<res>hello</res>\n", "wrong response"); |
michael@0 | 57 | } |
michael@0 | 58 | else { |
michael@0 | 59 | is(xhr.responseText, passFiles[i][4] || "hello pass\n", "wrong responseText"); |
michael@0 | 60 | is(xhr.response, passFiles[i][4] || "hello pass\n", "wrong response"); |
michael@0 | 61 | } |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | for (i = 0; i < failFiles.length; ++i) { |
michael@0 | 65 | xhr = new XMLHttpRequest(); |
michael@0 | 66 | var didthrow = false; |
michael@0 | 67 | try { |
michael@0 | 68 | xhr.open(failFiles[i][1], failFiles[i][0], false); |
michael@0 | 69 | xhr.send(null); |
michael@0 | 70 | } |
michael@0 | 71 | catch (e) { |
michael@0 | 72 | didthrow = true; |
michael@0 | 73 | } |
michael@0 | 74 | if (!didthrow) { |
michael@0 | 75 | is(xhr.status, 301, "wrong status"); |
michael@0 | 76 | is(xhr.responseText, "redirect file\n", "wrong response"); |
michael@0 | 77 | } |
michael@0 | 78 | else { |
michael@0 | 79 | ok(1, "should have thrown or given incorrect result"); |
michael@0 | 80 | } |
michael@0 | 81 | } |
michael@0 | 82 | |
michael@0 | 83 | function checkResponseTextAccessThrows(xhr) { |
michael@0 | 84 | var didthrow = false; |
michael@0 | 85 | try { xhr.responseText } catch (e) { didthrow = true; } |
michael@0 | 86 | ok(didthrow, "should have thrown when accessing responseText"); |
michael@0 | 87 | } |
michael@0 | 88 | function checkResponseXMLAccessThrows(xhr) { |
michael@0 | 89 | var didthrow = false; |
michael@0 | 90 | try { xhr.responseXML } catch (e) { didthrow = true; } |
michael@0 | 91 | ok(didthrow, "should have thrown when accessing responseXML"); |
michael@0 | 92 | } |
michael@0 | 93 | function checkSetResponseTypeThrows(xhr, type) { |
michael@0 | 94 | var didthrow = false; |
michael@0 | 95 | try { xhr.responseType = type; } catch (e) { didthrow = true; } |
michael@0 | 96 | ok(didthrow, "should have thrown when setting responseType"); |
michael@0 | 97 | } |
michael@0 | 98 | function checkOpenThrows(xhr, method, url, async) { |
michael@0 | 99 | var didthrow = false; |
michael@0 | 100 | try { xhr.open(method, url, async); } catch (e) { didthrow = true; } |
michael@0 | 101 | ok(didthrow, "should have thrown when open is called"); |
michael@0 | 102 | } |
michael@0 | 103 | |
michael@0 | 104 | // test response (sync, responseType is not changeable) |
michael@0 | 105 | xhr = new XMLHttpRequest(); |
michael@0 | 106 | xhr.open("GET", 'file_XHR_pass2.txt', false); |
michael@0 | 107 | checkSetResponseTypeThrows(xhr, ""); |
michael@0 | 108 | checkSetResponseTypeThrows(xhr, "text"); |
michael@0 | 109 | checkSetResponseTypeThrows(xhr, "document"); |
michael@0 | 110 | checkSetResponseTypeThrows(xhr, "arraybuffer"); |
michael@0 | 111 | checkSetResponseTypeThrows(xhr, "blob"); |
michael@0 | 112 | checkSetResponseTypeThrows(xhr, "json"); |
michael@0 | 113 | checkSetResponseTypeThrows(xhr, "moz-chunked-text"); |
michael@0 | 114 | checkSetResponseTypeThrows(xhr, "moz-chunked-arraybuffer"); |
michael@0 | 115 | xhr.send(null); |
michael@0 | 116 | checkSetResponseTypeThrows(xhr, "document"); |
michael@0 | 117 | is(xhr.status, 200, "wrong status"); |
michael@0 | 118 | is(xhr.response, "hello pass\n", "wrong response"); |
michael@0 | 119 | |
michael@0 | 120 | // test response (responseType='document') |
michael@0 | 121 | xhr = new XMLHttpRequest(); |
michael@0 | 122 | xhr.open("GET", 'file_XHR_pass1.xml'); |
michael@0 | 123 | xhr.responseType = 'document'; |
michael@0 | 124 | xhr.onloadend = continueTest; |
michael@0 | 125 | xhr.send(null); |
michael@0 | 126 | yield undefined; |
michael@0 | 127 | checkSetResponseTypeThrows(xhr, "document"); |
michael@0 | 128 | is(xhr.status, 200, "wrong status"); |
michael@0 | 129 | checkResponseTextAccessThrows(xhr); |
michael@0 | 130 | is((new XMLSerializer()).serializeToString(xhr.response.documentElement), |
michael@0 | 131 | "<res>hello</res>", |
michael@0 | 132 | "wrong response"); |
michael@0 | 133 | |
michael@0 | 134 | // test response (responseType='text') |
michael@0 | 135 | xhr = new XMLHttpRequest(); |
michael@0 | 136 | xhr.open("GET", 'file_XHR_pass2.txt'); |
michael@0 | 137 | xhr.responseType = 'text'; |
michael@0 | 138 | xhr.onloadend = continueTest; |
michael@0 | 139 | xhr.send(null); |
michael@0 | 140 | yield undefined; |
michael@0 | 141 | is(xhr.status, 200, "wrong status"); |
michael@0 | 142 | checkResponseXMLAccessThrows(xhr); |
michael@0 | 143 | is(xhr.response, "hello pass\n", "wrong response"); |
michael@0 | 144 | |
michael@0 | 145 | // test response (responseType='arraybuffer') |
michael@0 | 146 | function arraybuffer_equals_to(ab, s) { |
michael@0 | 147 | is(ab.byteLength, s.length, "wrong arraybuffer byteLength"); |
michael@0 | 148 | |
michael@0 | 149 | var u8v = new Uint8Array(ab); |
michael@0 | 150 | is(String.fromCharCode.apply(String, u8v), s, "wrong values"); |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | // with a simple text file |
michael@0 | 154 | xhr = new XMLHttpRequest(); |
michael@0 | 155 | xhr.open("GET", 'file_XHR_pass2.txt'); |
michael@0 | 156 | xhr.responseType = 'arraybuffer'; |
michael@0 | 157 | xhr.onloadend = continueTest; |
michael@0 | 158 | xhr.send(null); |
michael@0 | 159 | yield undefined; |
michael@0 | 160 | is(xhr.status, 200, "wrong status"); |
michael@0 | 161 | checkResponseTextAccessThrows(xhr); |
michael@0 | 162 | checkResponseXMLAccessThrows(xhr); |
michael@0 | 163 | var ab = xhr.response; |
michael@0 | 164 | ok(ab != null, "should have a non-null arraybuffer"); |
michael@0 | 165 | arraybuffer_equals_to(ab, "hello pass\n"); |
michael@0 | 166 | |
michael@0 | 167 | // test reusing the same XHR (Bug 680816) |
michael@0 | 168 | xhr.open("GET", 'file_XHR_binary1.bin'); |
michael@0 | 169 | xhr.responseType = 'arraybuffer'; |
michael@0 | 170 | xhr.onloadend = continueTest; |
michael@0 | 171 | xhr.send(null); |
michael@0 | 172 | yield undefined; |
michael@0 | 173 | is(xhr.status, 200, "wrong status"); |
michael@0 | 174 | var ab2 = xhr.response; |
michael@0 | 175 | ok(ab2 != null, "should have a non-null arraybuffer"); |
michael@0 | 176 | ok(ab2 != ab, "arraybuffer on XHR reuse should be distinct"); |
michael@0 | 177 | arraybuffer_equals_to(ab, "hello pass\n"); |
michael@0 | 178 | arraybuffer_equals_to(ab2, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb"); |
michael@0 | 179 | |
michael@0 | 180 | // with a binary file |
michael@0 | 181 | xhr = new XMLHttpRequest(); |
michael@0 | 182 | xhr.open("GET", 'file_XHR_binary1.bin'); |
michael@0 | 183 | xhr.responseType = 'arraybuffer'; |
michael@0 | 184 | xhr.onloadend = continueTest; |
michael@0 | 185 | xhr.send(null); |
michael@0 | 186 | yield undefined; |
michael@0 | 187 | is(xhr.status, 200, "wrong status"); |
michael@0 | 188 | checkResponseTextAccessThrows(xhr); |
michael@0 | 189 | checkResponseXMLAccessThrows(xhr); |
michael@0 | 190 | ab = xhr.response; |
michael@0 | 191 | ok(ab != null, "should have a non-null arraybuffer"); |
michael@0 | 192 | arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb"); |
michael@0 | 193 | is(xhr.response, xhr.response, "returns the same ArrayBuffer"); |
michael@0 | 194 | |
michael@0 | 195 | // test response (responseType='json') |
michael@0 | 196 | var xhr = new XMLHttpRequest(); |
michael@0 | 197 | xhr.open("POST", 'responseIdentical.sjs'); |
michael@0 | 198 | xhr.responseType = 'json'; |
michael@0 | 199 | var jsonObjStr = JSON.stringify({title: "aBook", author: "john"}); |
michael@0 | 200 | xhr.onloadend = continueTest; |
michael@0 | 201 | xhr.send(jsonObjStr); |
michael@0 | 202 | yield undefined; |
michael@0 | 203 | is(xhr.status, 200, "wrong status"); |
michael@0 | 204 | checkResponseTextAccessThrows(xhr); |
michael@0 | 205 | checkResponseXMLAccessThrows(xhr); |
michael@0 | 206 | is(JSON.stringify(xhr.response), jsonObjStr, "correct result"); |
michael@0 | 207 | is(xhr.response, xhr.response, "returning the same object on each access"); |
michael@0 | 208 | |
michael@0 | 209 | // with invalid json |
michael@0 | 210 | var xhr = new XMLHttpRequest(); |
michael@0 | 211 | xhr.open("POST", 'responseIdentical.sjs'); |
michael@0 | 212 | xhr.responseType = 'json'; |
michael@0 | 213 | xhr.onloadend = continueTest; |
michael@0 | 214 | xhr.send("{"); |
michael@0 | 215 | yield undefined; |
michael@0 | 216 | is(xhr.status, 200, "wrong status"); |
michael@0 | 217 | checkResponseTextAccessThrows(xhr); |
michael@0 | 218 | checkResponseXMLAccessThrows(xhr); |
michael@0 | 219 | is(xhr.response, null, "Bad JSON should result in null response."); |
michael@0 | 220 | is(xhr.response, null, "Bad JSON should result in null response even 2nd time."); |
michael@0 | 221 | |
michael@0 | 222 | // Test status/statusText in all readyStates |
michael@0 | 223 | xhr = new XMLHttpRequest(); |
michael@0 | 224 | function checkXHRStatus() { |
michael@0 | 225 | if (xhr.readyState == xhr.UNSENT || xhr.readyState == xhr.OPENED) { |
michael@0 | 226 | is(xhr.status, 0, "should be 0 before getting data"); |
michael@0 | 227 | is(xhr.statusText, "", "should be empty before getting data"); |
michael@0 | 228 | } |
michael@0 | 229 | else { |
michael@0 | 230 | is(xhr.status, 200, "should be 200 when we have data"); |
michael@0 | 231 | is(xhr.statusText, "OK", "should be OK when we have data"); |
michael@0 | 232 | } |
michael@0 | 233 | } |
michael@0 | 234 | checkXHRStatus(); |
michael@0 | 235 | xhr.open("GET", 'file_XHR_binary1.bin'); |
michael@0 | 236 | checkXHRStatus(); |
michael@0 | 237 | xhr.responseType = 'arraybuffer'; |
michael@0 | 238 | xhr.send(null); |
michael@0 | 239 | xhr.onreadystatechange = continueTest; |
michael@0 | 240 | while (xhr.readyState != 4) { |
michael@0 | 241 | checkXHRStatus(); |
michael@0 | 242 | yield undefined; |
michael@0 | 243 | } |
michael@0 | 244 | checkXHRStatus(); |
michael@0 | 245 | |
michael@0 | 246 | // test response (responseType='blob') |
michael@0 | 247 | var responseTypes = ['blob', 'moz-blob']; |
michael@0 | 248 | for (var i = 0; i < responseTypes.length; i++) { |
michael@0 | 249 | var t = responseTypes[i]; |
michael@0 | 250 | // with a simple text file |
michael@0 | 251 | xhr = new XMLHttpRequest(); |
michael@0 | 252 | xhr.open("GET", 'file_XHR_pass2.txt'); |
michael@0 | 253 | xhr.responseType = t; |
michael@0 | 254 | xhr.onloadend = continueTest; |
michael@0 | 255 | xhr.send(null); |
michael@0 | 256 | yield undefined; |
michael@0 | 257 | is(xhr.status, 200, "wrong status"); |
michael@0 | 258 | checkResponseTextAccessThrows(xhr); |
michael@0 | 259 | checkResponseXMLAccessThrows(xhr); |
michael@0 | 260 | var b = xhr.response; |
michael@0 | 261 | ok(b, "should have a non-null blob"); |
michael@0 | 262 | ok(b instanceof Blob, "should be a Blob"); |
michael@0 | 263 | ok(!(b instanceof File), "should not be a File"); |
michael@0 | 264 | is(b.size, "hello pass\n".length, "wrong blob size"); |
michael@0 | 265 | |
michael@0 | 266 | var fr = new FileReader(); |
michael@0 | 267 | fr.onload = continueTest; |
michael@0 | 268 | fr.readAsBinaryString(b); |
michael@0 | 269 | yield undefined; |
michael@0 | 270 | ok(fr.result, "hello pass\n", "wrong values"); |
michael@0 | 271 | |
michael@0 | 272 | // with a binary file |
michael@0 | 273 | xhr = new XMLHttpRequest(); |
michael@0 | 274 | xhr.open("GET", 'file_XHR_binary1.bin', true); |
michael@0 | 275 | xhr.send(null); |
michael@0 | 276 | xhr.onreadystatechange = continueTest; |
michael@0 | 277 | while(xhr.readyState != 2) |
michael@0 | 278 | yield undefined; |
michael@0 | 279 | |
michael@0 | 280 | is(xhr.status, 200, "wrong status"); |
michael@0 | 281 | xhr.responseType = t; |
michael@0 | 282 | |
michael@0 | 283 | while(xhr.readyState != 4) |
michael@0 | 284 | yield undefined; |
michael@0 | 285 | |
michael@0 | 286 | xhr.onreadystatechange = null; |
michael@0 | 287 | |
michael@0 | 288 | b = xhr.response; |
michael@0 | 289 | ok(b != null, "should have a non-null blob"); |
michael@0 | 290 | is(b.size, 12, "wrong blob size"); |
michael@0 | 291 | |
michael@0 | 292 | fr = new FileReader(); |
michael@0 | 293 | fr.readAsBinaryString(b); |
michael@0 | 294 | xhr = null; // kill the XHR object |
michael@0 | 295 | b = null; |
michael@0 | 296 | SpecialPowers.gc(); |
michael@0 | 297 | fr.onload = continueTest; |
michael@0 | 298 | yield undefined; |
michael@0 | 299 | is(fr.result, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb", "wrong values"); |
michael@0 | 300 | |
michael@0 | 301 | // with a larger binary file |
michael@0 | 302 | xhr = new XMLHttpRequest(); |
michael@0 | 303 | xhr.open("GET", 'file_XHR_binary2.bin', true); |
michael@0 | 304 | xhr.responseType = t; |
michael@0 | 305 | xhr.send(null); |
michael@0 | 306 | xhr.onreadystatechange = continueTest; |
michael@0 | 307 | |
michael@0 | 308 | while (xhr.readyState != 4) |
michael@0 | 309 | yield undefined; |
michael@0 | 310 | |
michael@0 | 311 | xhr.onreadystatechange = null; |
michael@0 | 312 | |
michael@0 | 313 | var b = xhr.response; |
michael@0 | 314 | ok(b != null, "should have a non-null blob"); |
michael@0 | 315 | is(b.size, 65536, "wrong blob size"); |
michael@0 | 316 | |
michael@0 | 317 | fr = new FileReader(); |
michael@0 | 318 | fr.readAsArrayBuffer(b); |
michael@0 | 319 | fr.onload = continueTest; |
michael@0 | 320 | xhr = null; // kill the XHR object |
michael@0 | 321 | b = null; |
michael@0 | 322 | SpecialPowers.gc(); |
michael@0 | 323 | yield undefined; |
michael@0 | 324 | |
michael@0 | 325 | var u8 = new Uint8Array(fr.result); |
michael@0 | 326 | for (var i = 0; i < 65536; i++) { |
michael@0 | 327 | if (u8[i] !== (i & 255)) { |
michael@0 | 328 | break; |
michael@0 | 329 | } |
michael@0 | 330 | } |
michael@0 | 331 | is(i, 65536, "wrong value at offset " + i); |
michael@0 | 332 | } |
michael@0 | 333 | |
michael@0 | 334 | var client = new XMLHttpRequest(); |
michael@0 | 335 | client.open("GET", "file_XHR_pass1.xml", true); |
michael@0 | 336 | client.send(); |
michael@0 | 337 | client.onreadystatechange = function() { |
michael@0 | 338 | if(client.readyState == 4) { |
michael@0 | 339 | try { |
michael@0 | 340 | is(client.responseXML, null, "responseXML should be null."); |
michael@0 | 341 | is(client.responseText, "", "responseText should be empty string."); |
michael@0 | 342 | is(client.response, "", "response should be empty string."); |
michael@0 | 343 | is(client.status, 0, "status should be 0."); |
michael@0 | 344 | is(client.statusText, "", "statusText should be empty string."); |
michael@0 | 345 | is(client.getAllResponseHeaders(), "", |
michael@0 | 346 | "getAllResponseHeaders() should return empty string."); |
michael@0 | 347 | } catch(ex) { |
michael@0 | 348 | ok(false, "Shouldn't throw! [" + ex + "]"); |
michael@0 | 349 | } |
michael@0 | 350 | } |
michael@0 | 351 | } |
michael@0 | 352 | client.abort(); |
michael@0 | 353 | |
michael@0 | 354 | SimpleTest.finish(); |
michael@0 | 355 | yield undefined; |
michael@0 | 356 | |
michael@0 | 357 | } /* runTests */ |
michael@0 | 358 | </script> |
michael@0 | 359 | </pre> |
michael@0 | 360 | </body> |
michael@0 | 361 | </html> |