#ifndef UT_MISC_STREAM #define UT_MISC_STREAM #include #include // The following line is known to crash in a Ryzom service CBitMemStream globalBms( false, 2048 ); // global to avoid reallocation // Test suite for stream based classes // ! not complete at all at time of writing ! class CUTMiscStream: public Test::Suite { public: CUTMiscStream () { TEST_ADD(CUTMiscStream::constAndStream); TEST_ADD(CUTMiscStream::memStreamSwap); TEST_ADD(CUTMiscStream::copyOnWrite); TEST_ADD(CUTMiscStream::preallocatedBitStream); } void preallocatedBitStream() { CBitMemStream localBms( false, 2048 ); // global to avoid reallocation } void copyOnWrite() { // test the copy on write strategy in the mem stream (and derived) class. // The point is to be able to copy a mem stream (e.g a CMessage) // but to do not copy the stream buffer. // If more than one stream use the same buffer, any attempt to // modifye the buffer content while lead to a buffer duplication CMemStream s1; CMemStream s2; CMemStream s3; uint32 i = 1; s1.serial(i); s2 = s1; s3 = s2; TEST_ASSERT(s1.buffer() == s2.buffer()); TEST_ASSERT(s1.buffer() == s3.buffer()); // change s1 s1.serial(i); TEST_ASSERT(s1.buffer() != s2.buffer()); TEST_ASSERT(s2.buffer() == s3.buffer()); s2.invert(); s3 = s2; TEST_ASSERT(s2.buffer() == s3.buffer()); s2.serial(i); TEST_ASSERT(s2.buffer() == s3.buffer()); } enum TEnum { e_a, e_b, e_c, e_d }; void constAndStream() { // check that we can serialize with const stream or const object CMemStream s1; NLMISC::IStream &is1 = s1; const string str("toto"); const uint32 i(1234546); const TEnum e(e_a); string str2("titi"); uint32 i2(123456); TEnum e2(e_b); // no need for const cast any more nlWriteSerial(s1, str); nlWriteSerial(s1, i); nlWrite(s1, serialEnum, e); nlWriteSerial(is1, str); nlWriteSerial(is1, i); nlWrite(is1, serialEnum, i); // this work as well s1.serial(str2); s1.serial(i2); s1.serialEnum(e2); is1.serial(str2); is1.serial(i2); is1.serialEnum(e2); const CMemStream &s2 = s1; const NLMISC::IStream &is2 = s2; string str3; uint32 i3; TEnum e3(e_c); // cant write in a const stream TEST_THROWS(nlReadSerial(s2, str3), NLMISC::ENotInputStream); TEST_THROWS(nlReadSerial(s2, i3), NLMISC::ENotInputStream); TEST_THROWS(nlRead(s2, serialEnum, e3), NLMISC::ENotInputStream); TEST_THROWS(nlReadSerial(is2, str3), NLMISC::ENotInputStream); TEST_THROWS(nlReadSerial(is2, i3), NLMISC::ENotInputStream); TEST_THROWS(nlRead(is2, serialEnum, e3), NLMISC::ENotInputStream); s1.invert(); nlReadSerial(s2, str3); nlReadSerial(s2, i3); nlRead(s2, serialEnum, e3); nlReadSerial(is2, str3); nlReadSerial(is2, i3); nlRead(is2, serialEnum, e3); // cant read a const value TEST_THROWS(nlWriteSerial(s1, str), NLMISC::ENotOutputStream); TEST_THROWS(nlWriteSerial(s1, i), NLMISC::ENotOutputStream); TEST_THROWS(nlWrite(s1, serialEnum, e), NLMISC::ENotOutputStream); TEST_THROWS(nlWriteSerial(is1, str), NLMISC::ENotOutputStream); TEST_THROWS(nlWriteSerial(is1, i), NLMISC::ENotOutputStream); TEST_THROWS(nlWrite(is1, serialEnum, e), NLMISC::ENotOutputStream); } void memStreamSwap() { CMemStream ms2; string s; { CMemStream ms1; s = "foo1"; ms1.serial(s); s = "foo2"; ms1.serial(s); s = ""; ms2.swap(ms1); // check that ms1 is empty now TEST_ASSERT(ms1.length() == 0); } TEST_ASSERT(!ms2.isReading()); ms2.invert(); ms2.serial(s); TEST_ASSERT(s == "foo1"); ms2.serial(s); TEST_ASSERT(s == "foo2"); } }; #endif