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_CHECK( ftell( f ) == expected_pos );
350 fclose( f );
351 }
352 {
353 //In append mode, file is positioned at EOF just before a write.
354 // After a write, file is at EOF. This is implementation-independent.
355 ofstream o( "test_file.txt", ios_base::app | ios_base::out );
356 o << "X";
357 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(10) );
358 CPPUNIT_CHECK( o.tellp() == ofstream::pos_type(10) );
359 }
360 }
361
buf()362 void FstreamTest::buf()
363 {
364 fstream ss( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
365
366 ss << "1234567\n89\n";
367 ss.seekg( 0, ios_base::beg );
368 char buf[10];
369 buf[7] = 'x';
370 ss.get( buf, 10 );
371 CPPUNIT_ASSERT( !ss.fail() );
372 CPPUNIT_ASSERT( buf[0] == '1' );
373 CPPUNIT_ASSERT( buf[1] == '2' );
374 CPPUNIT_ASSERT( buf[2] == '3' );
375 CPPUNIT_ASSERT( buf[3] == '4' );
376 CPPUNIT_ASSERT( buf[4] == '5' );
377 CPPUNIT_ASSERT( buf[5] == '6' );
378 CPPUNIT_ASSERT( buf[6] == '7' ); // 27.6.1.3 paragraph 10, paragraph 7
379 CPPUNIT_ASSERT( buf[7] == 0 ); // 27.6.1.3 paragraph 8
380 char c;
381 ss.get(c);
382 CPPUNIT_ASSERT( !ss.fail() );
383 CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 10, paragraph 7
384 ss.get(c);
385 CPPUNIT_ASSERT( !ss.fail() );
386 CPPUNIT_ASSERT( c == '8' );
387 }
388
seek()389 void FstreamTest::seek()
390 {
391 {
392 // Test in binary mode:
393 {
394 fstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
395 CPPUNIT_ASSERT( s );
396
397 s << "1234567890\n";
398 CPPUNIT_ASSERT( s );
399 }
400
401 char b1[] = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' };
402 fstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary );
403 CPPUNIT_ASSERT( s );
404
405 int chars_read = (int)s.rdbuf()->sgetn( b1, sizeof(b1) );
406 CPPUNIT_CHECK( chars_read == 11 );
407 CPPUNIT_CHECK( b1[9] == '0' );
408 CPPUNIT_ASSERT( s.rdbuf()->pubseekoff( 0, ios_base::cur ) == fstream::pos_type(chars_read) );
409 CPPUNIT_ASSERT( s.rdbuf()->pubseekoff( -chars_read, ios_base::cur ) == fstream::pos_type(0) );
410
411 char b2[10] = { 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y' };
412
413 CPPUNIT_ASSERT( s.rdbuf()->sgetn( b2, 10 ) == 10 );
414 CPPUNIT_CHECK( b2[9] == '0' );
415 }
416
417 {
418 // Test in text mode:
419 {
420 fstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
421 CPPUNIT_ASSERT( s );
422
423 s << "1234567890\n";
424 CPPUNIT_ASSERT( s );
425 }
426
427 char b1[] = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' };
428 fstream s( "test_file.txt", ios_base::in | ios_base::out );
429 CPPUNIT_ASSERT( s );
430
431 int chars_read = (int)s.rdbuf()->sgetn( b1, sizeof(b1) );
432 CPPUNIT_CHECK( chars_read == 11 );
433 CPPUNIT_CHECK( b1[9] == '0' );
434
435 fstream::pos_type pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
436 // Depending on how '\n' is written in file, file position can be greater or equal to the number of chars_read read.
437 streamoff offset = pos;
438 CPPUNIT_ASSERT( offset >= chars_read );
439 offset = s.rdbuf()->pubseekoff( -offset, ios_base::cur );
440 CPPUNIT_ASSERT( offset == 0 );
441
442 char b2[10] = { 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y' };
443
444 CPPUNIT_ASSERT( s.rdbuf()->sgetn( b2, 5 ) == 5 );
445 CPPUNIT_CHECK( b2[4] == '5' );
446
447 pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
448 CPPUNIT_ASSERT( pos == fstream::pos_type(5) );
449 CPPUNIT_ASSERT( s.rdbuf()->pubseekoff(-5, ios_base::cur) == fstream::pos_type(0) );
450 }
451
452 #if !defined (STLPORT) || \
453 (!defined (_STLP_NO_WCHAR_T) && defined (_STLP_USE_EXCEPTIONS))
454 {
455 // Test with a wariable encoding:
456 locale loc;
457 try
458 {
459 locale tmp(locale::classic(), new codecvt_byname<wchar_t, char, mbstate_t>(".UTF8"));
460 loc = tmp;
461 }
462 catch (const runtime_error&)
463 {
464 // Localization no supported so no test:
465 return;
466 }
467
468 {
469 wfstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
470 CPPUNIT_ASSERT( s );
471 s.imbue(loc);
472 CPPUNIT_ASSERT( s );
473
474 s << L"1234567890\n";
475 CPPUNIT_ASSERT( s );
476 }
477
478 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' };
479 wfstream s( "test_file.txt", ios_base::in | ios_base::out );
480 CPPUNIT_ASSERT( s );
481 s.imbue(loc);
482 CPPUNIT_ASSERT( s );
483
484 int chars_read = (int)s.rdbuf()->sgetn( b1, sizeof(b1) / sizeof(wchar_t) );
485 CPPUNIT_CHECK( chars_read == 11 );
486 CPPUNIT_CHECK( b1[9] == L'0' );
487
488 fstream::pos_type pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
489 // Depending on how '\n' is written in file, file position can be greater or equal to the number of chars_read read.
490 streamoff off = pos;
491 CPPUNIT_ASSERT( off >= chars_read );
492 off = s.rdbuf()->pubseekoff(-off, ios_base::cur);
493 CPPUNIT_ASSERT( off == -1 );
494 off = s.rdbuf()->pubseekoff(0, ios_base::beg);
495 CPPUNIT_ASSERT( off == 0 );
496
497 wchar_t b2[10] = { L'y', L'y', L'y', L'y', L'y', L'y', L'y', L'y', L'y', L'y' };
498
499 CPPUNIT_ASSERT( s.rdbuf()->sgetn( b2, 5 ) == 5 );
500 CPPUNIT_CHECK( b2[4] == L'5' );
501
502 pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
503 CPPUNIT_ASSERT( pos == fstream::pos_type(5) );
504 //CPPUNIT_ASSERT( s.rdbuf()->pubseekoff(-5, ios_base::cur) == fstream::pos_type(0) );
505 }
506 #endif
507 }
508
rdbuf()509 void FstreamTest::rdbuf()
510 {
511 fstream ss( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
512
513 ss << "1234567\n89\n";
514 ss.seekg( 0, ios_base::beg );
515
516 ostringstream os;
517 ss.get( *os.rdbuf(), '\n' );
518 CPPUNIT_ASSERT( !ss.fail() );
519 char c;
520 ss.get(c);
521 CPPUNIT_ASSERT( !ss.fail() );
522 CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 12
523 CPPUNIT_ASSERT( os.str() == "1234567" );
524 }
525
streambuf_output()526 void FstreamTest::streambuf_output()
527 {
528 {
529 ofstream ofstr("test_file.txt", ios_base::binary);
530 if (!ofstr)
531 //No test if we cannot create the file
532 return;
533 ofstr << "01234567890123456789";
534 CPPUNIT_ASSERT( ofstr );
535 }
536
537 {
538 ifstream in("test_file.txt", ios_base::binary);
539 CPPUNIT_ASSERT( in );
540
541 full_streambuf full_buf(10);
542 ostream out(&full_buf);
543 CPPUNIT_ASSERT( out );
544
545 out << in.rdbuf();
546 CPPUNIT_ASSERT( out );
547 CPPUNIT_ASSERT( in );
548 CPPUNIT_ASSERT( full_buf.str() == "0123456789" );
549
550 out << in.rdbuf();
551 CPPUNIT_ASSERT( out.fail() );
552 CPPUNIT_ASSERT( in );
553
554 ostringstream ostr;
555 ostr << in.rdbuf();
556 CPPUNIT_ASSERT( ostr );
557 CPPUNIT_ASSERT( in );
558 CPPUNIT_ASSERT( ostr.str() == "0123456789" );
559 }
560
561 # if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
562 {
563 //If the output stream buffer throws:
564 ifstream in("test_file.txt", ios_base::binary);
565 CPPUNIT_ASSERT( in );
566
567 full_streambuf full_buf(10, true);
568 ostream out(&full_buf);
569 CPPUNIT_ASSERT( out );
570
571 out << in.rdbuf();
572 CPPUNIT_ASSERT( out.bad() );
573 CPPUNIT_ASSERT( in );
574 //out is bad we have no guaranty on what has been extracted:
575 //CPPUNIT_ASSERT( full_buf.str() == "0123456789" );
576
577 out.clear();
578 out << in.rdbuf();
579 CPPUNIT_ASSERT( out.fail() && out.bad() );
580 CPPUNIT_ASSERT( in );
581
582 ostringstream ostr;
583 ostr << in.rdbuf();
584 CPPUNIT_ASSERT( ostr );
585 CPPUNIT_ASSERT( in );
586 CPPUNIT_ASSERT( ostr.str() == "0123456789" );
587 }
588 # endif
589 }
590
win32_file_format()591 void FstreamTest::win32_file_format()
592 {
593 const char* file_name = "win32_file_format.tmp";
594 const size_t nb_lines = 2049;
595 {
596 ofstream out(file_name);
597 CPPUNIT_ASSERT( out.good() );
598 out << 'a';
599 for (size_t i = 0; i < nb_lines - 1; ++i) {
600 out << '\n';
601 }
602 out << '\r';
603 CPPUNIT_ASSERT( out.good() );
604 }
605 {
606 ifstream in(file_name);
607 CPPUNIT_ASSERT( in.good() );
608 string line, last_line;
609 size_t nb_read_lines = 0;
610 while (getline(in, line)) {
611 ++nb_read_lines;
612 last_line = line;
613 }
614 CPPUNIT_ASSERT( in.eof() );
615 CPPUNIT_ASSERT( nb_read_lines == nb_lines );
616 CPPUNIT_ASSERT( !last_line.empty() && (last_line[0] == '\r') );
617 }
618 }
619
620 #if defined (DO_CUSTOM_FACET_TEST)
621 struct my_state {
622 char dummy;
623 };
624
625 struct my_traits : public char_traits<char> {
626 typedef my_state state_type;
627 typedef fpos<state_type> pos_type;
628 };
629
630 #if !defined (STLPORT)
631 //STLport grant a default implementation, other Standard libs implementation
632 //do not necessarily do the same:
633 namespace std {
634 template <>
635 class codecvt<char, char, my_state>
636 : public locale::facet, public codecvt_base {
637 public:
638 typedef char intern_type;
639 typedef char extern_type;
640 typedef my_state state_type;
641
codecvt(size_t __refs=0)642 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) const643 result out(state_type&,
644 const intern_type* __from,
645 const intern_type*,
646 const intern_type*& __from_next,
647 extern_type* __to,
648 extern_type*,
649 extern_type*& __to_next) const
650 { __from_next = __from; __to_next = __to; return noconv; }
651
in(state_type &,const extern_type * __from,const extern_type *,const extern_type * & __from_next,intern_type * __to,intern_type *,intern_type * & __to_next) const652 result in (state_type&,
653 const extern_type* __from,
654 const extern_type*,
655 const extern_type*& __from_next,
656 intern_type* __to,
657 intern_type*,
658 intern_type*& __to_next) const
659 { __from_next = __from; __to_next = __to; return noconv; }
660
unshift(state_type &,extern_type * __to,extern_type *,extern_type * & __to_next) const661 result unshift(state_type&,
662 extern_type* __to,
663 extern_type*,
664 extern_type*& __to_next) const
665 { __to_next = __to; return noconv; }
666
encoding() const667 int encoding() const throw()
668 { return 1; }
669
always_noconv() const670 bool always_noconv() const throw()
671 { return true; }
672
length(const state_type &,const extern_type * __from,const extern_type * __end,size_t __max) const673 int length(const state_type&,
674 const extern_type* __from,
675 const extern_type* __end,
676 size_t __max) const
677 { return (int)min(static_cast<size_t>(__end - __from), __max); }
678
max_length() const679 int max_length() const throw()
680 { return 1; }
681
682 static locale::id id;
683 };
684
685 locale::id codecvt<char, char, my_state>::id;
686 }
687 # else
688 # if defined (__BORLANDC__) && (__BORLANDC__ < 0x590)
689 template <>
690 locale::id codecvt<char, char, my_state>::id;
691 # endif
692 # endif
693 #endif
694
custom_facet()695 void FstreamTest::custom_facet()
696 {
697 #if defined (DO_CUSTOM_FACET_TEST)
698 const char* fileName = "test_file.txt";
699 //File preparation:
700 {
701 ofstream ofstr(fileName, ios_base::binary);
702 ofstr << "0123456789";
703 CPPUNIT_ASSERT( ofstr );
704 }
705
706 {
707 typedef basic_ifstream<char, my_traits> my_ifstream;
708 typedef basic_string<char, my_traits> my_string;
709
710 my_ifstream ifstr(fileName);
711 CPPUNIT_ASSERT( ifstr );
712
713 # if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
714 ifstr.imbue(locale::classic());
715 CPPUNIT_ASSERT( ifstr.fail() && !ifstr.bad() );
716 ifstr.clear();
717 # endif
718 typedef codecvt<char, char, my_state> my_codecvt;
719 locale my_loc(locale::classic(), new my_codecvt());
720 // Check that my_codecvt has not replace default codecvt:
721 CPPUNIT_ASSERT( (has_facet<my_codecvt>(my_loc)) );
722 CPPUNIT_ASSERT( (has_facet<codecvt<char, char, mbstate_t> >(my_loc)) );
723 # if !defined (STLPORT) || !defined (_STLP_NO_WCHAR_T)
724 CPPUNIT_ASSERT( (has_facet<codecvt<wchar_t, char, mbstate_t> >(my_loc)) );
725 # endif
726 ifstr.imbue(my_loc);
727 CPPUNIT_ASSERT( ifstr.good() );
728 /*
729 my_string res;
730 ifstr >> res;
731 CPPUNIT_ASSERT( !ifstr.fail() );
732 CPPUNIT_ASSERT( !ifstr.bad() );
733 CPPUNIT_ASSERT( ifstr.eof() );
734 CPPUNIT_ASSERT( res == "0123456789" );
735 */
736 }
737 #endif
738 }
739
740 # if defined (CHECK_BIG_FILE)
big_file()741 void FstreamTest::big_file()
742 {
743 vector<pair<streamsize, streamoff> > file_pos;
744
745 //Big file creation:
746 {
747 ofstream out("big_file.txt");
748 CPPUNIT_ASSERT( out );
749
750 //We are going to generate a file with the following schema for the content:
751 //0(1019 times)0000 //1023 characters + 1 charater for \n (for some platforms it will be a 1 ko line)
752 //0(1019 times)0001
753 //...
754 //0(1019 times)1234
755 //...
756
757 //Generation of the number of loop:
758 streamoff nb = 1;
759 for (int i = 0; i < 20; ++i) {
760 //This assertion check that the streamoff can at least represent the necessary integers values
761 //for this test:
762 CPPUNIT_ASSERT( (nb << 1) > nb );
763 nb <<= 1;
764 }
765 CPPUNIT_ASSERT( nb * CHECK_BIG_FILE >= nb );
766 nb *= CHECK_BIG_FILE;
767
768 //Preparation of the ouput stream state:
769 out << setiosflags(ios_base::right) << setfill('*');
770 for (streamoff index = 0; index < nb; ++index) {
771 if (index % 1024 == 0) {
772 file_pos.push_back(make_pair(out.tellp(), index));
773 CPPUNIT_ASSERT( file_pos.back().first != streamsize(-1) );
774 if (file_pos.size() > 1) {
775 CPPUNIT_ASSERT( file_pos[file_pos.size() - 1].first > file_pos[file_pos.size() - 2].first );
776 }
777 }
778 out << setw(1023) << index << '\n';
779 }
780 }
781
782 {
783 ifstream in("big_file.txt");
784 CPPUNIT_ASSERT( in );
785
786 string line;
787 vector<pair<streamsize, streamsize> >::const_iterator pit(file_pos.begin()),
788 pitEnd(file_pos.end());
789 for (; pit != pitEnd; ++pit) {
790 in.seekg((*pit).first);
791 CPPUNIT_ASSERT( in );
792 in >> line;
793 size_t lastStarPos = line.rfind('*');
794 CPPUNIT_ASSERT( atoi(line.substr(lastStarPos + 1).c_str()) == (*pit).second );
795 }
796 }
797
798 /*
799 The following test has been used to check that STLport do not generate
800 an infinite loop when the file size is larger than the streamsize and
801 streamoff representation (32 bits or 64 bits).
802 {
803 ifstream in("big_file.txt");
804 CPPUNIT_ASSERT( in );
805 char tmp[4096];
806 streamsize nb_reads = 0;
807 while ((!in.eof()) && in.good()){
808 in.read(tmp, 4096);
809 nb_reads += in.gcount();
810 }
811 }
812 */
813 }
814 # endif
815
null_stream()816 void FstreamTest::null_stream()
817 {
818 # if (defined (STLPORT) && defined (_STLP_USE_WIN32_IO)) || \
819 (!defined (STLPORT) && (defined (WIN32) || defined (_WIN32)))
820 const char* nullStreamName = "NUL";
821 # else
822 const char* nullStreamName = "/dev/null";
823 # endif
824 {
825 ofstream nullStream(nullStreamName);
826 CPPUNIT_CHECK( nullStream );
827 }
828
829 {
830 ofstream nullStream(nullStreamName, ios_base::ate);
831 CPPUNIT_CHECK( nullStream );
832 }
833
834 {
835 ofstream nullStream(nullStreamName, ios_base::trunc);
836 CPPUNIT_CHECK( nullStream );
837 }
838
839 {
840 ofstream nullStream(nullStreamName, ios_base::app);
841 CPPUNIT_CHECK( nullStream );
842 }
843
844 {
845 ifstream nullStream(nullStreamName);
846 CPPUNIT_CHECK( nullStream );
847 }
848
849 {
850 ifstream nullStream(nullStreamName, ios_base::ate);
851 CPPUNIT_CHECK( nullStream );
852 }
853
854 {
855 fstream nullStream(nullStreamName);
856 CPPUNIT_CHECK( nullStream );
857 }
858
859 {
860 fstream nullStream(nullStreamName, ios_base::in | ios_base::out | ios_base::ate);
861 CPPUNIT_CHECK( nullStream );
862 }
863
864 {
865 fstream nullStream(nullStreamName, ios_base::in | ios_base::out | ios_base::trunc);
866 CPPUNIT_CHECK( nullStream );
867 }
868 }
869
null_buf()870 void FstreamTest::null_buf()
871 {
872 /* **********************************************************************************
873
874 testcase for bug #1830513:
875 in _istream.c
876
877 template < class _CharT, class _Traits, class _Is_Delim>
878 streamsize _STLP_CALL __read_unbuffered(basic_istream<_CharT, _Traits>* __that,
879 basic_streambuf<_CharT, _Traits>* __buf,
880 streamsize _Num, _CharT* __s,
881 _Is_Delim __is_delim,
882 bool __extract_delim, bool __append_null,
883 bool __is_getline)
884
885 can't accept _Num == 0; this is legal case, and may happen from
886
887 template <class _CharT, class _Traits>
888 basic_istream<_CharT, _Traits>&
889 basic_istream<_CharT, _Traits>::getline(_CharT* __s, streamsize __n, _CharT __delim)
890
891 *********************************************************************************** */
892
893 fstream f( "test.txt", ios_base::in | ios_base::out | ios_base::trunc );
894 // string line;
895
896 for ( int i = 0; i < 0x200; ++i ) {
897 f.put( ' ' );
898 }
899
900 // const streambuf *b = f.rdbuf();
901
902 // string s;
903 char buf[1024];
904 buf[0] = 'a';
905 buf[1] = 'b';
906 buf[2] = 'c';
907
908 // getline( f, s );
909 // cerr << f.good() << endl;
910 f.seekg( 0, ios_base::beg );
911 // f.seekg( 0, ios_base::end );
912 // buf[0] = f.get();
913
914 // cerr << (void *)(b->_M_gptr()) << " " << (void *)(b->_M_egptr()) << endl;
915 // cerr << f.good() << endl;
916 // getline( f, s );
917 f.getline( buf, 1 ); // <-- key line
918 CPPUNIT_CHECK( buf[0] == 0 );
919 CPPUNIT_CHECK( f.fail() ); // due to delimiter not found while buffer was exhausted
920 }
921
922 # if !defined (STLPORT) || !defined (_STLP_WIN32)
offset()923 void FstreamTest::offset()
924 {
925 # if (defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE)) && !defined(_STLP_USE_DEFAULT_FILE_OFFSET)
926 CPPUNIT_CHECK( sizeof(streamoff) == 8 );
927 # else
928 CPPUNIT_CHECK( sizeof(streamoff) == sizeof(off_t) );
929 # endif
930 }
931 # endif
932
933 #endif
934