summaryrefslogtreecommitdiffstats
path: root/toolkit/components/autocomplete/tests/unit/test_393191.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/autocomplete/tests/unit/test_393191.js')
-rw-r--r--toolkit/components/autocomplete/tests/unit/test_393191.js272
1 files changed, 272 insertions, 0 deletions
diff --git a/toolkit/components/autocomplete/tests/unit/test_393191.js b/toolkit/components/autocomplete/tests/unit/test_393191.js
new file mode 100644
index 000000000..6fb57e6c4
--- /dev/null
+++ b/toolkit/components/autocomplete/tests/unit/test_393191.js
@@ -0,0 +1,272 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* 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/. */
+
+/**
+ * Unit test for Bug 393191 - AutoComplete crashes if result is null
+ */
+
+
+
+/**
+ * Dummy nsIAutoCompleteInput source that returns
+ * the given list of AutoCompleteSearch names.
+ *
+ * Implements only the methods needed for this test.
+ */
+function AutoCompleteInput(aSearches) {
+ this.searches = aSearches;
+}
+AutoCompleteInput.prototype = {
+ constructor: AutoCompleteInput,
+
+ // Array of AutoCompleteSearch names
+ searches: null,
+
+ minResultsForPopup: 0,
+ timeout: 10,
+ searchParam: "",
+ textValue: "",
+ disableAutoComplete: false,
+ completeDefaultIndex: false,
+
+ get searchCount() {
+ return this.searches.length;
+ },
+
+ getSearchAt: function(aIndex) {
+ return this.searches[aIndex];
+ },
+
+ onSearchBegin: function() {},
+ onSearchComplete: function() {},
+
+ popupOpen: false,
+
+ popup: {
+ setSelectedIndex: function(aIndex) {},
+ invalidate: function() {},
+
+ // nsISupports implementation
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsISupports) ||
+ iid.equals(Ci.nsIAutoCompletePopup))
+ return this;
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ }
+ },
+
+ // nsISupports implementation
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsISupports) ||
+ iid.equals(Ci.nsIAutoCompleteInput))
+ return this;
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ }
+}
+
+
+
+/**
+ * nsIAutoCompleteResult implementation
+ */
+function AutoCompleteResult(aValues, aComments, aStyles) {
+ this._values = aValues;
+ this._comments = aComments;
+ this._styles = aStyles;
+
+ if (this._values.length > 0) {
+ this.searchResult = Ci.nsIAutoCompleteResult.RESULT_SUCCESS;
+ } else {
+ this.searchResult = Ci.nsIAutoCompleteResult.NOMATCH;
+ }
+}
+AutoCompleteResult.prototype = {
+ constructor: AutoCompleteResult,
+
+ // Arrays
+ _values: null,
+ _comments: null,
+ _styles: null,
+
+ searchString: "",
+ searchResult: null,
+
+ defaultIndex: 0,
+
+ get matchCount() {
+ return this._values.length;
+ },
+
+ getValueAt: function(aIndex) {
+ return this._values[aIndex];
+ },
+
+ getLabelAt: function(aIndex) {
+ return this.getValueAt(aIndex);
+ },
+
+ getCommentAt: function(aIndex) {
+ return this._comments[aIndex];
+ },
+
+ getStyleAt: function(aIndex) {
+ return this._styles[aIndex];
+ },
+
+ getImageAt: function(aIndex) {
+ return "";
+ },
+
+ getFinalCompleteValueAt: function(aIndex) {
+ return this.getValueAt(aIndex);
+ },
+
+ removeValueAt: function (aRowIndex, aRemoveFromDb) {},
+
+ // nsISupports implementation
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsISupports) ||
+ iid.equals(Ci.nsIAutoCompleteResult))
+ return this;
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ }
+}
+
+
+
+/**
+ * nsIAutoCompleteSearch implementation that always returns
+ * the same result set.
+ */
+function AutoCompleteSearch(aName, aResult) {
+ this.name = aName;
+ this._result = aResult;
+}
+AutoCompleteSearch.prototype = {
+ constructor: AutoCompleteSearch,
+
+ // Search name. Used by AutoCompleteController
+ name: null,
+
+ // AutoCompleteResult
+ _result: null,
+
+
+ /**
+ * Return the same result set for every search
+ */
+ startSearch: function(aSearchString,
+ aSearchParam,
+ aPreviousResult,
+ aListener)
+ {
+ aListener.onSearchResult(this, this._result);
+ },
+
+ stopSearch: function() {},
+
+ // nsISupports implementation
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsISupports) ||
+ iid.equals(Ci.nsIFactory) ||
+ iid.equals(Ci.nsIAutoCompleteSearch))
+ return this;
+
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ },
+
+ // nsIFactory implementation
+ createInstance: function(outer, iid) {
+ return this.QueryInterface(iid);
+ }
+}
+
+
+
+/**
+ * Helper to register an AutoCompleteSearch with the given name.
+ * Allows the AutoCompleteController to find the search.
+ */
+function registerAutoCompleteSearch(aSearch) {
+ var name = "@mozilla.org/autocomplete/search;1?name=" + aSearch.name;
+
+ var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].
+ getService(Ci.nsIUUIDGenerator);
+ var cid = uuidGenerator.generateUUID();
+
+ var desc = "Test AutoCompleteSearch";
+
+ var componentManager = Components.manager
+ .QueryInterface(Ci.nsIComponentRegistrar);
+ componentManager.registerFactory(cid, desc, name, aSearch);
+
+ // Keep the id on the object so we can unregister later
+ aSearch.cid = cid;
+}
+
+
+
+/**
+ * Helper to unregister an AutoCompleteSearch.
+ */
+function unregisterAutoCompleteSearch(aSearch) {
+ var componentManager = Components.manager
+ .QueryInterface(Ci.nsIComponentRegistrar);
+ componentManager.unregisterFactory(aSearch.cid, aSearch);
+}
+
+
+
+/**
+ * Test AutoComplete with a search that returns a null result
+ */
+function run_test() {
+
+ // Make an AutoCompleteSearch that always returns nothing
+ var emptySearch = new AutoCompleteSearch("test-empty-search",
+ new AutoCompleteResult([], [], []));
+
+ // Register search so AutoCompleteController can find them
+ registerAutoCompleteSearch(emptySearch);
+
+ var controller = Components.classes["@mozilla.org/autocomplete/controller;1"].
+ getService(Components.interfaces.nsIAutoCompleteController);
+
+ // Make an AutoCompleteInput that uses our search
+ // and confirms results on search complete
+ var input = new AutoCompleteInput([emptySearch.name]);
+ var numSearchesStarted = 0;
+
+ input.onSearchBegin = function() {
+ numSearchesStarted++;
+ do_check_eq(numSearchesStarted, 1);
+ };
+
+ input.onSearchComplete = function() {
+
+ do_check_eq(numSearchesStarted, 1);
+
+ do_check_eq(controller.searchStatus,
+ Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH);
+ do_check_eq(controller.matchCount, 0);
+
+ // Unregister searches
+ unregisterAutoCompleteSearch(emptySearch);
+
+ do_test_finished();
+ };
+
+ controller.input = input;
+
+ // Search is asynchronous, so don't let the test finish immediately
+ do_test_pending();
+
+ controller.startSearch("test");
+}
+