diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /toolkit/components/satchel/test/unit/test_autocomplete.js | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/satchel/test/unit/test_autocomplete.js')
-rw-r--r-- | toolkit/components/satchel/test/unit/test_autocomplete.js | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/toolkit/components/satchel/test/unit/test_autocomplete.js b/toolkit/components/satchel/test/unit/test_autocomplete.js new file mode 100644 index 0000000000..81557f6630 --- /dev/null +++ b/toolkit/components/satchel/test/unit/test_autocomplete.js @@ -0,0 +1,388 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +var fac; + +var numRecords, timeGroupingSize, now; + +const DEFAULT_EXPIRE_DAYS = 180; + +function padLeft(number, length) { + let str = number + ""; + while (str.length < length) { + str = "0" + str; + } + return str; +} + +function getFormExpiryDays() { + if (Services.prefs.prefHasUserValue("browser.formfill.expire_days")) { + return Services.prefs.getIntPref("browser.formfill.expire_days"); + } + return DEFAULT_EXPIRE_DAYS; +} + +function run_test() { + // ===== test init ===== + let testfile = do_get_file("formhistory_autocomplete.sqlite"); + let profileDir = Services.dirsvc.get("ProfD", Ci.nsIFile); + + // Cleanup from any previous tests or failures. + let destFile = profileDir.clone(); + destFile.append("formhistory.sqlite"); + if (destFile.exists()) { + destFile.remove(false); + } + + testfile.copyTo(profileDir, "formhistory.sqlite"); + + fac = Cc["@mozilla.org/satchel/form-autocomplete;1"].getService( + Ci.nsIFormAutoComplete + ); + + timeGroupingSize = + Services.prefs.getIntPref("browser.formfill.timeGroupingSize") * + 1000 * + 1000; + + run_next_test(); +} + +add_test(function test0() { + let maxTimeGroupings = Services.prefs.getIntPref( + "browser.formfill.maxTimeGroupings" + ); + let bucketSize = Services.prefs.getIntPref("browser.formfill.bucketSize"); + + // ===== Tests with constant timesUsed and varying lastUsed date ===== + // insert 2 records per bucket to check alphabetical sort within + now = 1000 * Date.now(); + numRecords = Math.ceil(maxTimeGroupings / bucketSize) * 2; + + let changes = []; + for (let i = 0; i < numRecords; i += 2) { + let useDate = now - (i / 2) * bucketSize * timeGroupingSize; + + changes.push({ + op: "add", + fieldname: "field1", + value: "value" + padLeft(numRecords - 1 - i, 2), + timesUsed: 1, + firstUsed: useDate, + lastUsed: useDate, + }); + changes.push({ + op: "add", + fieldname: "field1", + value: "value" + padLeft(numRecords - 2 - i, 2), + timesUsed: 1, + firstUsed: useDate, + lastUsed: useDate, + }); + } + + updateFormHistory(changes, run_next_test); +}); + +add_test(function test1() { + do_log_info("Check initial state is as expected"); + + countEntries(null, null, function () { + countEntries("field1", null, function (count) { + Assert.ok(count > 0); + run_next_test(); + }); + }); +}); + +add_test(function test2() { + do_log_info("Check search contains all entries"); + + fac.autoCompleteSearchAsync("field1", "", null, null, null, { + onSearchCompletion(aResults) { + Assert.equal(numRecords, aResults.matchCount); + run_next_test(); + }, + }); +}); + +add_test(function test3() { + do_log_info("Check search result ordering with empty search term"); + + let lastFound = numRecords; + fac.autoCompleteSearchAsync("field1", "", null, null, null, { + onSearchCompletion(aResults) { + for (let i = 0; i < numRecords; i += 2) { + Assert.equal( + parseInt(aResults.getValueAt(i + 1).substr(5), 10), + --lastFound + ); + Assert.equal( + parseInt(aResults.getValueAt(i).substr(5), 10), + --lastFound + ); + } + run_next_test(); + }, + }); +}); + +add_test(function test4() { + do_log_info('Check search result ordering with "v"'); + + let lastFound = numRecords; + fac.autoCompleteSearchAsync("field1", "v", null, null, null, { + onSearchCompletion(aResults) { + for (let i = 0; i < numRecords; i += 2) { + Assert.equal( + parseInt(aResults.getValueAt(i + 1).substr(5), 10), + --lastFound + ); + Assert.equal( + parseInt(aResults.getValueAt(i).substr(5), 10), + --lastFound + ); + } + run_next_test(); + }, + }); +}); + +const timesUsedSamples = 20; + +add_test(function test5() { + do_log_info("Begin tests with constant use dates and varying timesUsed"); + + let changes = []; + for (let i = 0; i < timesUsedSamples; i++) { + let timesUsed = timesUsedSamples - i; + let change = { + op: "add", + fieldname: "field2", + value: "value" + (timesUsedSamples - 1 - i), + timesUsed: timesUsed * timeGroupingSize, + firstUsed: now, + lastUsed: now, + }; + changes.push(change); + } + updateFormHistory(changes, run_next_test); +}); + +add_test(function test6() { + do_log_info("Check search result ordering with empty search term"); + + let lastFound = timesUsedSamples; + fac.autoCompleteSearchAsync("field2", "", null, null, null, { + onSearchCompletion(aResults) { + for (let i = 0; i < timesUsedSamples; i++) { + Assert.equal( + parseInt(aResults.getValueAt(i).substr(5), 10), + --lastFound + ); + } + run_next_test(); + }, + }); +}); + +add_test(function test7() { + do_log_info('Check search result ordering with "v"'); + + let lastFound = timesUsedSamples; + fac.autoCompleteSearchAsync("field2", "v", null, null, null, { + onSearchCompletion(aResults) { + for (let i = 0; i < timesUsedSamples; i++) { + Assert.equal( + parseInt(aResults.getValueAt(i).substr(5), 10), + --lastFound + ); + } + run_next_test(); + }, + }); +}); + +add_test(function test8() { + do_log_info( + 'Check that "senior citizen" entries get a bonus (browser.formfill.agedBonus)' + ); + + let agedDate = + 1000 * (Date.now() - getFormExpiryDays() * 24 * 60 * 60 * 1000); + + let changes = []; + changes.push({ + op: "add", + fieldname: "field3", + value: "old but not senior", + timesUsed: 100, + firstUsed: agedDate + 60 * 1000 * 1000, + lastUsed: now, + }); + changes.push({ + op: "add", + fieldname: "field3", + value: "senior citizen", + timesUsed: 100, + firstUsed: agedDate - 60 * 1000 * 1000, + lastUsed: now, + }); + updateFormHistory(changes, run_next_test); +}); + +add_test(function test9() { + fac.autoCompleteSearchAsync("field3", "", null, null, null, { + onSearchCompletion(aResults) { + Assert.equal(aResults.getValueAt(0), "senior citizen"); + Assert.equal(aResults.getValueAt(1), "old but not senior"); + run_next_test(); + }, + }); +}); + +add_test(function test10() { + do_log_info("Check entries that are really old or in the future"); + + let changes = []; + changes.push({ + op: "add", + fieldname: "field4", + value: "date of 0", + timesUsed: 1, + firstUsed: 0, + lastUsed: 0, + }); + changes.push({ + op: "add", + fieldname: "field4", + value: "in the future 1", + timesUsed: 1, + firstUsed: 0, + lastUsed: now * 2, + }); + changes.push({ + op: "add", + fieldname: "field4", + value: "in the future 2", + timesUsed: 1, + firstUsed: now * 2, + lastUsed: now * 2, + }); + updateFormHistory(changes, run_next_test); +}); + +add_test(function test11() { + fac.autoCompleteSearchAsync("field4", "", null, null, null, { + onSearchCompletion(aResults) { + Assert.equal(aResults.matchCount, 3); + run_next_test(); + }, + }); +}); + +var syncValues = ["sync1", "sync1a", "sync2", "sync3"]; + +add_test(function test12() { + do_log_info("Check old synchronous api"); + + let changes = []; + for (let value of syncValues) { + changes.push({ op: "add", fieldname: "field5", value }); + } + updateFormHistory(changes, run_next_test); +}); + +add_test(function test_token_limit_DB() { + function test_token_limit_previousResult(previousResult) { + do_log_info( + "Check that the number of tokens used in a search is not capped to " + + "MAX_SEARCH_TOKENS when using a previousResult" + ); + // This provide more accuracy since performance is less of an issue. + // Search for a string where the first 10 tokens match the previous value but the 11th does not + // when re-using a previous result. + fac.autoCompleteSearchAsync( + "field_token_cap", + "a b c d e f g h i j .", + null, + previousResult, + null, + { + onSearchCompletion(aResults) { + Assert.equal( + aResults.matchCount, + 0, + "All search tokens should be used with previous results" + ); + run_next_test(); + }, + } + ); + } + + do_log_info( + "Check that the number of tokens used in a search is capped to MAX_SEARCH_TOKENS " + + "for performance when querying the DB" + ); + let changes = []; + changes.push({ + op: "add", + fieldname: "field_token_cap", + // value with 15 unique tokens + value: "a b c d e f g h i j k l m n o", + timesUsed: 1, + firstUsed: 0, + lastUsed: 0, + }); + updateFormHistory(changes, () => { + // Search for a string where the first 10 tokens match the value above but the 11th does not + // (which would prevent the result from being returned if the 11th term was used). + fac.autoCompleteSearchAsync( + "field_token_cap", + "a b c d e f g h i j .", + null, + null, + null, + { + onSearchCompletion(aResults) { + Assert.equal( + aResults.matchCount, + 1, + "Only the first MAX_SEARCH_TOKENS tokens " + + "should be used for DB queries" + ); + test_token_limit_previousResult(aResults); + }, + } + ); + }); +}); + +add_test(async function can_search_escape_marker() { + await promiseUpdate({ + op: "add", + fieldname: "field1", + value: "/* Further reading */ test", + timesUsed: 1, + firstUsed: now, + lastUsed: now, + }); + + fac.autoCompleteSearchAsync( + "field1", + "/* Further reading */ t", + null, + null, + null, + { + onSearchCompletion(aResults) { + Assert.equal(1, aResults.matchCount); + run_next_test(); + }, + } + ); +}); |