<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=338583
-->
<head>
  <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
  <title>Test for Bug 338583</title>
  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />

</head>
<body bgColor=white>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=338583">Mozilla Bug 338583</a>
<p id="display"></p>
<div id="content" style="display: none">

</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Tests for Bug 338583 **/

// we test:
//   1) the EventSource behaviour
//   2) if the events are trusted
//   3) possible invalid eventsources
//   4) the close method when the object is just been used
//   5) access-control
//   6) the data parameter
//   7) delayed server responses

// --

  var gTestsHaveFinished = [];

  function setTestHasFinished(test_id)
  {
    if (gTestsHaveFinished[test_id]) {
      return;
    }

    gTestsHaveFinished[test_id] = true;
    for (var i=0; i < gTestsHaveFinished.length; ++i) {
      if (!gTestsHaveFinished[i]) {
        return;
      }
    }

    SimpleTest.finish();
  }

  function runAllTests() {
    // these tests run asynchronously, and they will take 8000 ms
    var all_tests = [
      doTest1, doTest1_e, doTest1_f, doTest2, doTest3, doTest3_b, doTest3_c, doTest3_d,
      doTest3_e, doTest3_f, doTest3_g, doTest3_h, doTest4, doTest4_b,
      doTest5, doTest5_b, doTest5_c, doTest5_e, doTest6, doTest7
    ];

    for (let test_id=0; test_id < all_tests.length; ++test_id) {
      gTestsHaveFinished[test_id] = false;
      var fn = all_tests[test_id];
      fn(test_id);
    }

    setTimeout(function() {
      for (let test_id=0; test_id < all_tests.length; ++test_id) {
        if (!gTestsHaveFinished[test_id]) {
          ok(false, "Test " + test_id + " took too long");
          setTestHasFinished(test_id);
        }
      }
    }, 60000 * stress_factor); // all tests together are supposed to take less than 1 minute
  }

  function fn_onmessage(e) {
    if (e.currentTarget == e.target && e.target.hits != null)
      e.target.hits.fn_onmessage++;
  }

  function fn_event_listener_message(e) {
    if (e.currentTarget == e.target && e.target.hits != null)
      e.target.hits.fn_event_listener_message++;
  }

  function fn_other_event_name(e) {
    if (e.currentTarget == e.target && e.target.hits != null)
      e.target.hits.fn_other_event_name++;
  }

  var gEventSourceObj1 = null, gEventSourceObj1_e, gEventSourceObj1_f;
  var gEventSourceObj2 = null;
  var gEventSourceObj3_a = null, gEventSourceObj3_b = null,
      gEventSourceObj3_c = null, gEventSourceObj3_d = null,
      gEventSourceObj3_e = null, gEventSourceObj3_f = null,
      gEventSourceObj3_g = null, gEventSourceObj3_h = null;
  var gEventSourceObj4_a = null, gEventSourceObj4_b = null;
  var gEventSourceObj5_a = null, gEventSourceObj5_b = null,
      gEventSourceObj5_c = null, gEventSourceObj5_d = null,
      gEventSourceObj5_e = null, gEventSourceObj5_f = null;
  var gEventSourceObj6 = null;
  var gEventSourceObj7 = null;
  var stress_factor;  // used in the setTimeouts in order to help
                      // the test when running in slow machines

  function hasBeenHitFor1And2(obj, min) {
    if (obj.hits.fn_onmessage < min ||
        obj.hits.fn_event_listener_message < min ||
        obj.hits.fn_other_event_name < min)
      return false;
    return true;
  }

