1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 // Test the various ways opening a cookie database can fail in a synchronous
5 // (i.e. immediate) manner, and that the database is renamed and recreated
6 // under each circumstance. These circumstances are, in no particular order:
8 // 1) A corrupt database, such that opening the connection fails.
9 // 2) The 'moz_cookies' table doesn't exist.
10 // 3) Not all of the expected columns exist, and statement creation fails when:
11 // a) The schema version is larger than the current version.
12 // b) The schema version is less than or equal to the current version.
13 // 4) Migration fails. This will have different modes depending on the initial
15 // a) Schema 1: the 'lastAccessed' column already exists.
16 // b) Schema 2: the 'baseDomain' column already exists; or 'baseDomain'
17 // cannot be computed for a particular host.
18 // c) Schema 3: the 'creationTime' column already exists; or the
19 // 'moz_uniqueid' index already exists.
31 var COOKIE_DATABASE_SCHEMA_CURRENT
= 14;
33 var test_generator
= do_run_test();
37 do_run_generator(test_generator
);
40 function finish_test() {
41 executeSoon(function () {
42 test_generator
.return();
47 function* do_run_test() {
49 profile
= do_get_profile();
52 Services
.prefs
.setIntPref("network.cookie.cookieBehavior", 0);
53 Services
.prefs
.setBoolPref(
54 "network.cookieJarSettings.unblocked_for_testing",
58 // Get the cookie file and the backup file.
59 cookieFile
= profile
.clone();
60 cookieFile
.append("cookies.sqlite");
61 backupFile
= profile
.clone();
62 backupFile
.append("cookies.sqlite.bak");
63 Assert
.ok(!cookieFile
.exists());
64 Assert
.ok(!backupFile
.exists());
66 // Create a cookie object for testing.
67 now
= Date
.now() * 1000;
68 futureExpiry
= Math
.round(now
/ 1e6
+ 1000);
82 sub_generator
= run_test_1(test_generator
);
86 sub_generator
= run_test_2(test_generator
);
90 sub_generator
= run_test_3(test_generator
, 99);
94 sub_generator
= run_test_3(test_generator
, COOKIE_DATABASE_SCHEMA_CURRENT
);
98 sub_generator
= run_test_3(test_generator
, 4);
102 sub_generator
= run_test_3(test_generator
, 3);
103 sub_generator
.next();
106 sub_generator
= run_test_4_exists(
109 "ALTER TABLE moz_cookies ADD lastAccessed INTEGER"
111 sub_generator
.next();
114 sub_generator
= run_test_4_exists(
117 "ALTER TABLE moz_cookies ADD baseDomain TEXT"
119 sub_generator
.next();
122 sub_generator
= run_test_4_baseDomain(test_generator
);
123 sub_generator
.next();
126 sub_generator
= run_test_4_exists(
129 "ALTER TABLE moz_cookies ADD creationTime INTEGER"
131 sub_generator
.next();
134 sub_generator
= run_test_4_exists(
137 "CREATE UNIQUE INDEX moz_uniqueid ON moz_cookies (name, host, path)"
139 sub_generator
.next();
145 const garbage
= "hello thar!";
147 function create_garbage_file(file
) {
148 // Create an empty database file.
149 file
.create(Ci
.nsIFile
.NORMAL_FILE_TYPE
, -1);
150 Assert
.ok(file
.exists());
151 Assert
.equal(file
.fileSize
, 0);
153 // Write some garbage to it.
154 let ostream
= Cc
["@mozilla.org/network/file-output-stream;1"].createInstance(
155 Ci
.nsIFileOutputStream
157 ostream
.init(file
, -1, -1, 0);
158 ostream
.write(garbage
, garbage
.length
);
162 file
= file
.clone(); // Windows maintains a stat cache. It's lame.
163 Assert
.equal(file
.fileSize
, garbage
.length
);
166 function check_garbage_file(file
) {
167 Assert
.ok(file
.exists());
168 Assert
.equal(file
.fileSize
, garbage
.length
);
170 Assert
.ok(!file
.exists());
173 function* run_test_1(generator
) {
174 // Create a garbage database file.
175 create_garbage_file(cookieFile
);
177 let uri
= NetUtil
.newURI("http://foo.com/");
178 const channel
= NetUtil
.newChannel({
180 loadUsingSystemPrincipal
: true,
181 contentPolicyType
: Ci
.nsIContentPolicy
.TYPE_DOCUMENT
,
184 // Load the profile and populate it.
185 Services
.cookies
.setCookieStringFromHttp(
187 "oh=hai; max-age=1000",
191 // Fake a profile change.
192 do_close_profile(sub_generator
);
196 // Check that the new database contains the cookie, and the old file was
198 Assert
.equal(do_count_cookies(), 1);
199 check_garbage_file(backupFile
);
201 // Close the profile.
202 do_close_profile(sub_generator
);
206 cookieFile
.remove(false);
207 Assert
.ok(!cookieFile
.exists());
208 do_run_generator(generator
);
211 function* run_test_2(generator
) {
212 // Load the profile and populate it.
214 let uri
= NetUtil
.newURI("http://foo.com/");
215 const channel
= NetUtil
.newChannel({
217 loadUsingSystemPrincipal
: true,
218 contentPolicyType
: Ci
.nsIContentPolicy
.TYPE_DOCUMENT
,
220 Services
.cookies
.setCookieStringFromHttp(
222 "oh=hai; max-age=1000",
226 // Fake a profile change.
227 do_close_profile(sub_generator
);
231 let db
= Services
.storage
.openDatabase(cookieFile
);
232 db
.executeSimpleSQL("DROP TABLE moz_cookies");
235 // Load the profile and check that the table is recreated in-place.
237 Assert
.equal(do_count_cookies(), 0);
238 Assert
.ok(!backupFile
.exists());
240 // Close the profile.
241 do_close_profile(sub_generator
);
245 cookieFile
.remove(false);
246 Assert
.ok(!cookieFile
.exists());
247 do_run_generator(generator
);
250 function* run_test_3(generator
, schema
) {
251 // Manually create a schema 2 database, populate it, and set the schema
252 // version to the desired number.
253 let schema2db
= new CookieDatabaseConnection(do_get_cookie_file(profile
), 2);
254 schema2db
.insertCookie(cookie
);
255 schema2db
.db
.schemaVersion
= schema
;
258 // Load the profile and check that the column existence test fails.
260 Assert
.equal(do_count_cookies(), 0);
262 // Close the profile.
263 do_close_profile(sub_generator
);
266 // Check that the schema version has been reset.
267 let db
= Services
.storage
.openDatabase(cookieFile
);
268 Assert
.equal(db
.schemaVersion
, COOKIE_DATABASE_SCHEMA_CURRENT
);
272 cookieFile
.remove(false);
273 Assert
.ok(!cookieFile
.exists());
274 do_run_generator(generator
);
277 function* run_test_4_exists(generator
, schema
, stmt
) {
278 // Manually create a database, populate it, and add the desired column.
279 let db
= new CookieDatabaseConnection(do_get_cookie_file(profile
), schema
);
280 db
.insertCookie(cookie
);
281 db
.db
.executeSimpleSQL(stmt
);
284 // Load the profile and check that migration fails.
286 Assert
.equal(do_count_cookies(), 0);
288 // Close the profile.
289 do_close_profile(sub_generator
);
292 // Check that the schema version has been reset and the backup file exists.
293 db
= Services
.storage
.openDatabase(cookieFile
);
294 Assert
.equal(db
.schemaVersion
, COOKIE_DATABASE_SCHEMA_CURRENT
);
296 Assert
.ok(backupFile
.exists());
299 cookieFile
.remove(false);
300 backupFile
.remove(false);
301 Assert
.ok(!cookieFile
.exists());
302 Assert
.ok(!backupFile
.exists());
303 do_run_generator(generator
);
306 function* run_test_4_baseDomain(generator
) {
307 // Manually create a database and populate it with a bad host.
308 let db
= new CookieDatabaseConnection(do_get_cookie_file(profile
), 2);
309 let badCookie
= new Cookie(
321 db
.insertCookie(badCookie
);
324 // Load the profile and check that migration fails.
326 Assert
.equal(do_count_cookies(), 0);
328 // Close the profile.
329 do_close_profile(sub_generator
);
332 // Check that the schema version has been reset and the backup file exists.
333 db
= Services
.storage
.openDatabase(cookieFile
);
334 Assert
.equal(db
.schemaVersion
, COOKIE_DATABASE_SCHEMA_CURRENT
);
336 Assert
.ok(backupFile
.exists());
339 cookieFile
.remove(false);
340 backupFile
.remove(false);
341 Assert
.ok(!cookieFile
.exists());
342 Assert
.ok(!backupFile
.exists());
343 do_run_generator(generator
);