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.

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

mercurial