Warning, file /frameworks/khtml/src/xpath/interpreter_tester.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  * interpreter_tester.cpp - Copyright 2005 Frerich Raabe <raabe@kde.org>
0003  *
0004  * Redistribution and use in source and binary forms, with or without
0005  * modification, are permitted provided that the following conditions
0006  * are met:
0007  *
0008  * 1. Redistributions of source code must retain the above copyright
0009  *    notice, this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright
0011  *    notice, this list of conditions and the following disclaimer in the
0012  *    documentation and/or other materials provided with the distribution.
0013  *
0014  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0015  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0016  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0017  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0018  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0019  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0020  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0021  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0023  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0024  */
0025 #include "expression.h"
0026 #include "parsedstatement.h"
0027 
0028 #include "XPathExceptionImpl.h"
0029 
0030 #include "DocumentImpl.h"
0031 #include "DOMStringImpl.h"
0032 #include "KDOMParser.h"
0033 #include "KDOMParserFactory.h"
0034 #include "NamedAttrMapImpl.h"
0035 
0036 #include "kdom.h"
0037 
0038 #include <QApplication>
0039 #include <QBuffer>
0040 #include <QtDebug>
0041 
0042 using namespace KDOM;
0043 
0044 void check(DocumentImpl *doc, const QString &statement, const QString &expected)
0045 {
0046     ParsedStatement s(statement);
0047     Value result = s.evaluate(doc);
0048     if (!result.isString()) {
0049         qDebug("ERROR: Query '%s' did not return a string!", statement.latin1());
0050         exit(1);
0051     }
0052 
0053     QString string = result.toString();
0054     if (string != expected) {
0055         qDebug("ERROR: Failed to interprete '%s' correctly!", statement.latin1());
0056         qDebug("Expected to get: %s", expected.latin1());
0057         qDebug("Got            : %s", string.latin1());
0058         exit(1);
0059     }
0060 }
0061 
0062 void check(DocumentImpl *doc, const QString &statement, double expected)
0063 {
0064     ParsedStatement s(statement);
0065     Value result = s.evaluate(doc);
0066     if (!result.isNumber()) {
0067         qDebug("ERROR: Query '%s' did not return a number!", statement.latin1());
0068         exit(1);
0069     }
0070 
0071     double number = result.toNumber();
0072     if (number != expected) {
0073         qDebug("ERROR: Failed to interprete '%s' correctly!", statement.latin1());
0074         qDebug("Expected to get: %f", expected);
0075         qDebug("Got            : %f", number);
0076         exit(1);
0077     }
0078 }
0079 
0080 void check(DocumentImpl *doc, const QString &statement,
0081            const QStringList &idsOfExpectedMatches)
0082 {
0083     ParsedStatement s(statement);
0084     Value result = s.evaluate(doc);
0085     if (!result.isNodeset()) {
0086         qDebug("ERROR: Query '%s' did not return a nodeset!", statement.latin1());
0087         exit(1);
0088     }
0089 
0090     QStringList idsOfResultMatches;
0091 
0092     DomNodeList nodes = result.toNodeset();
0093     foreach (NodeImpl *node, nodes) {
0094         if (node->nodeType() != ELEMENT_NODE) {
0095             continue;
0096         }
0097         NodeImpl *idNode = 0;
0098         NamedAttrMapImpl *attrs = node->attributes(true /*read-only*/);
0099         for (unsigned long i = 0; i < attrs->length(); ++i) {
0100             idNode = attrs->item(i);
0101             if (idNode->nodeName()->string() == "id") {
0102                 break;
0103             }
0104         }
0105         if (!idNode) {
0106             qDebug("ERROR: Found match without id attribute!");
0107             exit(1);
0108         }
0109         idsOfResultMatches.append(idNode->nodeValue()->string());
0110     }
0111 
0112     bool failure = false;
0113 
0114     foreach (QString id, idsOfExpectedMatches) {
0115         if (!idsOfResultMatches.contains(id)) {
0116             failure = true;
0117             break;
0118         }
0119     }
0120 
0121     if (!failure) {
0122         foreach (QString id, idsOfResultMatches) {
0123             if (!idsOfExpectedMatches.contains(id)) {
0124                 failure = true;
0125                 break;
0126             }
0127         }
0128     }
0129 
0130     if (failure) {
0131         qCDebug(KHTML_LOG) << "ERROR: Failed to interprete '" << statement << "' correctly!";
0132         qCDebug(KHTML_LOG) << "Expected to match: " << idsOfExpectedMatches.join(",");
0133         qCDebug(KHTML_LOG) << "Got matches      : " << idsOfResultMatches.join(",");
0134         exit(1);
0135     }
0136 }
0137 
0138 int main(int argc, char **argv)
0139 {
0140     QString bookMarkup =
0141         "<book id=\"1\">"
0142         "<abstract id=\"2\">"
0143         "</abstract>"
0144         "<chapter id=\"3\" title=\"Introduction\">"
0145         "<para id=\"4\">Blah blah blah</para>"
0146         "<para id=\"5\">Foo bar yoyodyne</para>"
0147         "</chapter>"
0148         "<chapter id=\"6\" title=\"TEST\" type=\"x\">"
0149         "<para id=\"7\">My sister got bitten by a yak.</para>"
0150         "</chapter>"
0151         "<chapter id=\"8\" title=\"note\" type=\"y\">"
0152         "<para id=\"9\">141,000</para>"
0153         "</chapter>"
0154         "<chapter id=\"10\" title=\"note\">"
0155         "<para id=\"11\">Hell yeah, yaks are nice.</para>"
0156         "</chapter>"
0157         "</book>";
0158 
0159     QApplication::setApplicationName("interpreter_tester");
0160 
0161     QApplication app(argc, argv);
0162 
0163     // Parser::syncParse called blow deletes the given buffer, so we
0164     // cannot use QBuffer objects which live on the stack.
0165     QBuffer *buf = new QBuffer;
0166     buf->open(QBuffer::ReadWrite);
0167     buf->write(bookMarkup.toUtf8());
0168 
0169     // I can't believe that I have to go through all these hoops to get
0170     // a DocumentImpl* out of a string with markup.
0171     Parser *parser = ParserFactory::self()->request(KURL(), 0, "qxml");
0172     DocumentImpl *doc = parser->syncParse(buf);
0173 
0174     try {
0175         check(doc, "/book", QStringList() << "1");
0176         check(doc, "/book/chapter", QStringList() << "3" << "6" << "8");
0177         check(doc, "/book/chapter[@title=\"TEST\"]", QStringList() << "6");
0178         check(doc, "/book/chapter[last()-1]", QStringList() << "8");
0179         check(doc, "/book/chapter[contains(string(@title), \"tro\")]", QStringList() << "3");
0180         check(doc, "//para", QStringList() << "4" << "5" << "7" << "9");
0181         check(doc, "/book/chapter[position()=2]/following::*", QStringList() << "8" << "9");
0182         check(doc, "//chapter[@title and @type]", QStringList() << "6" << "8");
0183         check(doc, "/book/chapter[attribute::title = \"note\"][position() = 2]", QStringList() << "10");
0184         check(doc, "count(//para)", 5.0);
0185         check(doc, "string(/book/chapter/para[text() = \"Foo bar yoyodyne\" ])", QLatin1String("Foo bar yoyodyne"));
0186         check(doc, "substring-before(/book/chapter/para[@id=\"9\" ], ',' )", QLatin1String("141"));
0187     } catch (XPath::XPathExceptionImpl *e) {
0188         qDebug("Caught XPath exception '%s'.", e->codeAsString().latin1());
0189         delete e;
0190         return 1;
0191     }
0192 
0193     qDebug("All OK!");
0194 }
0195