blob: 6552749506f5c0e6a8d3cf0b1440bb3bae835617 [file] [log] [blame]
// Copyright (C) 2002-2003 Chad C. Yates cyates@uidaho.edu
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Common C++.
//
// The exception is that, if you link the Common C++ library with other
// files to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
//
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
//
// This exception applies only to the code released under the
// name Common C++. If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way. To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
#include "Test_Engine.h"
#include <cstdio>
CPPUNIT_TEST_SUITE_REGISTRATION(EngineTest);
void EngineTest::setUp()
{
// Create an example object with some sub objects and various data elements
complexObject.iInteger = 5;
complexObject.strString = "String 1";
complexObject.strString2 = "String 2";
complexObject.uninitializedNullPtr = NULL; // initialized here instead of constructor to see if it will be unpersisted as a null (vs defaulting to null from the constructor)
for(int i = 0; i < 10; i++)
complexObject.numbers.push_back(i);
complexObject.strings.push_back("a");
complexObject.strings.push_back("b");
complexObject.strings.push_back("c");
complexObject.strings.push_back("d");
complexObject.strings.push_back("e");
complexObject.moreStrings.push_back("z");
complexObject.moreStrings.push_back("y");
complexObject.moreStrings.push_back("x");
complexObject.moreStrings.push_back("w");
complexObject.moreStrings.push_back("v");
complexObject.subObjectPtr = new TestSub;
complexObject.subObjectPtr2 = complexObject.subObjectPtr; // set to point to the same thing as subObjectPtr to test unpersisting of shared instances
complexObject.subObjectPtr->iInteger = 5;
complexObject.subObjectPtr->strString = "SubStringPtr 1";
complexObject.subObjectPtr->strString2 = "SubStringPtr 2";
for(int j = 10; j < 20; j++)
complexObject.subObjectPtr->numbers.push_back(j);
complexObject.subObjectRef.iInteger = 5;
complexObject.subObjectRef.strString = "SubString2 1";
complexObject.subObjectRef.strString2 = "SubString2 2";
for(int k = 30; k < 35; k++)
complexObject.subObjectRef.numbers.push_back(k);
// make a std::deque of TestSub objects
for(int l = 0; l < 2; l++) {
TestSub newSubObject;
newSubObject.iInteger = l;
char tmp[50];
sprintf(tmp, "test %d", l+1);
newSubObject.strString = tmp;
for(int k = 30; k < 35; k++)
newSubObject.numbers.push_back(k);
complexObject.subObjects.push_back(newSubObject);
}
}
void EngineTest::tearDown()
{}
void EngineTest::testPrimitives()
{
// write primitive types
std::fstream outputArchive("EnginePrimitiveTest.dat", std::ios::out|std::ios::binary);
Engine outputEngine(outputArchive, ost::Engine::modeWrite);
TEST_PRIMITIVE_OUTPUT(int8, 0x01);
TEST_PRIMITIVE_OUTPUT(uint8, 0x01);
TEST_PRIMITIVE_OUTPUT(int16, 0x0123);
TEST_PRIMITIVE_OUTPUT(uint16, 0x0123);
TEST_PRIMITIVE_OUTPUT(int32, 0x01234567);
TEST_PRIMITIVE_OUTPUT(uint32, 0x01234567);
//TEST_PRIMITIVE_OUTPUT(int64, 0x0123456789ABCDEF); // warning: integer constant larger than the maximum value of an unsigned long int
//TEST_PRIMITIVE_OUTPUT(uint64, 0x0123456789ABCDEF); // warning: integer constant larger than the maximum value of an unsigned long int
TEST_PRIMITIVE_OUTPUT(float, 3.141592653589793238462643f);
TEST_PRIMITIVE_OUTPUT(double, 3.141592653589793238462643);
TEST_PRIMITIVE_OUTPUT(string, "abcdefghijklmnopqrstuvwxyz0123456789");
outputEngine.sync(); // flush Engine buffers before closing file
outputArchive.close();
// read primitive types back in and check
std::fstream inputArchive("EnginePrimitiveTest.dat", std::ios::in|std::ios::binary);
Engine inputEngine(inputArchive, ost::Engine::modeRead);
TEST_PRIMITIVE_INPUT(int8);
TEST_PRIMITIVE_INPUT(uint8);
TEST_PRIMITIVE_INPUT(int16);
TEST_PRIMITIVE_INPUT(uint16);
TEST_PRIMITIVE_INPUT(int32);
TEST_PRIMITIVE_INPUT(uint32);
//TEST_PRIMITIVE_INPUT(int64);
//TEST_PRIMITIVE_INPUT(uint64);
TEST_PRIMITIVE_INPUT(float);
TEST_PRIMITIVE_INPUT(double);
TEST_PRIMITIVE_INPUT(string);
inputArchive.close();
}
void EngineTest::testRawBinary()
{
int i;
// write raw binary data
std::fstream outputArchive("EngineRawBinaryTest.dat", std::ios::out|std::ios::binary);
Engine outputEngine(outputArchive, ost::Engine::modeWrite);
unsigned int binaryBuffer[BINARY_BUFFER_SIZE];
for(i = 0; i < BINARY_BUFFER_SIZE; i++)
binaryBuffer[i] = i;
outputEngine.writeBinary((const uint8*) binaryBuffer, sizeof(binaryBuffer));
outputEngine.sync(); // flush Engine buffers before closing file
outputArchive.close();
// read binary data back in and check
std::fstream inputArchive("EngineRawBinaryTest.dat", std::ios::in|std::ios::binary);
Engine inputEngine(inputArchive, ost::Engine::modeRead);
unsigned int binaryBuffer2[BINARY_BUFFER_SIZE];
inputEngine.readBinary((uint8*) binaryBuffer2, sizeof(binaryBuffer2));
inputArchive.close();
for(i = 0; i < BINARY_BUFFER_SIZE; i++)
CPPUNIT_ASSERT(binaryBuffer[i] == binaryBuffer2[i]);
}
void EngineTest::testSTLVector()
{
int i;
// write STL data
std::fstream outputArchive("EngineSTLVectorTest.dat", std::ios::out|std::ios::binary);
Engine outputEngine(outputArchive, ost::Engine::modeWrite);
std::vector<int32> intVector;
std::vector<int32>* pIntVector = new std::vector<int32>;
for(i = 0; i < STL_CONTAINER_SIZE; i++) {
intVector.push_back(i);
pIntVector->push_back(i);
}
outputEngine << intVector;
outputEngine << *pIntVector;
outputEngine.sync(); // flush Engine buffers before closing file
outputArchive.close();
// read STL std::vector back in and check
std::fstream inputArchive("EngineSTLVectorTest.dat", std::ios::in|std::ios::binary);
Engine inputEngine(inputArchive, ost::Engine::modeRead);
std::vector<int32> intVector2;
inputEngine >> intVector2;
CPPUNIT_ASSERT(intVector == intVector2);
std::vector<int32>* pIntVector2 = new std::vector<int32>;
inputEngine >> *pIntVector2;
CPPUNIT_ASSERT(*pIntVector == *pIntVector2);
delete pIntVector2;
inputArchive.close();
delete pIntVector;
}
void EngineTest::testSTLDeque()
{
int i;
// write STL std::deque data
std::fstream outputArchive("EngineSTLDequeTest.dat", std::ios::out|std::ios::binary);
Engine outputEngine(outputArchive, ost::Engine::modeWrite);
std::deque<int32> intDeque;
std::deque<int32>* pIntDeque = new std::deque<int32>;
for(i = 0; i < STL_CONTAINER_SIZE; i++) {
intDeque.push_back(i);
pIntDeque->push_back(i);
}
outputEngine << intDeque;
outputEngine << *pIntDeque;
outputEngine.sync(); // flush Engine buffers before closing file
outputArchive.close();
// read STL std::deque back in and check
std::fstream inputArchive("EngineSTLDequeTest.dat", std::ios::in|std::ios::binary);
Engine inputEngine(inputArchive, ost::Engine::modeRead);
std::deque<int32> intDeque2;
inputEngine >> intDeque2;
CPPUNIT_ASSERT(intDeque == intDeque2);
std::deque<int32>* pIntDeque2 = new std::deque<int32>;
inputEngine >> *pIntDeque2;
CPPUNIT_ASSERT(*pIntDeque == *pIntDeque2);
delete pIntDeque2;
inputArchive.close();
delete pIntDeque;
}
void EngineTest::testSTLMap()
{
int i;
// write STL std::map data
std::fstream outputArchive("EngineSTLMapTest.dat", std::ios::out|std::ios::binary);
Engine outputEngine(outputArchive, ost::Engine::modeWrite);
std::map<int32, int32> intMap;
std::map<int32, int32>* pIntMap = new std::map<int32, int32>;
for(i = 0; i < STL_CONTAINER_SIZE; i++) {
intMap.insert(std::pair<int32, int32>(i, i+10));
pIntMap->insert(std::pair<int32, int32>(i, i+11));
}
outputEngine << intMap;
outputEngine << *pIntMap;
outputEngine.sync(); // flush Engine buffers before closing file
outputArchive.close();
// read STL std::map back in and check
std::fstream inputArchive("EngineSTLMapTest.dat", std::ios::in|std::ios::binary);
Engine inputEngine(inputArchive, ost::Engine::modeRead);
std::map<int32, int32> intMap2;
inputEngine >> intMap2;
CPPUNIT_ASSERT(intMap == intMap2);
std::map<int32, int32>* pIntMap2 = new std::map<int32, int32>;
inputEngine >> *pIntMap2;
CPPUNIT_ASSERT(*pIntMap == *pIntMap2);
delete pIntMap2;
inputArchive.close();
delete pIntMap;
}
void EngineTest::testComplexObject()
{
// write BaseObject hierarchy
std::fstream outputArchive("EngineComplexObjectTest.dat", std::ios::out|std::ios::binary);
Engine outputEngine(outputArchive, ost::Engine::modeWrite);
outputEngine << complexObject;
outputEngine.sync(); // flush Engine buffers before closing file
outputArchive.close();
// Unpersist a new object structure into an uninitialized object
{
Test* myObjPtr = NULL; // must initialize pointer or new persistence engine will think it is already allocated
std::fstream inputArchive("EngineComplexObjectTest.dat", std::ios::in);
Engine inputEngine(inputArchive, ost::Engine::modeRead);
inputEngine >> myObjPtr;
inputArchive.close();
CPPUNIT_ASSERT_MESSAGE("Unpersisted into unallocated pointer == Original", *myObjPtr == complexObject);
CPPUNIT_ASSERT_MESSAGE("nullPtr is NULL", myObjPtr->nullPtr == NULL);
CPPUNIT_ASSERT_MESSAGE("uninitializedNullPtr is NULL", myObjPtr->uninitializedNullPtr == NULL);
myObjPtr->subObjectPtr->strString2 = "Changed SubStringPtr 1";
CPPUNIT_ASSERT_MESSAGE("subObjectPtr.strString2 should always equal subObjectPtr2.strString2", myObjPtr->subObjectPtr->strString2 == myObjPtr->subObjectPtr2->strString2);
CPPUNIT_ASSERT_MESSAGE("subObjectPtr.strString2 should now equal 'Changed SubStringPtr 1'", myObjPtr->subObjectPtr->strString2 == "Changed SubStringPtr 1");
CPPUNIT_ASSERT_MESSAGE("subObjectPtr.strString2 should still equal subObjectPtr2.strString2", myObjPtr->subObjectPtr->strString2 == myObjPtr->subObjectPtr2->strString2);
}
// Unpersist a new object structure into an instantiated class variable
{
Test myObjInstance;
std::fstream inputArchive("EngineComplexObjectTest.dat", std::ios::in);
Engine inputEngine(inputArchive, ost::Engine::modeRead);
inputEngine >> myObjInstance;
inputArchive.close();
CPPUNIT_ASSERT_MESSAGE("Unpersisted into default constructed instance == Original", myObjInstance == complexObject);
CPPUNIT_ASSERT_MESSAGE("nullPtr is NULL", myObjInstance.nullPtr == NULL);
CPPUNIT_ASSERT_MESSAGE("UninitializedNullPtr is NULL", myObjInstance.uninitializedNullPtr == NULL);
}
// Unpersist a new object structure into a pre-initialized pointer to an object
{
Test* myObjAllocatedPtr = new Test;
std::fstream inputArchive("EngineComplexObjectTest.dat", std::ios::in);
Engine inputEngine(inputArchive, ost::Engine::modeRead);
inputEngine >> myObjAllocatedPtr;
outputEngine.sync(); // flush Engine buffers before closing file
inputArchive.close();
CPPUNIT_ASSERT_MESSAGE("Unpersisted into pre-allocated pointer", *myObjAllocatedPtr == complexObject);
CPPUNIT_ASSERT_MESSAGE("nullPtr is NULL", myObjAllocatedPtr->nullPtr == NULL);
CPPUNIT_ASSERT_MESSAGE("uninitializedNullPtr is NULL", myObjAllocatedPtr->uninitializedNullPtr == NULL);
}
}
void EngineTest::testModeExceptions()
{
// write primitive types
std::fstream outputArchive("EnginePrimitiveTest.dat", std::ios::in|std::ios::binary);
Engine outputEngine(outputArchive, ost::Engine::modeWrite);
int32 test_Int32 = 0x01234567;
try {
outputEngine << test_Int32;
//CPPUNIT_FAIL("Call to persist to an input stream should throw an exception");
}
catch(PersistException &ex) {
CPPUNIT_ASSERT_MESSAGE(ex.getString(), true);
}
outputArchive.close();
}