[ 1070686 ] wxOutputStream::Close()
[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
32 ///////////////////////////////////////////////////////////////////////////////
33 // Template class that implements a test for all base stream functions.
34 //
35
36 template <class TStreamIn, class TStreamOut> class BaseStreamTestCase : public CppUnit::TestCase
37 {
38 protected:
39 typedef BaseStreamTestCase<TStreamIn, TStreamOut> StreamTestCase;
40
41 class CleanupHelper
42 {
43 public:
44 CleanupHelper(StreamTestCase *value)
45 :m_pCleanup(value)
46 {}
47 ~CleanupHelper()
48 {
49 m_pCleanup->DeleteInStream();
50 m_pCleanup->DeleteOutStream();
51 }
52 private:
53 StreamTestCase *m_pCleanup;
54 };
55 friend class CleanupHelper;
56
57 public:
58 BaseStreamTestCase()
59 :m_bSimpleTellITest(false),
60 m_bSimpleTellOTest(false),
61 m_bSeekInvalidBeyondEnd(true),
62 m_bEofAtLastRead(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 // Read, we move one byte along.
139 (void)stream_in.GetC();
140 #if 0
141 // EOF behaviour is different in streams, disabled (for now?)
142
143 if (m_bEofAtLastRead)
144 // EOF should only occure after the last successful get.
145 CPPUNIT_ASSERT_MESSAGE("Eof is detected too late.", !(stream_in.LastRead() != 1 && stream_in.Eof()));
146 else
147 // EOF should only occure after a failed get.
148 CPPUNIT_ASSERT_MESSAGE("Eof is detected too soon.", !(stream_in.LastRead() == 1 && stream_in.Eof()));
149 #endif
150 }
151
152 // Check EOF stream state.
153 CPPUNIT_ASSERT_MESSAGE("EOF is not EOF?", stream_in.Eof());
154
155 // Ok we found the end, lets see if we can go past it.
156 for (size_t i = 0; i < 100; i++)
157 (void)stream_in.GetC();
158
159 // Check for EOF correctness.
160 CPPUNIT_ASSERT_MESSAGE("EOF is wrong when we read past EOF!", stream_in.Eof());
161 CPPUNIT_ASSERT_MESSAGE("Last error is not EOF while stream_in.Eof() is true", stream_in.GetLastError() == wxSTREAM_EOF);
162 }
163
164 // Just try to perform a LastRead() on the input stream.
165 void Input_LastRead()
166 {
167 CleanupHelper cleanup(this);
168 TStreamIn &stream_in = CreateInStream();
169 CPPUNIT_ASSERT(!stream_in.Eof());
170
171 char buf[5];
172 (void)stream_in.Read(buf, 5);
173 CPPUNIT_ASSERT(stream_in.LastRead() == 5);
174 (void)stream_in.GetC();
175 CPPUNIT_ASSERT(stream_in.LastRead() == 1);
176 }
177
178 // Just try to perform a SeekI() on the input stream.
179 void Input_SeekI()
180 {
181 CleanupHelper cleanup(this);
182 TStreamIn &stream_in = CreateInStream();
183 CPPUNIT_ASSERT(!stream_in.Eof());
184
185 // Try to Seek in the stream...
186 // Note: streams not supporting this should register this test
187 // with CPPUNIT_TEST_FAIL instead of CPPUNIT_TEST.
188 CPPUNIT_ASSERT(stream_in.SeekI(2, wxFromStart) == 2);
189 CPPUNIT_ASSERT(stream_in.SeekI(2, wxFromCurrent) == 4);
190 // Not sure the following line is correct, so test it differently.
191 //CPPUNIT_ASSERT(stream_in.SeekI(-2, wxFromEnd) == (off_t)stream_in.GetSize()-2);
192 CPPUNIT_ASSERT(stream_in.SeekI(-2, wxFromEnd) != wxInvalidOffset);
193 // Go beyond the stream size.
194 CPPUNIT_ASSERT((stream_in.SeekI(10, wxFromCurrent) == wxInvalidOffset) == m_bSeekInvalidBeyondEnd);
195 }
196
197 // Just try to perform a TellI() on the input stream.
198 void Input_TellI()
199 {
200 CleanupHelper cleanup(this);
201 TStreamIn &stream_in = CreateInStream();
202 CPPUNIT_ASSERT(!stream_in.Eof());
203
204 // Try to Get the location in the stream...
205 CPPUNIT_ASSERT(stream_in.TellI() == 0);
206 (void)stream_in.GetC();
207 CPPUNIT_ASSERT(stream_in.TellI() == 1);
208 if (!m_bSimpleTellITest)
209 {
210 wxFileOffset pos = stream_in.SeekI(5, wxFromStart);
211 CPPUNIT_ASSERT(stream_in.TellI() == pos);
212 (void)stream_in.GetC();
213 CPPUNIT_ASSERT(stream_in.TellI() == 6);
214 pos = stream_in.SeekI(2, wxFromCurrent);
215 CPPUNIT_ASSERT(stream_in.TellI() == pos);
216 pos = stream_in.SeekI(5, wxFromStart);
217 CPPUNIT_ASSERT(stream_in.TellI() == pos);
218 }
219 }
220
221 // Just try to perform a Peek() on the input stream.
222 void Input_Peek()
223 {
224 CleanupHelper cleanup(this);
225 TStreamIn &stream_in = CreateInStream();
226
227 // Test the full stream
228 while (stream_in.IsOk())
229 {
230 char peekChar = stream_in.Peek();
231 char getChar = stream_in.GetC();
232 if (stream_in.LastRead() == 1)
233 CPPUNIT_ASSERT(peekChar == getChar);
234 }
235 }
236
237 // Just try to perform a Ungetch() on the input stream.
238 void Input_Ungetch()
239 {
240 CleanupHelper cleanup(this);
241 TStreamIn &stream_in = CreateInStream();
242 CPPUNIT_ASSERT(!stream_in.Eof());
243
244 const char *ungetstr = "test";
245 size_t ungetsize = stream_in.Ungetch(ungetstr, strlen(ungetstr) + 1);
246 if (ungetsize != 0)
247 {
248 CPPUNIT_ASSERT(ungetsize == strlen(ungetstr) + 1);
249 char buf[10];
250 (void)stream_in.Read(buf, ungetsize);
251 CPPUNIT_ASSERT(strcmp(buf, ungetstr) == 0);
252 }
253
254 if (stream_in.Ungetch('a'))
255 {
256 CPPUNIT_ASSERT(stream_in.GetC() == 'a');
257 }
258 }
259
260 /*
261 * Output stream tests.
262 */
263
264 // Just try to perform a PutC() on the output stream.
265 void Output_PutC()
266 {
267 CleanupHelper cleanup(this);
268 TStreamOut &stream_out = CreateOutStream();
269
270 char *buf = "Some text";
271 int i;
272 int len = strlen(buf);
273 for (i = 0; i < len; i++)
274 stream_out.PutC(buf[i]);
275
276 CPPUNIT_ASSERT(i == stream_out.TellO());
277 }
278
279 // Just try to perform a Write() on the output stream.
280 void Output_Write()
281 {
282 CleanupHelper cleanup(this);
283 TStreamOut &stream_out = CreateOutStream();
284
285 // Do the buffer version.
286 char *buf = "Some text";
287 int len = strlen(buf);
288 (void)stream_out.Write(buf, len);
289 CPPUNIT_ASSERT(stream_out.TellO() == len);
290
291 // Do the Stream version.
292 TStreamIn &stream_in = CreateInStream();
293 (void)stream_out.Write(stream_in);
294 CPPUNIT_ASSERT(stream_out.TellO() > len);
295 }
296
297 // Just try to perform a LastWrite() on the output stream.
298 void Output_LastWrite()
299 {
300 CleanupHelper cleanup(this);
301 TStreamOut &stream_out = CreateOutStream();
302
303 char *buf = "12345";
304 (void)stream_out.Write(buf, 5);
305 CPPUNIT_ASSERT(stream_out.LastWrite() == 5);
306 (void)stream_out.PutC('1');
307 CPPUNIT_ASSERT(stream_out.LastWrite() == 1);
308 }
309
310 // Just try to perform a SeekO() on the output stream.
311 void Output_SeekO()
312 {
313 CleanupHelper cleanup(this);
314 TStreamOut &stream_out = CreateOutStream();
315
316 // First put some data in the stream, so it is not empty.
317 char *buf = "1234567890";
318 (void)stream_out.Write(buf, 10);
319
320 // Try to Seek in the stream...
321 // Note: streams not supporting this should register this test
322 // with CPPUNIT_TEST_FAIL instead of CPPUNIT_TEST.
323 CPPUNIT_ASSERT(stream_out.SeekO(2, wxFromStart) == 2);
324 CPPUNIT_ASSERT(stream_out.SeekO(2, wxFromCurrent) == 4);
325 // Not sure the following line is correct, so test it differently.
326 //CPPUNIT_ASSERT(stream_out.SeekO(-2, wxFromEnd) == (off_t)stream_in.GetSize()-2);
327 CPPUNIT_ASSERT(stream_out.SeekO(-2, wxFromEnd) != wxInvalidOffset);
328 // Go beyond the stream size.
329 CPPUNIT_ASSERT((stream_out.SeekO(10, wxFromCurrent) == wxInvalidOffset) == m_bSeekInvalidBeyondEnd);
330 }
331
332 // Just try to perform a TellO() on the output stream.
333 void Output_TellO()
334 {
335 CleanupHelper cleanup(this);
336 TStreamOut &stream_out = CreateOutStream();
337
338 // Try to Get the location in the stream...
339 CPPUNIT_ASSERT(stream_out.TellO() == 0);
340 (void)stream_out.PutC('1');
341 CPPUNIT_ASSERT(stream_out.TellO() == 1);
342 if (!m_bSimpleTellOTest)
343 {
344 // First put some extra data in the stream, so it's not empty.
345 char *buf = "1234567890";
346 (void)stream_out.Write(buf, 10);
347
348 off_t pos = stream_out.SeekO(5, wxFromStart);
349 CPPUNIT_ASSERT(stream_out.TellO() == pos);
350 (void)stream_out.PutC('1');
351 CPPUNIT_ASSERT(stream_out.TellO() == 6);
352 pos = stream_out.SeekO(2, wxFromCurrent);
353 CPPUNIT_ASSERT(stream_out.TellO() == pos);
354 pos = stream_out.SeekO(5, wxFromStart);
355 CPPUNIT_ASSERT(stream_out.TellO() == pos);
356 }
357 }
358
359 protected:
360 // Some tests can be configured... here you can find the config settings
361 bool m_bSimpleTellITest; // if true, no SeekI will be used by the TellI test.
362 // Default false.
363 bool m_bSimpleTellOTest; // if true, no SeekO will be used by the TellI test.
364 // Default false.
365 bool m_bSeekInvalidBeyondEnd; // if true a SeekI|O beyond the end of the stream should return wxInvalidOffset
366 // Default true.
367 bool m_bEofAtLastRead; // Does EOF occure at the moment the last byte is read or when read past the last byte.
368 // Default true.
369 protected:
370 TStreamIn &CreateInStream()
371 {
372 if (m_pCurrentIn)
373 {
374 wxFAIL_MSG(_T("Error in test case, the previouse input stream needs to be delete first!"));
375 }
376
377 m_pCurrentIn = DoCreateInStream();
378 wxASSERT(m_pCurrentIn != NULL);
379 return *m_pCurrentIn;
380 }
381 TStreamOut &CreateOutStream()
382 {
383 if (m_pCurrentOut)
384 {
385 wxFAIL_MSG(_T("Error in test case, the previouse output stream needs to be delete first!"));
386 }
387
388 m_pCurrentOut = DoCreateOutStream();
389 wxASSERT(m_pCurrentOut != NULL);
390 return *m_pCurrentOut;
391 }
392
393 void DeleteInStream()
394 {
395 if (m_pCurrentIn == NULL)
396 return;
397 delete m_pCurrentIn;
398 m_pCurrentIn = NULL;
399 // Incase something extra needs to be done.
400 DoDeleteInStream();
401 }
402 void DeleteOutStream()
403 {
404 if (m_pCurrentOut == NULL)
405 return;
406
407 CPPUNIT_ASSERT(m_pCurrentOut->Close());
408
409 delete m_pCurrentOut;
410 m_pCurrentOut = NULL;
411 // Incase something extra needs to be done.
412 DoDeleteOutStream();
413 }
414
415 protected:
416 // Items that need to be implemented by a derived class!
417 virtual TStreamIn *DoCreateInStream() = 0;
418 virtual TStreamOut *DoCreateOutStream() = 0;
419 virtual void DoDeleteInStream() { /* Depends on the base class */ }
420 virtual void DoDeleteOutStream() { /* Depends on the base class */ }
421
422 private:
423 TStreamIn *m_pCurrentIn;
424 TStreamOut *m_pCurrentOut;
425 };
426
427 #endif
428
429