339 lines
9.8 KiB
JavaScript
339 lines
9.8 KiB
JavaScript
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org XPath Generator.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Alexander J. Vincent <ajvincent@gmail.com>.
|
|
* Portions created by the Initial Developer are Copyright (C) 2007
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
var _nodesList = null;
|
|
var generator = null;
|
|
var genResolver = null;
|
|
var doc = null;
|
|
|
|
const C_i = Components.interfaces;
|
|
|
|
/**
|
|
* Get a list of nodes to run the test on.
|
|
*/
|
|
function getNodesList() {
|
|
if (_nodesList)
|
|
return _nodesList;
|
|
|
|
doc.QueryInterface(C_i.nsIDOMDocumentTraversal);
|
|
var walker = doc.createTreeWalker(doc,
|
|
C_i.nsIDOMNodeFilter.SHOW_ALL,
|
|
null,
|
|
true);
|
|
var nodesList = [doc];
|
|
var i;
|
|
var node;
|
|
while (walker.nextNode()) {
|
|
node = walker.currentNode;
|
|
nodesList[nodesList.length] = node;
|
|
if (node instanceof C_i.nsIDOMElement) {
|
|
for (i = 0; i < node.attributes.length; i++) {
|
|
nodesList[nodesList.length] = node.attributes.item(i);
|
|
}
|
|
}
|
|
}
|
|
walker = null;
|
|
|
|
// Let's throw a spanner in the works.
|
|
var frag = doc.createDocumentFragment();
|
|
nodesList[nodesList.length] = frag;
|
|
node = doc.createElement("foo");
|
|
frag.appendChild(node);
|
|
nodesList[nodesList.length] = node;
|
|
node.setAttribute("one", "green");
|
|
node.setAttribute("two", "truck");
|
|
for (i = 0; i < node.attributes.length; i++)
|
|
{
|
|
nodesList[nodesList.length] = node.attributes.item(i);
|
|
}
|
|
nodesList[nodesList.length] = doc.createAttribute("disconnected");
|
|
|
|
for (i = 0; i < nodesList.length; i++) {
|
|
do_check_true(Boolean(nodesList[i]));
|
|
}
|
|
|
|
_nodesList = nodesList;
|
|
return _nodesList;
|
|
}
|
|
|
|
function runSingleTest(i, j, searchFlags) {
|
|
generator.searchFlags = searchFlags;
|
|
|
|
var nodesList = getNodesList();
|
|
var targetNode = nodesList[i];
|
|
var contextNode = nodesList[j];
|
|
var path = null;
|
|
var status = "success";
|
|
var failureReport = null;
|
|
var err = null;
|
|
|
|
targetNode.QueryInterface(C_i.nsIDOMNode);
|
|
contextNode.QueryInterface(C_i.nsIDOMNode);
|
|
|
|
/* Checks to see if we should fail */
|
|
if (targetNode.nodeType == C_i.nsIDOMNode.DOCUMENT_TYPE_NODE) {
|
|
status = "failure-expected";
|
|
}
|
|
|
|
if (contextNode.nodeType == C_i.nsIDOMNode.DOCUMENT_TYPE_NODE) {
|
|
status = "failure-expected";
|
|
}
|
|
|
|
if ((targetNode instanceof C_i.nsIDOMText) &&
|
|
(targetNode.previousSibling instanceof C_i.nsIDOMText) &&
|
|
(targetNode != contextNode)) {
|
|
status = "failure-expected";
|
|
}
|
|
|
|
var positionNode;
|
|
|
|
if (targetNode.nodeType == C_i.nsIDOMNode.ATTRIBUTE_NODE) {
|
|
targetNode.QueryInterface(C_i.nsIDOMAttr);
|
|
positionNode = targetNode.ownerElement;
|
|
} else {
|
|
positionNode = targetNode;
|
|
}
|
|
|
|
var compareNode;
|
|
if (contextNode.nodeType == C_i.nsIDOMNode.ATTRIBUTE_NODE) {
|
|
contextNode.QueryInterface(C_i.nsIDOMAttr);
|
|
compareNode = contextNode.ownerElement;
|
|
} else {
|
|
compareNode = contextNode;
|
|
}
|
|
|
|
if (targetNode == contextNode) {
|
|
positionNode = targetNode;
|
|
compareNode = targetNode;
|
|
}
|
|
|
|
if (positionNode && compareNode) {
|
|
positionNode.QueryInterface(C_i.nsIDOM3Node);
|
|
try {
|
|
position = positionNode.compareDocumentPosition(compareNode);
|
|
}
|
|
catch (e) {
|
|
position = C_i.nsIDOM3Node.DOCUMENT_POSITION_DISCONNECTED;
|
|
}
|
|
} else {
|
|
position = C_i.nsIDOM3Node.DOCUMENT_POSITION_DISCONNECTED;
|
|
}
|
|
|
|
if (position & C_i.nsIDOM3Node.DOCUMENT_POSITION_DISCONNECTED) {
|
|
status = "failure-expected";
|
|
}
|
|
|
|
var err = null;
|
|
|
|
try {
|
|
path = generator.generateXPath(targetNode, contextNode);
|
|
}
|
|
catch (e) {
|
|
if (status == "failure-expected")
|
|
status = "success";
|
|
else
|
|
status = "test-failed";
|
|
|
|
failureReport = {
|
|
i: i,
|
|
j: j,
|
|
targetNode: targetNode,
|
|
contextNode: contextNode,
|
|
err: e,
|
|
path: path,
|
|
status: status
|
|
}
|
|
err = e;
|
|
}
|
|
|
|
if (!err) {
|
|
const UNORDERED_NODE = C_i.nsIDOMXPathResult.ANY_UNORDERED_NODE_TYPE;
|
|
doc.QueryInterface(C_i.nsIDOMXPathEvaluator);
|
|
try {
|
|
var expr = doc.createExpression(path, genResolver);
|
|
var xpathResult = expr.evaluate(contextNode, UNORDERED_NODE, null);
|
|
xpathResult.QueryInterface(C_i.nsIDOMXPathResult);
|
|
|
|
var checkNode = xpathResult.singleNodeValue;
|
|
|
|
if (checkNode != targetNode) {
|
|
status = "test-failed";
|
|
failureReport = {
|
|
i: i,
|
|
j: j,
|
|
targetNode: targetNode,
|
|
contextNode: contextNode,
|
|
path: path,
|
|
checkNode: checkNode,
|
|
status: status,
|
|
err: null
|
|
}
|
|
}
|
|
} catch (e) {
|
|
status = "busted";
|
|
failureReport = {
|
|
i: i,
|
|
j: j,
|
|
targetNode: targetNode,
|
|
contextNode: contextNode,
|
|
err: e,
|
|
path: path,
|
|
status: status
|
|
}
|
|
err = e;
|
|
}
|
|
}
|
|
|
|
return {
|
|
status: status,
|
|
failureReport: failureReport,
|
|
err: err,
|
|
path: path
|
|
};
|
|
}
|
|
|
|
var failCount;
|
|
|
|
function runTestSuite(aSearchFlags) {
|
|
var nodesList = getNodesList();
|
|
var j;
|
|
|
|
for (i = 0; i < nodesList.length; i++) {
|
|
var targetNode = nodesList[i];
|
|
for (j = 0; j < nodesList.length; j++) {
|
|
var contextNode = nodesList[j];
|
|
|
|
var results = runSingleTest(i, j, aSearchFlags);
|
|
var status = results.status;
|
|
|
|
if (status == "failure-expected") {
|
|
failCount[failCount.length] = {
|
|
i: i,
|
|
j: j,
|
|
targetNode: targetNode,
|
|
contextNode: contextNode,
|
|
path: results.path,
|
|
status: status,
|
|
searchFlags: aSearchFlags,
|
|
err: null
|
|
}
|
|
} else if (results.failureReport && status != "success") {
|
|
results.failureReport.searchFlags = aSearchFlags;
|
|
failCount[failCount.length] = results.failureReport;
|
|
}
|
|
} // end for (j = 0; j < nodesList.length; j++)
|
|
} // end for (i = 0; i < nodesList.length; i++)
|
|
}
|
|
|
|
function run_test() {
|
|
generator = Components.classes["@mozilla.org/xpath-generator;1"]
|
|
.createInstance(C_i.nsIXPathGenerator);
|
|
genResolver = generator.resolver;
|
|
const MAX_FLAGS = C_i.nsIXPathGenerator.IGNORE_ID_TYPE_ATTRS |
|
|
C_i.nsIXPathGenerator.USE_DESCENDANT_AXIS;
|
|
|
|
// Check namespace handling.
|
|
generator.addNamespace("foo namespace 1", "foo");
|
|
do_check_eq(genResolver.lookupNamespaceURI("foo"), "foo namespace 1");
|
|
|
|
const filePath = "/extensions/xpath-generator/test/unit/test_xpathgen.xml";
|
|
doc = do_parse_document(filePath, "application/xml");
|
|
do_check_true(doc.documentElement.localName != "parsererror");
|
|
|
|
failCount = [];
|
|
for (var i = 0; i <= MAX_FLAGS; i++) {
|
|
runTestSuite(i);
|
|
}
|
|
|
|
doc = null;
|
|
genResolver = null;
|
|
generator = null;
|
|
|
|
/* Known failures:
|
|
({i:49, j:49,
|
|
targetNode: nsIDOMDocumentFragment,
|
|
contextNode: nsIDOMDocumentFragment,
|
|
path:".", status:"busted", searchFlags:0,
|
|
err:NS_ERROR_FAILURE})
|
|
|
|
({i:50, j:49,
|
|
targetNode: nsIDOMElement (parent == nsIDOMDocumentFragment 49),
|
|
contextNode: nsIDOMDocumentFragment,
|
|
path:"foo", status:"busted", searchFlags:0,
|
|
err: NS_ERROR_FAILURE})
|
|
|
|
({i:51, j:49,
|
|
targetNode: nsIDOMAttr (ownerElement == nsIDOMElement 50),
|
|
contextNode: nsIDOMDocumentFragment,
|
|
path:"foo/@one", status:"busted", searchFlags:0
|
|
err: NS_ERROR_FAILURE})
|
|
|
|
({i:52, j:49,
|
|
targetNode: nsIDOMAttr (ownerElement == nsIDOMElement 49),
|
|
contextNode: nsIDOMDocumentFragment,
|
|
path:"foo/@two", status:"busted", searchFlags:0,
|
|
err: NS_ERROR_FAILURE})
|
|
|
|
({i:53, j:53,
|
|
targetNode: nsIDOMAttr (ownerElement == null),
|
|
contextNode: nsIDOMAttr (ownerElement == null),
|
|
path:".", status:"busted", searchFlags:0,
|
|
err: NS_ERROR_OUT_OF_MEMORY})
|
|
*/
|
|
|
|
const EXPECTED_FAILURES = (MAX_FLAGS + 1) * 5;
|
|
|
|
if (failCount.length != EXPECTED_FAILURES) {
|
|
for (i = 0; i < failCount.length; i++) {
|
|
failCount[i].targetNode = failCount[i].targetNode ?
|
|
failCount[i].targetNode.toString() :
|
|
null;
|
|
failCount[i].contextNode = failCount[i].contextNode ?
|
|
failCount[i].contextNode.toString() :
|
|
null;
|
|
failCount[i].err = failCount[i].err ?
|
|
failCount[i].err.toString() :
|
|
null;
|
|
failCount[i] = failCount[i].toSource();
|
|
}
|
|
dump("\n\n");
|
|
dump(failCount.join("\n\n"));
|
|
dump("\n\n");
|
|
dump("expected test failures: " + EXPECTED_FAILURES + "\n");
|
|
do_throw("actual tests failed: " + failCount.length + "\n");
|
|
}
|
|
}
|