Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

"use strict";
// Test for bug 2043675: when two consumers open a READY entry and both return
// ENTRY_NEEDS_REVALIDATION, InvokeCallback must detect the mState change that
// occurred during the first consumer's OnCacheEntryCheck (lock released) and
// re-queue it rather than proceeding as a second concurrent revalidator.
//
// Consumer B is opened synchronously from within A's onCacheEntryCheck (while
// mLock is released). B's InvokeCallback runs inline, sets mState =
// REVALIDATING, and defers setValid via executeSoon. When A re-acquires the
// lock, mState is REVALIDATING (not READY). With the fix, A is re-queued and
// notified only after B calls setValid. Without the fix, A proceeds inline and
// fires before setValid has been called.
function run_test() {
do_get_profile();
asyncOpenCacheEntry(
"disk",
Ci.nsICacheStorage.OPEN_NORMALLY,
null,
new OpenCallback(NEW, "m1", "d1", function () {
let bSetValidCalled = false;
let bHandle = null;
let consumerB = {
QueryInterface: ChromeUtils.generateQI(["nsICacheEntryOpenCallback"]),
onCacheEntryCheck() {
return Ci.nsICacheEntryOpenCallback.ENTRY_NEEDS_REVALIDATION;
},
onCacheEntryAvailable(entry, isNew, status) {
Assert.equal(Cr.NS_OK, status);
bHandle = entry;
// Defer setValid so mState stays REVALIDATING when A re-acquires
// the lock.
executeSoon(function () {
bSetValidCalled = true;
bHandle.setValid();
});
},
};
let firstCheckDone = false;
asyncOpenCacheEntry(
"disk",
Ci.nsICacheStorage.OPEN_NORMALLY,
null,
{
QueryInterface: ChromeUtils.generateQI(["nsICacheEntryOpenCallback"]),
onCacheEntryCheck() {
if (!firstCheckDone) {
firstCheckDone = true;
// Open B while A's mLock is released. B processes synchronously:
// its OnCacheEntryCheck runs, sets mState = REVALIDATING, and
// B's onCacheEntryAvailable queues setValid via executeSoon.
asyncOpenCacheEntry(
"disk",
Ci.nsICacheStorage.OPEN_NORMALLY,
null,
consumerB
);
return Ci.nsICacheEntryOpenCallback.ENTRY_NEEDS_REVALIDATION;
}
// Second check (with fix, after B called setValid): just read.
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
},
onCacheEntryAvailable(entry, isNew, status) {
// With fix: A is re-queued when mState != READY after the first
// check, and notified only after B's setValid.
// Without fix: A fires inline before executeSoon, so
// bSetValidCalled is still false.
Assert.ok(
bSetValidCalled,
"A must be notified only after B has called setValid (bug 2043675)"
);
Assert.equal(Cr.NS_OK, status);
finish_cache2_test();
},
}
);
})
);
do_test_pending();
}