// in order to test (1):
//   a) if the EventSource constructor parameter is equal to its url attribute
//   b) let its fn_onmessage, fn_event_listener_message, and fn_other_event_name functions listeners be hit four times each
//   c) the close method (we expect readyState == CLOSED)
//   d) the close method (we expect no message events anymore)
//   e) use the default for withCredentials when passing dictionary arguments that don't explicitly set it
//   f) if a 204 HTTP response closes (interrupts) connections. See bug 869432.

  function doTest1(test_id) {
    gEventSourceObj1 = new EventSource("eventsource.resource");
    ok(gEventSourceObj1.url == "http://mochi.test:8888/tests/dom/base/test/eventsource.resource", "Test 1.a failed.");
    ok(gEventSourceObj1.readyState == 0 || gEventSourceObj1.readyState == 1, "Test 1.a failed.");

    doTest1_b(test_id);
  }

  function doTest1_b(test_id) {
    gEventSourceObj1.hits = [];
    gEventSourceObj1.hits.fn_onmessage = 0;
    gEventSourceObj1.onmessage = fn_onmessage;
    gEventSourceObj1.hits.fn_event_listener_message = 0;
    gEventSourceObj1.addEventListener('message', fn_event_listener_message, true);
    gEventSourceObj1.hits.fn_other_event_name = 0;
    gEventSourceObj1.addEventListener('other_event_name', fn_other_event_name, true);

    // the eventsources.res always use a retry of 0.5 second, so for four hits a timeout of 6 seconds is enough
    setTimeout(function(){
      bhits = hasBeenHitFor1And2(gEventSourceObj1, 4);
      ok(bhits, "Test 1.b failed.");

      doTest1_c(test_id);
    }, parseInt(6000*stress_factor));
  }

  function doTest1_c(test_id) {
    gEventSourceObj1.close();
    ok(gEventSourceObj1.readyState == 2, "Test 1.c failed.");

    doTest1_d(test_id);
  }

  function doTest1_d(test_id) {
    gEventSourceObj1.hits.fn_onmessage = 0;
    gEventSourceObj1.hits.fn_event_listener_message = 0;
    gEventSourceObj1.hits.fn_other_event_name = 0;

    setTimeout(function(){
      bhits = hasBeenHitFor1And2(gEventSourceObj1, 1);
      ok(!bhits, "Test 1.d failed.");
      gEventSourceObj1.close();
      setTestHasFinished(test_id);
    }, parseInt(2000*stress_factor));
  }

  function doTest1_e(test_id) {
    try {
      for (var options of [null, undefined, {}]) {
        gEventSourceObj1_e = new EventSource("eventsource.resource", options);
        is(gEventSourceObj1_e.withCredentials, false, "withCredentials should default to false");
        gEventSourceObj1_e.close();
      }
    } catch (e) {
      ok(false, "Test 1.e failed");
    }
    setTestHasFinished(test_id);
  }

  function doTest1_f(test_id) {
    var called_on_error = false;

    gEventSourceObj1_f = new EventSource("file_bug869432.eventsource");
    gEventSourceObj1_f.onopen = function(e) {
      ok(false, "Test 1.f failed: onopen was called");
    };
    gEventSourceObj1_f.onmessage = function(e) {
      ok(false, "Test 1.f failed: onmessage was called");
    };
    gEventSourceObj1_f.onerror = function(e) {
      if (called_on_error) {
        ok(false, "Test 1.f failed: onerror was called twice");
      }
      called_on_error = true;
      ok(gEventSourceObj1_f.readyState == 2, "Test 1.f failed: onerror was called with readyState = " + gEventSourceObj1_f.readyState);
    };

    setTimeout(function() {  // just to clean...
      ok(called_on_error, "Test 1.f failed: onerror was not called");
      setTestHasFinished(test_id);
    }, parseInt(5000*stress_factor));
  }

// in order to test (2)
//   a) set a eventsource that give the dom events messages
//   b) expect trusted events

  function doTest2(test_id) {
    var func = function(e) {
      ok(e.isTrusted, "Test 2 failed");
      gEventSourceObj2.close();
    };

    gEventSourceObj2 = new EventSource("eventsource.resource");
    gEventSourceObj2.onmessage = func;

    setTimeout(function() {  // just to clean...
      gEventSourceObj2.close();
      setTestHasFinished(test_id);
    }, parseInt(5000*stress_factor));
  }

