Main Page   Namespace List   File List   Examples  

UnitTests.cpp

CPPUnit Tests for this library. Binary should be installed as sp-gxmlcpp-test.

/*
 * (C) Copyright 2002, Schlund+Partner AG
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

// Local configuration
#include "config.h"

// C++ Libraries
#include <cppunit/TestCase.h>
#include <cppunit/TestSuite.h>
#include <cppunit/TestCaller.h>
#include <cppunit/TextTestRunner.h>

#include <sp-gxmlcpp/XMLTree.hpp>
#include <sp-gxmlcpp/XMLDump.hpp>
#include <sp-gxmlcpp/XSLTrans.hpp>
#include <sp-gxmlcpp/XMLNode.hpp>
#include <sp-gxmlcpp/XMLNodeSet.hpp>
#include <sp-gxmlcpp/XMLException.hpp>

namespace SP {
namespace GXML {

//
// XMLTree (&& XMLDump)
//
class TestXMLTreeOld: public CppUnit::TestCase
{
public:
        TestXMLTreeOld()
        {}
        void testRun()
        {
                // ^^ Note: dump will always use " (not ') to quote, so we must do this here too for string compare
                const std::string xmlString(
                        "<?xml version=\"1.0\"?>\n"
                        "<req>\n"
                        " <uid>5</uid>\n"
                        " <home>/home/absurd</home>\n"
                        " <key>AAAABBBBCCCCDDDD</key>\n"
                        "\n"
                        " <a>\n"
                        "   <b>\n"
                        "     <c>Wert1</c>\n"
                        "   </b>\n"
                        "   <b>\n"
                        "     <c> Wert 2</c>\n"
                        "  </b>\n"
                        " </a>\n"
                        "\n"
                        " <X>5</X>\n"
                        "\n"
                        " <int>-42</int>\n"
                        " <int>17</int>\n"
                        " <bool>0</bool>\n"
                        " <string> abc def </string>\n"
                        "\n"
                        " <X>13</X>\n"
                        "\n"
                        "<tags>\n"
                        " <subtag>EINS</subtag>\n"
                        "</tags>\n"
                        "\n"
                        " <tags>\n"
                        "  <subtag>ZWEI</subtag>\n"
                        " </tags>\n"
                        "\n"
                        " <X>17</X>\n"
                        "\n"
                        "</req>\n");

                // ^^ Note: dump will always add a \n to the last line (in a full ("/") dump, that is), so our string should have this too for string compare
                // Note2: It's a bit dumb to literally compare dumps here, as the default way of producing dumps might change... §STS§

                // Partial Tree && Dump
                XMLTree xmlTree1(xmlString.c_str(), xmlString.size());
                std::string dump1 = XMLDump(&xmlTree1, "/req/tags").get();
                CPPUNIT_ASSERT(dump1 ==
                                                                         "<tags>\n"
                                                                         " <subtag>EINS</subtag>\n"
                                                                         "</tags>");

                // Full Tree && Dump
                XMLTree xmlTree(xmlString.c_str(), xmlString.size());
                std::string dump = XMLDump(&xmlTree, "/").get();
                // §STS§ This does not work anymore with default encoding added in XMLDump
                //CPPUNIT_ASSERT(dump == xmlString);

                // XMLTree methods
                CPPUNIT_ASSERT(xmlTree.getValue("/req/string") == " abc def ");

                CPPUNIT_ASSERT(xmlTree.getCount("/req/int") == 2);
                CPPUNIT_ASSERT(xmlTree.getValue("/req/int") == "-42");
                CPPUNIT_ASSERT(xmlTree.getValue("/req/int[position()=2]") == "17");

                CPPUNIT_ASSERT(xmlTree.getCount("/req/tags/subtag") == 2);
                CPPUNIT_ASSERT(xmlTree.getValue("/req/tags/subtag") == "EINS");

                CPPUNIT_ASSERT(xmlTree.getCount("/req/nonexisting") == 0);
                CPPUNIT_ASSERT(xmlTree.getCount("/nonexisting/tag") == 0);
                CPPUNIT_ASSERT(xmlTree.getValue("/nonexisting/tag") == "");

                xmlTree.delTag("/req/int");
                CPPUNIT_ASSERT(xmlTree.getCount("/req/int") == 1);

                xmlTree.addTag("/req", "newtag", "contents of new tag");
                CPPUNIT_ASSERT(xmlTree.getValue("/req/newtag") == "contents of new tag");
        }
};


// XSLTrans Test
//
class TestXSLTrans : public CppUnit::TestCase
{
public:
        TestXSLTrans()
        {}
        void testRun()
        {
                std::string xmlString(
                        "<?xml version=\"1.0\"?>\n"
                        "<!DOCTYPE guestbook>\n"
                        "\n"
                        "<guestbook>\n"
                        "       <record>\n"
                        "               <name>kurt</name>\n"
                        "               <date>2.3.01</date>\n"
                        "               <text>\n"
                        "               find ich total klasse, koennte aber noch besser sein\n"
                        "               </text>\n"
                        "       </record>\n"
                        "       <record>\n"
                        "               <name>kurt</name>\n"
                        "               <date>2.3.01</date>\n"
                        "               <text>\n"
                        "               find ich total klasse, koennte aber noch besser sein\n"
                        "               </text>\n"
                        "       </record>\n"
                        "</guestbook>\n");

                std::string xslString(
                        "<?xml version=\"1.0\"?>\n"
                        "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n"
                        "<!-- Basic stylesheet for GUESTBOOK -->\n"
                        "<xsl:output indent=\"yes\" />\n"
                        "<xsl:template match=\"guestbook\">\n"
                        "       <html>\n"
                        "               <head>\n"
                        "                       <title>Gaestebuch</title>\n"
                        "               </head> \n"
                        "               <body bgcolor=\"FFFFFF\">\n"
                        "                       <h1>Mein Gaestebuch</h1>\n"
                        "                       <center>\n"
                        "                       <table cellspacing=\"2\" cellpadding=\"3\" border=\"0\">\n"
                        "                       \n"
                        "                       <xsl:apply-templates/>\n"
                        "                       \n"
                        "                       </table>\n"
                        "                       </center>\n"
                        "               </body>\n"
                        "       </html>\n"
                        "</xsl:template>\n"
                        "\n"
                        "<xsl:template match=\"record\">\n"
                        "       \n"
                        "       <tr> \n"
                        "       <td bgcolor=\"336699\"><font face=\"Arial,helvitica\" size=\"-1\" color=\"FFFFFF\">Name</font></td>\n"
                        "       <td bgcolor=\"336699\"><font face=\"Arial,helvitica\" size=\"-1\" color=\"FFFFFF\"><xsl:value-of select=\"name\"/></font></td>\n"
                        "       </tr>\n"
                        "       <tr>\n"
                        "       <td bgcolor=\"336699\"><font face=\"Arial,helvitica\" size=\"-1\" color=\"FFFFFF\">Datum</font></td>\n"
                        "       <td bgcolor=\"336699\"><font face=\"Arial,helvitica\" size=\"-1\" color=\"FFFFFF\"><xsl:value-of select=\"date\"/></font></td>\n"
                        "       </tr>\n"
                        "       <tr>\n"
                        "       <td bgcolor=\"336699\"><font face=\"Arial,helvitica\" size=\"-1\" color=\"FFFFFF\">Text</font></td>\n"
                        "       <td bgcolor=\"336699\"><font face=\"Arial,helvitica\" size=\"-1\" color=\"FFFFFF\"><xsl:value-of select=\"text\"/></font></td>\n"
                        "       </tr>\n"
                        "       <tr >\n"
                        "       <td colspan=\"2\"><hr height=\"1\"/></td>\n"
                        "       </tr>\n"
                        "       \n"
                        "</xsl:template>\n"
                        "</xsl:stylesheet>\n");

                XMLTree xmlTree(xmlString);
                XSLTrans xslTrans(xslString);

                std::auto_ptr<XMLTree> resultTree = xslTrans.transToXMLTree(xmlTree.getDocPtr());

                CPPUNIT_ASSERT(resultTree.get()->getValue("/html/head/title") == "Gaestebuch");
                CPPUNIT_ASSERT(resultTree.get()->getValue("/html/body/h1") == "Mein Gaestebuch");
                CPPUNIT_ASSERT(resultTree.get()->getCount("/html/body/center/table") == 1);
        }
};


// TestXMLTree
//
class TestXMLTree : public CppUnit::TestCase
{
public:
        TestXMLTree()
                :tree_(NULL)
        {
                // test XMLTree's following functions:
                // getString
                // getBool (XSLT-functions: boolean, false, true, not)
                // getFloat
                // getNodeSet
                // getXML
                // getTree
                xmlTree_ = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
                        "<test>\n"
                        "       <string>StringValue</string>\n"
                        "       <string>\n"
                        "               Also a string value\n"
                        "       </string>\n"
                        "       <boolean>1</boolean>\n"
                        "       <boolean>0</boolean>\n"
                        "       <boolean>-1</boolean>\n"
                        "       <float>3.5</float>\n"
                        "       <float>1.6</float>\n"
                        "       <float>-123.2</float>\n"
                        "</test>";
                tree_ = new XMLTree( xmlTree_.c_str() );
        }

        ~TestXMLTree()
        {
                delete tree_;
        }
        void testRun()
        {
                CPPUNIT_ASSERT( tree_ );

                testGetString();
                testGetBool();
                testGetFloat();
                testGetNodeSet();
                testGetXML();
                testGetTree();
        }

        void testGetString()
        {
                // test getString
                // string( xpath ) returns content of first xpath-node
                // string( invalid_xpath ) returns ""
                CPPUNIT_ASSERT( tree_->getString( "string( /test/string )" ) == "StringValue" );
                CPPUNIT_ASSERT( tree_->getString( "string( /test/string[position() = 2] )" ) == "\n\t\tAlso a string value\n\t" );
                CPPUNIT_ASSERT( tree_->getString( "string( /test/something )" ) == "" );
                try {
                        // xpath won't return a string
                        tree_->getString( "/test/string" );
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( GXML::XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLTREE_NO_STRING_FROM_PATH );
                }
                try {
                        // xpath won't return a string
                        tree_->getString( "/test/something" );
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLTREE_NO_STRING_FROM_PATH );
                }
        }

        void testGetBool()
        {
                // test getBool
                // 0 = false else true, "" = false else true
                CPPUNIT_ASSERT( tree_->getBool( "boolean( number( /test/boolean ) )" ) );
                CPPUNIT_ASSERT( ! tree_->getBool( "boolean( number( /test/boolean[position() = 2] ) )" ) );
                CPPUNIT_ASSERT( tree_->getBool( "boolean( number( /test/boolean[position() = 3] ) )" ) );
                CPPUNIT_ASSERT( tree_->getBool( "true()" ) );
                CPPUNIT_ASSERT( ! tree_->getBool( "false()" ) );
                CPPUNIT_ASSERT( tree_->getBool( "not( /test/something )" ) );
                CPPUNIT_ASSERT( ! tree_->getBool( "not( /test/string )" ) );
                CPPUNIT_ASSERT( tree_->getBool( "boolean( /test/string )" ) );
                CPPUNIT_ASSERT( ! tree_->getBool( "boolean( /test/something )" ) );
                CPPUNIT_ASSERT( tree_->getBool( "boolean( 'anything' )" ) );
                CPPUNIT_ASSERT( ! tree_->getBool( "boolean( '' )" ) );
                try {
                        // xpath won't return a boolean
                        tree_->getBool( "/test/string" );
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLTREE_NO_BOOL_FROM_PATH );
                }
        }

        void testGetFloat()
        {
                // test getFloat
                CPPUNIT_ASSERT_DOUBLES_EQUAL( double(-118.1), tree_->getFloat( "sum( /test/float )" ), 1E-10 );
                CPPUNIT_ASSERT_DOUBLES_EQUAL( double(-123.2), tree_->getFloat( "number( /test/float[position() = 3 ])" ), 1E-10 );
                CPPUNIT_ASSERT( tree_->getFloat( "count( /test/boolean )" ) == 3 );
                try {
                        // xpath won't return a number
                        tree_->getFloat( "/test/string" );
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLTREE_NO_FLOAT_FROM_PATH );
                }
        }

        void testGetNodeSet()
        {
                std::auto_ptr<XMLNodeSet> set = tree_->getNodeSet( "/test/*" );
                CPPUNIT_ASSERT( set->size() == 8 );
                try {
                        // xpath will return an empty set
                        std::auto_ptr<XMLNodeSet> set = tree_->getNodeSet( "/something" );
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLNODESET_NO_MATCH );
                }
                try {
                        // xpath won't return a set
                        std::auto_ptr<XMLNodeSet> set = tree_->getNodeSet( "true()" );
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLNODESET_NO_SET );
                }
        }

        void testGetXML()
        {
                CPPUNIT_ASSERT( xmlTree_+"\n" == tree_->getXML( "/" ) );
        }
        void testGetTree()
        {
                CPPUNIT_ASSERT( tree_->getXML() == tree_->getTree()->getXML() );
        }
private:
        std::string xmlTree_;
        XMLTree *tree_;
};


// TestXMLNode
//
class TestXMLNode : public CppUnit::TestCase
{
public:
        TestXMLNode()
        {
                // test XMLNode's following functions:
                // getNext
                // getPrev
                // getParent
                // getLast
                // getChild
                // getName
                // getContent
                // getAttribute( name )
                xmlTree_ = "<?xml version=\"1.0\"?>\n"
                        "<test><node>node1</node><node name=\"node2\">node2<child>child of node 2</child></node><node>last node</node></test>";
                tree_ = new XMLTree( xmlTree_.c_str() );
        }
        void testRun()
        {
                XMLNode node1 = XMLNode();
                XMLNode node2 = XMLNode();
                XMLNode node3 = XMLNode();
                std::auto_ptr<XMLNodeSet> set = tree_->getNodeSet( "/test/node" );
                for ( XMLNodeSet::Iterator iter = set->begin(); iter != set->end(); ++iter )
                {
                        switch ( iter.getPosition() )
                        {
                        case 0: node1 = *iter;
                                break;
                        case 1: node2 = *iter;
                                break;
                        case 2: node3 = *iter;
                                break;
                        default: CPPUNIT_ASSERT( false ); //should never get here.
                        }
                }

                CPPUNIT_ASSERT( node1.getName() == "node" );
                CPPUNIT_ASSERT( node1.getContent() == "node1" );
                CPPUNIT_ASSERT( node1.getNext().getContent() == node2.getContent() );
                //      CPPUNIT_ASSERT( node1.getLast().getContent() == node3.getContent() );

                CPPUNIT_ASSERT( node2.getContent() == "node2" );
                CPPUNIT_ASSERT( node2.getNext().getContent() == node3.getContent() );
                CPPUNIT_ASSERT( node2.getAttribute( "name" ) == "node2" );
                // first child of node2 is its content text-node, therefore take child->next
                CPPUNIT_ASSERT( node2.getChild().getNext().getContent() == "child of node 2" );

                CPPUNIT_ASSERT( node3.getPrev().getContent() == node2.getContent() );
                CPPUNIT_ASSERT( node3.getParent().getName() == node2.getParent().getName() );
                CPPUNIT_ASSERT( node3.getParent().getChild().getContent() == node1.getContent() );
                CPPUNIT_ASSERT( node3.getParent().getLast().getContent() == node3.getContent() );

                // first child of node with content is a text-node
                CPPUNIT_ASSERT( node3.getChild().getName() == "text" );

                // test for exceptions
                try {
                        node3 = node3.getNext();
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLNODE_LAST_NODE );
                }
                try {
                        node1 = node1.getPrev();
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLNODE_FIRST_NODE );
                }
                try {
                        // parent of parent is document node, which has no parent
                        node1 = node1.getParent().getParent().getParent();
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLNODE_NO_PARENT );
                }
                try {
                        node1 = node1.getPrev();
                        CPPUNIT_ASSERT( ! "Exception expected!!!" );
                } catch ( XMLException & e ) {
                        CPPUNIT_ASSERT( e.getException() == XMLException::XMLNODE_FIRST_NODE );
                }
        }

private:
        std::string xmlTree_;
        XMLTree *tree_;
};


// XMLNodeSet Test
//
class TestXMLNodeSet : public CppUnit::TestCase
{
public:
        TestXMLNodeSet()
        {};
        void testRun()
        {}
};

// Master Class for all tests
//
class UnitTests: public CppUnit::TestSuite
{
public:
        UnitTests()
        {
                addTest(new CppUnit::TestCaller<TestXMLTreeOld>("Testing XMLTree (old)", &TestXMLTreeOld::testRun));
                addTest(new CppUnit::TestCaller<TestXMLTree>   ("Testing XMLTree",       &TestXMLTree::testRun));
                addTest(new CppUnit::TestCaller<TestXSLTrans>  ("Testing XSLTrans",      &TestXSLTrans::testRun));
                addTest(new CppUnit::TestCaller<TestXMLNode>   ("Testing XMLNode",       &TestXMLNode::testRun));
                addTest(new CppUnit::TestCaller<TestXMLNodeSet>("Testing XMLNodeSet",    &TestXMLNodeSet::testRun));
        }
};

}}

// create binary that tests the XML* stuff
int
main(int argc, char **argv)
{
        CppUnit::TextTestRunner runner;
        // This must be an object, and must be created with new, as it is deleted by runner (this is braindead, but well).
        SP::GXML::UnitTests * unitTests = new SP::GXML::UnitTests();
        runner.addTest(unitTests);
        if (runner.run())
                return(0);
        else
                return(1);
}

Generated on Thu Jun 3 19:20:12 2004 for sp-gxmlcpp by doxygen1.2.15