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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/components/satchel/test/unit/test_autocomplete.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,281 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +"use strict";
     1.9 +
    1.10 +var testnum = 0;
    1.11 +var fac;
    1.12 +var prefs;
    1.13 +
    1.14 +let numRecords, timeGroupingSize, now;
    1.15 +
    1.16 +const DEFAULT_EXPIRE_DAYS = 180;
    1.17 +
    1.18 +function padLeft(number, length) {
    1.19 +    var str = number + '';
    1.20 +    while (str.length < length)
    1.21 +        str = '0' + str;
    1.22 +    return str;
    1.23 +}
    1.24 +
    1.25 +function getFormExpiryDays() {
    1.26 +    if (prefs.prefHasUserValue("browser.formfill.expire_days"))
    1.27 +        return prefs.getIntPref("browser.formfill.expire_days");
    1.28 +    else
    1.29 +        return DEFAULT_EXPIRE_DAYS;
    1.30 +}
    1.31 +
    1.32 +function run_test() {
    1.33 +    // ===== test init =====
    1.34 +    var testfile = do_get_file("formhistory_autocomplete.sqlite");
    1.35 +    var profileDir = dirSvc.get("ProfD", Ci.nsIFile);
    1.36 +
    1.37 +    // Cleanup from any previous tests or failures.
    1.38 +    var destFile = profileDir.clone();
    1.39 +    destFile.append("formhistory.sqlite");
    1.40 +    if (destFile.exists())
    1.41 +      destFile.remove(false);
    1.42 +
    1.43 +    testfile.copyTo(profileDir, "formhistory.sqlite");
    1.44 +
    1.45 +    fac = Cc["@mozilla.org/satchel/form-autocomplete;1"].
    1.46 +          getService(Ci.nsIFormAutoComplete);
    1.47 +    prefs = Cc["@mozilla.org/preferences-service;1"].
    1.48 +            getService(Ci.nsIPrefBranch);
    1.49 +
    1.50 +    timeGroupingSize = prefs.getIntPref("browser.formfill.timeGroupingSize") * 1000 * 1000;
    1.51 +
    1.52 +    run_next_test();
    1.53 +}
    1.54 +
    1.55 +add_test(function test0() {
    1.56 +    var maxTimeGroupings = prefs.getIntPref("browser.formfill.maxTimeGroupings");
    1.57 +    var bucketSize = prefs.getIntPref("browser.formfill.bucketSize");
    1.58 +
    1.59 +    // ===== Tests with constant timesUsed and varying lastUsed date =====
    1.60 +    // insert 2 records per bucket to check alphabetical sort within
    1.61 +    now = 1000 * Date.now();
    1.62 +    numRecords = Math.ceil(maxTimeGroupings / bucketSize) * 2;
    1.63 +
    1.64 +    let changes = [ ];
    1.65 +    for (let i = 0; i < numRecords; i+=2) {
    1.66 +        let useDate = now - (i/2 * bucketSize * timeGroupingSize);
    1.67 +
    1.68 +        changes.push({ op : "add", fieldname: "field1", value: "value" + padLeft(numRecords - 1 - i, 2),
    1.69 +                       timesUsed: 1, firstUsed: useDate, lastUsed: useDate });
    1.70 +        changes.push({ op : "add", fieldname: "field1", value: "value" + padLeft(numRecords - 2 - i, 2),
    1.71 +                       timesUsed: 1, firstUsed: useDate, lastUsed: useDate });
    1.72 +    }
    1.73 +
    1.74 +    updateFormHistory(changes, run_next_test);
    1.75 +});
    1.76 +
    1.77 +add_test(function test1() {
    1.78 +    do_log_info("Check initial state is as expected");
    1.79 +
    1.80 +    countEntries(null, null, function (count) {
    1.81 +      countEntries("field1", null, function (count) {
    1.82 +        do_check_true(count > 0);
    1.83 +        run_next_test();
    1.84 +      });
    1.85 +    });
    1.86 +});
    1.87 +
    1.88 +add_test(function test2() {
    1.89 +    do_log_info("Check search contains all entries");
    1.90 +
    1.91 +    fac.autoCompleteSearchAsync("field1", "", null, null, {
    1.92 +        onSearchCompletion : function(aResults) {
    1.93 +            do_check_eq(numRecords, aResults.matchCount);
    1.94 +            run_next_test();
    1.95 +        }
    1.96 +    });
    1.97 +});
    1.98 +
    1.99 +add_test(function test3() {
   1.100 +    do_log_info("Check search result ordering with empty search term");
   1.101 +
   1.102 +    let lastFound = numRecords;
   1.103 +    fac.autoCompleteSearchAsync("field1", "", null, null, {
   1.104 +        onSearchCompletion : function(aResults) {
   1.105 +            for (let i = 0; i < numRecords; i+=2) {
   1.106 +                do_check_eq(parseInt(aResults.getValueAt(i + 1).substr(5), 10), --lastFound);
   1.107 +                do_check_eq(parseInt(aResults.getValueAt(i).substr(5), 10), --lastFound);
   1.108 +            }
   1.109 +            run_next_test();
   1.110 +        }
   1.111 +    });
   1.112 +});
   1.113 +
   1.114 +add_test(function test4() {
   1.115 +    do_log_info("Check search result ordering with \"v\"");
   1.116 +
   1.117 +    let lastFound = numRecords;
   1.118 +    fac.autoCompleteSearchAsync("field1", "v", null, null, {
   1.119 +        onSearchCompletion : function(aResults) {
   1.120 +            for (let i = 0; i < numRecords; i+=2) {
   1.121 +                do_check_eq(parseInt(aResults.getValueAt(i + 1).substr(5), 10), --lastFound);
   1.122 +                do_check_eq(parseInt(aResults.getValueAt(i).substr(5), 10), --lastFound);
   1.123 +            }
   1.124 +            run_next_test();
   1.125 +        }
   1.126 +    });
   1.127 +});
   1.128 +
   1.129 +const timesUsedSamples = 20;
   1.130 +
   1.131 +add_test(function test5() {
   1.132 +    do_log_info("Begin tests with constant use dates and varying timesUsed");
   1.133 +
   1.134 +    let changes =  [];
   1.135 +    for (let i = 0; i < timesUsedSamples; i++) {
   1.136 +        let timesUsed = (timesUsedSamples - i);
   1.137 +        let change = { op : "add", fieldname: "field2", value: "value" + (timesUsedSamples - 1 -  i),
   1.138 +                       timesUsed: timesUsed * timeGroupingSize, firstUsed: now, lastUsed: now };
   1.139 +        changes.push(change);
   1.140 +    }
   1.141 +    updateFormHistory(changes, run_next_test);
   1.142 +});
   1.143 +
   1.144 +add_test(function test6() {
   1.145 +    do_log_info("Check search result ordering with empty search term");
   1.146 +
   1.147 +    let lastFound = timesUsedSamples;
   1.148 +    fac.autoCompleteSearchAsync("field2", "", null, null, {
   1.149 +        onSearchCompletion : function(aResults) {
   1.150 +            for (let i = 0; i < timesUsedSamples; i++) {
   1.151 +                do_check_eq(parseInt(aResults.getValueAt(i).substr(5)), --lastFound);
   1.152 +            }
   1.153 +            run_next_test();
   1.154 +        }
   1.155 +    });
   1.156 +});
   1.157 +
   1.158 +add_test(function test7() {
   1.159 +    do_log_info("Check search result ordering with \"v\"");
   1.160 +
   1.161 +    let lastFound = timesUsedSamples;
   1.162 +    fac.autoCompleteSearchAsync("field2", "v", null, null, {
   1.163 +        onSearchCompletion : function(aResults) {
   1.164 +            for (let i = 0; i < timesUsedSamples; i++) {
   1.165 +                do_check_eq(parseInt(aResults.getValueAt(i).substr(5)), --lastFound);
   1.166 +            }
   1.167 +            run_next_test();
   1.168 +        }
   1.169 +    });
   1.170 +});
   1.171 +
   1.172 +add_test(function test8() {
   1.173 +    do_log_info("Check that \"senior citizen\" entries get a bonus (browser.formfill.agedBonus)");
   1.174 +
   1.175 +    let agedDate = 1000 * (Date.now() - getFormExpiryDays() * 24 * 60 * 60 * 1000);
   1.176 +
   1.177 +    let changes = [ ];
   1.178 +    changes.push({ op : "add", fieldname: "field3", value: "old but not senior",
   1.179 +                   timesUsed: 100, firstUsed: (agedDate + 60 * 1000 * 1000), lastUsed: now });
   1.180 +    changes.push({ op : "add", fieldname: "field3", value: "senior citizen",
   1.181 +                   timesUsed: 100, firstUsed: (agedDate - 60 * 1000 * 1000), lastUsed: now });
   1.182 +    updateFormHistory(changes, run_next_test);
   1.183 +});
   1.184 +
   1.185 +add_test(function test9() {
   1.186 +    fac.autoCompleteSearchAsync("field3", "", null, null, {
   1.187 +        onSearchCompletion : function(aResults) {
   1.188 +            do_check_eq(aResults.getValueAt(0), "senior citizen");
   1.189 +            do_check_eq(aResults.getValueAt(1), "old but not senior");
   1.190 +            run_next_test();
   1.191 +        }
   1.192 +    });
   1.193 +});
   1.194 +
   1.195 +add_test(function test10() {
   1.196 +    do_log_info("Check entries that are really old or in the future");
   1.197 +
   1.198 +    let changes = [ ];
   1.199 +    changes.push({ op : "add", fieldname: "field4", value: "date of 0",
   1.200 +                   timesUsed: 1, firstUsed: 0, lastUsed: 0 });
   1.201 +    changes.push({ op : "add", fieldname: "field4", value: "in the future 1",
   1.202 +                   timesUsed: 1, firstUsed: 0, lastUsed: now * 2 });
   1.203 +    changes.push({ op : "add", fieldname: "field4", value: "in the future 2",
   1.204 +                   timesUsed: 1, firstUsed: now * 2, lastUsed: now * 2 });
   1.205 +    updateFormHistory(changes, run_next_test);
   1.206 +});
   1.207 +
   1.208 +add_test(function test11() {
   1.209 +    fac.autoCompleteSearchAsync("field4", "", null, null, {
   1.210 +        onSearchCompletion : function(aResults) {
   1.211 +            do_check_eq(aResults.matchCount, 3);
   1.212 +            run_next_test();
   1.213 +        }
   1.214 +    });
   1.215 +});
   1.216 +
   1.217 +let syncValues = ["sync1", "sync1a", "sync2", "sync3"]
   1.218 +
   1.219 +add_test(function test12() {
   1.220 +    do_log_info("Check old synchronous api");
   1.221 +
   1.222 +    let changes = [ ];
   1.223 +    for (let value of syncValues) {
   1.224 +      changes.push({ op : "add", fieldname: "field5", value: value });
   1.225 +    }
   1.226 +    updateFormHistory(changes, run_next_test);
   1.227 +});
   1.228 +
   1.229 +add_test(function test13() {
   1.230 +  let autocompleteService = Cc["@mozilla.org/satchel/form-autocomplete;1"].getService(Ci.nsIFormAutoComplete);
   1.231 +  let results = autocompleteService.autoCompleteSearch("field5", "", null, null);
   1.232 +  do_check_eq(results.matchCount, syncValues.length, "synchronous matchCount");
   1.233 +  for (let i = 0; i < results.matchCount; i++) {
   1.234 +    do_check_eq(results.getValueAt(i), syncValues[i]);
   1.235 +  }
   1.236 +
   1.237 +  let results = autocompleteService.autoCompleteSearch("field5", "sync1", null, null);
   1.238 +  do_check_eq(results.matchCount, 2, "synchronous matchCount");
   1.239 +  do_check_eq(results.getValueAt(0), "sync1");
   1.240 +  do_check_eq(results.getValueAt(1), "sync1a");
   1.241 +  run_next_test();
   1.242 +});
   1.243 +
   1.244 +add_test(function test_token_limit_DB() {
   1.245 +    function test_token_limit_previousResult(previousResult) {
   1.246 +        do_log_info("Check that the number of tokens used in a search is not capped to " +
   1.247 +                    "MAX_SEARCH_TOKENS when using a previousResult");
   1.248 +        // This provide more accuracy since performance is less of an issue.
   1.249 +        // Search for a string where the first 10 tokens match the previous value but the 11th does not
   1.250 +        // when re-using a previous result.
   1.251 +        fac.autoCompleteSearchAsync("field_token_cap",
   1.252 +                                    "a b c d e f g h i j .",
   1.253 +                                    null, previousResult, {
   1.254 +                                        onSearchCompletion : function(aResults) {
   1.255 +                                            do_check_eq(aResults.matchCount, 0,
   1.256 +                                                        "All search tokens should be used with " +
   1.257 +                                                        "previous results");
   1.258 +                                            run_next_test();
   1.259 +                                        }
   1.260 +                                    });
   1.261 +    }
   1.262 +
   1.263 +    do_log_info("Check that the number of tokens used in a search is capped to MAX_SEARCH_TOKENS " +
   1.264 +                "for performance when querying the DB");
   1.265 +    let changes = [ ];
   1.266 +    changes.push({ op : "add", fieldname: "field_token_cap",
   1.267 +                   // value with 15 unique tokens
   1.268 +                   value: "a b c d e f g h i j k l m n o",
   1.269 +                   timesUsed: 1, firstUsed: 0, lastUsed: 0 });
   1.270 +    updateFormHistory(changes, () => {
   1.271 +        // Search for a string where the first 10 tokens match the value above but the 11th does not
   1.272 +        // (which would prevent the result from being returned if the 11th term was used).
   1.273 +        fac.autoCompleteSearchAsync("field_token_cap",
   1.274 +                                    "a b c d e f g h i j .",
   1.275 +                                    null, null, {
   1.276 +                                        onSearchCompletion : function(aResults) {
   1.277 +                                            do_check_eq(aResults.matchCount, 1,
   1.278 +                                                        "Only the first MAX_SEARCH_TOKENS tokens " +
   1.279 +                                                        "should be used for DB queries");
   1.280 +                                            test_token_limit_previousResult(aResults);
   1.281 +                                        }
   1.282 +        });
   1.283 +    });
   1.284 +});

mercurial