Home | History | Annotate | Download | only in unit
      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 //
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    643     explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {}
    644     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 
    653     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 
    662     result unshift(state_type&,
    663                    extern_type* __to,
    664                    extern_type*,
    665                    extern_type*& __to_next) const
    666     { __to_next = __to; return noconv; }
    667 
    668     int encoding() const throw()
    669     { return 1; }
    670 
    671     bool always_noconv() const throw()
    672     { return true; }
    673 
    674     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 
    680     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 
    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)
    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 
    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 
    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)
    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