stream tests improvements (patch 924438)
[wxWidgets.git] / tests / streams / bstream.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/streams/bstream.h
3 // Purpose: Template class for testing base stream functions.
4 // Author: Hans Van Leemputten
5 // RCS-ID: $Id$
6 // Copyright: (c) 2004 Hans Van Leemputten
7 // Licence: wxWidgets licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #ifndef _WX_TESTBSTREAM_H__
11 #define _WX_TESTBSTREAM_H__
12
13 #include "wx/cppunit.h"
14 using namespace CppUnit;
15
16 ///////////////////////////////////////////////////////////////////////////////
17 // Some macros preventing us from typing too much ;-)
18 //
19
20 #define STREAM_TEST_NAME "Streams"
21 #define COMPOSE_TEST_NAME(Name) \
22 STREAM_TEST_NAME "." #Name
23 #define STREAM_REGISTER_SUB_SUITE(Name) \
24 extern Test* Get##Name##Suite(); \
25 suite->addTest(Get##Name##Suite())
26 #define STREAM_IMPLEMENT_SUB_REGISTRATION_ROUTINE(Name) \
27 Test* Get##Name##Suite() { return Name::suite(); }
28 #define STREAM_TEST_SUBSUITE_NAMED_REGISTRATION(Name) \
29 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( Name, COMPOSE_TEST_NAME(Name) ); \
30 STREAM_IMPLEMENT_SUB_REGISTRATION_ROUTINE( Name )
31
32
33 ///////////////////////////////////////////////////////////////////////////////
34 // Template class that implements a test for all base stream functions.
35 //
36
37 template <class TStreamIn, class TStreamOut> class BaseStreamTestCase : public TestCase
38 {
39 protected:
40 typedef BaseStreamTestCase<TStreamIn, TStreamOut> StreamTestCase;
41
42 class CleanupHelper
43 {
44 public:
45 CleanupHelper(StreamTestCase *value)
46 :m_pCleanup(value)
47 {}
48 ~CleanupHelper()
49 {
50 m_pCleanup->DeleteInStream();
51 m_pCleanup->DeleteOutStream();
52 }
53 private:
54 StreamTestCase *m_pCleanup;
55 };
56 friend class CleanupHelper;
57
58 public:
59 BaseStreamTestCase()
60 :m_bSimpleTellITest(false),
61 m_bSimpleTellOTest(false),
62 m_bSeekInvalidBeyondEnd(true),
63 m_pCurrentIn(NULL),
64 m_pCurrentOut(NULL)
65 { /* Nothing extra */ }
66 virtual ~BaseStreamTestCase()
67 {
68 // Prevent mem leaks!
69 delete m_pCurrentIn;
70 delete m_pCurrentOut;
71 }
72
73 protected:
74 /*
75 * Input stream tests.
76 */
77
78 // Just try to perform a GetSize() on the input stream.
79 void Input_GetSize()
80 {
81 CleanupHelper cleanup(this);
82 const TStreamIn &stream_in = CreateInStream();
83 CPPUNIT_ASSERT(!stream_in.Eof());
84
85 // Size should be greater then zero.
86 // Note: streams not supporting this should register this test
87 // with CPPUNIT_TEST_FAIL instead of CPPUNIT_TEST.
88 CPPUNIT_ASSERT(stream_in.GetSize() != 0);
89 }
90
91 // Just try to perform a GetC() on the input stream.
92 void Input_GetC()
93 {
94 CleanupHelper cleanup(this);
95 TStreamIn &stream_in = CreateInStream();
96 CPPUNIT_ASSERT(!stream_in.Eof());
97
98 // If no exception occurs the test is successful.
99 (void)stream_in.GetC();
100 }
101
102 // Just try to perform a Read() on the input stream.
103 void Input_Read()
104 {
105 CleanupHelper cleanup(this);
106 TStreamIn &stream_in = CreateInStream();
107 CPPUNIT_ASSERT(!stream_in.Eof());
108
109 // Note: the input stream should at least be of min size +10!
110
111 char buf[10];
112 (void)stream_in.Read(buf, 10);
113
114 CPPUNIT_ASSERT(!stream_in.Eof());
115 CPPUNIT_ASSERT(stream_in.IsOk());
116
117 // Test the stream version aswell.
118 TStreamOut &stream_out = CreateOutStream();
119 (void)stream_in.Read(stream_out);
120
121 // The output stream should have read the input stream till the end.
122 CPPUNIT_ASSERT(stream_in.Eof());
123 }
124
125 // Test and see what happens to the EOF when we
126 // read after EOF was encountered.
127 void Input_Eof()
128 {
129 CleanupHelper cleanup(this);
130 TStreamIn &stream_in = CreateInStream();
131 CPPUNIT_ASSERT(!stream_in.Eof());
132 // Double check to see if Eof it self doesn't changes the Eof status.
133 CPPUNIT_ASSERT(!stream_in.Eof());
134
135 // Travel to the end of the stream.
136 while(!stream_in.Eof())
137 {
138 // Double check to see if normal Eof works.
139 CPPUNIT_ASSERT_MESSAGE("Eof() doesn't return true when IsOk returns false!", stream_in.IsOk());
140 // Read, we move one byte along.
141 (void)stream_in.GetC();
142 }
143
144 // Ok we found the end, lets see if we can go past it.
145 for (size_t i = 0; i < 100; i++)
146 (void)stream_in.GetC();
147
148 // Check for EOF correctness.
149 CPPUNIT_ASSERT_MESSAGE("EOF is wrong when we read past EOF!", stream_in.Eof());
150 }
151
152 // Just try to perform a LastRead() on the input stream.
153 void Input_LastRead()
154 {
155 CleanupHelper cleanup(this);
156 TStreamIn &stream_in = CreateInStream();
157 CPPUNIT_ASSERT(!stream_in.Eof());
158
159 char buf[5];
160 (void)stream_in.Read(buf, 5);
161 CPPUNIT_ASSERT(stream_in.LastRead() == 5);
162 (void)stream_in.GetC();
163 CPPUNIT_ASSERT(stream_in.LastRead() == 1);
164 }
165
166 // Just try to perform a SeekI() on the input stream.
167 void Input_SeekI()
168 {
169 CleanupHelper cleanup(this);
170 TStreamIn &stream_in = CreateInStream();
171 CPPUNIT_ASSERT(!stream_in.Eof());
172
173 // Try to Seek in the stream...
174 // Note: streams not supporting this should register this test
175 // with CPPUNIT_TEST_FAIL instead of CPPUNIT_TEST.
176 CPPUNIT_ASSERT(stream_in.SeekI(2, wxFromStart) == 2);
177 CPPUNIT_ASSERT(stream_in.SeekI(2, wxFromCurrent) == 4);
178 // Not sure the following line is correct, so test it differently.
179 //CPPUNIT_ASSERT(stream_in.SeekI(-2, wxFromEnd) == (off_t)stream_in.GetSize()-2);
180 CPPUNIT_ASSERT(stream_in.SeekI(-2, wxFromEnd) != wxInvalidOffset);
181 // Go beyond the stream size.
182 CPPUNIT_ASSERT((stream_in.SeekI(10, wxFromCurrent) == wxInvalidOffset) == m_bSeekInvalidBeyondEnd);
183 }
184
185 // Just try to perform a TellI() on the input stream.
186 void Input_TellI()
187 {
188 CleanupHelper cleanup(this);
189 TStreamIn &stream_in = CreateInStream();
190 CPPUNIT_ASSERT(!stream_in.Eof());
191
192 // Try to Get the location in the stream...
193 CPPUNIT_ASSERT(stream_in.TellI() == 0);
194 (void)stream_in.GetC();
195 CPPUNIT_ASSERT(stream_in.TellI() == 1);
196 if (!m_bSimpleTellITest)
197 {
198 off_t pos = stream_in.SeekI(5, wxFromStart);
199 CPPUNIT_ASSERT(stream_in.TellI() == pos);
200 (void)stream_in.GetC();
201 CPPUNIT_ASSERT(stream_in.TellI() == 6);
202 pos = stream_in.SeekI(2, wxFromCurrent);
203 CPPUNIT_ASSERT(stream_in.TellI() == pos);
204 pos = stream_in.SeekI(5, wxFromStart);
205 CPPUNIT_ASSERT(stream_in.TellI() == pos);
206 }
207 }
208
209 // Just try to perform a Peek() on the input stream.
210 void Input_Peek()
211 {
212 CleanupHelper cleanup(this);
213 TStreamIn &stream_in = CreateInStream();
214
215 // Test the full stream
216 while (stream_in.IsOk())
217 {
218 char peekChar = stream_in.Peek();
219 char getChar = stream_in.GetC();
220 if (stream_in.LastRead() == 1)
221 CPPUNIT_ASSERT(peekChar == getChar);
222 }
223 }
224
225 // Just try to perform a Ungetch() on the input stream.
226 void Input_Ungetch()
227 {
228 CleanupHelper cleanup(this);
229 TStreamIn &stream_in = CreateInStream();
230 CPPUNIT_ASSERT(!stream_in.Eof());
231
232 const char *ungetstr = "test";
233 size_t ungetsize = stream_in.Ungetch(ungetstr, strlen(ungetstr) + 1);
234 if (ungetsize != 0)
235 {
236 CPPUNIT_ASSERT(ungetsize == strlen(ungetstr) + 1);
237 char buf[10];
238 (void)stream_in.Read(buf, ungetsize);
239 CPPUNIT_ASSERT(strcmp(buf, ungetstr) == 0);
240 }
241
242 if (stream_in.Ungetch('a'))
243 {
244 CPPUNIT_ASSERT(stream_in.GetC() == 'a');
245 }
246 }
247
248 /*
249 * Output stream tests.
250 */
251
252 // Just try to perform a PutC() on the output stream.
253 void Output_PutC()
254 {
255 CleanupHelper cleanup(this);
256 TStreamOut &stream_out = CreateOutStream();
257
258 char *buf = "Some text";
259 off_t i;
260 off_t len = (off_t) strlen(buf);
261 for (i = 0; i < len; i++)
262 stream_out.PutC(buf[i]);
263
264 CPPUNIT_ASSERT(i == stream_out.TellO());
265 }
266
267 // Just try to perform a Write() on the output stream.
268 void Output_Write()
269 {
270 CleanupHelper cleanup(this);
271 TStreamOut &stream_out = CreateOutStream();
272
273 // Do the buffer version.
274 char *buf = "Some text";
275 off_t len = (off_t) strlen(buf);
276 (void)stream_out.Write(buf, len);
277 CPPUNIT_ASSERT(stream_out.TellO() == len);
278
279 // Do the Stream version.
280 TStreamIn &stream_in = CreateInStream();
281 (void)stream_out.Write(stream_in);
282 CPPUNIT_ASSERT(stream_out.TellO() > len);
283 }
284
285 // Just try to perform a LastWrite() on the output stream.
286 void Output_LastWrite()
287 {
288 CleanupHelper cleanup(this);
289 TStreamOut &stream_out = CreateOutStream();
290
291 char *buf = "12345";
292 (void)stream_out.Write(buf, 5);
293 CPPUNIT_ASSERT(stream_out.LastWrite() == 5);
294 (void)stream_out.PutC('1');
295 CPPUNIT_ASSERT(stream_out.LastWrite() == 1);
296 }
297
298 // Just try to perform a SeekO() on the output stream.
299 void Output_SeekO()
300 {
301 CleanupHelper cleanup(this);
302 TStreamOut &stream_out = CreateOutStream();
303
304 // First put some data in the stream, so it is not empty.
305 char *buf = "1234567890";
306 (void)stream_out.Write(buf, 10);
307
308 // Try to Seek in the stream...
309 // Note: streams not supporting this should register this test
310 // with CPPUNIT_TEST_FAIL instead of CPPUNIT_TEST.
311 CPPUNIT_ASSERT(stream_out.SeekO(2, wxFromStart) == 2);
312 CPPUNIT_ASSERT(stream_out.SeekO(2, wxFromCurrent) == 4);
313 // Not sure the following line is correct, so test it differently.
314 //CPPUNIT_ASSERT(stream_out.SeekO(-2, wxFromEnd) == (off_t)stream_in.GetSize()-2);
315 CPPUNIT_ASSERT(stream_out.SeekO(-2, wxFromEnd) != wxInvalidOffset);
316 // Go beyond the stream size.
317 CPPUNIT_ASSERT((stream_out.SeekO(10, wxFromCurrent) == wxInvalidOffset) == m_bSeekInvalidBeyondEnd);
318 }
319
320 // Just try to perform a TellO() on the output stream.
321 void Output_TellO()
322 {
323 CleanupHelper cleanup(this);
324 TStreamOut &stream_out = CreateOutStream();
325
326 // Try to Get the location in the stream...
327 CPPUNIT_ASSERT(stream_out.TellO() == 0);
328 (void)stream_out.PutC('1');
329 CPPUNIT_ASSERT(stream_out.TellO() == 1);
330 if (!m_bSimpleTellOTest)
331 {
332 // First put some extra data in the stream, so it's not empty.
333 char *buf = "1234567890";
334 (void)stream_out.Write(buf, 10);
335
336 off_t pos = stream_out.SeekO(5, wxFromStart);
337 CPPUNIT_ASSERT(stream_out.TellO() == pos);
338 (void)stream_out.PutC('1');
339 CPPUNIT_ASSERT(stream_out.TellO() == 6);
340 pos = stream_out.SeekO(2, wxFromCurrent);
341 CPPUNIT_ASSERT(stream_out.TellO() == pos);
342 pos = stream_out.SeekO(5, wxFromStart);
343 CPPUNIT_ASSERT(stream_out.TellO() == pos);
344 }
345 }
346
347 protected:
348 // Some tests can be configured... here you can find the config settings
349 bool m_bSimpleTellITest; // if true, no SeekI will be used by the TellI test.
350 // Default false.
351 bool m_bSimpleTellOTest; // if true, no SeekO will be used by the TellI test.
352 // Default false.
353 bool m_bSeekInvalidBeyondEnd; // if true a SeekI|O beyond the end of the stream should return wxInvalidOffset
354 // Default true.
355
356 protected:
357 TStreamIn &CreateInStream()
358 {
359 if (m_pCurrentIn)
360 {
361 wxFAIL_MSG(_T("Error in test case, the previouse input stream needs to be delete first!"));
362 }
363
364 m_pCurrentIn = DoCreateInStream();
365 wxASSERT(m_pCurrentIn != NULL);
366 return *m_pCurrentIn;
367 }
368 TStreamOut &CreateOutStream()
369 {
370 if (m_pCurrentOut)
371 {
372 wxFAIL_MSG(_T("Error in test case, the previouse output stream needs to be delete first!"));
373 }
374
375 m_pCurrentOut = DoCreateOutStream();
376 wxASSERT(m_pCurrentOut != NULL);
377 return *m_pCurrentOut;
378 }
379
380 void DeleteInStream()
381 {
382 if (m_pCurrentIn == NULL)
383 return;
384 delete m_pCurrentIn;
385 m_pCurrentIn = NULL;
386 // Incase something extra needs to be done.
387 DoDeleteInStream();
388 }
389 void DeleteOutStream()
390 {
391 if (m_pCurrentOut == NULL)
392 return;
393 delete m_pCurrentOut;
394 m_pCurrentOut = NULL;
395 // Incase something extra needs to be done.
396 DoDeleteOutStream();
397 }
398
399 protected:
400 // Items that need to be implemented by a derived class!
401 virtual TStreamIn *DoCreateInStream() = 0;
402 virtual TStreamOut *DoCreateOutStream() = 0;
403 virtual void DoDeleteInStream() { /* Depends on the base class */ }
404 virtual void DoDeleteOutStream() { /* Depends on the base class */ }
405
406 private:
407 TStreamIn *m_pCurrentIn;
408 TStreamOut *m_pCurrentOut;
409 };
410
411 #endif
412
413