toolkit/components/satchel/test/unit/test_history_api.js

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 var testnum = 0;
michael@0 6 let dbConnection; // used for deleted table tests
michael@0 7
michael@0 8 Cu.import("resource://gre/modules/Promise.jsm");
michael@0 9
michael@0 10 function countDeletedEntries(expected)
michael@0 11 {
michael@0 12 let deferred = Promise.defer();
michael@0 13 let stmt = dbConnection.createAsyncStatement("SELECT COUNT(*) AS numEntries FROM moz_deleted_formhistory");
michael@0 14 stmt.executeAsync({
michael@0 15 handleResult: function(resultSet) {
michael@0 16 do_check_eq(expected, resultSet.getNextRow().getResultByName("numEntries"));
michael@0 17 deferred.resolve();
michael@0 18 },
michael@0 19 handleError : function () {
michael@0 20 do_throw("Error occurred counting deleted entries: " + error);
michael@0 21 deferred.reject();
michael@0 22 },
michael@0 23 handleCompletion : function () {
michael@0 24 stmt.finalize();
michael@0 25 }
michael@0 26 });
michael@0 27 return deferred.promise;
michael@0 28 }
michael@0 29
michael@0 30 function checkTimeDeleted(guid, checkFunction)
michael@0 31 {
michael@0 32 let deferred = Promise.defer();
michael@0 33 let stmt = dbConnection.createAsyncStatement("SELECT timeDeleted FROM moz_deleted_formhistory WHERE guid = :guid");
michael@0 34 stmt.params.guid = guid;
michael@0 35 stmt.executeAsync({
michael@0 36 handleResult: function(resultSet) {
michael@0 37 checkFunction(resultSet.getNextRow().getResultByName("timeDeleted"));
michael@0 38 deferred.resolve();
michael@0 39 },
michael@0 40 handleError : function () {
michael@0 41 do_throw("Error occurred getting deleted entries: " + error);
michael@0 42 deferred.reject();
michael@0 43 },
michael@0 44 handleCompletion : function () {
michael@0 45 stmt.finalize();
michael@0 46 }
michael@0 47 });
michael@0 48 return deferred.promise;
michael@0 49 }
michael@0 50
michael@0 51 function promiseUpdateEntry(op, name, value)
michael@0 52 {
michael@0 53 var change = { op: op };
michael@0 54 if (name !== null)
michael@0 55 change.fieldname = name;
michael@0 56 if (value !== null)
michael@0 57 change.value = value;
michael@0 58 return promiseUpdate(change);
michael@0 59 }
michael@0 60
michael@0 61 function promiseUpdate(change)
michael@0 62 {
michael@0 63 let deferred = Promise.defer();
michael@0 64 FormHistory.update(change,
michael@0 65 { handleError: function (error) {
michael@0 66 do_throw("Error occurred updating form history: " + error);
michael@0 67 deferred.reject(error);
michael@0 68 },
michael@0 69 handleCompletion: function (reason) { if (!reason) deferred.resolve(); }
michael@0 70 });
michael@0 71 return deferred.promise;
michael@0 72 }
michael@0 73
michael@0 74 function promiseSearchEntries(terms, params)
michael@0 75 {
michael@0 76 let deferred = Promise.defer();
michael@0 77 let results = [];
michael@0 78 FormHistory.search(terms, params,
michael@0 79 { handleResult: function(result) results.push(result),
michael@0 80 handleError: function (error) {
michael@0 81 do_throw("Error occurred searching form history: " + error);
michael@0 82 deferred.reject(error);
michael@0 83 },
michael@0 84 handleCompletion: function (reason) { if (!reason) deferred.resolve(results); }
michael@0 85 });
michael@0 86 return deferred.promise;
michael@0 87 }
michael@0 88
michael@0 89 function promiseCountEntries(name, value, checkFn)
michael@0 90 {
michael@0 91 let deferred = Promise.defer();
michael@0 92 countEntries(name, value, function (result) { checkFn(result); deferred.resolve(); } );
michael@0 93 return deferred.promise;
michael@0 94 }
michael@0 95
michael@0 96 add_task(function ()
michael@0 97 {
michael@0 98 let oldSupportsDeletedTable = FormHistory._supportsDeletedTable;
michael@0 99 FormHistory._supportsDeletedTable = true;
michael@0 100
michael@0 101 try {
michael@0 102
michael@0 103 // ===== test init =====
michael@0 104 var testfile = do_get_file("formhistory_apitest.sqlite");
michael@0 105 var profileDir = dirSvc.get("ProfD", Ci.nsIFile);
michael@0 106
michael@0 107 // Cleanup from any previous tests or failures.
michael@0 108 var destFile = profileDir.clone();
michael@0 109 destFile.append("formhistory.sqlite");
michael@0 110 if (destFile.exists())
michael@0 111 destFile.remove(false);
michael@0 112
michael@0 113 testfile.copyTo(profileDir, "formhistory.sqlite");
michael@0 114
michael@0 115 function checkExists(num) { do_check_true(num > 0); }
michael@0 116 function checkNotExists(num) { do_check_true(num == 0); }
michael@0 117
michael@0 118 // ===== 1 =====
michael@0 119 // Check initial state is as expected
michael@0 120 testnum++;
michael@0 121 yield promiseCountEntries("name-A", null, checkExists);
michael@0 122 yield promiseCountEntries("name-B", null, checkExists);
michael@0 123 yield promiseCountEntries("name-C", null, checkExists);
michael@0 124 yield promiseCountEntries("name-D", null, checkExists);
michael@0 125 yield promiseCountEntries("name-A", "value-A", checkExists);
michael@0 126 yield promiseCountEntries("name-B", "value-B1", checkExists);
michael@0 127 yield promiseCountEntries("name-B", "value-B2", checkExists);
michael@0 128 yield promiseCountEntries("name-C", "value-C", checkExists);
michael@0 129 yield promiseCountEntries("name-D", "value-D", checkExists);
michael@0 130 // time-A/B/C/D checked below.
michael@0 131
michael@0 132 // Delete anything from the deleted table
michael@0 133 let dbFile = Services.dirsvc.get("ProfD", Ci.nsIFile).clone();
michael@0 134 dbFile.append("formhistory.sqlite");
michael@0 135 dbConnection = Services.storage.openUnsharedDatabase(dbFile);
michael@0 136
michael@0 137 let deferred = Promise.defer();
michael@0 138
michael@0 139 let stmt = dbConnection.createAsyncStatement("DELETE FROM moz_deleted_formhistory");
michael@0 140 stmt.executeAsync({
michael@0 141 handleResult: function(resultSet) { },
michael@0 142 handleError : function () {
michael@0 143 do_throw("Error occurred counting deleted all entries: " + error);
michael@0 144 },
michael@0 145 handleCompletion : function () {
michael@0 146 stmt.finalize();
michael@0 147 deferred.resolve();
michael@0 148 }
michael@0 149 });
michael@0 150 yield deferred.promise;
michael@0 151
michael@0 152 // ===== 2 =====
michael@0 153 // Test looking for nonexistent / bogus data.
michael@0 154 testnum++;
michael@0 155 yield promiseCountEntries("blah", null, checkNotExists);
michael@0 156 yield promiseCountEntries("", null, checkNotExists);
michael@0 157 yield promiseCountEntries("name-A", "blah", checkNotExists);
michael@0 158 yield promiseCountEntries("name-A", "", checkNotExists);
michael@0 159 yield promiseCountEntries("name-A", null, checkExists);
michael@0 160 yield promiseCountEntries("blah", "value-A", checkNotExists);
michael@0 161 yield promiseCountEntries("", "value-A", checkNotExists);
michael@0 162 yield promiseCountEntries(null, "value-A", checkExists);
michael@0 163
michael@0 164 // Cannot use promiseCountEntries when name and value are null because it treats null values as not set
michael@0 165 // and here a search should be done explicity for null.
michael@0 166 deferred = Promise.defer();
michael@0 167 yield FormHistory.count({ fieldname: null, value: null },
michael@0 168 { handleResult: function(result) checkNotExists(result),
michael@0 169 handleError: function (error) {
michael@0 170 do_throw("Error occurred searching form history: " + error);
michael@0 171 },
michael@0 172 handleCompletion: function(reason) { if (!reason) deferred.resolve() }
michael@0 173 });
michael@0 174 yield deferred.promise;
michael@0 175
michael@0 176 // ===== 3 =====
michael@0 177 // Test removeEntriesForName with a single matching value
michael@0 178 testnum++;
michael@0 179 yield promiseUpdateEntry("remove", "name-A", null);
michael@0 180
michael@0 181 yield promiseCountEntries("name-A", "value-A", checkNotExists);
michael@0 182 yield promiseCountEntries("name-B", "value-B1", checkExists);
michael@0 183 yield promiseCountEntries("name-B", "value-B2", checkExists);
michael@0 184 yield promiseCountEntries("name-C", "value-C", checkExists);
michael@0 185 yield promiseCountEntries("name-D", "value-D", checkExists);
michael@0 186 yield countDeletedEntries(1);
michael@0 187
michael@0 188 // ===== 4 =====
michael@0 189 // Test removeEntriesForName with multiple matching values
michael@0 190 testnum++;
michael@0 191 yield promiseUpdateEntry("remove", "name-B", null);
michael@0 192
michael@0 193 yield promiseCountEntries("name-A", "value-A", checkNotExists);
michael@0 194 yield promiseCountEntries("name-B", "value-B1", checkNotExists);
michael@0 195 yield promiseCountEntries("name-B", "value-B2", checkNotExists);
michael@0 196 yield promiseCountEntries("name-C", "value-C", checkExists);
michael@0 197 yield promiseCountEntries("name-D", "value-D", checkExists);
michael@0 198 yield countDeletedEntries(3);
michael@0 199
michael@0 200 // ===== 5 =====
michael@0 201 // Test removing by time range (single entry, not surrounding entries)
michael@0 202 testnum++;
michael@0 203 yield promiseCountEntries("time-A", null, checkExists); // firstUsed=1000, lastUsed=1000
michael@0 204 yield promiseCountEntries("time-B", null, checkExists); // firstUsed=1000, lastUsed=1099
michael@0 205 yield promiseCountEntries("time-C", null, checkExists); // firstUsed=1099, lastUsed=1099
michael@0 206 yield promiseCountEntries("time-D", null, checkExists); // firstUsed=2001, lastUsed=2001
michael@0 207 yield promiseUpdate({ op : "remove", firstUsedStart: 1050, firstUsedEnd: 2000 });
michael@0 208
michael@0 209 yield promiseCountEntries("time-A", null, checkExists);
michael@0 210 yield promiseCountEntries("time-B", null, checkExists);
michael@0 211 yield promiseCountEntries("time-C", null, checkNotExists);
michael@0 212 yield promiseCountEntries("time-D", null, checkExists);
michael@0 213 yield countDeletedEntries(4);
michael@0 214
michael@0 215 // ===== 6 =====
michael@0 216 // Test removing by time range (multiple entries)
michael@0 217 testnum++;
michael@0 218 yield promiseUpdate({ op : "remove", firstUsedStart: 1000, firstUsedEnd: 2000 });
michael@0 219
michael@0 220 yield promiseCountEntries("time-A", null, checkNotExists);
michael@0 221 yield promiseCountEntries("time-B", null, checkNotExists);
michael@0 222 yield promiseCountEntries("time-C", null, checkNotExists);
michael@0 223 yield promiseCountEntries("time-D", null, checkExists);
michael@0 224 yield countDeletedEntries(6);
michael@0 225
michael@0 226 // ===== 7 =====
michael@0 227 // test removeAllEntries
michael@0 228 testnum++;
michael@0 229 yield promiseUpdateEntry("remove", null, null);
michael@0 230
michael@0 231 yield promiseCountEntries("name-C", null, checkNotExists);
michael@0 232 yield promiseCountEntries("name-D", null, checkNotExists);
michael@0 233 yield promiseCountEntries("name-C", "value-C", checkNotExists);
michael@0 234 yield promiseCountEntries("name-D", "value-D", checkNotExists);
michael@0 235
michael@0 236 yield promiseCountEntries(null, null, checkNotExists);
michael@0 237 yield countDeletedEntries(6);
michael@0 238
michael@0 239 // ===== 8 =====
michael@0 240 // Add a single entry back
michael@0 241 testnum++;
michael@0 242 yield promiseUpdateEntry("add", "newname-A", "newvalue-A");
michael@0 243 yield promiseCountEntries("newname-A", "newvalue-A", checkExists);
michael@0 244
michael@0 245 // ===== 9 =====
michael@0 246 // Remove the single entry
michael@0 247 testnum++;
michael@0 248 yield promiseUpdateEntry("remove", "newname-A", "newvalue-A");
michael@0 249 yield promiseCountEntries("newname-A", "newvalue-A", checkNotExists);
michael@0 250
michael@0 251 // ===== 10 =====
michael@0 252 // Add a single entry
michael@0 253 testnum++;
michael@0 254 yield promiseUpdateEntry("add", "field1", "value1");
michael@0 255 yield promiseCountEntries("field1", "value1", checkExists);
michael@0 256
michael@0 257 let processFirstResult = function processResults(results)
michael@0 258 {
michael@0 259 // Only handle the first result
michael@0 260 if (results.length > 0) {
michael@0 261 let result = results[0];
michael@0 262 return [result.timesUsed, result.firstUsed, result.lastUsed, result.guid];
michael@0 263 }
michael@0 264 }
michael@0 265
michael@0 266 results = yield promiseSearchEntries(["timesUsed", "firstUsed", "lastUsed"],
michael@0 267 { fieldname: "field1", value: "value1" });
michael@0 268 let [timesUsed, firstUsed, lastUsed] = processFirstResult(results);
michael@0 269 do_check_eq(1, timesUsed);
michael@0 270 do_check_true(firstUsed > 0);
michael@0 271 do_check_true(lastUsed > 0);
michael@0 272 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 1));
michael@0 273
michael@0 274 // ===== 11 =====
michael@0 275 // Add another single entry
michael@0 276 testnum++;
michael@0 277 yield promiseUpdateEntry("add", "field1", "value1b");
michael@0 278 yield promiseCountEntries("field1", "value1", checkExists);
michael@0 279 yield promiseCountEntries("field1", "value1b", checkExists);
michael@0 280 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 2));
michael@0 281
michael@0 282 // ===== 12 =====
michael@0 283 // Update a single entry
michael@0 284 testnum++;
michael@0 285
michael@0 286 results = yield promiseSearchEntries(["guid"], { fieldname: "field1", value: "value1" });
michael@0 287 let guid = processFirstResult(results)[3];
michael@0 288
michael@0 289 yield promiseUpdate({ op : "update", guid: guid, value: "modifiedValue" });
michael@0 290 yield promiseCountEntries("field1", "modifiedValue", checkExists);
michael@0 291 yield promiseCountEntries("field1", "value1", checkNotExists);
michael@0 292 yield promiseCountEntries("field1", "value1b", checkExists);
michael@0 293 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 2));
michael@0 294
michael@0 295 // ===== 13 =====
michael@0 296 // Add a single entry with times
michael@0 297 testnum++;
michael@0 298 yield promiseUpdate({ op : "add", fieldname: "field2", value: "value2",
michael@0 299 timesUsed: 20, firstUsed: 100, lastUsed: 500 });
michael@0 300
michael@0 301 results = yield promiseSearchEntries(["timesUsed", "firstUsed", "lastUsed"],
michael@0 302 { fieldname: "field2", value: "value2" });
michael@0 303 [timesUsed, firstUsed, lastUsed] = processFirstResult(results);
michael@0 304
michael@0 305 do_check_eq(20, timesUsed);
michael@0 306 do_check_eq(100, firstUsed);
michael@0 307 do_check_eq(500, lastUsed);
michael@0 308 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 3));
michael@0 309
michael@0 310 // ===== 14 =====
michael@0 311 // Bump an entry, which updates its lastUsed field
michael@0 312 testnum++;
michael@0 313 yield promiseUpdate({ op : "bump", fieldname: "field2", value: "value2",
michael@0 314 timesUsed: 20, firstUsed: 100, lastUsed: 500 });
michael@0 315 results = yield promiseSearchEntries(["timesUsed", "firstUsed", "lastUsed"],
michael@0 316 { fieldname: "field2", value: "value2" });
michael@0 317 [timesUsed, firstUsed, lastUsed] = processFirstResult(results);
michael@0 318 do_check_eq(21, timesUsed);
michael@0 319 do_check_eq(100, firstUsed);
michael@0 320 do_check_true(lastUsed > 500);
michael@0 321 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 3));
michael@0 322
michael@0 323 // ===== 15 =====
michael@0 324 // Bump an entry that does not exist
michael@0 325 testnum++;
michael@0 326 yield promiseUpdate({ op : "bump", fieldname: "field3", value: "value3",
michael@0 327 timesUsed: 10, firstUsed: 50, lastUsed: 400 });
michael@0 328 results = yield promiseSearchEntries(["timesUsed", "firstUsed", "lastUsed"],
michael@0 329 { fieldname: "field3", value: "value3" });
michael@0 330 [timesUsed, firstUsed, lastUsed] = processFirstResult(results);
michael@0 331 do_check_eq(10, timesUsed);
michael@0 332 do_check_eq(50, firstUsed);
michael@0 333 do_check_eq(400, lastUsed);
michael@0 334 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 4));
michael@0 335
michael@0 336 // ===== 16 =====
michael@0 337 // Bump an entry with a guid
michael@0 338 testnum++;
michael@0 339 results = yield promiseSearchEntries(["guid"], { fieldname: "field3", value: "value3" });
michael@0 340 guid = processFirstResult(results)[3];
michael@0 341 yield promiseUpdate({ op : "bump", guid: guid, timesUsed: 20, firstUsed: 55, lastUsed: 400 });
michael@0 342 results = yield promiseSearchEntries(["timesUsed", "firstUsed", "lastUsed"],
michael@0 343 { fieldname: "field3", value: "value3" });
michael@0 344 [timesUsed, firstUsed, lastUsed] = processFirstResult(results);
michael@0 345 do_check_eq(11, timesUsed);
michael@0 346 do_check_eq(50, firstUsed);
michael@0 347 do_check_true(lastUsed > 400);
michael@0 348 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 4));
michael@0 349
michael@0 350 // ===== 17 =====
michael@0 351 // Remove an entry
michael@0 352 testnum++;
michael@0 353 yield countDeletedEntries(7);
michael@0 354
michael@0 355 results = yield promiseSearchEntries(["guid"], { fieldname: "field1", value: "value1b" });
michael@0 356 guid = processFirstResult(results)[3];
michael@0 357
michael@0 358 yield promiseUpdate({ op : "remove", guid: guid});
michael@0 359 yield promiseCountEntries("field1", "modifiedValue", checkExists);
michael@0 360 yield promiseCountEntries("field1", "value1b", checkNotExists);
michael@0 361 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 3));
michael@0 362
michael@0 363 yield countDeletedEntries(8);
michael@0 364 yield checkTimeDeleted(guid, function (timeDeleted) do_check_true(timeDeleted > 10000));
michael@0 365
michael@0 366 // ===== 18 =====
michael@0 367 // Add yet another single entry
michael@0 368 testnum++;
michael@0 369 yield promiseUpdate({ op : "add", fieldname: "field4", value: "value4",
michael@0 370 timesUsed: 5, firstUsed: 230, lastUsed: 600 });
michael@0 371 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 4));
michael@0 372
michael@0 373 // ===== 19 =====
michael@0 374 // Remove an entry by time
michael@0 375 testnum++;
michael@0 376 yield promiseUpdate({ op : "remove", firstUsedStart: 60, firstUsedEnd: 250 });
michael@0 377 yield promiseCountEntries("field1", "modifiedValue", checkExists);
michael@0 378 yield promiseCountEntries("field2", "value2", checkNotExists);
michael@0 379 yield promiseCountEntries("field3", "value3", checkExists);
michael@0 380 yield promiseCountEntries("field4", "value4", checkNotExists);
michael@0 381 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 2));
michael@0 382 yield countDeletedEntries(10);
michael@0 383
michael@0 384 // ===== 20 =====
michael@0 385 // Bump multiple existing entries at once
michael@0 386 testnum++;
michael@0 387
michael@0 388 yield promiseUpdate([{ op : "add", fieldname: "field5", value: "value5",
michael@0 389 timesUsed: 5, firstUsed: 230, lastUsed: 600 },
michael@0 390 { op : "add", fieldname: "field6", value: "value6",
michael@0 391 timesUsed: 12, firstUsed: 430, lastUsed: 700 }]);
michael@0 392 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 4));
michael@0 393
michael@0 394 yield promiseUpdate([
michael@0 395 { op : "bump", fieldname: "field5", value: "value5" },
michael@0 396 { op : "bump", fieldname: "field6", value: "value6" }]);
michael@0 397 results = yield promiseSearchEntries(["fieldname", "timesUsed", "firstUsed", "lastUsed"], { });
michael@0 398
michael@0 399 do_check_eq(6, results[2].timesUsed);
michael@0 400 do_check_eq(13, results[3].timesUsed);
michael@0 401 do_check_eq(230, results[2].firstUsed);
michael@0 402 do_check_eq(430, results[3].firstUsed);
michael@0 403 do_check_true(results[2].lastUsed > 600);
michael@0 404 do_check_true(results[3].lastUsed > 700);
michael@0 405
michael@0 406 yield promiseCountEntries(null, null, function(num) do_check_eq(num, 4));
michael@0 407
michael@0 408 } catch (e) {
michael@0 409 throw "FAILED in test #" + testnum + " -- " + e;
michael@0 410 }
michael@0 411 finally {
michael@0 412 FormHistory._supportsDeletedTable = oldSupportsDeletedTable;
michael@0 413 dbConnection.asyncClose(do_test_finished);
michael@0 414 }
michael@0 415 });
michael@0 416
michael@0 417 function run_test() run_next_test();

mercurial