2009-04-23 15:10:21 +00:00
|
|
|
/*! @file
|
|
|
|
|
|
|
|
@id $Id$
|
|
|
|
*/
|
|
|
|
// 1 2 3 4 5 6 7 8
|
|
|
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
|
|
|
|
#include <xml-cxx/xml.hxx>
|
|
|
|
#include <cppunit/TestFixture.h>
|
|
|
|
#include <cppunit/ui/text/TestRunner.h>
|
|
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
#include <cppunit/extensions/TestFactoryRegistry.h>
|
2009-05-04 14:56:01 +00:00
|
|
|
#include <cppunit/XmlOutputter.h>
|
|
|
|
#include <fstream>
|
2009-04-23 15:10:21 +00:00
|
|
|
|
2009-04-24 07:13:10 +00:00
|
|
|
class A: public xml::Serialize {
|
2009-04-23 15:10:21 +00:00
|
|
|
public:
|
|
|
|
int _anInteger;
|
|
|
|
bool _aBool;
|
|
|
|
double _aDouble;
|
|
|
|
std::string _aString;
|
|
|
|
std::string _anotherString;
|
|
|
|
unsigned long _aLong;
|
|
|
|
protected:
|
|
|
|
void initXmlMembers() {
|
|
|
|
className("A");
|
|
|
|
persist(_anInteger, "anInteger");
|
|
|
|
persist(_aBool, "aBool");
|
|
|
|
persist(_aDouble, "aDouble");
|
|
|
|
persist(_aString, "aString");
|
|
|
|
persist(_anotherString, "anotherString");
|
|
|
|
persist(_aLong, "aLong");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-04-27 10:48:27 +00:00
|
|
|
class B: public xml::Serialize {
|
|
|
|
public:
|
|
|
|
long aLong;
|
|
|
|
char aChar;
|
|
|
|
protected:
|
|
|
|
void initXmlMembers() {
|
|
|
|
className("B");
|
|
|
|
persist(aLong, "aLong");
|
|
|
|
persist(aChar, "aChar");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class B2: public B {
|
|
|
|
public:
|
|
|
|
float aFloat;
|
|
|
|
short aShort;
|
|
|
|
protected:
|
|
|
|
void initXmlMembers() {
|
|
|
|
B::initXmlMembers();
|
|
|
|
className("B2");
|
|
|
|
persist(aFloat, "float");
|
|
|
|
persist(aShort, "short");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Complex Example: Class A2 is a class that inherits another class
|
|
|
|
// (A) and contains a class (B2) that inherits another class (B)
|
|
|
|
class A2: public A {
|
|
|
|
public:
|
|
|
|
std::string aText;
|
|
|
|
B2 childOfB;
|
|
|
|
protected:
|
|
|
|
void initXmlMembers() {
|
|
|
|
A::initXmlMembers();
|
|
|
|
className("A2");
|
|
|
|
persist(aText, "aText");
|
|
|
|
persist(childOfB, "childOfB");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class C: public xml::Serialize {
|
|
|
|
public:
|
|
|
|
A2 a2;
|
|
|
|
B2 b2;
|
|
|
|
protected:
|
|
|
|
void initXmlMembers() {
|
|
|
|
className("C")
|
|
|
|
.persist(a2, "a2")
|
|
|
|
.persist(b2, "b2");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-04-23 15:10:21 +00:00
|
|
|
class SerializationTest: public CppUnit::TestFixture {
|
|
|
|
public:
|
|
|
|
std::string _file;
|
|
|
|
A _a;
|
|
|
|
void setUp() {
|
|
|
|
_a._anInteger = 15;
|
|
|
|
_a._aBool = true;
|
|
|
|
_a._aDouble = 123.456;
|
|
|
|
_a._aString = "Hello World";
|
|
|
|
_a._anotherString = "This is another Text";
|
2009-04-24 07:13:10 +00:00
|
|
|
_a._aLong = 4123674622ul;
|
2009-04-23 15:10:21 +00:00
|
|
|
try {
|
|
|
|
std::stringstream ss;
|
|
|
|
_a.saveXml(ss);
|
|
|
|
_file = ss.str();
|
|
|
|
} catch (...) {}
|
|
|
|
}
|
|
|
|
void memberDeclaration() {
|
|
|
|
// This is more a compile time test than a runtime test.
|
|
|
|
A a;
|
|
|
|
a._anInteger = 15;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(15, a._anInteger);
|
|
|
|
a._aString = "Hello World";
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("Hello World"), a._aString);
|
|
|
|
std::stringstream ss;
|
|
|
|
}
|
|
|
|
void store() {
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
CPPUNIT_ASSERT_NO_THROW(_a.saveXml(ss));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("<A>\n"
|
|
|
|
"\t<anInteger>15</anInteger>\n"
|
2009-04-28 07:36:07 +00:00
|
|
|
"\t<aBool>true</aBool>\n"
|
2009-04-23 15:10:21 +00:00
|
|
|
"\t<aDouble>123.456</aDouble>\n"
|
|
|
|
"\t<aString>Hello World</aString>\n"
|
|
|
|
"\t<anotherString>This is"
|
|
|
|
" another Text</anotherString>\n"
|
|
|
|
"\t<aLong>4123674622</aLong>\n"
|
|
|
|
"</A>"),
|
|
|
|
ss.str());
|
|
|
|
} { // again - initialisation of A should be done only once
|
|
|
|
std::stringstream ss;
|
|
|
|
CPPUNIT_ASSERT_NO_THROW(_a.saveXml(ss));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(_file, ss.str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void restore() {
|
|
|
|
A a;
|
|
|
|
std::stringstream ss(_file);
|
|
|
|
CPPUNIT_ASSERT(_file.size()>0);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(_file, ss.str());
|
|
|
|
CPPUNIT_ASSERT_NO_THROW(a.loadXml(ss));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(15, a._anInteger);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(true, a._aBool);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(123.456, a._aDouble);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("Hello World"), a._aString);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("This is another Text"),
|
|
|
|
a._anotherString);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(4123674622ul, a._aLong);
|
|
|
|
}
|
2009-04-27 10:48:27 +00:00
|
|
|
void complexLoad() {
|
|
|
|
std::stringstream ss("<A2>\n"
|
|
|
|
" <anInteger>-1234</anInteger>\n"
|
2009-04-28 07:36:07 +00:00
|
|
|
" <aBool>true</aBool>\n"
|
2009-04-27 10:48:27 +00:00
|
|
|
" <aDouble>3.141</aDouble>\n"
|
|
|
|
" <aString>This is A inside of A2</aString>\n"
|
|
|
|
" <anotherString>Another A-String</anotherString>\n"
|
|
|
|
" <aLong>1234567890</aLong>\n"
|
|
|
|
" <aText>Text from A2</aText>\n"
|
|
|
|
" <childOfB>\n"
|
|
|
|
" <aLong>987654321</aLong>\n"
|
|
|
|
" <aChar>Q</aChar>\n"
|
|
|
|
" <float>2.5</float>\n"
|
|
|
|
" <short>-127</short>\n"
|
|
|
|
" </childOfB>\n"
|
|
|
|
"</A2>");
|
|
|
|
A2 a2;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("<A2>\n"
|
|
|
|
"\t<anInteger/>\n"
|
|
|
|
"\t<aBool/>\n"
|
|
|
|
"\t<aDouble/>\n"
|
|
|
|
"\t<aString/>\n"
|
|
|
|
"\t<anotherString/>\n"
|
|
|
|
"\t<aLong/>\n"
|
|
|
|
"\t<aText/>\n"
|
|
|
|
"\t<childOfB>\n"
|
|
|
|
"\t\t<aLong/>\n"
|
|
|
|
"\t\t<aChar/>\n"
|
|
|
|
"\t\t<float/>\n"
|
|
|
|
"\t\t<short/>\n"
|
|
|
|
"\t</childOfB>\n"
|
|
|
|
"</A2>"), a2.schema());
|
|
|
|
CPPUNIT_ASSERT_NO_THROW(a2.loadXml(ss));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(-1234, a2._anInteger);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(true, a2._aBool);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(3.141, a2._aDouble);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("This is A inside of A2"), a2._aString);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("Another A-String"), a2._anotherString);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1234567890ul, a2._aLong);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("Text from A2"), a2.aText);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(987654321l, a2.childOfB.aLong);
|
|
|
|
CPPUNIT_ASSERT_EQUAL('Q', a2.childOfB.aChar);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(2.5f, a2.childOfB.aFloat);
|
|
|
|
CPPUNIT_ASSERT_EQUAL((short)-127, a2.childOfB.aShort);
|
|
|
|
}
|
|
|
|
void complexSave() {
|
|
|
|
A2 a2;
|
|
|
|
a2._anInteger = -1234;
|
|
|
|
a2._aBool = true;
|
|
|
|
a2._aDouble = 3.141;
|
|
|
|
a2._aString = std::string("This is A inside of A2");
|
|
|
|
a2._anotherString = std::string("Another A-String");
|
|
|
|
a2._aLong = 1234567890ul;
|
|
|
|
a2.aText = std::string("Text from A2");
|
|
|
|
a2.childOfB.aLong = 987654321l;
|
|
|
|
a2.childOfB.aChar = 'Q';
|
|
|
|
a2.childOfB.aFloat = 2.5f;
|
|
|
|
a2.childOfB.aShort = (short)-127;
|
|
|
|
std::stringstream ss;
|
|
|
|
a2.saveXml(ss);
|
|
|
|
CPPUNIT_ASSERT_EQUAL
|
|
|
|
(std::string("<A2>\n"
|
|
|
|
"\t<anInteger>-1234</anInteger>\n"
|
2009-04-28 07:36:07 +00:00
|
|
|
"\t<aBool>true</aBool>\n"
|
2009-04-27 10:48:27 +00:00
|
|
|
"\t<aDouble>3.141</aDouble>\n"
|
|
|
|
"\t<aString>This is A inside of A2</aString>\n"
|
|
|
|
"\t<anotherString>Another A-String</anotherString>\n"
|
|
|
|
"\t<aLong>1234567890</aLong>\n"
|
|
|
|
"\t<aText>Text from A2</aText>\n"
|
|
|
|
"\t<childOfB>\n"
|
|
|
|
"\t\t<aLong>987654321</aLong>\n"
|
|
|
|
"\t\t<aChar>Q</aChar>\n"
|
|
|
|
"\t\t<float>2.5</float>\n"
|
|
|
|
"\t\t<short>-127</short>\n"
|
|
|
|
"\t</childOfB>\n"
|
|
|
|
"</A2>"), ss.str());
|
|
|
|
}
|
|
|
|
void moreComplexLoad() {
|
|
|
|
std::stringstream ss
|
|
|
|
("<C>\n"
|
|
|
|
" <a2>\n"
|
|
|
|
" <anInteger>-1234</anInteger>\n"
|
2009-04-28 07:36:07 +00:00
|
|
|
" <aBool>true</aBool>\n"
|
2009-04-27 10:48:27 +00:00
|
|
|
" <aDouble>3.141</aDouble>\n"
|
|
|
|
" <aString>This is A inside of A2</aString>\n"
|
|
|
|
" <anotherString>Another A-String</anotherString>\n"
|
|
|
|
" <aLong>1234567890</aLong>\n"
|
|
|
|
" <aText>Text from A2</aText>\n"
|
|
|
|
" <childOfB>\n"
|
|
|
|
" <aLong>987654321</aLong>\n"
|
|
|
|
" <aChar>Q</aChar>\n"
|
|
|
|
" <float>2.5</float>\n"
|
|
|
|
" <short>-127</short>\n"
|
|
|
|
" </childOfB>\n"
|
|
|
|
" </a2>\n"
|
|
|
|
" <b2>\n"
|
|
|
|
" <aLong>212121</aLong>\n"
|
|
|
|
" <aChar>W</aChar>\n"
|
|
|
|
" <float>2.25</float>\n"
|
|
|
|
" <short>124</short>\n"
|
|
|
|
" </b2>\n"
|
|
|
|
"</C>");
|
|
|
|
C c;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("<C>\n"
|
|
|
|
"\t<a2>\n"
|
|
|
|
"\t\t<anInteger/>\n"
|
|
|
|
"\t\t<aBool/>\n"
|
|
|
|
"\t\t<aDouble/>\n"
|
|
|
|
"\t\t<aString/>\n"
|
|
|
|
"\t\t<anotherString/>\n"
|
|
|
|
"\t\t<aLong/>\n"
|
|
|
|
"\t\t<aText/>\n"
|
|
|
|
"\t\t<childOfB>\n"
|
|
|
|
"\t\t\t<aLong/>\n"
|
|
|
|
"\t\t\t<aChar/>\n"
|
|
|
|
"\t\t\t<float/>\n"
|
|
|
|
"\t\t\t<short/>\n"
|
|
|
|
"\t\t</childOfB>\n"
|
|
|
|
"\t</a2>\n"
|
|
|
|
"\t<b2>\n"
|
|
|
|
"\t\t<aLong/>\n"
|
|
|
|
"\t\t<aChar/>\n"
|
|
|
|
"\t\t<float/>\n"
|
|
|
|
"\t\t<short/>\n"
|
|
|
|
"\t</b2>\n"
|
|
|
|
"</C>"), c.schema());
|
|
|
|
CPPUNIT_ASSERT_NO_THROW(c.loadXml(ss));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(-1234, c.a2._anInteger);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(true, c.a2._aBool);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(3.141, c.a2._aDouble);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("This is A inside of A2"),
|
|
|
|
c.a2._aString);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("Another A-String"),
|
|
|
|
c.a2._anotherString);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1234567890ul, c.a2._aLong);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(std::string("Text from A2"), c.a2.aText);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(987654321l, c.a2.childOfB.aLong);
|
|
|
|
CPPUNIT_ASSERT_EQUAL('Q', c.a2.childOfB.aChar);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(2.5f, c.a2.childOfB.aFloat);
|
|
|
|
CPPUNIT_ASSERT_EQUAL((short)-127, c.a2.childOfB.aShort);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(212121l, c.b2.aLong);
|
|
|
|
CPPUNIT_ASSERT_EQUAL('W', c.b2.aChar);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(2.25f, c.b2.aFloat);
|
|
|
|
CPPUNIT_ASSERT_EQUAL((short)124, c.b2.aShort);
|
|
|
|
}
|
|
|
|
void moreComplexSave() {
|
|
|
|
C c;
|
|
|
|
c.a2._anInteger = -1234;
|
|
|
|
c.a2._aBool = true;
|
|
|
|
c.a2._aDouble = 3.141;
|
|
|
|
c.a2._aString = std::string("This is A inside of A2");
|
|
|
|
c.a2._anotherString = std::string("Another A-String");
|
|
|
|
c.a2._aLong = 1234567890ul;
|
|
|
|
c.a2.aText = std::string("Text from A2");
|
|
|
|
c.a2.childOfB.aLong = 987654321l;
|
|
|
|
c.a2.childOfB.aChar = 'Q';
|
|
|
|
c.a2.childOfB.aFloat = 2.5f;
|
|
|
|
c.a2.childOfB.aShort = (short)-127;
|
|
|
|
c.b2.aLong = 212121l;
|
|
|
|
c.b2.aChar = 'W';
|
|
|
|
c.b2.aFloat = 2.25f;
|
|
|
|
c.b2.aShort = (short)124;
|
|
|
|
std::stringstream ss;
|
|
|
|
c.saveXml(ss);
|
|
|
|
CPPUNIT_ASSERT_EQUAL
|
|
|
|
(std::string("<C>\n"
|
|
|
|
"\t<a2>\n"
|
|
|
|
"\t\t<anInteger>-1234</anInteger>\n"
|
2009-04-28 07:36:07 +00:00
|
|
|
"\t\t<aBool>true</aBool>\n"
|
2009-04-27 10:48:27 +00:00
|
|
|
"\t\t<aDouble>3.141</aDouble>\n"
|
|
|
|
"\t\t<aString>This is A inside of A2</aString>\n"
|
|
|
|
"\t\t<anotherString>Another A-String</anotherString>\n"
|
|
|
|
"\t\t<aLong>1234567890</aLong>\n"
|
|
|
|
"\t\t<aText>Text from A2</aText>\n"
|
|
|
|
"\t\t<childOfB>\n"
|
|
|
|
"\t\t\t<aLong>987654321</aLong>\n"
|
|
|
|
"\t\t\t<aChar>Q</aChar>\n"
|
|
|
|
"\t\t\t<float>2.5</float>\n"
|
|
|
|
"\t\t\t<short>-127</short>\n"
|
|
|
|
"\t\t</childOfB>\n"
|
|
|
|
"\t</a2>\n"
|
|
|
|
"\t<b2>\n"
|
|
|
|
"\t\t<aLong>212121</aLong>\n"
|
|
|
|
"\t\t<aChar>W</aChar>\n"
|
|
|
|
"\t\t<float>2.25</float>\n"
|
|
|
|
"\t\t<short>124</short>\n"
|
|
|
|
"\t</b2>\n"
|
|
|
|
"</C>"), ss.str());
|
|
|
|
}
|
2009-04-23 15:10:21 +00:00
|
|
|
CPPUNIT_TEST_SUITE(SerializationTest);
|
|
|
|
CPPUNIT_TEST(memberDeclaration);
|
|
|
|
CPPUNIT_TEST(store);
|
|
|
|
CPPUNIT_TEST(restore);
|
2009-04-27 10:48:27 +00:00
|
|
|
CPPUNIT_TEST(complexLoad);
|
|
|
|
CPPUNIT_TEST(complexSave);
|
|
|
|
CPPUNIT_TEST(moreComplexLoad);
|
|
|
|
CPPUNIT_TEST(moreComplexSave);
|
2009-04-23 15:10:21 +00:00
|
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
};
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(SerializationTest);
|
|
|
|
|
2009-05-04 14:56:01 +00:00
|
|
|
int main(int argc, char** argv) try {
|
|
|
|
std::ofstream ofs((*argv+std::string(".xml")).c_str());
|
2009-04-23 15:10:21 +00:00
|
|
|
CppUnit::TextUi::TestRunner runner;
|
2009-05-04 14:56:01 +00:00
|
|
|
runner.setOutputter(new CppUnit::XmlOutputter(&runner.result(), ofs));
|
2009-04-23 15:10:21 +00:00
|
|
|
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
|
|
|
|
return runner.run() ? 0 : 1;
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
std::cerr<<"***Exception: "<<e.what()<<std::endl;
|
|
|
|
return 1;
|
|
|
|
}
|