1 #include <string>
2 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
3 # include <fstream>
4 # include <iostream>
5 # include <iomanip>
6 # include <sstream>
7 # include <vector>
8 # include <stdexcept>
9
10 #include <stdio.h>
11
12 # include "full_streambuf.h"
13 # include "cppunit/cppunit_proxy.h"
14
15 # if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
16 using namespace std;
17 # endif
18
19 //The macro value gives approximately the generated file
20 //size in Go
21 //#define CHECK_BIG_FILE 4
22
23 # if (!defined(STLPORT) && (defined (__GNUC__) && (__GNUC__ > 3))) || \
24 (defined (STLPORT) && !defined (_STLP_NO_CUSTOM_IO) && !defined (_STLP_NO_MEMBER_TEMPLATES) && \
25 !((defined (_STLP_MSVC) && (_STLP_MSVC < 1300)) || \
26 (defined (__GNUC__) && (__GNUC__ < 3)) || \
27 (defined (__SUNPRO_CC)) || \
28 (defined (__DMC__) && defined (_DLL))))
29 # define DO_CUSTOM_FACET_TEST
30 # endif
31
32 //
33 // TestCase class
34 //
35 class FstreamTest : public CPPUNIT_NS::TestCase
36 {
37 CPPUNIT_TEST_SUITE(FstreamTest);
38 CPPUNIT_TEST(output);
39 CPPUNIT_TEST(input);
40 CPPUNIT_TEST(input_char);
41 CPPUNIT_TEST(io);
42 CPPUNIT_TEST(err);
43 CPPUNIT_TEST(tellg);
44 CPPUNIT_TEST(tellp);
45 CPPUNIT_TEST(seek);
46 CPPUNIT_TEST(buf);
47 CPPUNIT_TEST(rdbuf);
48 CPPUNIT_TEST(streambuf_output);
49 CPPUNIT_TEST(win32_file_format);
50 CPPUNIT_TEST(null_stream);
51 # if defined (STLPORT) && (defined (_STLP_NO_WCHAR_T) || !defined (_STLP_USE_EXCEPTIONS))
52 CPPUNIT_IGNORE;
53 # endif
54 CPPUNIT_TEST(null_buf);
55 # if !defined (STLPORT) || !defined (_STLP_WIN32)
56 CPPUNIT_TEST(offset);
57 # endif
58 # if defined (CHECK_BIG_FILE)
59 CPPUNIT_TEST(big_file);
60 # endif
61 # if !defined (DO_CUSTOM_FACET_TEST)
62 CPPUNIT_IGNORE;
63 # endif
64 CPPUNIT_TEST(custom_facet);
65 CPPUNIT_TEST_SUITE_END();
66
67 protected:
68 void output();
69 void input();
70 void input_char();
71 void io();
72 void err();
73 void tellg();
74 void tellp();
75 void seek();
76 void buf();
77 void rdbuf();
78 void streambuf_output();
79 void win32_file_format();
80 void null_stream();
81 void null_buf();
82 # if !defined (STLPORT) || !defined (_STLP_WIN32)
83 void offset();
84 # endif
85 void custom_facet();
86 # if defined (CHECK_BIG_FILE)
87 void big_file();
88 # endif
89 };
90
91 CPPUNIT_TEST_SUITE_REGISTRATION(FstreamTest);
92
93 //
94 // tests implementation
95 //
output()96 void FstreamTest::output()
97 {
98 ofstream f( "test_file.txt" );
99
100 #if 1
101 CPPUNIT_ASSERT (f.good());
102 f << 1;
103 CPPUNIT_ASSERT (f.good());
104 f << '\n';
105 CPPUNIT_ASSERT (f.good());
106 f << 2.0;
107 CPPUNIT_ASSERT (f.good());
108 f << '\n';
109 CPPUNIT_ASSERT (f.good());
110 f << "abcd\n";
111 CPPUNIT_ASSERT (f.good());
112 f << "ghk lm\n";
113 CPPUNIT_ASSERT (f.good());
114 f << "abcd ef";
115 CPPUNIT_ASSERT (f.good());
116 #else
117 f << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef";
118 CPPUNIT_ASSERT (f.good());
119 #endif
120 // CPPUNIT_ASSERT( s.str() == "1\n2\nabcd\nghk lm\nabcd ef" );
121 }
122
input()123 void FstreamTest::input()
124 {
125 {
126 ifstream f( "test_file.txt" );
127 int i = 0;
128 f >> i;
129 CPPUNIT_ASSERT( f.good() );
130 CPPUNIT_ASSERT( i == 1 );
131 double d = 0.0;
132 f >> d;
133 CPPUNIT_ASSERT( f.good() );
134 CPPUNIT_ASSERT( d == 2.0 );
135 string str;
136 f >> str;
137 CPPUNIT_ASSERT( f.good() );
138 CPPUNIT_ASSERT( str == "abcd" );
139 char c;
140 f.get(c); // extract newline, that not extracted by operator >>
141 CPPUNIT_ASSERT( f.good() );
142 CPPUNIT_ASSERT( c == '\n' );
143 getline( f, str );
144 CPPUNIT_ASSERT( f.good() );
145 CPPUNIT_ASSERT( str == "ghk lm" );
146 getline( f, str );
147 CPPUNIT_ASSERT( f.eof() );
148 CPPUNIT_ASSERT( str == "abcd ef" );
149 }
150 #if defined (STLPORT) && !defined (_STLP_USE_WIN32_IO)
151 {
152 ifstream in("/tmp");
153 if (in.good()) {
154 string s;
155 getline(in, s);
156 CPPUNIT_ASSERT( in.fail() );
157 }
158 }
159 #endif
160 }
161
input_char()162 void FstreamTest::input_char()
163 {
164 char buf[16] = { 0, '1', '2', '3' };
165 ifstream s( "test_file.txt" );
166 s >> buf;
167
168 CPPUNIT_ASSERT( buf[0] == '1' );
169 CPPUNIT_ASSERT( buf[1] == 0 );
170 CPPUNIT_ASSERT( buf[2] == '2' );
171 }
172
io()173 void FstreamTest::io()
174 {
175 basic_fstream<char,char_traits<char> > f( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
176
177 CPPUNIT_ASSERT( f.is_open() );
178
179 f << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef";
180
181 // f.flush();
182 f.seekg( 0, ios_base::beg );
183
184 int i = 0;
185 f >> i;
186 CPPUNIT_ASSERT( f.good() );
187 CPPUNIT_ASSERT( i == 1 );
188 double d = 0.0;
189 f >> d;
190 CPPUNIT_ASSERT( d == 2.0 );
191 string s;
192 f >> s;
193 CPPUNIT_ASSERT( f.good() );
194 CPPUNIT_ASSERT( s == "abcd" );
195 char c;
196 f.get(c); // extract newline, that not extracted by operator >>
197 CPPUNIT_ASSERT( f.good() );
198 CPPUNIT_ASSERT( c == '\n' );
199 getline( f, s );
200 CPPUNIT_ASSERT( f.good() );
201 CPPUNIT_ASSERT( s == "ghk lm" );
202 getline( f, s );
203 CPPUNIT_ASSERT( !f.fail() );
204 CPPUNIT_ASSERT( s == "abcd ef" );
205 CPPUNIT_ASSERT( f.eof() );
206 }
207
err()208 void FstreamTest::err()
209 {
210 basic_fstream<char,char_traits<char> > f( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
211
212 CPPUNIT_ASSERT( f.is_open() );
213
214 int i = 9;
215 f << i;
216 CPPUNIT_ASSERT( f.good() );
217 i = 0;
218 f.seekg( 0, ios_base::beg );
219 f >> i;
220 CPPUNIT_ASSERT( !f.fail() );
221 CPPUNIT_ASSERT( i == 9 );
222 f >> i;
223 CPPUNIT_ASSERT( f.fail() );
224 CPPUNIT_ASSERT( f.eof() );
225 CPPUNIT_ASSERT( i == 9 );
226 }
227
tellg()228 void FstreamTest::tellg()
229 {
230 {
231 // bogus ios_base::binary is for Wins
232 ofstream of("test_file.txt", ios_base::out | ios_base::binary | ios_base::trunc);
233 CPPUNIT_ASSERT( of.is_open() );
234
235 for (int i = 0; i < 50; ++i) {
236 of << "line " << setiosflags(ios_base::right) << setfill('0') << setw(2) << i << "\n";
237 CPPUNIT_ASSERT( !of.fail() );
238 }
239 of.close();
240 }
241
242 {
243 // bogus ios_base::binary is for Wins
244 ifstream is("test_file.txt", ios_base::in | ios_base::binary);
245 CPPUNIT_ASSERT( is.is_open() );
246 char buf[64];
247
248 // CPPUNIT_ASSERT( is.tellg() == 0 );
249 streampos p = 0;
250 for (int i = 0; i < 50; ++i) {
251 is.read(buf, 0);
252 CPPUNIT_ASSERT( is.gcount() == 0 );
253 CPPUNIT_ASSERT( is.tellg() == p );
254 is.read( buf, 8 );
255 CPPUNIT_ASSERT( !is.fail() );
256 CPPUNIT_ASSERT( is.gcount() == 8 );
257 p += 8;
258 }
259 }
260
261 {
262 // bogus ios_base::binary is for Wins
263 ifstream is("test_file.txt", ios_base::in | ios_base::binary);
264 CPPUNIT_ASSERT( is.is_open() );
265
266 streampos p = 0;
267 for (int i = 0; i < 50; ++i) {
268 CPPUNIT_ASSERT( !is.fail() );
269 is.tellg();
270 CPPUNIT_ASSERT( is.tellg() == p );
271 p += 8;
272 is.seekg( p, ios_base::beg );
273 CPPUNIT_ASSERT( !is.fail() );
274 }
275 }
276
277 {
278 // bogus ios_base::binary is for Wins
279 ifstream is("test_file.txt", ios_base::in | ios_base::binary);
280 CPPUNIT_ASSERT( is.is_open() );
281
282 streampos p = 0;
283 for (int i = 0; i < 50; ++i) {
284 CPPUNIT_ASSERT( is.tellg() == p );
285 p += 8;
286 is.seekg( 8, ios_base::cur );
287 CPPUNIT_ASSERT( !is.fail() );
288 }
289 }
290 }
291
tellp()292 void FstreamTest::tellp()
293 {
294 {
295 ofstream o( "test_file.txt" );
296
297 o << "123456";
298
299 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(6) );
300 CPPUNIT_CHECK( o.tellp() == ofstream::pos_type(6) );
301 }
302 {
303 ofstream o( "test_file.txt" );
304
305 o << "123456789";
306
307 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(9) );
308 CPPUNIT_CHECK( o.tellp() == ofstream::pos_type(9) );
309 }
310 /* According to the standard
311 ofstream o( "test_file.txt", ios_base::app | ios_base::out )
312 should give the same effect as fopen( "test_file.txt", "a" ).
313 Problem is fopen( "test_file.txt", "a" ) has a bit different behaviour
314 on different platforms, and this difference is not covered by specification.
315 After fopen( "test_file.txt", "a" ) in this context ftell( f ) == 9 for
316 Linux and Mac OS X (I expect the same for others POSIX-like platforms too);
317 on Windows (independently from version?) ftell( f ) == 0, i.e. write pointer not
318 shifted to EOF (but shifted to EOF just before write, as described in the specs).
319
320 It isn't specifications violation, neither for Linux and Mac OS X nor for Windows.
321
322 The code below is intended to demonstrate ambiguity (dependance from fopen implementation).
323 */
324 {
325 #ifdef WIN32
326 //In Windows, stlport and fopen use kernel32.CreateFile for open.
327 //File position is at BOF after open, unless we open with ios_base::ate
328 long expected_pos = 0;
329 #else
330 //On UNIX flavours, stlport and fopen use unix's open
331 //File position is at EOF after open
332 //
333 //3rd possible scenario, "other platforms" - _STLP_USE_STDIO_IO
334 //stlport uses fopen here. This case may fail this test, since the file position after
335 //fopen is implementation-dependent
336 long expected_pos = 9;
337 #endif
338 ofstream o( "test_file.txt", ios_base::app | ios_base::out );
339 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(expected_pos) );
340 CPPUNIT_CHECK( o.tellp() == ofstream::pos_type(expected_pos) );
341 }
342 { // for reference, to test fopen/ftell behaviour in append mode:
343 #ifdef WIN32
344 long expected_pos = 0;
345 #else
346 long expected_pos = 9;
347 #endif
348 FILE* f = fopen( "test_file.txt", "a" );
349 CPPUNIT_ASSERT( f != NULL );
350 CPPUNIT_CHECK( ftell( f ) == expected_pos );
351 fclose( f );
352 }
353 {
354 //In append mode, file is positioned at EOF just before a write.
355 // After a write, file is at EOF. This is implementation-independent.
356 ofstream o( "test_file.txt", ios_base::app | ios_base::out );
357 o << "X";
358 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(10) );
359 CPPUNIT_CHECK( o.tellp() == ofstream::pos_type(10) );
360 }
361 }
362
buf()363 void FstreamTest::buf()
364 {
365 fstream ss( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
366
367 ss << "1234567\n89\n";
368 ss.seekg( 0, ios_base::beg );
369 char buf[10];
370 buf[7] = 'x';
371 ss.get( buf, 10 );
372 CPPUNIT_ASSERT( !ss.fail() );
373 CPPUNIT_ASSERT( buf[0] == '1' );
374 CPPUNIT_ASSERT( buf[1] == '2' );
375 CPPUNIT_ASSERT( buf[2] == '3' );
376 CPPUNIT_ASSERT( buf[3] == '4' );
377 CPPUNIT_ASSERT( buf[4] == '5' );
378 CPPUNIT_ASSERT( buf[5] == '6' );
379 CPPUNIT_ASSERT( buf[6] == '7' ); // 27.6.1.3 paragraph 10, paragraph 7
380 CPPUNIT_ASSERT( buf[7] == 0 ); // 27.6.1.3 paragraph 8
381 char c;
382 ss.get(c);
383 CPPUNIT_ASSERT( !ss.fail() );
384 CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 10, paragraph 7
385 ss.get(c);
386 CPPUNIT_ASSERT( !ss.fail() );
387 CPPUNIT_ASSERT( c == '8' );
388 }
389
seek()390 void FstreamTest::seek()
391 {
392 {
393 // Test in binary mode:
394 {
395 fstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
396 CPPUNIT_ASSERT( s );
397
398 s << "1234567890\n";
399 CPPUNIT_ASSERT( s );
400 }
401
402 char b1[] = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' };
403 fstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary );
404 CPPUNIT_ASSERT( s );
405
406 int chars_read = (int)s.rdbuf()->sgetn( b1, sizeof(b1) );
407 CPPUNIT_CHECK( chars_read == 11 );
408 CPPUNIT_CHECK( b1[9] == '0' );
409 CPPUNIT_ASSERT( s.rdbuf()->pubseekoff( 0, ios_base::cur ) == fstream::pos_type(chars_read) );
410 CPPUNIT_ASSERT( s.rdbuf()->pubseekoff( -chars_read, ios_base::cur ) == fstream::pos_type(0) );
411
412 char b2[10] = { 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y' };
413
414 CPPUNIT_ASSERT( s.rdbuf()->sgetn( b2, 10 ) == 10 );
415 CPPUNIT_CHECK( b2[9] == '0' );
416 }
417
418 {
419 // Test in text mode:
420 {
421 fstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
422 CPPUNIT_ASSERT( s );
423
424 s << "1234567890\n";
425 CPPUNIT_ASSERT( s );
426 }
427
428 char b1[] = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' };
429 fstream s( "test_file.txt", ios_base::in | ios_base::out );
430 CPPUNIT_ASSERT( s );
431
432 int chars_read = (int)s.rdbuf()->sgetn( b1, sizeof(b1) );
433 CPPUNIT_CHECK( chars_read == 11 );
434 CPPUNIT_CHECK( b1[9] == '0' );
435
436 fstream::pos_type pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
437 // Depending on how '\n' is written in file, file position can be greater or equal to the number of chars_read read.
438 streamoff offset = pos;
439 CPPUNIT_ASSERT( offset >= chars_read );
440 offset = s.rdbuf()->pubseekoff( -offset, ios_base::cur );
441 CPPUNIT_ASSERT( offset == 0 );
442
443 char b2[10] = { 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y' };
444
445 CPPUNIT_ASSERT( s.rdbuf()->sgetn( b2, 5 ) == 5 );
446 CPPUNIT_CHECK( b2[4] == '5' );
447
448 pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
449 CPPUNIT_ASSERT( pos == fstream::pos_type(5) );
450 CPPUNIT_ASSERT( s.rdbuf()->pubseekoff(-5, ios_base::cur) == fstream::pos_type(0) );
451 }
452
453 #if !defined (STLPORT) || \
454 (!defined (_STLP_NO_WCHAR_T) && defined (_STLP_USE_EXCEPTIONS))
455 {
456 // Test with a wariable encoding:
457 locale loc;
458 try
459 {
460 locale tmp(locale::classic(), new codecvt_byname<wchar_t, char, mbstate_t>(".UTF8"));
461 loc = tmp;
462 }
463 catch (const runtime_error&)
464 {
465 // Localization no supported so no test:
466 return;
467 }
468
469 {
470 wfstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
471 CPPUNIT_ASSERT( s );
472 s.imbue(loc);
473 CPPUNIT_ASSERT( s );
474
475 s << L"1234567890\n";
476 CPPUNIT_ASSERT( s );
477 }
478
479 wchar_t b1[] = { L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x' };
480 wfstream s( "test_file.txt", ios_base::in | ios_base::out );
481 CPPUNIT_ASSERT( s );
482 s.imbue(loc);
483 CPPUNIT_ASSERT( s );
484
485 int chars_read = (int)s.rdbuf()->sgetn( b1, sizeof(b1) / sizeof(wchar_t) );
486 CPPUNIT_CHECK( chars_read == 11 );
487 CPPUNIT_CHECK( b1[9] == L'0' );
488
489 fstream::pos_type pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
490 // Depending on how '\n' is written in file, file position can be greater or equal to the number of chars_read read.
491 streamoff off = pos;
492 CPPUNIT_ASSERT( off >= chars_read );
493 off = s.rdbuf()->pubseekoff(-off, ios_base::cur);
494 CPPUNIT_ASSERT( off == -1 );
495 off = s.rdbuf()->pubseekoff(0, ios_base::beg);
496 CPPUNIT_ASSERT( off == 0 );
497
498 wchar_t b2[10] = { L'y', L'y', L'y', L'y', L'y', L'y', L'y', L'y', L'y', L'y' };
499
500 CPPUNIT_ASSERT( s.rdbuf()->sgetn( b2, 5 ) == 5 );
501 CPPUNIT_CHECK( b2[4] == L'5' );
502
503 pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
504 CPPUNIT_ASSERT( pos == fstream::pos_type(5) );
505 //CPPUNIT_ASSERT( s.rdbuf()->pubseekoff(-5, ios_base::cur) == fstream::pos_type(0) );
506 }
507 #endif
508 }
509
rdbuf()510 void FstreamTest::rdbuf()
511 {
512 fstream ss( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
513
514 ss << "1234567\n89\n";
515 ss.seekg( 0, ios_base::beg );
516
517 ostringstream os;
518 ss.get( *os.rdbuf(), '\n' );
519 CPPUNIT_ASSERT( !ss.fail() );
520 char c;
521 ss.get(c);
522 CPPUNIT_ASSERT( !ss.fail() );
523 CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 12
524 CPPUNIT_ASSERT( os.str() == "1234567" );
525 }
526
streambuf_output()527 void FstreamTest::streambuf_output()
528 {
529 {
530 ofstream ofstr("test_file.txt", ios_base::binary);
531 if (!ofstr)
532 //No test if we cannot create the file
533 return;
534 ofstr << "01234567890123456789";
535 CPPUNIT_ASSERT( ofstr );
536 }
537
538 {
539 ifstream in("test_file.txt", ios_base::binary);
540 CPPUNIT_ASSERT( in );
541
542 full_streambuf full_buf(10);
543 ostream out(&full_buf);
544 CPPUNIT_ASSERT( out );
545
546 out << in.rdbuf();
547 CPPUNIT_ASSERT( out );
548 CPPUNIT_ASSERT( in );
549 CPPUNIT_ASSERT( full_buf.str() == "0123456789" );
550
551 out << in.rdbuf();
552 CPPUNIT_ASSERT( out.fail() );
553 CPPUNIT_ASSERT( in );
554
555 ostringstream ostr;
556 ostr << in.rdbuf();
557 CPPUNIT_ASSERT( ostr );
558 CPPUNIT_ASSERT( in );
559 CPPUNIT_ASSERT( ostr.str() == "0123456789" );
560 }
561
562 # if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
563 {
564 //If the output stream buffer throws:
565 ifstream in("test_file.txt", ios_base::binary);
566 CPPUNIT_ASSERT( in );
567
568 full_streambuf full_buf(10, true);
569 ostream out(&full_buf);
570 CPPUNIT_ASSERT( out );
571
572 out << in.rdbuf();
573 CPPUNIT_ASSERT( out.bad() );
574 CPPUNIT_ASSERT( in );
575 //out is bad we have no guaranty on what has been extracted:
576 //CPPUNIT_ASSERT( full_buf.str() == "0123456789" );
577
578 out.clear();
579 out << in.rdbuf();
580 CPPUNIT_ASSERT( out.fail() && out.bad() );
581 CPPUNIT_ASSERT( in );
582
583 ostringstream ostr;
584 ostr << in.rdbuf();
585 CPPUNIT_ASSERT( ostr );
586 CPPUNIT_ASSERT( in );
587 CPPUNIT_ASSERT( ostr.str() == "0123456789" );
588 }
589 # endif
590 }
591
win32_file_format()592 void FstreamTest::win32_file_format()
593 {
594 const char* file_name = "win32_file_format.tmp";
595 const size_t nb_lines = 2049;
596 {
597 ofstream out(file_name);
598 CPPUNIT_ASSERT( out.good() );
599 out << 'a';
600 for (size_t i = 0; i < nb_lines - 1; ++i) {
601 out << '\n';
602 }
603 out << '\r';
604 CPPUNIT_ASSERT( out.good() );
605 }
606 {
607 ifstream in(file_name);
608 CPPUNIT_ASSERT( in.good() );
609 string line, last_line;
610 size_t nb_read_lines = 0;
611 while (getline(in, line)) {
612 ++nb_read_lines;
613 last_line = line;
614 }
615 CPPUNIT_ASSERT( in.eof() );
616 CPPUNIT_ASSERT( nb_read_lines == nb_lines );
617 CPPUNIT_ASSERT( !last_line.empty() && (last_line[0] == '\r') );
618 }
619 }
620
621 #if defined (DO_CUSTOM_FACET_TEST)
622 struct my_state {
623 char dummy;
624 };
625
626 struct my_traits : public char_traits<char> {
627 typedef my_state state_type;
628 typedef fpos<state_type> pos_type;
629 };
630
631 #if !defined (STLPORT)
632 //STLport grant a default implementation, other Standard libs implementation
633 //do not necessarily do the same:
634 namespace std {
635 template <>
636 class codecvt<char, char, my_state>
637 : public locale::facet, public codecvt_base {
638 public:
639 typedef char intern_type;
640 typedef char extern_type;
641 typedef my_state state_type;
642
codecvt(size_t __refs=0)643 explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {}
out(state_type &,const intern_type * __from,const intern_type *,const intern_type * & __from_next,extern_type * __to,extern_type *,extern_type * & __to_next) const644 result out(state_type&,
645 const intern_type* __from,
646 const intern_type*,
647 const intern_type*& __from_next,
648 extern_type* __to,
649 extern_type*,
650 extern_type*& __to_next) const
651 { __from_next = __from; __to_next = __to; return noconv; }
652
in(state_type &,const extern_type * __from,const extern_type *,const extern_type * & __from_next,intern_type * __to,intern_type *,intern_type * & __to_next) const653 result in (state_type&,
654 const extern_type* __from,
655 const extern_type*,
656 const extern_type*& __from_next,
657 intern_type* __to,
658 intern_type*,
659 intern_type*& __to_next) const
660 { __from_next = __from; __to_next = __to; return noconv; }
661
unshift(state_type &,extern_type * __to,extern_type *,extern_type * & __to_next) const662 result unshift(state_type&,
663 extern_type* __to,
664 extern_type*,
665 extern_type*& __to_next) const
666 { __to_next = __to; return noconv; }
667
encoding() const668 int encoding() const throw()
669 { return 1; }
670
always_noconv() const671 bool always_noconv() const throw()
672 { return true; }
673
length(const state_type &,const extern_type * __from,const extern_type * __end,size_t __max) const674 int length(const state_type&,
675 const extern_type* __from,
676 const extern_type* __end,
677 size_t __max) const
678 { return (int)min(static_cast<size_t>(__end - __from), __max); }
679
max_length() const680 int max_length() const throw()
681 { return 1; }
682
683 static locale::id id;
684 };
685
686 locale::id codecvt<char, char, my_state>::id;
687 }
688 # else
689 # if defined (__BORLANDC__) && (__BORLANDC__ < 0x590)
690 template <>
691 locale::id codecvt<char, char, my_state>::id;
692 # endif
693 # endif
694 #endif
695
custom_facet()696 void FstreamTest::custom_facet()
697 {
698 #if defined (DO_CUSTOM_FACET_TEST)
699 const char* fileName = "test_file.txt";
700 //File preparation:
701 {
702 ofstream ofstr(fileName, ios_base::binary);
703 ofstr << "0123456789";
704 CPPUNIT_ASSERT( ofstr );
705 }
706
707 {
708 typedef basic_ifstream<char, my_traits> my_ifstream;
709 typedef basic_string<char, my_traits> my_string;
710
711 my_ifstream ifstr(fileName);
712 CPPUNIT_ASSERT( ifstr );
713
714 # if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
715 ifstr.imbue(locale::classic());
716 CPPUNIT_ASSERT( ifstr.fail() && !ifstr.bad() );
717 ifstr.clear();
718 # endif
719 typedef codecvt<char, char, my_state> my_codecvt;
720 locale my_loc(locale::classic(), new my_codecvt());
721 // Check that my_codecvt has not replace default codecvt:
722 CPPUNIT_ASSERT( (has_facet<my_codecvt>(my_loc)) );
723 CPPUNIT_ASSERT( (has_facet<codecvt<char, char, mbstate_t> >(my_loc)) );
724 # if !defined (STLPORT) || !defined (_STLP_NO_WCHAR_T)
725 CPPUNIT_ASSERT( (has_facet<codecvt<wchar_t, char, mbstate_t> >(my_loc)) );
726 # endif
727 ifstr.imbue(my_loc);
728 CPPUNIT_ASSERT( ifstr.good() );
729 /*
730 my_string res;
731 ifstr >> res;
732 CPPUNIT_ASSERT( !ifstr.fail() );
733 CPPUNIT_ASSERT( !ifstr.bad() );
734 CPPUNIT_ASSERT( ifstr.eof() );
735 CPPUNIT_ASSERT( res == "0123456789" );
736 */
737 }
738 #endif
739 }
740
741 # if defined (CHECK_BIG_FILE)
big_file()742 void FstreamTest::big_file()
743 {
744 vector<pair<streamsize, streamoff> > file_pos;
745
746 //Big file creation:
747 {
748 ofstream out("big_file.txt");
749 CPPUNIT_ASSERT( out );
750
751 //We are going to generate a file with the following schema for the content:
752 //0(1019 times)0000 //1023 characters + 1 charater for \n (for some platforms it will be a 1 ko line)
753 //0(1019 times)0001
754 //...
755 //0(1019 times)1234
756 //...
757
758 //Generation of the number of loop:
759 streamoff nb = 1;
760 for (int i = 0; i < 20; ++i) {
761 //This assertion check that the streamoff can at least represent the necessary integers values
762 //for this test:
763 CPPUNIT_ASSERT( (nb << 1) > nb );
764 nb <<= 1;
765 }
766 CPPUNIT_ASSERT( nb * CHECK_BIG_FILE >= nb );
767 nb *= CHECK_BIG_FILE;
768
769 //Preparation of the ouput stream state:
770 out << setiosflags(ios_base::right) << setfill('*');
771 for (streamoff index = 0; index < nb; ++index) {
772 if (index % 1024 == 0) {
773 file_pos.push_back(make_pair(out.tellp(), index));
774 CPPUNIT_ASSERT( file_pos.back().first != streamsize(-1) );
775 if (file_pos.size() > 1) {
776 CPPUNIT_ASSERT( file_pos[file_pos.size() - 1].first > file_pos[file_pos.size() - 2].first );
777 }
778 }
779 out << setw(1023) << index << '\n';
780 }
781 }
782
783 {
784 ifstream in("big_file.txt");
785 CPPUNIT_ASSERT( in );
786
787 string line;
788 vector<pair<streamsize, streamsize> >::const_iterator pit(file_pos.begin()),
789 pitEnd(file_pos.end());
790 for (; pit != pitEnd; ++pit) {
791 in.seekg((*pit).first);
792 CPPUNIT_ASSERT( in );
793 in >> line;
794 size_t lastStarPos = line.rfind('*');
795 CPPUNIT_ASSERT( atoi(line.substr(lastStarPos + 1).c_str()) == (*pit).second );
796 }
797 }
798
799 /*
800 The following test has been used to check that STLport do not generate
801 an infinite loop when the file size is larger than the streamsize and
802 streamoff representation (32 bits or 64 bits).
803 {
804 ifstream in("big_file.txt");
805 CPPUNIT_ASSERT( in );
806 char tmp[4096];
807 streamsize nb_reads = 0;
808 while ((!in.eof()) && in.good()){
809 in.read(tmp, 4096);
810 nb_reads += in.gcount();
811 }
812 }
813 */
814 }
815 # endif
816
null_stream()817 void FstreamTest::null_stream()
818 {
819 # if (defined (STLPORT) && defined (_STLP_USE_WIN32_IO)) || \
820 (!defined (STLPORT) && (defined (WIN32) || defined (_WIN32)))
821 const char* nullStreamName = "NUL";
822 # else
823 const char* nullStreamName = "/dev/null";
824 # endif
825 {
826 ofstream nullStream(nullStreamName);
827 CPPUNIT_CHECK( nullStream );
828 }
829
830 {
831 ofstream nullStream(nullStreamName, ios_base::ate);
832 CPPUNIT_CHECK( nullStream );
833 }
834
835 {
836 ofstream nullStream(nullStreamName, ios_base::trunc);
837 CPPUNIT_CHECK( nullStream );
838 }
839
840 {
841 ofstream nullStream(nullStreamName, ios_base::app);
842 CPPUNIT_CHECK( nullStream );
843 }
844
845 {
846 ifstream nullStream(nullStreamName);
847 CPPUNIT_CHECK( nullStream );
848 }
849
850 {
851 ifstream nullStream(nullStreamName, ios_base::ate);
852 CPPUNIT_CHECK( nullStream );
853 }
854
855 {
856 fstream nullStream(nullStreamName);
857 CPPUNIT_CHECK( nullStream );
858 }
859
860 {
861 fstream nullStream(nullStreamName, ios_base::in | ios_base::out | ios_base::ate);
862 CPPUNIT_CHECK( nullStream );
863 }
864
865 {
866 fstream nullStream(nullStreamName, ios_base::in | ios_base::out | ios_base::trunc);
867 CPPUNIT_CHECK( nullStream );
868 }
869 }
870
null_buf()871 void FstreamTest::null_buf()
872 {
873 /* **********************************************************************************
874
875 testcase for bug #1830513:
876 in _istream.c
877
878 template < class _CharT, class _Traits, class _Is_Delim>
879 streamsize _STLP_CALL __read_unbuffered(basic_istream<_CharT, _Traits>* __that,
880 basic_streambuf<_CharT, _Traits>* __buf,
881 streamsize _Num, _CharT* __s,
882 _Is_Delim __is_delim,
883 bool __extract_delim, bool __append_null,
884 bool __is_getline)
885
886 can't accept _Num == 0; this is legal case, and may happen from
887
888 template <class _CharT, class _Traits>
889 basic_istream<_CharT, _Traits>&
890 basic_istream<_CharT, _Traits>::getline(_CharT* __s, streamsize __n, _CharT __delim)
891
892 *********************************************************************************** */
893
894 fstream f( "test.txt", ios_base::in | ios_base::out | ios_base::trunc );
895 // string line;
896
897 for ( int i = 0; i < 0x200; ++i ) {
898 f.put( ' ' );
899 }
900
901 // const streambuf *b = f.rdbuf();
902
903 // string s;
904 char buf[1024];
905 buf[0] = 'a';
906 buf[1] = 'b';
907 buf[2] = 'c';
908
909 // getline( f, s );
910 // cerr << f.good() << endl;
911 f.seekg( 0, ios_base::beg );
912 // f.seekg( 0, ios_base::end );
913 // buf[0] = f.get();
914
915 // cerr << (void *)(b->_M_gptr()) << " " << (void *)(b->_M_egptr()) << endl;
916 // cerr << f.good() << endl;
917 // getline( f, s );
918 f.getline( buf, 1 ); // <-- key line
919 CPPUNIT_CHECK( buf[0] == 0 );
920 CPPUNIT_CHECK( f.fail() ); // due to delimiter not found while buffer was exhausted
921 }
922
923 # if !defined (STLPORT) || !defined (_STLP_WIN32)
offset()924 void FstreamTest::offset()
925 {
926 # if (defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE)) && !defined(_STLP_USE_DEFAULT_FILE_OFFSET)
927 CPPUNIT_CHECK( sizeof(streamoff) == 8 );
928 # else
929 CPPUNIT_CHECK( sizeof(streamoff) == sizeof(off_t) );
930 # endif
931 }
932 # endif
933
934 #endif
935