summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/queries/test_querySerialization.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/queries/test_querySerialization.js')
-rw-r--r--toolkit/components/places/tests/queries/test_querySerialization.js797
1 files changed, 0 insertions, 797 deletions
diff --git a/toolkit/components/places/tests/queries/test_querySerialization.js b/toolkit/components/places/tests/queries/test_querySerialization.js
deleted file mode 100644
index 24cf8aa9b..000000000
--- a/toolkit/components/places/tests/queries/test_querySerialization.js
+++ /dev/null
@@ -1,797 +0,0 @@
-/* -*- 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/. */
-
-/**
- * Tests Places query serialization. Associated bug is
- * https://bugzilla.mozilla.org/show_bug.cgi?id=370197
- *
- * The simple idea behind this test is to try out different combinations of
- * query switches and ensure that queries are the same before serialization
- * as they are after de-serialization.
- *
- * In the code below, "switch" refers to a query option -- "option" in a broad
- * sense, not nsINavHistoryQueryOptions specifically (which is why we refer to
- * them as switches, not options). Both nsINavHistoryQuery and
- * nsINavHistoryQueryOptions allow you to specify switches that affect query
- * strings. nsINavHistoryQuery instances have attributes hasBeginTime,
- * hasEndTime, hasSearchTerms, and so on. nsINavHistoryQueryOptions instances
- * have attributes sortingMode, resultType, excludeItems, etc.
- *
- * Ideally we would like to test all 2^N subsets of switches, where N is the
- * total number of switches; switches might interact in erroneous or other ways
- * we do not expect. However, since N is large (21 at this time), that's
- * impractical for a single test in a suite.
- *
- * Instead we choose all possible subsets of a certain, smaller size. In fact
- * we begin by choosing CHOOSE_HOW_MANY_SWITCHES_LO and ramp up to
- * CHOOSE_HOW_MANY_SWITCHES_HI.
- *
- * There are two more wrinkles. First, for some switches we'd like to be able to
- * test multiple values. For example, it seems like a good idea to test both an
- * empty string and a non-empty string for switch nsINavHistoryQuery.searchTerms.
- * When switches have more than one value for a test run, we use the Cartesian
- * product of their values to generate all possible combinations of values.
- *
- * Second, we need to also test serialization of multiple nsINavHistoryQuery
- * objects at once. To do this, we remember the previous NUM_MULTIPLE_QUERIES
- * queries we tested individually and then serialize them together. We do this
- * each time we test an individual query. Thus the set of queries we test
- * together loses one query and gains another each time.
- *
- * To summarize, here's how this test works:
- *
- * - For n = CHOOSE_HOW_MANY_SWITCHES_LO to CHOOSE_HOW_MANY_SWITCHES_HI:
- * - From the total set of switches choose all possible subsets of size n.
- * For each of those subsets s:
- * - Collect the test runs of each switch in subset s and take their
- * Cartesian product. For each sequence in the product:
- * - Create nsINavHistoryQuery and nsINavHistoryQueryOptions objects
- * with the chosen switches and test run values.
- * - Serialize the query.
- * - De-serialize and ensure that the de-serialized query objects equal
- * the originals.
- * - For each of the previous NUM_MULTIPLE_QUERIES
- * nsINavHistoryQueryOptions objects o we created:
- * - Serialize the previous NUM_MULTIPLE_QUERIES nsINavHistoryQuery
- * objects together with o.
- * - De-serialize and ensure that the de-serialized query objects
- * equal the originals.
- */
-
-const CHOOSE_HOW_MANY_SWITCHES_LO = 1;
-const CHOOSE_HOW_MANY_SWITCHES_HI = 2;
-
-const NUM_MULTIPLE_QUERIES = 2;
-
-// The switches are represented by objects below, in arrays querySwitches and
-// queryOptionSwitches. Use them to set up test runs.
-//
-// Some switches have special properties (where noted), but all switches must
-// have the following properties:
-//
-// matches: A function that takes two nsINavHistoryQuery objects (in the case
-// of nsINavHistoryQuery switches) or two nsINavHistoryQueryOptions
-// objects (for nsINavHistoryQueryOptions switches) and returns true
-// if the values of the switch in the two objects are equal. This is
-// the foundation of how we determine if two queries are equal.
-// runs: An array of functions. Each function takes an nsINavHistoryQuery
-// object and an nsINavHistoryQueryOptions object. The functions
-// should set the attributes of one of the two objects as appropriate
-// to their switches. This is how switch values are set for each test
-// run.
-//
-// The following properties are optional:
-//
-// desc: An informational string to print out during runs when the switch
-// is chosen. Hopefully helpful if the test fails.
-
-// nsINavHistoryQuery switches
-const querySwitches = [
- // hasBeginTime
- {
- // flag and subswitches are used by the flagSwitchMatches function. Several
- // of the nsINavHistoryQuery switches (like this one) are really guard flags
- // that indicate if other "subswitches" are enabled.
- flag: "hasBeginTime",
- subswitches: ["beginTime", "beginTimeReference", "absoluteBeginTime"],
- desc: "nsINavHistoryQuery.hasBeginTime",
- matches: flagSwitchMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.beginTime = Date.now() * 1000;
- aQuery.beginTimeReference = Ci.nsINavHistoryQuery.TIME_RELATIVE_EPOCH;
- },
- function (aQuery, aQueryOptions) {
- aQuery.beginTime = Date.now() * 1000;
- aQuery.beginTimeReference = Ci.nsINavHistoryQuery.TIME_RELATIVE_TODAY;
- }
- ]
- },
- // hasEndTime
- {
- flag: "hasEndTime",
- subswitches: ["endTime", "endTimeReference", "absoluteEndTime"],
- desc: "nsINavHistoryQuery.hasEndTime",
- matches: flagSwitchMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.endTime = Date.now() * 1000;
- aQuery.endTimeReference = Ci.nsINavHistoryQuery.TIME_RELATIVE_EPOCH;
- },
- function (aQuery, aQueryOptions) {
- aQuery.endTime = Date.now() * 1000;
- aQuery.endTimeReference = Ci.nsINavHistoryQuery.TIME_RELATIVE_TODAY;
- }
- ]
- },
- // hasSearchTerms
- {
- flag: "hasSearchTerms",
- subswitches: ["searchTerms"],
- desc: "nsINavHistoryQuery.hasSearchTerms",
- matches: flagSwitchMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.searchTerms = "shrimp and white wine";
- },
- function (aQuery, aQueryOptions) {
- aQuery.searchTerms = "";
- }
- ]
- },
- // hasDomain
- {
- flag: "hasDomain",
- subswitches: ["domain", "domainIsHost"],
- desc: "nsINavHistoryQuery.hasDomain",
- matches: flagSwitchMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.domain = "mozilla.com";
- aQuery.domainIsHost = false;
- },
- function (aQuery, aQueryOptions) {
- aQuery.domain = "www.mozilla.com";
- aQuery.domainIsHost = true;
- },
- function (aQuery, aQueryOptions) {
- aQuery.domain = "";
- }
- ]
- },
- // hasUri
- {
- flag: "hasUri",
- subswitches: ["uri"],
- desc: "nsINavHistoryQuery.hasUri",
- matches: flagSwitchMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.uri = uri("http://mozilla.com");
- },
- ]
- },
- // hasAnnotation
- {
- flag: "hasAnnotation",
- subswitches: ["annotation", "annotationIsNot"],
- desc: "nsINavHistoryQuery.hasAnnotation",
- matches: flagSwitchMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.annotation = "bookmarks/toolbarFolder";
- aQuery.annotationIsNot = false;
- },
- function (aQuery, aQueryOptions) {
- aQuery.annotation = "bookmarks/toolbarFolder";
- aQuery.annotationIsNot = true;
- }
- ]
- },
- // minVisits
- {
- // property is used by function simplePropertyMatches.
- property: "minVisits",
- desc: "nsINavHistoryQuery.minVisits",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.minVisits = 0x7fffffff; // 2^31 - 1
- }
- ]
- },
- // maxVisits
- {
- property: "maxVisits",
- desc: "nsINavHistoryQuery.maxVisits",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.maxVisits = 0x7fffffff; // 2^31 - 1
- }
- ]
- },
- // onlyBookmarked
- {
- property: "onlyBookmarked",
- desc: "nsINavHistoryQuery.onlyBookmarked",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.onlyBookmarked = true;
- }
- ]
- },
- // getFolders
- {
- desc: "nsINavHistoryQuery.getFolders",
- matches: function (aQuery1, aQuery2) {
- var q1Folders = aQuery1.getFolders();
- var q2Folders = aQuery2.getFolders();
- if (q1Folders.length !== q2Folders.length)
- return false;
- for (let i = 0; i < q1Folders.length; i++) {
- if (q2Folders.indexOf(q1Folders[i]) < 0)
- return false;
- }
- for (let i = 0; i < q2Folders.length; i++) {
- if (q1Folders.indexOf(q2Folders[i]) < 0)
- return false;
- }
- return true;
- },
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.setFolders([], 0);
- },
- function (aQuery, aQueryOptions) {
- aQuery.setFolders([PlacesUtils.placesRootId], 1);
- },
- function (aQuery, aQueryOptions) {
- aQuery.setFolders([PlacesUtils.placesRootId, PlacesUtils.tagsFolderId], 2);
- }
- ]
- },
- // tags
- {
- desc: "nsINavHistoryQuery.getTags",
- matches: function (aQuery1, aQuery2) {
- if (aQuery1.tagsAreNot !== aQuery2.tagsAreNot)
- return false;
- var q1Tags = aQuery1.tags;
- var q2Tags = aQuery2.tags;
- if (q1Tags.length !== q2Tags.length)
- return false;
- for (let i = 0; i < q1Tags.length; i++) {
- if (q2Tags.indexOf(q1Tags[i]) < 0)
- return false;
- }
- for (let i = 0; i < q2Tags.length; i++) {
- if (q1Tags.indexOf(q2Tags[i]) < 0)
- return false;
- }
- return true;
- },
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.tags = [];
- },
- function (aQuery, aQueryOptions) {
- aQuery.tags = [""];
- },
- function (aQuery, aQueryOptions) {
- aQuery.tags = [
- "foo",
- "七難",
- "",
- "いっぱいおっぱい",
- "Abracadabra",
- "123",
- "Here's a pretty long tag name with some = signs and 1 2 3s and spaces oh jeez will it work I hope so!",
- "アスキーでございません",
- "あいうえお",
- ];
- },
- function (aQuery, aQueryOptions) {
- aQuery.tags = [
- "foo",
- "七難",
- "",
- "いっぱいおっぱい",
- "Abracadabra",
- "123",
- "Here's a pretty long tag name with some = signs and 1 2 3s and spaces oh jeez will it work I hope so!",
- "アスキーでございません",
- "あいうえお",
- ];
- aQuery.tagsAreNot = true;
- }
- ]
- },
- // transitions
- {
- desc: "tests nsINavHistoryQuery.getTransitions",
- matches: function (aQuery1, aQuery2) {
- var q1Trans = aQuery1.getTransitions();
- var q2Trans = aQuery2.getTransitions();
- if (q1Trans.length !== q2Trans.length)
- return false;
- for (let i = 0; i < q1Trans.length; i++) {
- if (q2Trans.indexOf(q1Trans[i]) < 0)
- return false;
- }
- for (let i = 0; i < q2Trans.length; i++) {
- if (q1Trans.indexOf(q2Trans[i]) < 0)
- return false;
- }
- return true;
- },
- runs: [
- function (aQuery, aQueryOptions) {
- aQuery.setTransitions([], 0);
- },
- function (aQuery, aQueryOptions) {
- aQuery.setTransitions([Ci.nsINavHistoryService.TRANSITION_DOWNLOAD],
- 1);
- },
- function (aQuery, aQueryOptions) {
- aQuery.setTransitions([Ci.nsINavHistoryService.TRANSITION_TYPED,
- Ci.nsINavHistoryService.TRANSITION_BOOKMARK], 2);
- }
- ]
- },
-];
-
-// nsINavHistoryQueryOptions switches
-const queryOptionSwitches = [
- // sortingMode
- {
- desc: "nsINavHistoryQueryOptions.sortingMode",
- matches: function (aOptions1, aOptions2) {
- if (aOptions1.sortingMode === aOptions2.sortingMode) {
- switch (aOptions1.sortingMode) {
- case aOptions1.SORT_BY_ANNOTATION_ASCENDING:
- case aOptions1.SORT_BY_ANNOTATION_DESCENDING:
- return aOptions1.sortingAnnotation === aOptions2.sortingAnnotation;
- }
- return true;
- }
- return false;
- },
- runs: [
- function (aQuery, aQueryOptions) {
- aQueryOptions.sortingMode = aQueryOptions.SORT_BY_DATE_ASCENDING;
- },
- function (aQuery, aQueryOptions) {
- aQueryOptions.sortingMode = aQueryOptions.SORT_BY_ANNOTATION_ASCENDING;
- aQueryOptions.sortingAnnotation = "bookmarks/toolbarFolder";
- }
- ]
- },
- // resultType
- {
- // property is used by function simplePropertyMatches.
- property: "resultType",
- desc: "nsINavHistoryQueryOptions.resultType",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQueryOptions.resultType = aQueryOptions.RESULTS_AS_URI;
- },
- function (aQuery, aQueryOptions) {
- aQueryOptions.resultType = aQueryOptions.RESULTS_AS_FULL_VISIT;
- }
- ]
- },
- // excludeItems
- {
- property: "excludeItems",
- desc: "nsINavHistoryQueryOptions.excludeItems",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQueryOptions.excludeItems = true;
- }
- ]
- },
- // excludeQueries
- {
- property: "excludeQueries",
- desc: "nsINavHistoryQueryOptions.excludeQueries",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQueryOptions.excludeQueries = true;
- }
- ]
- },
- // expandQueries
- {
- property: "expandQueries",
- desc: "nsINavHistoryQueryOptions.expandQueries",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQueryOptions.expandQueries = true;
- }
- ]
- },
- // includeHidden
- {
- property: "includeHidden",
- desc: "nsINavHistoryQueryOptions.includeHidden",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQueryOptions.includeHidden = true;
- }
- ]
- },
- // maxResults
- {
- property: "maxResults",
- desc: "nsINavHistoryQueryOptions.maxResults",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQueryOptions.maxResults = 0xffffffff; // 2^32 - 1
- }
- ]
- },
- // queryType
- {
- property: "queryType",
- desc: "nsINavHistoryQueryOptions.queryType",
- matches: simplePropertyMatches,
- runs: [
- function (aQuery, aQueryOptions) {
- aQueryOptions.queryType = aQueryOptions.QUERY_TYPE_HISTORY;
- },
- function (aQuery, aQueryOptions) {
- aQueryOptions.queryType = aQueryOptions.QUERY_TYPE_UNIFIED;
- }
- ]
- },
-];
-
-/**
- * Enumerates all the sequences of the cartesian product of the arrays contained
- * in aSequences. Examples:
- *
- * cartProd([[1, 2, 3], ["a", "b"]], callback);
- * // callback is called 3 * 2 = 6 times with the following arrays:
- * // [1, "a"], [1, "b"], [2, "a"], [2, "b"], [3, "a"], [3, "b"]
- *
- * cartProd([["a"], [1, 2, 3], ["X", "Y"]], callback);
- * // callback is called 1 * 3 * 2 = 6 times with the following arrays:
- * // ["a", 1, "X"], ["a", 1, "Y"], ["a", 2, "X"], ["a", 2, "Y"],
- * // ["a", 3, "X"], ["a", 3, "Y"]
- *
- * cartProd([[1], [2], [3], [4]], callback);
- * // callback is called 1 * 1 * 1 * 1 = 1 time with the following array:
- * // [1, 2, 3, 4]
- *
- * cartProd([], callback);
- * // callback is 0 times
- *
- * cartProd([[1, 2, 3, 4]], callback);
- * // callback is called 4 times with the following arrays:
- * // [1], [2], [3], [4]
- *
- * @param aSequences
- * an array that contains an arbitrary number of arrays
- * @param aCallback
- * a function that is passed each sequence of the product as it's
- * computed
- * @return the total number of sequences in the product
- */
-function cartProd(aSequences, aCallback)
-{
- if (aSequences.length === 0)
- return 0;
-
- // For each sequence in aSequences, we maintain a pointer (an array index,
- // really) to the element we're currently enumerating in that sequence
- var seqEltPtrs = aSequences.map(i => 0);
-
- var numProds = 0;
- var done = false;
- while (!done) {
- numProds++;
-
- // prod = sequence in product we're currently enumerating
- let prod = [];
- for (let i = 0; i < aSequences.length; i++) {
- prod.push(aSequences[i][seqEltPtrs[i]]);
- }
- aCallback(prod);
-
- // The next sequence in the product differs from the current one by just a
- // single element. Determine which element that is. We advance the
- // "rightmost" element pointer to the "right" by one. If we move past the
- // end of that pointer's sequence, reset the pointer to the first element
- // in its sequence and then try the sequence to the "left", and so on.
-
- // seqPtr = index of rightmost input sequence whose element pointer is not
- // past the end of the sequence
- let seqPtr = aSequences.length - 1;
- while (!done) {
- // Advance the rightmost element pointer.
- seqEltPtrs[seqPtr]++;
-
- // The rightmost element pointer is past the end of its sequence.
- if (seqEltPtrs[seqPtr] >= aSequences[seqPtr].length) {
- seqEltPtrs[seqPtr] = 0;
- seqPtr--;
-
- // All element pointers are past the ends of their sequences.
- if (seqPtr < 0)
- done = true;
- }
- else break;
- }
- }
- return numProds;
-}
-
-/**
- * Enumerates all the subsets in aSet of size aHowMany. There are
- * C(aSet.length, aHowMany) such subsets. aCallback will be passed each subset
- * as it is generated. Note that aSet and the subsets enumerated are -- even
- * though they're arrays -- not sequences; the ordering of their elements is not
- * important. Example:
- *
- * choose([1, 2, 3, 4], 2, callback);
- * // callback is called C(4, 2) = 6 times with the following sets (arrays):
- * // [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]
- *
- * @param aSet
- * an array from which to choose elements, aSet.length > 0
- * @param aHowMany
- * the number of elements to choose, > 0 and <= aSet.length
- * @return the total number of sets chosen
- */
-function choose(aSet, aHowMany, aCallback)
-{
- // ptrs = indices of the elements in aSet we're currently choosing
- var ptrs = [];
- for (let i = 0; i < aHowMany; i++) {
- ptrs.push(i);
- }
-
- var numFound = 0;
- var done = false;
- while (!done) {
- numFound++;
- aCallback(ptrs.map(p => aSet[p]));
-
- // The next subset to be chosen differs from the current one by just a
- // single element. Determine which element that is. Advance the "rightmost"
- // pointer to the "right" by one. If we move past the end of set, move the
- // next non-adjacent rightmost pointer to the right by one, and reset all
- // succeeding pointers so that they're adjacent to it. When all pointers
- // are clustered all the way to the right, we're done.
-
- // Advance the rightmost pointer.
- ptrs[ptrs.length - 1]++;
-
- // The rightmost pointer has gone past the end of set.
- if (ptrs[ptrs.length - 1] >= aSet.length) {
- // Find the next rightmost pointer that is not adjacent to the current one.
- let si = aSet.length - 2; // aSet index
- let pi = ptrs.length - 2; // ptrs index
- while (pi >= 0 && ptrs[pi] === si) {
- pi--;
- si--;
- }
-
- // All pointers are adjacent and clustered all the way to the right.
- if (pi < 0)
- done = true;
- else {
- // pi = index of rightmost pointer with a gap between it and its
- // succeeding pointer. Move it right and reset all succeeding pointers
- // so that they're adjacent to it.
- ptrs[pi]++;
- for (let i = 0; i < ptrs.length - pi - 1; i++) {
- ptrs[i + pi + 1] = ptrs[pi] + i + 1;
- }
- }
- }
- }
- return numFound;
-}
-
-/**
- * Convenience function for nsINavHistoryQuery switches that act as flags. This
- * is attached to switch objects. See querySwitches array above.
- *
- * @param aQuery1
- * an nsINavHistoryQuery object
- * @param aQuery2
- * another nsINavHistoryQuery object
- * @return true if this switch is the same in both aQuery1 and aQuery2
- */
-function flagSwitchMatches(aQuery1, aQuery2)
-{
- if (aQuery1[this.flag] && aQuery2[this.flag]) {
- for (let p in this.subswitches) {
- if (p in aQuery1 && p in aQuery2) {
- if (aQuery1[p] instanceof Ci.nsIURI) {
- if (!aQuery1[p].equals(aQuery2[p]))
- return false;
- }
- else if (aQuery1[p] !== aQuery2[p])
- return false;
- }
- }
- }
- else if (aQuery1[this.flag] || aQuery2[this.flag])
- return false;
-
- return true;
-}
-
-/**
- * Tests if aObj1 and aObj2 are equal. This function is general and may be used
- * for either nsINavHistoryQuery or nsINavHistoryQueryOptions objects. aSwitches
- * determines which set of switches is used for comparison. Pass in either
- * querySwitches or queryOptionSwitches.
- *
- * @param aSwitches
- * determines which set of switches applies to aObj1 and aObj2, either
- * querySwitches or queryOptionSwitches
- * @param aObj1
- * an nsINavHistoryQuery or nsINavHistoryQueryOptions object
- * @param aObj2
- * another nsINavHistoryQuery or nsINavHistoryQueryOptions object
- * @return true if aObj1 and aObj2 are equal
- */
-function queryObjsEqual(aSwitches, aObj1, aObj2)
-{
- for (let i = 0; i < aSwitches.length; i++) {
- if (!aSwitches[i].matches(aObj1, aObj2))
- return false;
- }
- return true;
-}
-
-/**
- * This drives the test runs. See the comment at the top of this file.
- *
- * @param aHowManyLo
- * the size of the switch subsets to start with
- * @param aHowManyHi
- * the size of the switch subsets to end with (inclusive)
- */
-function runQuerySequences(aHowManyLo, aHowManyHi)
-{
- var allSwitches = querySwitches.concat(queryOptionSwitches);
- var prevQueries = [];
- var prevOpts = [];
-
- // Choose aHowManyLo switches up to aHowManyHi switches.
- for (let howMany = aHowManyLo; howMany <= aHowManyHi; howMany++) {
- let numIters = 0;
- print("CHOOSING " + howMany + " SWITCHES");
-
- // Choose all subsets of size howMany from allSwitches.
- choose(allSwitches, howMany, function (chosenSwitches) {
- print(numIters);
- numIters++;
-
- // Collect the runs.
- // runs = [ [runs from switch 1], ..., [runs from switch howMany] ]
- var runs = chosenSwitches.map(function (s) {
- if (s.desc)
- print(" " + s.desc);
- return s.runs;
- });
-
- // cartProd(runs) => [
- // [switch 1 run 1, switch 2 run 1, ..., switch howMany run 1 ],
- // ...,
- // [switch 1 run 1, switch 2 run 1, ..., switch howMany run N ],
- // ..., ...,
- // [switch 1 run N, switch 2 run N, ..., switch howMany run 1 ],
- // ...,
- // [switch 1 run N, switch 2 run N, ..., switch howMany run N ],
- // ]
- cartProd(runs, function (runSet) {
- // Create a new query, apply the switches in runSet, and test it.
- var query = PlacesUtils.history.getNewQuery();
- var opts = PlacesUtils.history.getNewQueryOptions();
- for (let i = 0; i < runSet.length; i++) {
- runSet[i](query, opts);
- }
- serializeDeserialize([query], opts);
-
- // Test the previous NUM_MULTIPLE_QUERIES queries together.
- prevQueries.push(query);
- prevOpts.push(opts);
- if (prevQueries.length >= NUM_MULTIPLE_QUERIES) {
- // We can serialize multiple nsINavHistoryQuery objects together but
- // only one nsINavHistoryQueryOptions object with them. So, test each
- // of the previous NUM_MULTIPLE_QUERIES nsINavHistoryQueryOptions.
- for (let i = 0; i < prevOpts.length; i++) {
- serializeDeserialize(prevQueries, prevOpts[i]);
- }
- prevQueries.shift();
- prevOpts.shift();
- }
- });
- });
- }
- print("\n");
-}
-
-/**
- * Serializes the nsINavHistoryQuery objects in aQueryArr and the
- * nsINavHistoryQueryOptions object aQueryOptions, de-serializes the
- * serialization, and ensures (using do_check_* functions) that the
- * de-serialized objects equal the originals.
- *
- * @param aQueryArr
- * an array containing nsINavHistoryQuery objects
- * @param aQueryOptions
- * an nsINavHistoryQueryOptions object
- */
-function serializeDeserialize(aQueryArr, aQueryOptions)
-{
- var queryStr = PlacesUtils.history.queriesToQueryString(aQueryArr,
- aQueryArr.length,
- aQueryOptions);
- print(" " + queryStr);
- var queryArr2 = {};
- var opts2 = {};
- PlacesUtils.history.queryStringToQueries(queryStr, queryArr2, {}, opts2);
- queryArr2 = queryArr2.value;
- opts2 = opts2.value;
-
- // The two sets of queries cannot be the same if their lengths differ.
- do_check_eq(aQueryArr.length, queryArr2.length);
-
- // Although the query serialization code as it is written now practically
- // ensures that queries appear in the query string in the same order they
- // appear in both the array to be serialized and the array resulting from
- // de-serialization, the interface does not guarantee any ordering. So, for
- // each query in aQueryArr, find its equivalent in queryArr2 and delete it
- // from queryArr2. If queryArr2 is empty after looping through aQueryArr,
- // the two sets of queries are equal.
- for (let i = 0; i < aQueryArr.length; i++) {
- let j = 0;
- for (; j < queryArr2.length; j++) {
- if (queryObjsEqual(querySwitches, aQueryArr[i], queryArr2[j]))
- break;
- }
- if (j < queryArr2.length)
- queryArr2.splice(j, 1);
- }
- do_check_eq(queryArr2.length, 0);
-
- // Finally check the query options objects.
- do_check_true(queryObjsEqual(queryOptionSwitches, aQueryOptions, opts2));
-}
-
-/**
- * Convenience function for switches that have simple values. This is attached
- * to switch objects. See querySwitches and queryOptionSwitches arrays above.
- *
- * @param aObj1
- * an nsINavHistoryQuery or nsINavHistoryQueryOptions object
- * @param aObj2
- * another nsINavHistoryQuery or nsINavHistoryQueryOptions object
- * @return true if this switch is the same in both aObj1 and aObj2
- */
-function simplePropertyMatches(aObj1, aObj2)
-{
- return aObj1[this.property] === aObj2[this.property];
-}
-
-function run_test()
-{
- runQuerySequences(CHOOSE_HOW_MANY_SWITCHES_LO, CHOOSE_HOW_MANY_SWITCHES_HI);
-}