diff --git a/extensions/cookie/test/unit/head_cookies.js b/extensions/cookie/test/unit/head_cookies.js index ded1a9f2f6c0..8647a446b4a5 100644 --- a/extensions/cookie/test/unit/head_cookies.js +++ b/extensions/cookie/test/unit/head_cookies.js @@ -36,6 +36,26 @@ function do_check_throws(f, result, stack) do_throw("expected result " + result + ", none thrown", stack); } +// Helper to step a generator function and catch a StopIteration exception. +function do_run_generator(generator) +{ + try { + generator.next(); + } catch (e) { + if (e != StopIteration) + do_throw("caught exception " + e, Components.stack.caller); + } +} + +// Helper to finish a generator function test. +function do_finish_generator_test(generator) +{ + do_execute_soon(function() { + generator.close(); + do_test_finished(); + }); +} + function _observer(generator, service, topic) { Services.obs.addObserver(this, topic, false); @@ -51,14 +71,8 @@ _observer.prototype = { Services.obs.removeObserver(this, this.topic); // Continue executing the generator function. - if (this.generator) { - try { - this.generator.next(); - } catch (e) { - if (e != StopIteration) - do_throw("caught exception " + e, Components.stack.caller); - } - } + if (this.generator) + do_run_generator(this.generator); this.generator = null; this.service = null; diff --git a/extensions/cookie/test/unit/test_eviction.js b/extensions/cookie/test/unit/test_eviction.js index 3787cafbbef8..bb9f66e9f51c 100644 --- a/extensions/cookie/test/unit/test_eviction.js +++ b/extensions/cookie/test/unit/test_eviction.js @@ -4,105 +4,194 @@ let test_generator = do_run_test(); -function run_test() { +function run_test() +{ do_test_pending(); - test_generator.next(); + do_run_generator(test_generator); } -function finish_test() { +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. + do_check_true(gPurgeAge < 64); + gPurgeAge *= 2; + do_execute_soon(function() { test_generator.close(); - do_test_finished(); + test_generator = do_run_test(); + do_run_generator(test_generator); }); } +// Purge threshold, in seconds. +let gPurgeAge = 1; + +// 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; +} + function do_run_test() { // Set up a profile. let profile = do_get_profile(); // twiddle prefs to convenient values for this test - Services.prefs.setIntPref("network.cookie.purgeAge", 1); - Services.prefs.setIntPref("network.cookie.maxNumber", 1000); + 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% (1100), and when cookies are older than purgeAge + // 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. - force_eviction(1101, 50); + Services.cookiemgr.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(); - - do_check_true(check_remaining_cookies(1101, 50, 1051)); + do_check_true(check_remaining_cookies(111, 5, 106)); // 2) excess and age are satisfied, and all of the excess are old enough // to be purged. - force_eviction(1101, 100); + Services.cookiemgr.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(); - do_check_true(check_remaining_cookies(1101, 100, 1001)); + do_check_true(check_remaining_cookies(111, 10, 101)); // 3) excess and age are satisfied, and more than the excess are old enough // to be purged. - force_eviction(1101, 500); + Services.cookiemgr.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(); - do_check_true(check_remaining_cookies(1101, 500, 1001)); + do_check_true(check_remaining_cookies(111, 50, 101)); // 4) excess but not age are satisfied. - force_eviction(2000, 0); + Services.cookiemgr.removeAll(); + if (!set_cookies(0, 120, expiry)) { + repeat_test(); + return; + } + do_close_profile(test_generator); yield; do_load_profile(); - do_check_true(check_remaining_cookies(2000, 0, 2000)); + do_check_true(check_remaining_cookies(120, 0, 120)); // 5) age but not excess are satisfied. - force_eviction(1100, 200); + Services.cookiemgr.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(); - do_check_true(check_remaining_cookies(1100, 200, 1100)); + do_check_true(check_remaining_cookies(110, 20, 110)); - finish_test(); + do_finish_generator_test(test_generator); } -// Set 'aNumberTotal' cookies, ensuring that the first 'aNumberOld' cookies -// will be measurably older than the rest. -function -force_eviction(aNumberTotal, aNumberOld) +// Set 'end - begin' total cookies, with consecutively increasing hosts numbered +// 'begin' to 'end'. +function set_cookies(begin, end, expiry) { - Services.cookiemgr.removeAll(); - var expiry = (Date.now() + 1e6) * 1000; + do_check_true(begin != end); - var i; - for (i = 0; i < aNumberTotal; ++i) { - var host = "eviction." + i + ".tests"; + let beginTime; + for (let i = begin; i < end; ++i) { + let host = "eviction." + i + ".tests"; Services.cookiemgr.add(host, "", "test", "eviction", false, false, false, expiry); - if (i == aNumberOld - 1) { - // Sleep a while, to make sure the first batch of cookies is older than - // the second (timer resolution varies on different platforms). This - // delay must be measurably greater than the eviction age threshold. - sleep(1100); - } + if (i == begin) + beginTime = get_creationTime(i); } + + let endTime = get_creationTime(end - 1); + do_check_true(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 enumerator = Services.cookiemgr.getCookiesFromHost(host); + do_check_true(enumerator.hasMoreElements()); + let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2); + 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 -// are exceeded. +// + 10% are exceeded. function check_remaining_cookies(aNumberTotal, aNumberOld, aNumberToExpect) { var enumerator = Services.cookiemgr.enumerator; @@ -120,11 +209,3 @@ function check_remaining_cookies(aNumberTotal, aNumberOld, aNumberToExpect) { return i == aNumberToExpect; } - -// delay for a number of milliseconds -function sleep(delay) -{ - var start = Date.now(); - while (Date.now() < start + delay); -} -