blob: 6552749506f5c0e6a8d3cf0b1440bb3bae835617 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 2002-2003 Chad C. Yates cyates@uidaho.edu
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation; either version 2 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program; if not, write to the Free Software
15// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16//
17// As a special exception to the GNU General Public License, permission is
18// granted for additional uses of the text contained in its release
19// of Common C++.
20//
21// The exception is that, if you link the Common C++ library with other
22// files to produce an executable, this does not by itself cause the
23// resulting executable to be covered by the GNU General Public License.
24// Your use of that executable is in no way restricted on account of
25// linking the Common C++ library code into it.
26//
27// This exception does not however invalidate any other reasons why
28// the executable file might be covered by the GNU General Public License.
29//
30// This exception applies only to the code released under the
31// name Common C++. If you copy code from other releases into a copy of
32// Common C++, as the General Public License permits, the exception does
33// not apply to the code that you add in this way. To avoid misleading
34// anyone as to the status of such modified files, you must delete
35// this exception notice from them.
36//
37// If you write modifications of your own for Common C++, it is your choice
38// whether to permit this exception to apply to your modifications.
39// If you do not wish that, delete this exception notice.
40
41#include "Test_Engine.h"
42#include <cstdio>
43
44CPPUNIT_TEST_SUITE_REGISTRATION(EngineTest);
45
46void EngineTest::setUp()
47{
48 // Create an example object with some sub objects and various data elements
49 complexObject.iInteger = 5;
50 complexObject.strString = "String 1";
51 complexObject.strString2 = "String 2";
52 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)
53 for(int i = 0; i < 10; i++)
54 complexObject.numbers.push_back(i);
55 complexObject.strings.push_back("a");
56 complexObject.strings.push_back("b");
57 complexObject.strings.push_back("c");
58 complexObject.strings.push_back("d");
59 complexObject.strings.push_back("e");
60
61 complexObject.moreStrings.push_back("z");
62 complexObject.moreStrings.push_back("y");
63 complexObject.moreStrings.push_back("x");
64 complexObject.moreStrings.push_back("w");
65 complexObject.moreStrings.push_back("v");
66
67 complexObject.subObjectPtr = new TestSub;
68 complexObject.subObjectPtr2 = complexObject.subObjectPtr; // set to point to the same thing as subObjectPtr to test unpersisting of shared instances
69 complexObject.subObjectPtr->iInteger = 5;
70 complexObject.subObjectPtr->strString = "SubStringPtr 1";
71 complexObject.subObjectPtr->strString2 = "SubStringPtr 2";
72 for(int j = 10; j < 20; j++)
73 complexObject.subObjectPtr->numbers.push_back(j);
74
75 complexObject.subObjectRef.iInteger = 5;
76 complexObject.subObjectRef.strString = "SubString2 1";
77 complexObject.subObjectRef.strString2 = "SubString2 2";
78 for(int k = 30; k < 35; k++)
79 complexObject.subObjectRef.numbers.push_back(k);
80
81 // make a std::deque of TestSub objects
82 for(int l = 0; l < 2; l++) {
83 TestSub newSubObject;
84 newSubObject.iInteger = l;
85 char tmp[50];
86 sprintf(tmp, "test %d", l+1);
87 newSubObject.strString = tmp;
88 for(int k = 30; k < 35; k++)
89 newSubObject.numbers.push_back(k);
90 complexObject.subObjects.push_back(newSubObject);
91 }
92}
93
94void EngineTest::tearDown()
95{}
96
97void EngineTest::testPrimitives()
98{
99 // write primitive types
100 std::fstream outputArchive("EnginePrimitiveTest.dat", std::ios::out|std::ios::binary);
101 Engine outputEngine(outputArchive, ost::Engine::modeWrite);
102
103 TEST_PRIMITIVE_OUTPUT(int8, 0x01);
104 TEST_PRIMITIVE_OUTPUT(uint8, 0x01);
105 TEST_PRIMITIVE_OUTPUT(int16, 0x0123);
106 TEST_PRIMITIVE_OUTPUT(uint16, 0x0123);
107 TEST_PRIMITIVE_OUTPUT(int32, 0x01234567);
108 TEST_PRIMITIVE_OUTPUT(uint32, 0x01234567);
109 //TEST_PRIMITIVE_OUTPUT(int64, 0x0123456789ABCDEF); // warning: integer constant larger than the maximum value of an unsigned long int
110 //TEST_PRIMITIVE_OUTPUT(uint64, 0x0123456789ABCDEF); // warning: integer constant larger than the maximum value of an unsigned long int
111 TEST_PRIMITIVE_OUTPUT(float, 3.141592653589793238462643f);
112 TEST_PRIMITIVE_OUTPUT(double, 3.141592653589793238462643);
113 TEST_PRIMITIVE_OUTPUT(string, "abcdefghijklmnopqrstuvwxyz0123456789");
114
115 outputEngine.sync(); // flush Engine buffers before closing file
116 outputArchive.close();
117
118 // read primitive types back in and check
119 std::fstream inputArchive("EnginePrimitiveTest.dat", std::ios::in|std::ios::binary);
120 Engine inputEngine(inputArchive, ost::Engine::modeRead);
121
122 TEST_PRIMITIVE_INPUT(int8);
123 TEST_PRIMITIVE_INPUT(uint8);
124 TEST_PRIMITIVE_INPUT(int16);
125 TEST_PRIMITIVE_INPUT(uint16);
126 TEST_PRIMITIVE_INPUT(int32);
127 TEST_PRIMITIVE_INPUT(uint32);
128 //TEST_PRIMITIVE_INPUT(int64);
129 //TEST_PRIMITIVE_INPUT(uint64);
130 TEST_PRIMITIVE_INPUT(float);
131 TEST_PRIMITIVE_INPUT(double);
132 TEST_PRIMITIVE_INPUT(string);
133
134 inputArchive.close();
135}
136
137
138void EngineTest::testRawBinary()
139{
140 int i;
141
142 // write raw binary data
143 std::fstream outputArchive("EngineRawBinaryTest.dat", std::ios::out|std::ios::binary);
144 Engine outputEngine(outputArchive, ost::Engine::modeWrite);
145
146 unsigned int binaryBuffer[BINARY_BUFFER_SIZE];
147 for(i = 0; i < BINARY_BUFFER_SIZE; i++)
148 binaryBuffer[i] = i;
149
150 outputEngine.writeBinary((const uint8*) binaryBuffer, sizeof(binaryBuffer));
151 outputEngine.sync(); // flush Engine buffers before closing file
152 outputArchive.close();
153
154 // read binary data back in and check
155 std::fstream inputArchive("EngineRawBinaryTest.dat", std::ios::in|std::ios::binary);
156 Engine inputEngine(inputArchive, ost::Engine::modeRead);
157
158 unsigned int binaryBuffer2[BINARY_BUFFER_SIZE];
159 inputEngine.readBinary((uint8*) binaryBuffer2, sizeof(binaryBuffer2));
160 inputArchive.close();
161
162 for(i = 0; i < BINARY_BUFFER_SIZE; i++)
163 CPPUNIT_ASSERT(binaryBuffer[i] == binaryBuffer2[i]);
164}
165
166void EngineTest::testSTLVector()
167{
168 int i;
169
170 // write STL data
171 std::fstream outputArchive("EngineSTLVectorTest.dat", std::ios::out|std::ios::binary);
172 Engine outputEngine(outputArchive, ost::Engine::modeWrite);
173
174 std::vector<int32> intVector;
175 std::vector<int32>* pIntVector = new std::vector<int32>;
176 for(i = 0; i < STL_CONTAINER_SIZE; i++) {
177 intVector.push_back(i);
178 pIntVector->push_back(i);
179 }
180
181 outputEngine << intVector;
182 outputEngine << *pIntVector;
183 outputEngine.sync(); // flush Engine buffers before closing file
184 outputArchive.close();
185
186 // read STL std::vector back in and check
187 std::fstream inputArchive("EngineSTLVectorTest.dat", std::ios::in|std::ios::binary);
188 Engine inputEngine(inputArchive, ost::Engine::modeRead);
189
190 std::vector<int32> intVector2;
191 inputEngine >> intVector2;
192 CPPUNIT_ASSERT(intVector == intVector2);
193
194 std::vector<int32>* pIntVector2 = new std::vector<int32>;
195 inputEngine >> *pIntVector2;
196 CPPUNIT_ASSERT(*pIntVector == *pIntVector2);
197 delete pIntVector2;
198
199 inputArchive.close();
200
201 delete pIntVector;
202}
203
204void EngineTest::testSTLDeque()
205{
206 int i;
207
208 // write STL std::deque data
209 std::fstream outputArchive("EngineSTLDequeTest.dat", std::ios::out|std::ios::binary);
210 Engine outputEngine(outputArchive, ost::Engine::modeWrite);
211
212 std::deque<int32> intDeque;
213 std::deque<int32>* pIntDeque = new std::deque<int32>;
214 for(i = 0; i < STL_CONTAINER_SIZE; i++) {
215 intDeque.push_back(i);
216 pIntDeque->push_back(i);
217 }
218
219 outputEngine << intDeque;
220 outputEngine << *pIntDeque;
221 outputEngine.sync(); // flush Engine buffers before closing file
222 outputArchive.close();
223
224 // read STL std::deque back in and check
225 std::fstream inputArchive("EngineSTLDequeTest.dat", std::ios::in|std::ios::binary);
226 Engine inputEngine(inputArchive, ost::Engine::modeRead);
227
228 std::deque<int32> intDeque2;
229 inputEngine >> intDeque2;
230 CPPUNIT_ASSERT(intDeque == intDeque2);
231
232 std::deque<int32>* pIntDeque2 = new std::deque<int32>;
233 inputEngine >> *pIntDeque2;
234 CPPUNIT_ASSERT(*pIntDeque == *pIntDeque2);
235 delete pIntDeque2;
236
237 inputArchive.close();
238
239 delete pIntDeque;
240}
241
242void EngineTest::testSTLMap()
243{
244 int i;
245
246 // write STL std::map data
247 std::fstream outputArchive("EngineSTLMapTest.dat", std::ios::out|std::ios::binary);
248 Engine outputEngine(outputArchive, ost::Engine::modeWrite);
249
250 std::map<int32, int32> intMap;
251 std::map<int32, int32>* pIntMap = new std::map<int32, int32>;
252 for(i = 0; i < STL_CONTAINER_SIZE; i++) {
253 intMap.insert(std::pair<int32, int32>(i, i+10));
254 pIntMap->insert(std::pair<int32, int32>(i, i+11));
255 }
256
257 outputEngine << intMap;
258 outputEngine << *pIntMap;
259 outputEngine.sync(); // flush Engine buffers before closing file
260 outputArchive.close();
261
262 // read STL std::map back in and check
263 std::fstream inputArchive("EngineSTLMapTest.dat", std::ios::in|std::ios::binary);
264 Engine inputEngine(inputArchive, ost::Engine::modeRead);
265
266 std::map<int32, int32> intMap2;
267 inputEngine >> intMap2;
268 CPPUNIT_ASSERT(intMap == intMap2);
269
270 std::map<int32, int32>* pIntMap2 = new std::map<int32, int32>;
271 inputEngine >> *pIntMap2;
272 CPPUNIT_ASSERT(*pIntMap == *pIntMap2);
273 delete pIntMap2;
274
275 inputArchive.close();
276
277 delete pIntMap;
278}
279
280void EngineTest::testComplexObject()
281{
282 // write BaseObject hierarchy
283 std::fstream outputArchive("EngineComplexObjectTest.dat", std::ios::out|std::ios::binary);
284 Engine outputEngine(outputArchive, ost::Engine::modeWrite);
285 outputEngine << complexObject;
286 outputEngine.sync(); // flush Engine buffers before closing file
287 outputArchive.close();
288
289 // Unpersist a new object structure into an uninitialized object
290 {
291 Test* myObjPtr = NULL; // must initialize pointer or new persistence engine will think it is already allocated
292 std::fstream inputArchive("EngineComplexObjectTest.dat", std::ios::in);
293 Engine inputEngine(inputArchive, ost::Engine::modeRead);
294 inputEngine >> myObjPtr;
295 inputArchive.close();
296
297 CPPUNIT_ASSERT_MESSAGE("Unpersisted into unallocated pointer == Original", *myObjPtr == complexObject);
298 CPPUNIT_ASSERT_MESSAGE("nullPtr is NULL", myObjPtr->nullPtr == NULL);
299 CPPUNIT_ASSERT_MESSAGE("uninitializedNullPtr is NULL", myObjPtr->uninitializedNullPtr == NULL);
300
301 myObjPtr->subObjectPtr->strString2 = "Changed SubStringPtr 1";
302 CPPUNIT_ASSERT_MESSAGE("subObjectPtr.strString2 should always equal subObjectPtr2.strString2", myObjPtr->subObjectPtr->strString2 == myObjPtr->subObjectPtr2->strString2);
303 CPPUNIT_ASSERT_MESSAGE("subObjectPtr.strString2 should now equal 'Changed SubStringPtr 1'", myObjPtr->subObjectPtr->strString2 == "Changed SubStringPtr 1");
304 CPPUNIT_ASSERT_MESSAGE("subObjectPtr.strString2 should still equal subObjectPtr2.strString2", myObjPtr->subObjectPtr->strString2 == myObjPtr->subObjectPtr2->strString2);
305 }
306
307 // Unpersist a new object structure into an instantiated class variable
308 {
309 Test myObjInstance;
310 std::fstream inputArchive("EngineComplexObjectTest.dat", std::ios::in);
311 Engine inputEngine(inputArchive, ost::Engine::modeRead);
312 inputEngine >> myObjInstance;
313 inputArchive.close();
314
315 CPPUNIT_ASSERT_MESSAGE("Unpersisted into default constructed instance == Original", myObjInstance == complexObject);
316 CPPUNIT_ASSERT_MESSAGE("nullPtr is NULL", myObjInstance.nullPtr == NULL);
317 CPPUNIT_ASSERT_MESSAGE("UninitializedNullPtr is NULL", myObjInstance.uninitializedNullPtr == NULL);
318 }
319
320 // Unpersist a new object structure into a pre-initialized pointer to an object
321 {
322 Test* myObjAllocatedPtr = new Test;
323 std::fstream inputArchive("EngineComplexObjectTest.dat", std::ios::in);
324 Engine inputEngine(inputArchive, ost::Engine::modeRead);
325 inputEngine >> myObjAllocatedPtr;
326 outputEngine.sync(); // flush Engine buffers before closing file
327 inputArchive.close();
328
329 CPPUNIT_ASSERT_MESSAGE("Unpersisted into pre-allocated pointer", *myObjAllocatedPtr == complexObject);
330 CPPUNIT_ASSERT_MESSAGE("nullPtr is NULL", myObjAllocatedPtr->nullPtr == NULL);
331 CPPUNIT_ASSERT_MESSAGE("uninitializedNullPtr is NULL", myObjAllocatedPtr->uninitializedNullPtr == NULL);
332 }
333}
334
335void EngineTest::testModeExceptions()
336{
337 // write primitive types
338 std::fstream outputArchive("EnginePrimitiveTest.dat", std::ios::in|std::ios::binary);
339 Engine outputEngine(outputArchive, ost::Engine::modeWrite);
340
341 int32 test_Int32 = 0x01234567;
342 try {
343 outputEngine << test_Int32;
344 //CPPUNIT_FAIL("Call to persist to an input stream should throw an exception");
345 }
346 catch(PersistException &ex) {
347 CPPUNIT_ASSERT_MESSAGE(ex.getString(), true);
348 }
349
350 outputArchive.close();
351}