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.

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

mercurial