gecko-dev/dom/base/test/test_bug338583.html

667 строки
22 KiB
HTML

<!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)
// eslint-disable-next-line no-eval
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>