applied rest of streams test suite patch
[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_bEofAtLastRead(true),
64 m_pCurrentIn(NULL),
65 m_pCurrentOut(NULL)
66 { /* Nothing extra */ }
67 virtual ~BaseStreamTestCase()
68 {
69 // Prevent mem leaks!
70 delete m_pCurrentIn;
71 delete m_pCurrentOut;
72 }
73
74 protected:
75 /*
76 * Input stream tests.
77 */
78
79 // Just try to perform a GetSize() on the input stream.
80 void Input_GetSize()
81 {
82 CleanupHelper cleanup(this);
83 const TStreamIn &stream_in = CreateInStream();
84 CPPUNIT_ASSERT(!stream_in.Eof());
85
86 // Size should be greater then zero.
87 // Note: streams not supporting this should register this test
88 // with CPPUNIT_TEST_FAIL instead of CPPUNIT_TEST.
89 CPPUNIT_ASSERT(stream_in.GetSize() != 0);
90 }
91
92 // Just try to perform a GetC() on the input stream.
93 void Input_GetC()
94 {
95 CleanupHelper cleanup(this);
96 TStreamIn &stream_in = CreateInStream();
97 CPPUNIT_ASSERT(!stream_in.Eof());
98
99 // If no exception occurs the test is successful.
100 (void)stream_in.GetC();
101 }
102
103 // Just try to perform a Read() on the input stream.
104 void Input_Read()
105 {
106 CleanupHelper cleanup(this);
107 TStreamIn &stream_in = CreateInStream();
108 CPPUNIT_ASSERT(!stream_in.Eof());
109
110 // Note: the input stream should at least be of min size +10!
111
112 char buf[10];
113 (void)stream_in.Read(buf, 10);
114
115 CPPUNIT_ASSERT(!stream_in.Eof());
116 CPPUNIT_ASSERT(stream_in.IsOk());
117
118 // Test the stream version aswell.
119 TStreamOut &stream_out = CreateOutStream();
120 (void)stream_in.Read(stream_out);
121
122 // The output stream should have read the input stream till the end.
123 CPPUNIT_ASSERT(stream_in.Eof());
124 }
125
126 // Test and see what happens to the EOF when we
127 // read after EOF was encountered.
128 void Input_Eof()
129 {
130 CleanupHelper cleanup(this);
131 TStreamIn &stream_in = CreateInStream();
132 CPPUNIT_ASSERT(!stream_in.Eof());
133 // Double check to see if Eof it self doesn't changes the Eof status.
134 CPPUNIT_ASSERT(!stream_in.Eof());
135
136 // Travel to the end of the stream.
137 while(!stream_in.Eof())
138 {
139 // Read, we move one byte along.
140 (void)stream_in.GetC();
141 #if 0
142 // EOF behaviour is different in streams, disabled (for now?)
143
144 if (m_bEofAtLastRead)
145 // EOF should only occure after the last successful get.
146 CPPUNIT_ASSERT_MESSAGE("Eof is detected too late.", !(stream_in.LastRead() != 1 && stream_in.Eof()));
147 else
148 // EOF should only occure after a failed get.
149 CPPUNIT_ASSERT_MESSAGE("Eof is detected too soon.", !(stream_in.LastRead() == 1 && stream_in.Eof()));
150 #endif
151 }
152
153 // Check EOF stream state.
154 CPPUNIT_ASSERT_MESSAGE("EOF is not EOF?", stream_in.Eof());
155
156 // Ok we found the end, lets see if we can go past it.
157 for (size_t i = 0; i < 100; i++)
158 (void)stream_in.GetC();
159
160 // Check for EOF correctness.
161 CPPUNIT_ASSERT_MESSAGE("EOF is wrong when we read past EOF!", stream_in.Eof());
162 CPPUNIT_ASSERT_MESSAGE("Last error is not EOF while stream_in.Eof() is true", stream_in.GetLastError() == wxSTREAM_EOF);
163 }
164
165 // Just try to perform a LastRead() on the input stream.
166 void Input_LastRead()
167 {
168 CleanupHelper cleanup(this);
169 TStreamIn &stream_in = CreateInStream();
170 CPPUNIT_ASSERT(!stream_in.Eof());
171
172 char buf[5];
173 (void)stream_in.Read(buf, 5);
174 CPPUNIT_ASSERT(stream_in.LastRead() == 5);
175 (void)stream_in.GetC();
176 CPPUNIT_ASSERT(stream_in.LastRead() == 1);
177 }
178
179 // Just try to perform a SeekI() on the input stream.
180 void Input_SeekI()
181 {
182 CleanupHelper cleanup(this);
183 TStreamIn &stream_in = CreateInStream();
184 CPPUNIT_ASSERT(!stream_in.Eof());
185
186 // Try to Seek in the stream...
187 // Note: streams not supporting this should register this test
188 // with CPPUNIT_TEST_FAIL instead of CPPUNIT_TEST.
189 CPPUNIT_ASSERT(stream_in.SeekI(2, wxFromStart) == 2);
190 CPPUNIT_ASSERT(stream_in.SeekI(2, wxFromCurrent) == 4);
191 // Not sure the following line is correct, so test it differently.
192 //CPPUNIT_ASSERT(stream_in.SeekI(-2, wxFromEnd) == (off_t)stream_in.GetSize()-2);
193 CPPUNIT_ASSERT(stream_in.SeekI(-2, wxFromEnd) != wxInvalidOffset);
194 // Go beyond the stream size.
195 CPPUNIT_ASSERT((stream_in.SeekI(10, wxFromCurrent) == wxInvalidOffset) == m_bSeekInvalidBeyondEnd);
196 }
197
198 // Just try to perform a TellI() on the input stream.
199 void Input_TellI()
200 {
201 CleanupHelper cleanup(this);
202 TStreamIn &stream_in = CreateInStream();
203 CPPUNIT_ASSERT(!stream_in.Eof());
204
205 // Try to Get the location in the stream...
206 CPPUNIT_ASSERT(stream_in.TellI() == 0);
207 (void)stream_in.GetC();
208 CPPUNIT_ASSERT(stream_in.TellI() == 1);
209 if (!m_bSimpleTellITest)
210 {
211 off_t pos = stream_in.SeekI(5, wxFromStart);
212 CPPUNIT_ASSERT(stream_in.TellI() == pos);
213 (void)stream_in.GetC();
214 CPPUNIT_ASSERT(stream_in.TellI() == 6);
215 pos = stream_in.SeekI(2, wxFromCurrent);
216 CPPUNIT_ASSERT(stream_in.TellI() == pos);
217 pos = stream_in.SeekI(5, wxFromStart);
218 CPPUNIT_ASSERT(stream_in.TellI() == pos);
219 }
220 }
221
222 // Just try to perform a Peek() on the input stream.
223 void Input_Peek()
224 {
225 CleanupHelper cleanup(this);
226 TStreamIn &stream_in = CreateInStream();
227
228 // Test the full stream
229 while (stream_in.IsOk())
230 {
231 char peekChar = stream_in.Peek();
232 char getChar = stream_in.GetC();
233 if (stream_in.LastRead() == 1)
234 CPPUNIT_ASSERT(peekChar == getChar);
235 }
236 }
237
238 // Just try to perform a Ungetch() on the input stream.
239 void Input_Ungetch()
240 {
241 CleanupHelper cleanup(this);
242 TStreamIn &stream_in = CreateInStream();
243 CPPUNIT_ASSERT(!stream_in.Eof());
244
245 const char *ungetstr = "test";
246 size_t ungetsize = stream_in.Ungetch(ungetstr, strlen(ungetstr) + 1);
247 if (ungetsize != 0)
248 {
249 CPPUNIT_ASSERT(ungetsize == strlen(ungetstr) + 1);
250 char buf[10];
251 (void)stream_in.Read(buf, ungetsize);
252 CPPUNIT_ASSERT(strcmp(buf, ungetstr) == 0);
253 }
254
255 if (stream_in.Ungetch('a'))
256 {
257 CPPUNIT_ASSERT(stream_in.GetC() == 'a');
258 }
259 }
260
261 /*
262 * Output stream tests.
263 */
264
265 // Just try to perform a PutC() on the output stream.
266 void Output_PutC()
267 {
268 CleanupHelper cleanup(this);
269 TStreamOut &stream_out = CreateOutStream();
270
271 char *buf = "Some text";
272 off_t i;
273 off_t len = (off_t) strlen(buf);
274 for (i = 0; i < len; i++)
275 stream_out.PutC(buf[i]);
276
277 CPPUNIT_ASSERT(i == stream_out.TellO());
278 }
279
280 // Just try to perform a Write() on the output stream.
281 void Output_Write()
282 {
283 CleanupHelper cleanup(this);
284 TStreamOut &stream_out = CreateOutStream();
285
286 // Do the buffer version.
287 char *buf = "Some text";
288 off_t len = (off_t) strlen(buf);
289 (void)stream_out.Write(buf, len);
290 CPPUNIT_ASSERT(stream_out.TellO() == len);
291
292 // Do the Stream version.
293 TStreamIn &stream_in = CreateInStream();
294 (void)stream_out.Write(stream_in);
295 CPPUNIT_ASSERT(stream_out.TellO() > len);
296 }
297
298 // Just try to perform a LastWrite() on the output stream.
299 void Output_LastWrite()
300 {
301 CleanupHelper cleanup(this);
302 TStreamOut &stream_out = CreateOutStream();
303
304 char *buf = "12345";
305 (void)stream_out.Write(buf, 5);
306 CPPUNIT_ASSERT(stream_out.LastWrite() == 5);
307 (void)stream_out.PutC('1');
308 CPPUNIT_ASSERT(stream_out.LastWrite() == 1);
309 }
310
311 // Just try to perform a SeekO() on the output stream.
312 void Output_SeekO()
313 {
314 CleanupHelper cleanup(this);
315 TStreamOut &stream_out = CreateOutStream();
316
317 // First put some data in the stream, so it is not empty.
318 char *buf = "1234567890";
319 (void)stream_out.Write(buf, 10);
320
321 // Try to Seek in the stream...
322 // Note: streams not supporting this should register this test
323 // with CPPUNIT_TEST_FAIL instead of CPPUNIT_TEST.
324 CPPUNIT_ASSERT(stream_out.SeekO(2, wxFromStart) == 2);
325 CPPUNIT_ASSERT(stream_out.SeekO(2, wxFromCurrent) == 4);
326 // Not sure the following line is correct, so test it differently.
327 //CPPUNIT_ASSERT(stream_out.SeekO(-2, wxFromEnd) == (off_t)stream_in.GetSize()-2);
328 CPPUNIT_ASSERT(stream_out.SeekO(-2, wxFromEnd) != wxInvalidOffset);
329 // Go beyond the stream size.
330 CPPUNIT_ASSERT((stream_out.SeekO(10, wxFromCurrent) == wxInvalidOffset) == m_bSeekInvalidBeyondEnd);
331 }
332
333 // Just try to perform a TellO() on the output stream.
334 void Output_TellO()
335 {
336 CleanupHelper cleanup(this);
337 TStreamOut &stream_out = CreateOutStream();
338
339 // Try to Get the location in the stream...
340 CPPUNIT_ASSERT(stream_out.TellO() == 0);
341 (void)stream_out.PutC('1');
342 CPPUNIT_ASSERT(stream_out.TellO() == 1);
343 if (!m_bSimpleTellOTest)
344 {
345 // First put some extra data in the stream, so it's not empty.
346 char *buf = "1234567890";
347 (void)stream_out.Write(buf, 10);
348
349 off_t pos = stream_out.SeekO(5, wxFromStart);
350 CPPUNIT_ASSERT(stream_out.TellO() == pos);
351 (void)stream_out.PutC('1');
352 CPPUNIT_ASSERT(stream_out.TellO() == 6);
353 pos = stream_out.SeekO(2, wxFromCurrent);
354 CPPUNIT_ASSERT(stream_out.TellO() == pos);
355 pos = stream_out.SeekO(5, wxFromStart);
356 CPPUNIT_ASSERT(stream_out.TellO() == pos);
357 }
358 }
359
360 protected:
361 // Some tests can be configured... here you can find the config settings
362 bool m_bSimpleTellITest; // if true, no SeekI will be used by the TellI test.
363 // Default false.
364 bool m_bSimpleTellOTest; // if true, no SeekO will be used by the TellI test.
365 // Default false.
366 bool m_bSeekInvalidBeyondEnd; // if true a SeekI|O beyond the end of the stream should return wxInvalidOffset
367 // Default true.
368 bool m_bEofAtLastRead; // Does EOF occure at the moment the last byte is read or when read past the last byte.
369 // Default true.
370 protected:
371 TStreamIn &CreateInStream()
372 {
373 if (m_pCurrentIn)
374 {
375 wxFAIL_MSG(_T("Error in test case, the previouse input stream needs to be delete first!"));
376 }
377
378 m_pCurrentIn = DoCreateInStream();
379 wxASSERT(m_pCurrentIn != NULL);
380 return *m_pCurrentIn;
381 }
382 TStreamOut &CreateOutStream()
383 {
384 if (m_pCurrentOut)
385 {
386 wxFAIL_MSG(_T("Error in test case, the previouse output stream needs to be delete first!"));
387 }
388
389 m_pCurrentOut = DoCreateOutStream();
390 wxASSERT(m_pCurrentOut != NULL);
391 return *m_pCurrentOut;
392 }
393
394 void DeleteInStream()
395 {
396 if (m_pCurrentIn == NULL)
397 return;
398 delete m_pCurrentIn;
399 m_pCurrentIn = NULL;
400 // Incase something extra needs to be done.
401 DoDeleteInStream();
402 }
403 void DeleteOutStream()
404 {
405 if (m_pCurrentOut == NULL)
406 return;
407 delete m_pCurrentOut;
408 m_pCurrentOut = NULL;
409 // Incase something extra needs to be done.
410 DoDeleteOutStream();
411 }
412
413 protected:
414 // Items that need to be implemented by a derived class!
415 virtual TStreamIn *DoCreateInStream() = 0;
416 virtual TStreamOut *DoCreateOutStream() = 0;
417 virtual void DoDeleteInStream() { /* Depends on the base class */ }
418 virtual void DoDeleteOutStream() { /* Depends on the base class */ }
419
420 private:
421 TStreamIn *m_pCurrentIn;
422 TStreamOut *m_pCurrentOut;
423 };
424
425 #endif
426
427