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