Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
"use strict";
var test_generator = do_run_test();
function run_test() {
do_test_pending();
do_run_generator(test_generator);
}
function continue_test() {
do_run_generator(test_generator);
}
function repeat_test() {
// The test is probably going to fail because setting a batch of cookies took
// a significant fraction of 'gPurgeAge'. Compensate by rerunning the
// test with a larger purge age.
Assert.ok(gPurgeAge < 64);
gPurgeAge *= 2;
gShortExpiry *= 2;
executeSoon(function () {
test_generator.return();
test_generator = do_run_test();
do_run_generator(test_generator);
});
}
// Purge threshold, in seconds.
var gPurgeAge = 1;
// Short expiry age, in seconds.
var gShortExpiry = 2;
// Required delay to ensure a purge occurs, in milliseconds. This must be at
// least gPurgeAge + 10%, and includes a little fuzz to account for timer
// resolution and possible differences between PR_Now() and Date.now().
function get_purge_delay() {
return gPurgeAge * 1100 + 100;
}
// Required delay to ensure a cookie set with an expiry time 'gShortExpiry' into
// the future will have expired.
function get_expiry_delay() {
return gShortExpiry * 1000 + 100;
}
function* do_run_test() {
// Set up a profile.
do_get_profile();
// twiddle prefs to convenient values for this test
Services.prefs.setIntPref("network.cookie.purgeAge", gPurgeAge);
Services.prefs.setIntPref("network.cookie.maxNumber", 100);
let expiry = Date.now() / 1000 + 1000;
// eviction is performed based on two limits: when the total number of cookies
// exceeds maxNumber + 10% (110), and when cookies are older than purgeAge
// (1 second). purging is done when both conditions are satisfied, and only
// those cookies are purged.
// we test the following cases of eviction:
// 1) excess and age are satisfied, but only some of the excess are old enough
// to be purged.
Services.cookies.removeAll();
if (!set_cookies(0, 5, expiry)) {
repeat_test();
return;
}
// Sleep a while, to make sure the first batch of cookies is older than
// the second (timer resolution varies on different platforms).
do_timeout(get_purge_delay(), continue_test);
yield;
if (!set_cookies(5, 111, expiry)) {
repeat_test();
return;
}
// Fake a profile change, to ensure eviction affects the database correctly.
do_close_profile(test_generator);
yield;
do_load_profile();
Assert.ok(check_remaining_cookies(111, 5, 106));
// 2) excess and age are satisfied, and all of the excess are old enough
// to be purged.
Services.cookies.removeAll();
if (!set_cookies(0, 10, expiry)) {
repeat_test();
return;
}
do_timeout(get_purge_delay(), continue_test);
yield;
if (!set_cookies(10, 111, expiry)) {
repeat_test();
return;
}
do_close_profile(test_generator);
yield;
do_load_profile();
Assert.ok(check_remaining_cookies(111, 10, 101));
// 3) excess and age are satisfied, and more than the excess are old enough
// to be purged.
Services.cookies.removeAll();
if (!set_cookies(0, 50, expiry)) {
repeat_test();
return;
}
do_timeout(get_purge_delay(), continue_test);
yield;
if (!set_cookies(50, 111, expiry)) {
repeat_test();
return;
}
do_close_profile(test_generator);
yield;
do_load_profile();
Assert.ok(check_remaining_cookies(111, 50, 101));
// 4) excess but not age are satisfied.
Services.cookies.removeAll();
if (!set_cookies(0, 120, expiry)) {
repeat_test();
return;
}
do_close_profile(test_generator);
yield;
do_load_profile();
Assert.ok(check_remaining_cookies(120, 0, 120));
// 5) age but not excess are satisfied.
Services.cookies.removeAll();
if (!set_cookies(0, 20, expiry)) {
repeat_test();
return;
}
do_timeout(get_purge_delay(), continue_test);
yield;
if (!set_cookies(20, 110, expiry)) {
repeat_test();
return;
}
do_close_profile(test_generator);
yield;
do_load_profile();
Assert.ok(check_remaining_cookies(110, 20, 110));
// 6) Excess and age are satisfied, but the cookie limit can be satisfied by
// purging expired cookies.
Services.cookies.removeAll();
let shortExpiry = Math.floor(Date.now() / 1000) + gShortExpiry;
if (!set_cookies(0, 20, shortExpiry)) {
repeat_test();
return;
}
do_timeout(get_expiry_delay(), continue_test);
yield;
if (!set_cookies(20, 110, expiry)) {
repeat_test();
return;
}
do_timeout(get_purge_delay(), continue_test);
yield;
if (!set_cookies(110, 111, expiry)) {
repeat_test();
return;
}
do_close_profile(test_generator);
yield;
do_load_profile();
Assert.ok(check_remaining_cookies(111, 20, 91));
do_finish_generator_test(test_generator);
}
// Set 'end - begin' total cookies, with consecutively increasing hosts numbered
// 'begin' to 'end'.
function set_cookies(begin, end, expiry) {
Assert.ok(begin != end);
let beginTime;
for (let i = begin; i < end; ++i) {
let host = "eviction." + i + ".tests";
Services.cookies.add(
host,
"",
"test",
"eviction",
false,
false,
false,
expiry,
{},
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
if (i == begin) {
beginTime = get_creationTime(i);
}
}
let endTime = get_creationTime(end - 1);
Assert.ok(begin == end - 1 || endTime > beginTime);
if (endTime - beginTime > gPurgeAge * 1000000) {
// Setting cookies took an amount of time very close to the purge threshold.
// Retry the test with a larger threshold.
return false;
}
return true;
}
function get_creationTime(i) {
let host = "eviction." + i + ".tests";
let cookies = Services.cookies.getCookiesFromHost(host, {});
Assert.ok(cookies.length);
let cookie = cookies[0];
return cookie.creationTime;
}
// Test that 'aNumberToExpect' cookies remain after purging is complete, and
// that the cookies that remain consist of the set expected given the number of
// of older and newer cookies -- eviction should occur by order of lastAccessed
// time, if both the limit on total cookies (maxNumber + 10%) and the purge age
// + 10% are exceeded.
function check_remaining_cookies(aNumberTotal, aNumberOld, aNumberToExpect) {
let i = 0;
for (let cookie of Services.cookies.cookies) {
++i;
if (aNumberTotal != aNumberToExpect) {
// make sure the cookie is one of the batch we expect was purged.
var hostNumber = Number(cookie.rawHost.split(".")[1]);
if (hostNumber < aNumberOld - aNumberToExpect) {
break;
}
}
}
return i == aNumberToExpect;
}