// in order to test (3)
//   a) XSite domain error test
//   b) protocol file:// test
//   c) protocol javascript: test
//   d) wrong Content-Type test
//   e) bad http response code test
//   f) message eventsource without a data test
//   g) DNS error
//   h) EventSource which last message doesn't end with an empty line. See bug 710546

  function doTest3(test_id) {
    gEventSourceObj3_a = new EventSource("http://example.org/tests/dom/base/test/eventsource.resource");

    gEventSourceObj3_a.onmessage = fn_onmessage;
    gEventSourceObj3_a.hits = [];
    gEventSourceObj3_a.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj3_a.hits.fn_onmessage == 0, "Test 3.a failed");
      gEventSourceObj3_a.close();
      setTestHasFinished(test_id);
    }, parseInt(1500*stress_factor));
  }

  function doTest3_b(test_id) {
    // currently no support yet for local files for b2g/Android mochitest, see bug 838726
    if (navigator.appVersion.includes("Android") || SpecialPowers.Services.appinfo.name == "B2G") {
      setTestHasFinished(test_id);
      return;
    }

    var xhr = new XMLHttpRequest;
    xhr.open("GET", "/dynamic/getMyDirectory.sjs", false);
    xhr.send();
    var basePath = xhr.responseText;

    gEventSourceObj3_b = new EventSource("file://" + basePath + "eventsource.resource");

    gEventSourceObj3_b.onmessage = fn_onmessage;
    gEventSourceObj3_b.hits = [];
    gEventSourceObj3_b.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj3_b.hits.fn_onmessage == 0, "Test 3.b failed");
      gEventSourceObj3_b.close();
      setTestHasFinished(test_id);
    }, parseInt(1500*stress_factor));
  }

  function jsEvtSource()
  {
    return "event: message\n" +
           "data: 1\n\n";
  }

  function doTest3_c(test_id) {
    gEventSourceObj3_c = new EventSource("javascript: return jsEvtSource()");

    gEventSourceObj3_c.onmessage = fn_onmessage;
    gEventSourceObj3_c.hits = [];
    gEventSourceObj3_c.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj3_c.hits.fn_onmessage == 0, "Test 3.c failed");
      gEventSourceObj3_c.close();
      setTestHasFinished(test_id);
    }, parseInt(1500*stress_factor));
  }

  function doTest3_d(test_id) {
    gEventSourceObj3_d = new EventSource("badContentType.eventsource");

    gEventSourceObj3_d.onmessage = fn_onmessage;
    gEventSourceObj3_d.hits = [];
    gEventSourceObj3_d.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj3_d.hits.fn_onmessage == 0, "Test 3.d failed");
      gEventSourceObj3_d.close();
      setTestHasFinished(test_id);
    }, parseInt(1500*stress_factor));
  }

  function doTest3_e(test_id) {
    gEventSourceObj3_e = new EventSource("badHTTPResponseCode.eventsource");

    gEventSourceObj3_e.onmessage = fn_onmessage;
    gEventSourceObj3_e.hits = [];
    gEventSourceObj3_e.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj3_e.hits.fn_onmessage == 0, "Test 3.e failed");
      gEventSourceObj3_e.close();
      setTestHasFinished(test_id);
    }, parseInt(1500*stress_factor));
  }

  function doTest3_f(test_id) {
    gEventSourceObj3_f = new EventSource("badMessageEvent.eventsource");

    gEventSourceObj3_f.onmessage = fn_onmessage;
    gEventSourceObj3_f.hits = [];
    gEventSourceObj3_f.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj3_f.hits.fn_onmessage == 0, "Test 3.f failed");
      gEventSourceObj3_f.close();
      setTestHasFinished(test_id);
    }, parseInt(1500*stress_factor));
  }

  function fnInvalidNCName() {
    fnInvalidNCName.hits++;
  }

  function doTest3_g(test_id) {
    gEventSourceObj3_g = new EventSource("http://hdfskjghsbg.jtiyoejowe.example.com");

    gEventSourceObj3_g.onmessage = fn_onmessage;
    gEventSourceObj3_g.hits = [];
    gEventSourceObj3_g.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj3_g.hits.fn_onmessage == 0, "Test 3.g failed");
      gEventSourceObj3_g.close();
      setTestHasFinished(test_id);
    }, parseInt(1500*stress_factor));
  }

  function fnMessageListenerTest3h(e) {
    fnMessageListenerTest3h.msg_ok = (fnMessageListenerTest3h.msg_ok && e.data == "ok");
    fnMessageListenerTest3h.id_ok = (fnMessageListenerTest3h.id_ok && e.lastEventId == "");
  }

  function doTest3_h(test_id) {
    gEventSourceObj3_h = new EventSource("badMessageEvent2.eventsource");

    gEventSourceObj3_h.addEventListener('message', fnMessageListenerTest3h, true);
    fnMessageListenerTest3h.msg_ok = true;
    fnMessageListenerTest3h.id_ok = true;

    gEventSourceObj3_h.onmessage = fn_onmessage;
    gEventSourceObj3_h.hits = [];
    gEventSourceObj3_h.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj3_h.hits.fn_onmessage > 1, "Test 3.h.1 failed");
      if (gEventSourceObj3_h.hits.fn_onmessage > 1) {
        ok(fnMessageListenerTest3h.msg_ok, "Test 3.h.2 failed");
        ok(fnMessageListenerTest3h.id_ok, "Test 3.h.3 failed");
      }
      gEventSourceObj3_h.close();
      setTestHasFinished(test_id);
    }, parseInt(6000*stress_factor));
  }

