diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /netwerk/test/unit/test_eviction.js | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | netwerk/test/unit/test_eviction.js | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_eviction.js b/netwerk/test/unit/test_eviction.js new file mode 100644 index 0000000000..eac7ece5be --- /dev/null +++ b/netwerk/test/unit/test_eviction.js @@ -0,0 +1,252 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"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; +} |