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