gecko-dev/toolkit/components/url-classifier/tests/mochitest/test_cachemiss.html
Kris Maglione f70e67ad2d Bug 1541557: Part 4 - Stop relying on synchronous preference getters/setters. r=nika
The SpecialPowers set*Pref/get*Pref APIs currently use synchronous messaging
to set and get preference values from the parent process. Aside from directly
affecting callers of those APIs, it also affects callers of `pushPrefEnv`,
which is meant to be asynchronous, but is in practice usually synchronous due
to the synchronous messaging it uses.

This patch updates the getPref APIs to use the in-process preference service
(which most callers are expecting anyway), and also updates the callers of
the setPref and pushPrefEnv APIs to await the result if they're relying on it
taking effect immediately.

Unfortunately, there are some corner cases in tests that appear to only work
because of the quirks of the current sync messaging approach. The synchronous
setPref APIs, for instance, trigger preference changes in the parent
instantly, but don't update the values in the child until we've returned to
the event loop and had a chance to process the notifications from the parent.
The differnce in timing leads some tests to fail in strange ways, which this
patch works around by just adding timeouts.

There should be follow-ups for test owners to fix the flakiness.

Differential Revision: https://phabricator.services.mozilla.com/D35054

--HG--
extra : rebase_source : 941298157e7c82f420cf50ce057154ce9b85301c
extra : source : 189dc8a359815e059a4a217f788d183260bb2bfe
2019-06-13 09:34:39 -07:00

165 lines
4.8 KiB
HTML

<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1272239 - Test gethash.</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="classifierHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script src="head.js"></script>
<script class="testbody" type="text/javascript">
const MALWARE_LIST = "test-malware-simple";
const MALWARE_HOST = "malware.example.com/";
const UNWANTED_LIST = "test-unwanted-simple";
const UNWANTED_HOST = "unwanted.example.com/";
const GETHASH_URL = "http://mochi.test:8888/tests/toolkit/components/url-classifier/tests/mochitest/cache.sjs";
var shouldLoad = false;
var gPreGethashCounter = 0;
var gCurGethashCounter = 0;
function loadTestFrame() {
return new Promise(function(resolve, reject) {
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "gethashFrame.html");
document.body.appendChild(iframe);
iframe.onload = function() {
document.body.removeChild(iframe);
resolve();
};
}).then(getGethashCounter);
}
function getGethashCounter() {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest;
xhr.open("PUT", GETHASH_URL + "?gethashcount");
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.onreadystatechange = function() {
if (this.readyState == this.DONE) {
gPreGethashCounter = gCurGethashCounter;
gCurGethashCounter = parseInt(xhr.response);
resolve();
}
};
xhr.send();
});
}
// add 4-bytes prefixes to local database, so when we access the url,
// it will trigger gethash request.
function addPrefixToDB(list, url) {
var testData = [{ db: list, url, len: 4 }];
return classifierHelper.addUrlToDB(testData)
.catch(function(err) {
ok(false, "Couldn't update classifier. Error code: " + err);
// Abort test.
SimpleTest.finish();
});
}
// manually reset DB to make sure next test won't be affected by cache.
function reset() {
return classifierHelper.resetDatabase();
}
// This test has to come before testPositiveCache to ensure gethash server doesn't
// contain completions.
function testNegativeCache() {
shouldLoad = true;
async function setup() {
await classifierHelper.allowCompletion([MALWARE_LIST, UNWANTED_LIST], GETHASH_URL);
// Only add prefix to database. not server, so gethash will not return
// result.
return Promise.all([
addPrefixToDB(MALWARE_LIST, MALWARE_HOST),
addPrefixToDB(UNWANTED_LIST, UNWANTED_HOST),
]);
}
return Promise.resolve()
.then(setup)
.then(() => loadTestFrame())
.then(() => {
ok(gCurGethashCounter > gPreGethashCounter, "Gethash request is triggered.");
})
// Second load should not trigger gethash request because cache.
.then(() => loadTestFrame())
.then(() => {
ok(gCurGethashCounter == gPreGethashCounter, "Gethash request is nottriggered.");
})
.then(reset);
}
function testPositiveCache() {
shouldLoad = false;
async function setup() {
await classifierHelper.allowCompletion([MALWARE_LIST, UNWANTED_LIST], GETHASH_URL);
return Promise.all([
addPrefixToDB(MALWARE_LIST, MALWARE_HOST),
addPrefixToDB(UNWANTED_LIST, UNWANTED_HOST),
addCompletionToServer(MALWARE_LIST, MALWARE_HOST, GETHASH_URL),
addCompletionToServer(UNWANTED_LIST, UNWANTED_HOST, GETHASH_URL),
]);
}
return Promise.resolve()
.then(setup)
.then(() => loadTestFrame())
.then(() => {
ok(gCurGethashCounter > gPreGethashCounter, "Gethash request is triggered.");
})
// Second load should not trigger gethash request because cache.
.then(() => loadTestFrame())
.then(() => {
ok(gCurGethashCounter == gPreGethashCounter, "Gethash request is nottriggered.");
})
.then(reset);
}
function runTest() {
Promise.resolve()
// This test resources get blocked when gethash returns successfully
.then(classifierHelper.waitForInit)
.then(testNegativeCache)
.then(testPositiveCache)
.then(function() {
SimpleTest.finish();
}).catch(function(e) {
ok(false, "Some test failed with error " + e);
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
// 'network.predictor.enabled' is disabled because if other testcase load
// evil.js, evil.css ...etc resources, it may cause we load them from cache
// directly and bypass classifier check
SpecialPowers.pushPrefEnv({"set": [
["browser.safebrowsing.malware.enabled", true],
["urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple"],
["network.predictor.enabled", false],
["urlclassifier.gethash.timeout_ms", 30000],
]}, runTest);
</script>
</pre>
</body>
</html>