michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: // Test the various ways opening a cookie database can fail in an asynchronous michael@0: // (i.e. after synchronous initialization) manner, and that the database is michael@0: // renamed and recreated under each circumstance. These circumstances are, in no michael@0: // particular order: michael@0: // michael@0: // 1) A write operation failing after the database has been read in. michael@0: // 2) Asynchronous read failure due to a corrupt database. michael@0: // 3) Synchronous read failure due to a corrupt database, when reading: michael@0: // a) a single base domain; michael@0: // b) the entire database. michael@0: // 4) Asynchronous read failure, followed by another failure during INSERT but michael@0: // before the database closes for rebuilding. (The additional error should be michael@0: // ignored.) michael@0: // 5) Asynchronous read failure, followed by an INSERT failure during rebuild. michael@0: // This should result in an abort of the database rebuild; the partially- michael@0: // built database should be moved to 'cookies.sqlite.bak-rebuild'. michael@0: michael@0: let test_generator = do_run_test(); michael@0: michael@0: function run_test() { michael@0: do_test_pending(); michael@0: do_run_generator(test_generator); michael@0: } michael@0: michael@0: function finish_test() { michael@0: do_execute_soon(function() { michael@0: test_generator.close(); michael@0: do_test_finished(); michael@0: }); michael@0: } michael@0: michael@0: function do_run_test() { michael@0: // Set up a profile. michael@0: this.profile = do_get_profile(); michael@0: michael@0: // Allow all cookies. michael@0: Services.prefs.setIntPref("network.cookie.cookieBehavior", 0); michael@0: michael@0: // Get the cookie file and the backup file. michael@0: do_check_false(do_get_cookie_file(profile).exists()); michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: michael@0: // Create a cookie object for testing. michael@0: this.now = Date.now() * 1000; michael@0: this.futureExpiry = Math.round(this.now / 1e6 + 1000); michael@0: this.cookie = new Cookie("oh", "hai", "bar.com", "/", this.futureExpiry, michael@0: this.now, this.now, false, false, false); michael@0: michael@0: this.sub_generator = run_test_1(test_generator); michael@0: sub_generator.next(); michael@0: yield; michael@0: michael@0: this.sub_generator = run_test_2(test_generator); michael@0: sub_generator.next(); michael@0: yield; michael@0: michael@0: this.sub_generator = run_test_3(test_generator); michael@0: sub_generator.next(); michael@0: yield; michael@0: michael@0: this.sub_generator = run_test_4(test_generator); michael@0: sub_generator.next(); michael@0: yield; michael@0: michael@0: this.sub_generator = run_test_5(test_generator); michael@0: sub_generator.next(); michael@0: yield; michael@0: michael@0: finish_test(); michael@0: return; michael@0: } michael@0: michael@0: function do_get_backup_file(profile) michael@0: { michael@0: let file = profile.clone(); michael@0: file.append("cookies.sqlite.bak"); michael@0: return file; michael@0: } michael@0: michael@0: function do_get_rebuild_backup_file(profile) michael@0: { michael@0: let file = profile.clone(); michael@0: file.append("cookies.sqlite.bak-rebuild"); michael@0: return file; michael@0: } michael@0: michael@0: function do_corrupt_db(file) michael@0: { michael@0: // Sanity check: the database size should be larger than 450k, since we've michael@0: // written about 460k of data. If it's not, let's make it obvious now. michael@0: let size = file.fileSize; michael@0: do_check_true(size > 450e3); michael@0: michael@0: // Corrupt the database by writing bad data to the end of the file. We michael@0: // assume that the important metadata -- table structure etc -- is stored michael@0: // elsewhere, and that doing this will not cause synchronous failure when michael@0: // initializing the database connection. This is totally empirical -- michael@0: // overwriting between 1k and 100k of live data seems to work. (Note that the michael@0: // database file will be larger than the actual content requires, since the michael@0: // cookie service uses a large growth increment. So we calculate the offset michael@0: // based on the expected size of the content, not just the file size.) michael@0: let ostream = Cc["@mozilla.org/network/file-output-stream;1"]. michael@0: createInstance(Ci.nsIFileOutputStream); michael@0: ostream.init(file, 2, -1, 0); michael@0: let sstream = ostream.QueryInterface(Ci.nsISeekableStream); michael@0: let n = size - 450e3 + 20e3; michael@0: sstream.seek(Ci.nsISeekableStream.NS_SEEK_SET, size - n); michael@0: for (let i = 0; i < n; ++i) { michael@0: ostream.write("a", 1); michael@0: } michael@0: ostream.flush(); michael@0: ostream.close(); michael@0: michael@0: do_check_eq(file.clone().fileSize, size); michael@0: return size; michael@0: } michael@0: michael@0: function run_test_1(generator) michael@0: { michael@0: // Load the profile and populate it. michael@0: let uri = NetUtil.newURI("http://foo.com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Open a database connection now, before we load the profile and begin michael@0: // asynchronous write operations. In order to tell when the async delete michael@0: // statement has completed, we do something tricky: open a schema 2 connection michael@0: // and add a cookie with null baseDomain. We can then wait until we see it michael@0: // deleted in the new database. michael@0: let db2 = new CookieDatabaseConnection(do_get_cookie_file(profile), 2); michael@0: db2.db.executeSimpleSQL("INSERT INTO moz_cookies (baseDomain) VALUES (NULL)"); michael@0: db2.close(); michael@0: let db = new CookieDatabaseConnection(do_get_cookie_file(profile), 4); michael@0: do_check_eq(do_count_cookies_in_db(db.db), 2); michael@0: michael@0: // Load the profile, and wait for async read completion... michael@0: do_load_profile(sub_generator); michael@0: yield; michael@0: michael@0: // ... and the DELETE statement to finish. michael@0: while (do_count_cookies_in_db(db.db) == 2) { michael@0: do_execute_soon(function() { michael@0: do_run_generator(sub_generator); michael@0: }); michael@0: yield; michael@0: } michael@0: do_check_eq(do_count_cookies_in_db(db.db), 1); michael@0: michael@0: // Insert a row. michael@0: db.insertCookie(cookie); michael@0: db.close(); michael@0: michael@0: // Attempt to insert a cookie with the same (name, host, path) triplet. michael@0: Services.cookiemgr.add(cookie.host, cookie.path, cookie.name, "hallo", michael@0: cookie.isSecure, cookie.isHttpOnly, cookie.isSession, cookie.expiry); michael@0: michael@0: // Check that the cookie service accepted the new cookie. michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost(cookie.host), 1); michael@0: michael@0: // Wait for the cookie service to rename the old database and rebuild. michael@0: new _observer(sub_generator, "cookie-db-rebuilding"); michael@0: yield; michael@0: do_execute_soon(function() { do_run_generator(sub_generator); }); michael@0: yield; michael@0: michael@0: // At this point, the cookies should still be in memory. michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("foo.com"), 1); michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost(cookie.host), 1); michael@0: do_check_eq(do_count_cookies(), 2); michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Check that the original database was renamed, and that it contains the michael@0: // original cookie. michael@0: do_check_true(do_get_backup_file(profile).exists()); michael@0: let backupdb = Services.storage.openDatabase(do_get_backup_file(profile)); michael@0: do_check_eq(do_count_cookies_in_db(backupdb, "foo.com"), 1); michael@0: backupdb.close(); michael@0: michael@0: // Load the profile, and check that it contains the new cookie. michael@0: do_load_profile(); michael@0: michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("foo.com"), 1); michael@0: let enumerator = Services.cookiemgr.getCookiesFromHost(cookie.host); michael@0: do_check_true(enumerator.hasMoreElements()); michael@0: let dbcookie = enumerator.getNext().QueryInterface(Ci.nsICookie2); michael@0: do_check_eq(dbcookie.value, "hallo"); michael@0: do_check_false(enumerator.hasMoreElements()); michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Clean up. michael@0: do_get_cookie_file(profile).remove(false); michael@0: do_get_backup_file(profile).remove(false); michael@0: do_check_false(do_get_cookie_file(profile).exists()); michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: do_run_generator(generator); michael@0: } michael@0: michael@0: function run_test_2(generator) michael@0: { michael@0: // Load the profile and populate it. michael@0: do_load_profile(); michael@0: for (let i = 0; i < 3000; ++i) { michael@0: let uri = NetUtil.newURI("http://" + i + ".com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); michael@0: } michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Corrupt the database file. michael@0: let size = do_corrupt_db(do_get_cookie_file(profile)); michael@0: michael@0: // Load the profile. michael@0: do_load_profile(); michael@0: michael@0: // At this point, the database connection should be open. Ensure that it michael@0: // succeeded. michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: michael@0: // Synchronously read in the first cookie. This will cause it to go into the michael@0: // cookie table, whereupon it will be written out during database rebuild. michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); michael@0: michael@0: // Wait for the asynchronous read to choke, at which point the backup file michael@0: // will be created and the database rebuilt. michael@0: new _observer(sub_generator, "cookie-db-rebuilding"); michael@0: yield; michael@0: do_execute_soon(function() { do_run_generator(sub_generator); }); michael@0: yield; michael@0: michael@0: // At this point, the cookies should still be in memory. michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); michael@0: do_check_eq(do_count_cookies(), 1); michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Check that the original database was renamed. michael@0: do_check_true(do_get_backup_file(profile).exists()); michael@0: do_check_eq(do_get_backup_file(profile).fileSize, size); michael@0: let db = Services.storage.openDatabase(do_get_cookie_file(profile)); michael@0: do_check_eq(do_count_cookies_in_db(db, "0.com"), 1); michael@0: db.close(); michael@0: michael@0: // Load the profile, and check that it contains the new cookie. michael@0: do_load_profile(); michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); michael@0: do_check_eq(do_count_cookies(), 1); michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Clean up. michael@0: do_get_cookie_file(profile).remove(false); michael@0: do_get_backup_file(profile).remove(false); michael@0: do_check_false(do_get_cookie_file(profile).exists()); michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: do_run_generator(generator); michael@0: } michael@0: michael@0: function run_test_3(generator) michael@0: { michael@0: // Set the maximum cookies per base domain limit to a large value, so that michael@0: // corrupting the database is easier. michael@0: Services.prefs.setIntPref("network.cookie.maxPerHost", 3000); michael@0: michael@0: // Load the profile and populate it. michael@0: do_load_profile(); michael@0: for (let i = 0; i < 10; ++i) { michael@0: let uri = NetUtil.newURI("http://hither.com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh" + i + "=hai; max-age=1000", michael@0: null); michael@0: } michael@0: for (let i = 10; i < 3000; ++i) { michael@0: let uri = NetUtil.newURI("http://haithur.com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh" + i + "=hai; max-age=1000", michael@0: null); michael@0: } michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Corrupt the database file. michael@0: let size = do_corrupt_db(do_get_cookie_file(profile)); michael@0: michael@0: // Load the profile. michael@0: do_load_profile(); michael@0: michael@0: // At this point, the database connection should be open. Ensure that it michael@0: // succeeded. michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: michael@0: // Synchronously read in the cookies for our two domains. The first should michael@0: // succeed, but the second should fail midway through, resulting in none of michael@0: // those cookies being present. michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("hither.com"), 10); michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("haithur.com"), 0); michael@0: michael@0: // Wait for the backup file to be created and the database rebuilt. michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: new _observer(sub_generator, "cookie-db-rebuilding"); michael@0: yield; michael@0: do_execute_soon(function() { do_run_generator(sub_generator); }); michael@0: yield; michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: let db = Services.storage.openDatabase(do_get_cookie_file(profile)); michael@0: do_check_eq(do_count_cookies_in_db(db, "hither.com"), 10); michael@0: do_check_eq(do_count_cookies_in_db(db), 10); michael@0: db.close(); michael@0: michael@0: // Check that the original database was renamed. michael@0: do_check_true(do_get_backup_file(profile).exists()); michael@0: do_check_eq(do_get_backup_file(profile).fileSize, size); michael@0: michael@0: // Rename it back, and try loading the entire database synchronously. michael@0: do_get_backup_file(profile).moveTo(null, "cookies.sqlite"); michael@0: do_load_profile(); michael@0: michael@0: // At this point, the database connection should be open. Ensure that it michael@0: // succeeded. michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: michael@0: // Synchronously read in everything. michael@0: do_check_eq(do_count_cookies(), 0); michael@0: michael@0: // Wait for the backup file to be created and the database rebuilt. michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: new _observer(sub_generator, "cookie-db-rebuilding"); michael@0: yield; michael@0: do_execute_soon(function() { do_run_generator(sub_generator); }); michael@0: yield; michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: let db = Services.storage.openDatabase(do_get_cookie_file(profile)); michael@0: do_check_eq(do_count_cookies_in_db(db), 0); michael@0: db.close(); michael@0: michael@0: // Check that the original database was renamed. michael@0: do_check_true(do_get_backup_file(profile).exists()); michael@0: do_check_eq(do_get_backup_file(profile).fileSize, size); michael@0: michael@0: // Clean up. michael@0: do_get_cookie_file(profile).remove(false); michael@0: do_get_backup_file(profile).remove(false); michael@0: do_check_false(do_get_cookie_file(profile).exists()); michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: do_run_generator(generator); michael@0: } michael@0: michael@0: function run_test_4(generator) michael@0: { michael@0: // Load the profile and populate it. michael@0: do_load_profile(); michael@0: for (let i = 0; i < 3000; ++i) { michael@0: let uri = NetUtil.newURI("http://" + i + ".com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); michael@0: } michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Corrupt the database file. michael@0: let size = do_corrupt_db(do_get_cookie_file(profile)); michael@0: michael@0: // Load the profile. michael@0: do_load_profile(); michael@0: michael@0: // At this point, the database connection should be open. Ensure that it michael@0: // succeeded. michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: michael@0: // Synchronously read in the first cookie. This will cause it to go into the michael@0: // cookie table, whereupon it will be written out during database rebuild. michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); michael@0: michael@0: // Queue up an INSERT for the same base domain. This should also go into michael@0: // memory and be written out during database rebuild. michael@0: let uri = NetUtil.newURI("http://0.com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh2=hai; max-age=1000", null); michael@0: michael@0: // Wait for the asynchronous read to choke and the insert to fail shortly michael@0: // thereafter, at which point the backup file will be created and the database michael@0: // rebuilt. michael@0: new _observer(sub_generator, "cookie-db-rebuilding"); michael@0: yield; michael@0: do_execute_soon(function() { do_run_generator(sub_generator); }); michael@0: yield; michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Check that the original database was renamed. michael@0: do_check_true(do_get_backup_file(profile).exists()); michael@0: do_check_eq(do_get_backup_file(profile).fileSize, size); michael@0: let db = Services.storage.openDatabase(do_get_cookie_file(profile)); michael@0: do_check_eq(do_count_cookies_in_db(db, "0.com"), 2); michael@0: db.close(); michael@0: michael@0: // Load the profile, and check that it contains the new cookie. michael@0: do_load_profile(); michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 2); michael@0: do_check_eq(do_count_cookies(), 2); michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Clean up. michael@0: do_get_cookie_file(profile).remove(false); michael@0: do_get_backup_file(profile).remove(false); michael@0: do_check_false(do_get_cookie_file(profile).exists()); michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: do_run_generator(generator); michael@0: } michael@0: michael@0: function run_test_4(generator) michael@0: { michael@0: // Load the profile and populate it. michael@0: do_load_profile(); michael@0: for (let i = 0; i < 3000; ++i) { michael@0: let uri = NetUtil.newURI("http://" + i + ".com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); michael@0: } michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Corrupt the database file. michael@0: let size = do_corrupt_db(do_get_cookie_file(profile)); michael@0: michael@0: // Load the profile. michael@0: do_load_profile(); michael@0: michael@0: // At this point, the database connection should be open. Ensure that it michael@0: // succeeded. michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: michael@0: // Synchronously read in the first cookie. This will cause it to go into the michael@0: // cookie table, whereupon it will be written out during database rebuild. michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); michael@0: michael@0: // Queue up an INSERT for the same base domain. This should also go into michael@0: // memory and be written out during database rebuild. michael@0: let uri = NetUtil.newURI("http://0.com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh2=hai; max-age=1000", null); michael@0: michael@0: // Wait for the asynchronous read to choke and the insert to fail shortly michael@0: // thereafter, at which point the backup file will be created and the database michael@0: // rebuilt. michael@0: new _observer(sub_generator, "cookie-db-rebuilding"); michael@0: yield; michael@0: do_execute_soon(function() { do_run_generator(sub_generator); }); michael@0: yield; michael@0: michael@0: // At this point, the cookies should still be in memory. michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 2); michael@0: do_check_eq(do_count_cookies(), 2); michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Check that the original database was renamed. michael@0: do_check_true(do_get_backup_file(profile).exists()); michael@0: do_check_eq(do_get_backup_file(profile).fileSize, size); michael@0: let db = Services.storage.openDatabase(do_get_cookie_file(profile)); michael@0: do_check_eq(do_count_cookies_in_db(db, "0.com"), 2); michael@0: db.close(); michael@0: michael@0: // Load the profile, and check that it contains the new cookie. michael@0: do_load_profile(); michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 2); michael@0: do_check_eq(do_count_cookies(), 2); michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Clean up. michael@0: do_get_cookie_file(profile).remove(false); michael@0: do_get_backup_file(profile).remove(false); michael@0: do_check_false(do_get_cookie_file(profile).exists()); michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: do_run_generator(generator); michael@0: } michael@0: michael@0: function run_test_5(generator) michael@0: { michael@0: // Load the profile and populate it. michael@0: do_load_profile(); michael@0: let uri = NetUtil.newURI("http://bar.com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh=hai; path=/; max-age=1000", michael@0: null); michael@0: for (let i = 0; i < 3000; ++i) { michael@0: let uri = NetUtil.newURI("http://" + i + ".com/"); michael@0: Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); michael@0: } michael@0: michael@0: // Close the profile. michael@0: do_close_profile(sub_generator); michael@0: yield; michael@0: michael@0: // Corrupt the database file. michael@0: let size = do_corrupt_db(do_get_cookie_file(profile)); michael@0: michael@0: // Load the profile. michael@0: do_load_profile(); michael@0: michael@0: // At this point, the database connection should be open. Ensure that it michael@0: // succeeded. michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: michael@0: // Synchronously read in the first two cookies. This will cause them to go michael@0: // into the cookie table, whereupon it will be written out during database michael@0: // rebuild. michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("bar.com"), 1); michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); michael@0: michael@0: // Wait for the asynchronous read to choke, at which point the backup file michael@0: // will be created and a new connection opened. michael@0: new _observer(sub_generator, "cookie-db-rebuilding"); michael@0: yield; michael@0: michael@0: // At this point, the cookies should still be in memory. (Note that these michael@0: // calls are re-entrant into the cookie service, but it's OK!) michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("bar.com"), 1); michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); michael@0: do_check_eq(do_count_cookies(), 2); michael@0: do_check_true(do_get_backup_file(profile).exists()); michael@0: do_check_eq(do_get_backup_file(profile).fileSize, size); michael@0: do_check_false(do_get_rebuild_backup_file(profile).exists()); michael@0: michael@0: // Open a database connection, and write a row that will trigger a constraint michael@0: // violation. michael@0: let db = new CookieDatabaseConnection(do_get_cookie_file(profile), 4); michael@0: db.insertCookie(cookie); michael@0: do_check_eq(do_count_cookies_in_db(db.db, "bar.com"), 1); michael@0: do_check_eq(do_count_cookies_in_db(db.db), 1); michael@0: db.close(); michael@0: michael@0: // Wait for the rebuild to bail and the database to be closed. michael@0: new _observer(sub_generator, "cookie-db-closed"); michael@0: yield; michael@0: michael@0: // Check that the original backup and the database itself are gone. michael@0: do_check_true(do_get_rebuild_backup_file(profile).exists()); michael@0: do_check_true(do_get_backup_file(profile).exists()); michael@0: do_check_eq(do_get_backup_file(profile).fileSize, size); michael@0: do_check_false(do_get_cookie_file(profile).exists()); michael@0: michael@0: // Check that the rebuild backup has the original bar.com cookie, and possibly michael@0: // a 0.com cookie depending on whether it got written out first or second. michael@0: db = new CookieDatabaseConnection(do_get_rebuild_backup_file(profile), 4); michael@0: do_check_eq(do_count_cookies_in_db(db.db, "bar.com"), 1); michael@0: let count = do_count_cookies_in_db(db.db); michael@0: do_check_true(count == 1 || michael@0: count == 2 && do_count_cookies_in_db(db.db, "0.com") == 1); michael@0: db.close(); michael@0: michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("bar.com"), 1); michael@0: do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); michael@0: do_check_eq(do_count_cookies(), 2); michael@0: michael@0: // Close the profile. We do not need to wait for completion, because the michael@0: // database has already been closed. michael@0: do_close_profile(); michael@0: michael@0: // Clean up. michael@0: do_get_backup_file(profile).remove(false); michael@0: do_get_rebuild_backup_file(profile).remove(false); michael@0: do_check_false(do_get_cookie_file(profile).exists()); michael@0: do_check_false(do_get_backup_file(profile).exists()); michael@0: do_check_false(do_get_rebuild_backup_file(profile).exists()); michael@0: do_run_generator(generator); michael@0: } michael@0: