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