// in order to test (4)
//   a) close the object when it is in use, which is being processed and that is expected
//      to dispatch more eventlisteners
//   b) remove an eventlistener in use

  function fn_onmessage4_a(e)
  {
    if (e.data > gEventSourceObj4_a.lastData)
      gEventSourceObj4_a.lastData = e.data;
    if (e.data == 2)
      gEventSourceObj4_a.close();
  }

  function fn_onmessage4_b(e)
  {
    if (e.data > gEventSourceObj4_b.lastData)
      gEventSourceObj4_b.lastData = e.data;
    if (e.data == 2)
      gEventSourceObj4_b.removeEventListener('message', fn_onmessage4_b, true);
  }

  function doTest4(test_id) {
    gEventSourceObj4_a = new EventSource("forRemoval.resource");
    gEventSourceObj4_a.lastData = 0;
    gEventSourceObj4_a.onmessage = fn_onmessage4_a;

    setTimeout(function() {
      ok(gEventSourceObj4_a.lastData == 2, "Test 4.a failed");
      gEventSourceObj4_a.close();
      setTestHasFinished(test_id);
    }, parseInt(3000*stress_factor));
  }

  function doTest4_b(test_id)
  {
    gEventSourceObj4_b = new EventSource("forRemoval.resource");
    gEventSourceObj4_b.lastData = 0;
    gEventSourceObj4_b.addEventListener('message', fn_onmessage4_b, true);

    setTimeout(function() {
      ok(gEventSourceObj4_b.lastData == 2, "Test 4.b failed");
      gEventSourceObj4_b.close();
      setTestHasFinished(test_id);
    }, parseInt(3000*stress_factor));
  }

