/*! @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> #include <cppunit/XmlOutputter.h> #include <fstream> class A: public xml::Serialize { 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"); } }; 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"); } }; 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"; _a._aLong = 4123674622ul; 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" "\t<aBool>true</aBool>\n" "\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); } void complexLoad() { std::stringstream ss("<A2>\n" " <anInteger>-1234</anInteger>\n" " <aBool>true</aBool>\n" " <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" "\t<aBool>true</aBool>\n" "\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" " <aBool>true</aBool>\n" " <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" "\t\t<aBool>true</aBool>\n" "\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()); } CPPUNIT_TEST_SUITE(SerializationTest); CPPUNIT_TEST(memberDeclaration); CPPUNIT_TEST(store); CPPUNIT_TEST(restore); CPPUNIT_TEST(complexLoad); CPPUNIT_TEST(complexSave); CPPUNIT_TEST(moreComplexLoad); CPPUNIT_TEST(moreComplexSave); CPPUNIT_TEST_SUITE_END(); }; CPPUNIT_TEST_SUITE_REGISTRATION(SerializationTest); int main(int argc, char** argv) try { std::ofstream ofs((*argv+std::string(".xml")).c_str()); CppUnit::TextUi::TestRunner runner; runner.setOutputter(new CppUnit::XmlOutputter(&runner.result(), ofs)); runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); return runner.run() ? 0 : 1; } catch (std::exception& e) { std::cerr<<"***Exception: "<<e.what()<<std::endl; return 1; }