KHTML
interpreter_tester.cpp
Go to the documentation of this file.
00001 /* 00002 * interpreter_tester.cpp - Copyright 2005 Frerich Raabe <raabe@kde.org> 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00017 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 */ 00025 #include "expression.h" 00026 #include "parsedstatement.h" 00027 00028 #include "XPathExceptionImpl.h" 00029 00030 #include "DocumentImpl.h" 00031 #include "DOMStringImpl.h" 00032 #include "KDOMParser.h" 00033 #include "KDOMParserFactory.h" 00034 #include "NamedAttrMapImpl.h" 00035 00036 #include "kdom.h" 00037 00038 #include <kaboutdata.h> 00039 #include <kapplication.h> 00040 #include <kcmdlineargs.h> 00041 00042 #include <QBuffer> 00043 #include <QtDebug> 00044 00045 using namespace KDOM; 00046 00047 void check( DocumentImpl *doc, const QString &statement, const QString &expected ) 00048 { 00049 ParsedStatement s( statement ); 00050 Value result = s.evaluate( doc ); 00051 if ( !result.isString() ) { 00052 qDebug( "ERROR: Query '%s' did not return a string!", statement.latin1() ); 00053 exit( 1 ); 00054 } 00055 00056 QString string = result.toString(); 00057 if ( string != expected ) { 00058 qDebug( "ERROR: Failed to interprete '%s' correctly!", statement.latin1() ); 00059 qDebug( "Expected to get: %s", expected.latin1() ); 00060 qDebug( "Got : %s", string.latin1() ); 00061 exit( 1 ); 00062 } 00063 } 00064 00065 00066 void check( DocumentImpl *doc, const QString &statement, double expected ) 00067 { 00068 ParsedStatement s( statement ); 00069 Value result = s.evaluate( doc ); 00070 if ( !result.isNumber() ) { 00071 qDebug( "ERROR: Query '%s' did not return a number!", statement.latin1() ); 00072 exit( 1 ); 00073 } 00074 00075 double number = result.toNumber(); 00076 if ( number != expected ) { 00077 qDebug( "ERROR: Failed to interprete '%s' correctly!", statement.latin1() ); 00078 qDebug( "Expected to get: %f", expected ); 00079 qDebug( "Got : %f", number ); 00080 exit( 1 ); 00081 } 00082 } 00083 00084 void check( DocumentImpl *doc, const QString &statement, 00085 const QStringList &idsOfExpectedMatches ) 00086 { 00087 ParsedStatement s( statement ); 00088 Value result = s.evaluate( doc ); 00089 if ( !result.isNodeset() ) { 00090 qDebug( "ERROR: Query '%s' did not return a nodeset!", statement.latin1() ); 00091 exit( 1 ); 00092 } 00093 00094 QStringList idsOfResultMatches; 00095 00096 DomNodeList nodes = result.toNodeset(); 00097 foreach( NodeImpl *node, nodes ) { 00098 if ( node->nodeType() != ELEMENT_NODE ) { 00099 continue; 00100 } 00101 NodeImpl *idNode = 0; 00102 NamedAttrMapImpl *attrs = node->attributes( true /*read-only*/ ); 00103 for ( unsigned long i = 0; i < attrs->length(); ++i ) { 00104 idNode = attrs->item( i ); 00105 if ( idNode->nodeName()->string() == "id" ) { 00106 break; 00107 } 00108 } 00109 if ( !idNode ) { 00110 qDebug( "ERROR: Found match without id attribute!" ); 00111 exit( 1 ); 00112 } 00113 idsOfResultMatches.append( idNode->nodeValue()->string() ); 00114 } 00115 00116 bool failure = false; 00117 00118 foreach( QString id, idsOfExpectedMatches ) { 00119 if ( !idsOfResultMatches.contains( id ) ) { 00120 failure = true; 00121 break; 00122 } 00123 } 00124 00125 if ( !failure ) { 00126 foreach( QString id, idsOfResultMatches ) { 00127 if ( !idsOfExpectedMatches.contains( id ) ) { 00128 failure = true; 00129 break; 00130 } 00131 } 00132 } 00133 00134 if ( failure ) { 00135 qDebug() << "ERROR: Failed to interprete '" << statement << "' correctly!"; 00136 qDebug() << "Expected to match: " << idsOfExpectedMatches.join( "," ); 00137 qDebug() << "Got matches : " << idsOfResultMatches.join( "," ); 00138 exit( 1 ); 00139 } 00140 } 00141 00142 int main( int argc, char **argv ) 00143 { 00144 QString bookMarkup = 00145 "<book id=\"1\">" 00146 "<abstract id=\"2\">" 00147 "</abstract>" 00148 "<chapter id=\"3\" title=\"Introduction\">" 00149 "<para id=\"4\">Blah blah blah</para>" 00150 "<para id=\"5\">Foo bar yoyodyne</para>" 00151 "</chapter>" 00152 "<chapter id=\"6\" title=\"TEST\" type=\"x\">" 00153 "<para id=\"7\">My sister got bitten by a yak.</para>" 00154 "</chapter>" 00155 "<chapter id=\"8\" title=\"note\" type=\"y\">" 00156 "<para id=\"9\">141,000</para>" 00157 "</chapter>" 00158 "<chapter id=\"10\" title=\"note\">" 00159 "<para id=\"11\">Hell yeah, yaks are nice.</para>" 00160 "</chapter>" 00161 "</book>"; 00162 00163 KAboutData about( "interpreter_tester", "interpreter_tester", "0.1", "Tests KDOM's XPath 1.0 Interpreter" ); 00164 KCmdLineArgs::init( argc, argv, &about ); 00165 00166 KApplication::disableAutoDcopRegistration(); 00167 KApplication app( false, false ); 00168 00169 // Parser::syncParse called blow deletes the given buffer, so we 00170 // cannot use QBuffer objects which live on the stack. 00171 QBuffer *buf = new QBuffer; 00172 buf->open( QBuffer::ReadWrite ); 00173 buf->write( bookMarkup.toUtf8() ); 00174 00175 // I can't believe that I have to go through all these hoops to get 00176 // a DocumentImpl* out of a string with markup. 00177 Parser *parser = ParserFactory::self()->request( KURL(), 0, "qxml" ); 00178 DocumentImpl *doc = parser->syncParse( buf ); 00179 00180 try { 00181 check( doc, "/book", QStringList() << "1" ); 00182 check( doc, "/book/chapter", QStringList() << "3" << "6" << "8" ); 00183 check( doc, "/book/chapter[@title=\"TEST\"]", QStringList() << "6" ); 00184 check( doc, "/book/chapter[last()-1]", QStringList() << "8" ); 00185 check( doc, "/book/chapter[contains(string(@title), \"tro\")]", QStringList() << "3" ); 00186 check( doc, "//para", QStringList() << "4" << "5" << "7" << "9" ); 00187 check( doc, "/book/chapter[position()=2]/following::*", QStringList() << "8" << "9" ); 00188 check( doc, "//chapter[@title and @type]", QStringList() << "6" << "8" ); 00189 check( doc, "/book/chapter[attribute::title = \"note\"][position() = 2]", QStringList() << "10" ); 00190 check( doc, "count(//para)", 5.0 ); 00191 check( doc, "string(/book/chapter/para[text() = \"Foo bar yoyodyne\" ])", QLatin1String( "Foo bar yoyodyne" ) ); 00192 check( doc, "substring-before(/book/chapter/para[@id=\"9\" ], ',' )", QLatin1String( "141" ) ); 00193 } catch ( XPath::XPathExceptionImpl *e ) { 00194 qDebug( "Caught XPath exception '%s'.", e->codeAsString().latin1() ); 00195 delete e; 00196 return 1; 00197 } 00198 00199 qDebug( "All OK!" ); 00200 } 00201
KDE 4.6 API Reference