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