Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 function run_test() {
6 //**************************************************************************//
7 // Database Creation, Schema Migration, and Backup
9 // Note: in these tests we use createInstance instead of getService
10 // so we can instantiate the service multiple times and make it run
11 // its database initialization code each time.
13 // Create a new database.
14 {
15 ContentPrefTest.deleteDatabase();
17 // Get the service and make sure it has a ready database connection.
18 let cps = Cc["@mozilla.org/content-pref/service;1"].
19 createInstance(Ci.nsIContentPrefService);
20 do_check_true(cps.DBConnection.connectionReady);
21 cps.DBConnection.close();
22 }
24 // Open an existing database.
25 {
26 let dbFile = ContentPrefTest.deleteDatabase();
28 let cps = Cc["@mozilla.org/content-pref/service;1"].
29 createInstance(Ci.nsIContentPrefService);
30 cps.DBConnection.close();
31 do_check_true(dbFile.exists());
33 // Get the service and make sure it has a ready database connection.
34 cps = Cc["@mozilla.org/content-pref/service;1"].
35 createInstance(Ci.nsIContentPrefService);
36 do_check_true(cps.DBConnection.connectionReady);
37 cps.DBConnection.close();
38 }
40 // Open an empty database.
41 {
42 let dbFile = ContentPrefTest.deleteDatabase();
44 // Create an empty database.
45 let dbService = Cc["@mozilla.org/storage/service;1"].
46 getService(Ci.mozIStorageService);
47 let dbConnection = dbService.openDatabase(dbFile);
48 do_check_eq(dbConnection.schemaVersion, 0);
49 dbConnection.close();
50 do_check_true(dbFile.exists());
52 // Get the service and make sure it has created the schema.
53 let cps = Cc["@mozilla.org/content-pref/service;1"].
54 createInstance(Ci.nsIContentPrefService);
55 do_check_neq(cps.DBConnection.schemaVersion, 0);
56 cps.DBConnection.close();
57 }
59 // Open a corrupted database.
60 {
61 let dbFile = ContentPrefTest.deleteDatabase();
62 let backupDBFile = ContentPrefTest.deleteBackupDatabase();
64 // Create a corrupted database.
65 let foStream = Cc["@mozilla.org/network/file-output-stream;1"].
66 createInstance(Ci.nsIFileOutputStream);
67 foStream.init(dbFile, 0x02 | 0x08 | 0x20, 0666, 0);
68 let garbageData = "garbage that makes SQLite think the file is corrupted";
69 foStream.write(garbageData, garbageData.length);
70 foStream.close();
72 // Get the service and make sure it backs up and recreates the database.
73 let cps = Cc["@mozilla.org/content-pref/service;1"].
74 createInstance(Ci.nsIContentPrefService);
75 do_check_true(backupDBFile.exists());
76 do_check_true(cps.DBConnection.connectionReady);
78 cps.DBConnection.close();
79 }
81 // Open a database with a corrupted schema.
82 {
83 let dbFile = ContentPrefTest.deleteDatabase();
84 let backupDBFile = ContentPrefTest.deleteBackupDatabase();
86 // Create an empty database and set the schema version to a number
87 // that will trigger a schema migration that will fail.
88 let dbService = Cc["@mozilla.org/storage/service;1"].
89 getService(Ci.mozIStorageService);
90 let dbConnection = dbService.openDatabase(dbFile);
91 dbConnection.schemaVersion = -1;
92 dbConnection.close();
93 do_check_true(dbFile.exists());
95 // Get the service and make sure it backs up and recreates the database.
96 let cps = Cc["@mozilla.org/content-pref/service;1"].
97 createInstance(Ci.nsIContentPrefService);
98 do_check_true(backupDBFile.exists());
99 do_check_true(cps.DBConnection.connectionReady);
101 cps.DBConnection.close();
102 }
105 // Now get the content pref service for real for use by the rest of the tests.
106 let cps = new ContentPrefInstance(null);
108 var uri = ContentPrefTest.getURI("http://www.example.com/");
110 // Make sure disk synchronization checking is turned off by default.
111 var statement = cps.DBConnection.createStatement("PRAGMA synchronous");
112 statement.executeStep();
113 do_check_eq(0, statement.getInt32(0));
115 //**************************************************************************//
116 // Nonexistent Pref
118 do_check_eq(cps.getPref(uri, "test.nonexistent.getPref"), undefined);
119 do_check_eq(cps.setPref(uri, "test.nonexistent.setPref", 5), undefined);
120 do_check_false(cps.hasPref(uri, "test.nonexistent.hasPref"));
121 do_check_eq(cps.removePref(uri, "test.nonexistent.removePref"), undefined);
124 //**************************************************************************//
125 // Existing Pref
127 cps.setPref(uri, "test.existing", 5);
129 // getPref should return the pref value
130 do_check_eq(cps.getPref(uri, "test.existing"), 5);
132 // setPref should return undefined and change the value of the pref
133 do_check_eq(cps.setPref(uri, "test.existing", 6), undefined);
134 do_check_eq(cps.getPref(uri, "test.existing"), 6);
136 // hasPref should return true
137 do_check_true(cps.hasPref(uri, "test.existing"));
139 // removePref should return undefined and remove the pref
140 do_check_eq(cps.removePref(uri, "test.existing"), undefined);
141 do_check_false(cps.hasPref(uri, "test.existing"));
144 //**************************************************************************//
145 // Round-Trip Data Integrity
147 // Make sure pref values remain the same from setPref to getPref.
149 cps.setPref(uri, "test.data-integrity.integer", 5);
150 do_check_eq(cps.getPref(uri, "test.data-integrity.integer"), 5);
152 cps.setPref(uri, "test.data-integrity.float", 5.5);
153 do_check_eq(cps.getPref(uri, "test.data-integrity.float"), 5.5);
155 cps.setPref(uri, "test.data-integrity.boolean", true);
156 do_check_eq(cps.getPref(uri, "test.data-integrity.boolean"), true);
158 cps.setPref(uri, "test.data-integrity.string", "test");
159 do_check_eq(cps.getPref(uri, "test.data-integrity.string"), "test");
161 cps.setPref(uri, "test.data-integrity.null", null);
162 do_check_eq(cps.getPref(uri, "test.data-integrity.null"), null);
164 // XXX Test arbitrary binary data.
166 // Make sure hasPref and removePref work on all data types.
168 do_check_true(cps.hasPref(uri, "test.data-integrity.integer"));
169 do_check_true(cps.hasPref(uri, "test.data-integrity.float"));
170 do_check_true(cps.hasPref(uri, "test.data-integrity.boolean"));
171 do_check_true(cps.hasPref(uri, "test.data-integrity.string"));
172 do_check_true(cps.hasPref(uri, "test.data-integrity.null"));
174 do_check_eq(cps.removePref(uri, "test.data-integrity.integer"), undefined);
175 do_check_eq(cps.removePref(uri, "test.data-integrity.float"), undefined);
176 do_check_eq(cps.removePref(uri, "test.data-integrity.boolean"), undefined);
177 do_check_eq(cps.removePref(uri, "test.data-integrity.string"), undefined);
178 do_check_eq(cps.removePref(uri, "test.data-integrity.null"), undefined);
180 do_check_false(cps.hasPref(uri, "test.data-integrity.integer"));
181 do_check_false(cps.hasPref(uri, "test.data-integrity.float"));
182 do_check_false(cps.hasPref(uri, "test.data-integrity.boolean"));
183 do_check_false(cps.hasPref(uri, "test.data-integrity.string"));
184 do_check_false(cps.hasPref(uri, "test.data-integrity.null"));
187 //**************************************************************************//
188 // getPrefs
190 cps.setPref(uri, "test.getPrefs.a", 1);
191 cps.setPref(uri, "test.getPrefs.b", 2);
192 cps.setPref(uri, "test.getPrefs.c", 3);
194 var prefs = cps.getPrefs(uri);
195 do_check_true(prefs.hasKey("test.getPrefs.a"));
196 do_check_eq(prefs.get("test.getPrefs.a"), 1);
197 do_check_true(prefs.hasKey("test.getPrefs.b"));
198 do_check_eq(prefs.get("test.getPrefs.b"), 2);
199 do_check_true(prefs.hasKey("test.getPrefs.c"));
200 do_check_eq(prefs.get("test.getPrefs.c"), 3);
203 //**************************************************************************//
204 // Site-Specificity
206 // These are all different sites, and setting a pref for one of them
207 // shouldn't set it for the others.
208 var uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
209 var uri2 = ContentPrefTest.getURI("http://foo.domain1.com/");
210 var uri3 = ContentPrefTest.getURI("http://domain1.com/");
211 var uri4 = ContentPrefTest.getURI("http://www.domain2.com/");
213 cps.setPref(uri1, "test.site-specificity.uri1", 5);
214 do_check_false(cps.hasPref(uri2, "test.site-specificity.uri1"));
215 do_check_false(cps.hasPref(uri3, "test.site-specificity.uri1"));
216 do_check_false(cps.hasPref(uri4, "test.site-specificity.uri1"));
218 cps.setPref(uri2, "test.site-specificity.uri2", 5);
219 do_check_false(cps.hasPref(uri1, "test.site-specificity.uri2"));
220 do_check_false(cps.hasPref(uri3, "test.site-specificity.uri2"));
221 do_check_false(cps.hasPref(uri4, "test.site-specificity.uri2"));
223 cps.setPref(uri3, "test.site-specificity.uri3", 5);
224 do_check_false(cps.hasPref(uri1, "test.site-specificity.uri3"));
225 do_check_false(cps.hasPref(uri2, "test.site-specificity.uri3"));
226 do_check_false(cps.hasPref(uri4, "test.site-specificity.uri3"));
228 cps.setPref(uri4, "test.site-specificity.uri4", 5);
229 do_check_false(cps.hasPref(uri1, "test.site-specificity.uri4"));
230 do_check_false(cps.hasPref(uri2, "test.site-specificity.uri4"));
231 do_check_false(cps.hasPref(uri3, "test.site-specificity.uri4"));
234 //**************************************************************************//
235 // Observers
237 var specificObserver = {
238 interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports],
240 QueryInterface: function ContentPrefTest_QueryInterface(iid) {
241 if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
242 throw Cr.NS_ERROR_NO_INTERFACE;
243 return this;
244 },
246 numTimesSetCalled: 0,
247 onContentPrefSet: function specificObserver_onContentPrefSet(group, name, value) {
248 ++this.numTimesSetCalled;
249 do_check_eq(group, "www.example.com");
250 do_check_eq(name, "test.observer.1");
251 do_check_eq(value, "test value");
252 },
254 numTimesRemovedCalled: 0,
255 onContentPrefRemoved: function specificObserver_onContentPrefRemoved(group, name) {
256 ++this.numTimesRemovedCalled;
257 do_check_eq(group, "www.example.com");
258 do_check_eq(name, "test.observer.1");
259 }
261 };
263 var genericObserver = {
264 interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports],
266 QueryInterface: function ContentPrefTest_QueryInterface(iid) {
267 if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
268 throw Cr.NS_ERROR_NO_INTERFACE;
269 return this;
270 },
272 numTimesSetCalled: 0,
273 onContentPrefSet: function genericObserver_onContentPrefSet(group, name, value) {
274 ++this.numTimesSetCalled;
275 do_check_eq(group, "www.example.com");
276 if (name != "test.observer.1" && name != "test.observer.2")
277 do_throw("genericObserver.onContentPrefSet: " +
278 "name not in (test.observer.1, test.observer.2)");
279 do_check_eq(value, "test value");
280 },
282 numTimesRemovedCalled: 0,
283 onContentPrefRemoved: function genericObserver_onContentPrefRemoved(group, name) {
284 ++this.numTimesRemovedCalled;
285 do_check_eq(group, "www.example.com");
286 if (name != "test.observer.1" && name != "test.observer.2")
287 do_throw("genericObserver.onContentPrefSet: " +
288 "name not in (test.observer.1, test.observer.2)");
289 }
291 };
293 // Make sure we can add observers, observers get notified about changes,
294 // specific observers only get notified about changes to the specific setting,
295 // and generic observers get notified about changes to all settings.
296 cps.addObserver("test.observer.1", specificObserver);
297 cps.addObserver(null, genericObserver);
298 cps.setPref(uri, "test.observer.1", "test value");
299 cps.setPref(uri, "test.observer.2", "test value");
300 cps.removePref(uri, "test.observer.1");
301 cps.removePref(uri, "test.observer.2");
302 do_check_eq(specificObserver.numTimesSetCalled, 1);
303 do_check_eq(genericObserver.numTimesSetCalled, 2);
304 do_check_eq(specificObserver.numTimesRemovedCalled, 1);
305 do_check_eq(genericObserver.numTimesRemovedCalled, 2);
307 // Make sure we can remove observers and they don't get notified
308 // about changes anymore.
309 cps.removeObserver("test.observer.1", specificObserver);
310 cps.removeObserver(null, genericObserver);
311 cps.setPref(uri, "test.observer.1", "test value");
312 cps.removePref(uri, "test.observer.1", "test value");
313 do_check_eq(specificObserver.numTimesSetCalled, 1);
314 do_check_eq(genericObserver.numTimesSetCalled, 2);
315 do_check_eq(specificObserver.numTimesRemovedCalled, 1);
316 do_check_eq(genericObserver.numTimesRemovedCalled, 2);
319 //**************************************************************************//
320 // Get/Remove Prefs By Name
322 {
323 var anObserver = {
324 interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports],
326 QueryInterface: function ContentPrefTest_QueryInterface(iid) {
327 if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
328 throw Cr.NS_ERROR_NO_INTERFACE;
329 return this;
330 },
332 onContentPrefSet: function anObserver_onContentPrefSet(group, name, value) {
333 },
335 expectedDomains: [],
336 numTimesRemovedCalled: 0,
337 onContentPrefRemoved: function anObserver_onContentPrefRemoved(group, name) {
338 ++this.numTimesRemovedCalled;
340 // remove the domain from the list of expected domains
341 var index = this.expectedDomains.indexOf(group);
342 do_check_true(index >= 0);
343 this.expectedDomains.splice(index, 1);
344 }
345 };
347 var uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
348 var uri2 = ContentPrefTest.getURI("http://foo.domain1.com/");
349 var uri3 = ContentPrefTest.getURI("http://domain1.com/");
350 var uri4 = ContentPrefTest.getURI("http://www.domain2.com/");
352 cps.setPref(uri1, "test.byname.1", 1);
353 cps.setPref(uri1, "test.byname.2", 2);
354 cps.setPref(uri2, "test.byname.1", 4);
355 cps.setPref(uri3, "test.byname.3", 8);
356 cps.setPref(uri4, "test.byname.1", 16);
357 cps.setPref(null, "test.byname.1", 32);
358 cps.setPref(null, "test.byname.2", false);
360 function enumerateAndCheck(testName, expectedSum, expectedDomains) {
361 var prefsByName = cps.getPrefsByName(testName);
362 var enumerator = prefsByName.enumerator;
363 var sum = 0;
364 while (enumerator.hasMoreElements()) {
365 var property = enumerator.getNext().QueryInterface(Components.interfaces.nsIProperty);
366 sum += parseInt(property.value);
368 // remove the domain from the list of expected domains
369 var index = expectedDomains.indexOf(property.name);
370 do_check_true(index >= 0);
371 expectedDomains.splice(index, 1);
372 }
373 do_check_eq(sum, expectedSum);
374 // check all domains have been removed from the array
375 do_check_eq(expectedDomains.length, 0);
376 }
378 enumerateAndCheck("test.byname.1", 53,
379 ["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"]);
380 enumerateAndCheck("test.byname.2", 2, ["www.domain1.com", null]);
381 enumerateAndCheck("test.byname.3", 8, ["domain1.com"]);
383 cps.addObserver("test.byname.1", anObserver);
384 anObserver.expectedDomains = ["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"];
386 cps.removePrefsByName("test.byname.1");
387 do_check_false(cps.hasPref(uri1, "test.byname.1"));
388 do_check_false(cps.hasPref(uri2, "test.byname.1"));
389 do_check_false(cps.hasPref(uri3, "test.byname.1"));
390 do_check_false(cps.hasPref(uri4, "test.byname.1"));
391 do_check_false(cps.hasPref(null, "test.byname.1"));
392 do_check_true(cps.hasPref(uri1, "test.byname.2"));
393 do_check_true(cps.hasPref(uri3, "test.byname.3"));
395 do_check_eq(anObserver.numTimesRemovedCalled, 4);
396 do_check_eq(anObserver.expectedDomains.length, 0);
398 cps.removeObserver("test.byname.1", anObserver);
400 // Clean up after ourselves
401 cps.removePref(uri1, "test.byname.2");
402 cps.removePref(uri3, "test.byname.3");
403 cps.removePref(null, "test.byname.2");
404 }
407 //**************************************************************************//
408 // Clear Private Data Pref Removal
410 {
411 let uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
412 let uri2 = ContentPrefTest.getURI("http://www.domain2.com/");
413 let uri3 = ContentPrefTest.getURI("http://www.domain3.com/");
415 let dbConnection = cps.DBConnection;
417 let prefCount = dbConnection.createStatement("SELECT COUNT(*) AS count FROM prefs");
419 let groupCount = dbConnection.createStatement("SELECT COUNT(*) AS count FROM groups");
421 // Add some prefs for multiple domains.
422 cps.setPref(uri1, "test.removeAllGroups", 1);
423 cps.setPref(uri2, "test.removeAllGroups", 2);
424 cps.setPref(uri3, "test.removeAllGroups", 3);
426 // Add a global pref.
427 cps.setPref(null, "test.removeAllGroups", 1);
429 // Make sure there are some prefs and groups in the database.
430 prefCount.executeStep();
431 do_check_true(prefCount.row.count > 0);
432 prefCount.reset();
433 groupCount.executeStep();
434 do_check_true(groupCount.row.count > 0);
435 groupCount.reset();
437 // Remove all prefs and groups from the database using the same routine
438 // the Clear Private Data dialog uses.
439 cps.removeGroupedPrefs();
441 // Make sure there are no longer any groups in the database and the only pref
442 // is the global one.
443 prefCount.executeStep();
444 do_check_true(prefCount.row.count == 1);
445 prefCount.reset();
446 groupCount.executeStep();
447 do_check_true(groupCount.row.count == 0);
448 groupCount.reset();
449 let globalPref = dbConnection.createStatement("SELECT groupID FROM prefs");
450 globalPref.executeStep();
451 do_check_true(globalPref.row.groupID == null);
452 globalPref.reset();
453 }
454 }