/*! @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>
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>1</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>1</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>1</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>1</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>1</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 ( ) try {
CppUnit : : TextUi : : TestRunner runner ;
runner . addTest ( CppUnit : : TestFactoryRegistry : : getRegistry ( ) . makeTest ( ) ) ;
return runner . run ( ) ? 0 : 1 ;
} catch ( std : : exception & e ) {
std : : cerr < < " ***Exception: " < < e . what ( ) < < std : : endl ;
return 1 ;
}