// in order to test (5)
//   a) valid access-control xsite request
//   b) invalid access-control xsite request
//   c) valid access-control xsite request on a restricted page with credentials
//   d) valid access-control xsite request on a restricted page without credentials
//   e) valid access-control xsite request on a restricted page when the parameter withCredentials is a getter
//   f) valid access-control xsite request on a restricted page when the parameter withCredentials is missing

  function doTest5(test_id)
  {
    gEventSourceObj5_a = new EventSource("http://example.org/tests/dom/base/test/accesscontrol.resource");

    gEventSourceObj5_a.onmessage = fn_onmessage;
    gEventSourceObj5_a.hits = [];
    gEventSourceObj5_a.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj5_a.hits.fn_onmessage != 0, "Test 5.a failed");
      gEventSourceObj5_a.close();
      setTestHasFinished(test_id);
    }, parseInt(3000*stress_factor));
  }

  function doTest5_b(test_id)
  {
    gEventSourceObj5_b = new EventSource("http://example.org/tests/dom/base/test/invalid_accesscontrol.resource");

    gEventSourceObj5_b.onmessage = fn_onmessage;
    gEventSourceObj5_b.hits = [];
    gEventSourceObj5_b.hits.fn_onmessage = 0;

    setTimeout(function() {
      ok(gEventSourceObj5_b.hits.fn_onmessage == 0, "Test 5.b failed");
      gEventSourceObj5_b.close();
      setTestHasFinished(test_id);
    }, parseInt(3000*stress_factor));
  }

  function doTest5_c(test_id)
  {
    // credentials using the auth cache
    var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
    // also, test mixed mode UI
    xhr.open("GET", "https://example.com/tests/dom/base/test/file_restrictedEventSource.sjs?test=user1_xhr", true, "user 1", "password 1");
    xhr.send();
    xhr.onloadend = function() {
      ok(xhr.status == 200, "Failed to set credentials in test 5.c");

      gEventSourceObj5_c = new EventSource("https://example.com/tests/dom/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
                                           { withCredentials: true } );
      ok(gEventSourceObj5_c.withCredentials, "Wrong withCredentials in test 5.c");

      gEventSourceObj5_c.onmessage = function(e) {
        ok(e.origin == "https://example.com", "Wrong Origin in test 5.c");
        fn_onmessage(e);
      };
      gEventSourceObj5_c.hits = [];
      gEventSourceObj5_c.hits.fn_onmessage = 0;

      setTimeout(function() {
        ok(gEventSourceObj5_c.hits.fn_onmessage > 0, "Test 5.c failed");
        gEventSourceObj5_c.close();
        doTest5_d(test_id);
      }, parseInt(3000*stress_factor));
    };
  }

  function doTest5_d(test_id)
  {
    var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
    xhr.open("GET", "https://example.com/tests/dom/base/test/file_restrictedEventSource.sjs?test=user2_xhr", true, "user 2", "password 2");
    xhr.send();
    xhr.onloadend = function() {
      ok(xhr.status == 200, "Failed to set credentials in test 5.d");

      gEventSourceObj5_d = new EventSource("https://example.com/tests/dom/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc");
      ok(!gEventSourceObj5_d.withCredentials, "Wrong withCredentials in test 5.d");

      gEventSourceObj5_d.onmessage = function(e) {
        ok(e.origin == "https://example.com", "Wrong Origin in test 5.d");
        fn_onmessage(e);
      };
      gEventSourceObj5_d.hits = [];
      gEventSourceObj5_d.hits.fn_onmessage = 0;

      setTimeout(function() {
        ok(gEventSourceObj5_d.hits.fn_onmessage == 0, "Test 5.d failed");
        gEventSourceObj5_d.close();
        setTestHasFinished(test_id);
      }, parseInt(3000*stress_factor));
    };
  }

  function doTest5_e(test_id)
  {
    // credentials using the auth cache
    var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
    xhr.open("GET", "http://example.org/tests/dom/base/test/file_restrictedEventSource.sjs?test=user1_xhr", true, "user 1", "password 1");
    xhr.send();
    xhr.onloadend = function() {
      ok(xhr.status == 200, "Failed to set credentials in test 5.e");

      gEventSourceObj5_e = new EventSource("http://example.org/tests/dom/base/test/file_restrictedEventSource.sjs?test=user1_evtsrc",
                                           { get withCredentials() { return true; } } );
      ok(gEventSourceObj5_e.withCredentials, "Wrong withCredentials in test 5.e");

      gEventSourceObj5_e.onmessage = function(e) {
        ok(e.origin == "http://example.org", "Wrong Origin in test 5.e");
        fn_onmessage(e);
      };
      gEventSourceObj5_e.hits = [];
      gEventSourceObj5_e.hits.fn_onmessage = 0;

      setTimeout(function() {
        ok(gEventSourceObj5_e.hits.fn_onmessage > 0, "Test 5.e failed");
        gEventSourceObj5_e.close();
        doTest5_f(test_id);
      }, parseInt(5000*stress_factor));
    };
  }

  function doTest5_f(test_id)
  {
    var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
    xhr.open("GET", "http://example.org/tests/dom/base/test/file_restrictedEventSource.sjs?test=user2_xhr", true, "user 2", "password 2");
    xhr.send();
    xhr.onloadend = function() {
      ok(xhr.status == 200, "Failed to set credentials in test 5.f");

      gEventSourceObj5_f = new EventSource("http://example.org/tests/dom/base/test/file_restrictedEventSource.sjs?test=user2_evtsrc",
                                           { });
      ok(!gEventSourceObj5_f.withCredentials, "Wrong withCredentials in test 5.f");

      gEventSourceObj5_f.onmessage = function(e) {
        ok(e.origin == "http://example.org", "Wrong Origin in test 5.f");
        fn_onmessage(e);
      };
      gEventSourceObj5_f.hits = [];
      gEventSourceObj5_f.hits.fn_onmessage = 0;

      setTimeout(function() {
        ok(gEventSourceObj5_f.hits.fn_onmessage == 0, "Test 5.f failed");
        gEventSourceObj5_f.close();
        setTestHasFinished(test_id);
      }, parseInt(3000*stress_factor));
    };
  }

  function doTest6(test_id)
  {
    gEventSourceObj6 = new EventSource("somedatas.resource");
    var fn_somedata = function(e) {
      if (fn_somedata.expected == 0) {
        ok(e.data == "123456789\n123456789123456789\n123456789123456789123456789123456789\n 123456789123456789123456789123456789123456789123456789123456789123456789\nçãá\"\'@`~Ý Ḿyyyy",
          "Test 6.a failed");
      } else if (fn_somedata.expected == 1) {
        ok(e.data == " :xxabcdefghij\nçãá\"\'@`~Ý Ḿyyyy : zz",
          "Test 6.b failed");
        gEventSourceObj6.close();
      } else {
        ok(false, "Test 6 failed (unexpected message event)");
      }
      fn_somedata.expected++;
    }
    fn_somedata.expected = 0;
    gEventSourceObj6.onmessage = fn_somedata;

    setTimeout(function() {
      gEventSourceObj6.close();
      setTestHasFinished(test_id);
    }, parseInt(2500*stress_factor));
  }

  function doTest7(test_id)
  {
    gEventSourceObj7 = new EventSource("delayedServerEvents.sjs");
    gEventSourceObj7.msg_received = [];
    gEventSourceObj7.onmessage = function(e)
    {
      e.target.msg_received.push(e.data);
    }

    setTimeout(function() {
      gEventSourceObj7.close();

      ok(gEventSourceObj7.msg_received[0] == "" &&
         gEventSourceObj7.msg_received[1] == "delayed1" &&
         gEventSourceObj7.msg_received[2] == "delayed2", "Test 7 failed");

      document.getElementById('waitSpan').innerHTML = '';
      setTestHasFinished(test_id);
    }, parseInt(8000*stress_factor));
  }

  function doTest()
  {
    // Allow all cookies, then run the actual test
    SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]},
    function() {
      SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}],
        doTestCallback);
    });
  }

  function doTestCallback()
  {

    // we get a good stress_factor by testing 10 setTimeouts and some float
    // arithmetic taking my machine as stress_factor==1 (time=589)

    var begin_time = (new Date()).getTime();

    var f = function() {
      for (var j=0; j<f.i; ++j)
        eval("Math.log(Math.atan(Math.sqrt(Math.pow(3.1415, 13.1415))/0.0007))");
      if (f.i < 10) {
        f.i++;
        setTimeout(f, 10 + 10*f.i);
      } else {
        stress_factor = ((new Date()).getTime()-begin_time)*1/589;
        stress_factor *= 1.50; // also, a margin of 50%

        runAllTests();
      }
    }
    f.i = 0;

    setTimeout(f, 10);
  }

  SimpleTest.waitForExplicitFinish();
  SimpleTest.requestFlakyTimeout("untriaged");
  addLoadEvent(doTest);

</script>
</pre>
  <span id=waitSpan>Wait please...</span>
</body>
</html>
