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