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_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 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 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 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 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 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 642 explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} 643 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 652 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 661 result unshift(state_type&, 662 extern_type* __to, 663 extern_type*, 664 extern_type*& __to_next) const 665 { __to_next = __to; return noconv; } 666 667 int encoding() const throw() 668 { return 1; } 669 670 bool always_noconv() const throw() 671 { return true; } 672 673 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 679 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 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) 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 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 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) 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