stdio_test.cpp revision 69f05d291d848de654c72e5278de8ca06fbf5d2f
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <gtest/gtest.h> 18 19#include <errno.h> 20#include <fcntl.h> 21#include <limits.h> 22#include <math.h> 23#include <stdio.h> 24#include <sys/types.h> 25#include <sys/stat.h> 26#include <unistd.h> 27#include <wchar.h> 28#include <locale.h> 29 30#include "TemporaryFile.h" 31 32TEST(stdio, tmpfile_fileno_fprintf_rewind_fgets) { 33 FILE* fp = tmpfile(); 34 ASSERT_TRUE(fp != NULL); 35 36 int fd = fileno(fp); 37 ASSERT_NE(fd, -1); 38 39 struct stat sb; 40 int rc = fstat(fd, &sb); 41 ASSERT_NE(rc, -1); 42 ASSERT_EQ(sb.st_mode & 0777, 0600U); 43 44 rc = fprintf(fp, "hello\n"); 45 ASSERT_EQ(rc, 6); 46 47 rewind(fp); 48 49 char buf[16]; 50 char* s = fgets(buf, sizeof(buf), fp); 51 ASSERT_TRUE(s != NULL); 52 ASSERT_STREQ("hello\n", s); 53 54 fclose(fp); 55} 56 57TEST(stdio, dprintf) { 58 TemporaryFile tf; 59 60 int rc = dprintf(tf.fd, "hello\n"); 61 ASSERT_EQ(rc, 6); 62 63 lseek(tf.fd, SEEK_SET, 0); 64 FILE* tfile = fdopen(tf.fd, "r"); 65 ASSERT_TRUE(tfile != NULL); 66 67 char buf[7]; 68 ASSERT_EQ(buf, fgets(buf, sizeof(buf), tfile)); 69 ASSERT_STREQ("hello\n", buf); 70 // Make sure there isn't anything else in the file. 71 ASSERT_EQ(NULL, fgets(buf, sizeof(buf), tfile)); 72 fclose(tfile); 73} 74 75TEST(stdio, getdelim) { 76 FILE* fp = tmpfile(); 77 ASSERT_TRUE(fp != NULL); 78 79 const char* line_written = "This is a test"; 80 int rc = fprintf(fp, "%s", line_written); 81 ASSERT_EQ(rc, static_cast<int>(strlen(line_written))); 82 83 rewind(fp); 84 85 char* word_read = NULL; 86 size_t allocated_length = 0; 87 88 const char* expected[] = { "This ", " ", "is ", "a ", "test" }; 89 for (size_t i = 0; i < 5; ++i) { 90 ASSERT_FALSE(feof(fp)); 91 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), static_cast<int>(strlen(expected[i]))); 92 ASSERT_GE(allocated_length, strlen(expected[i])); 93 ASSERT_STREQ(word_read, expected[i]); 94 } 95 // The last read should have set the end-of-file indicator for the stream. 96 ASSERT_TRUE(feof(fp)); 97 clearerr(fp); 98 99 // getdelim returns -1 but doesn't set errno if we're already at EOF. 100 // It should set the end-of-file indicator for the stream, though. 101 errno = 0; 102 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), -1); 103 ASSERT_EQ(0, errno); 104 ASSERT_TRUE(feof(fp)); 105 106 free(word_read); 107 fclose(fp); 108} 109 110TEST(stdio, getdelim_invalid) { 111 FILE* fp = tmpfile(); 112 ASSERT_TRUE(fp != NULL); 113 114 char* buffer = NULL; 115 size_t buffer_length = 0; 116 117 // The first argument can't be NULL. 118 errno = 0; 119 ASSERT_EQ(getdelim(NULL, &buffer_length, ' ', fp), -1); 120 ASSERT_EQ(EINVAL, errno); 121 122 // The second argument can't be NULL. 123 errno = 0; 124 ASSERT_EQ(getdelim(&buffer, NULL, ' ', fp), -1); 125 ASSERT_EQ(EINVAL, errno); 126 127 // The underlying fd can't be closed. 128 ASSERT_EQ(0, close(fileno(fp))); 129 errno = 0; 130 ASSERT_EQ(getdelim(&buffer, &buffer_length, ' ', fp), -1); 131 ASSERT_EQ(EBADF, errno); 132 fclose(fp); 133} 134 135TEST(stdio, getline) { 136 FILE* fp = tmpfile(); 137 ASSERT_TRUE(fp != NULL); 138 139 const char* line_written = "This is a test for getline\n"; 140 const size_t line_count = 5; 141 142 for (size_t i = 0; i < line_count; ++i) { 143 int rc = fprintf(fp, "%s", line_written); 144 ASSERT_EQ(rc, static_cast<int>(strlen(line_written))); 145 } 146 147 rewind(fp); 148 149 char* line_read = NULL; 150 size_t allocated_length = 0; 151 152 size_t read_line_count = 0; 153 ssize_t read_char_count; 154 while ((read_char_count = getline(&line_read, &allocated_length, fp)) != -1) { 155 ASSERT_EQ(read_char_count, static_cast<int>(strlen(line_written))); 156 ASSERT_GE(allocated_length, strlen(line_written)); 157 ASSERT_STREQ(line_read, line_written); 158 ++read_line_count; 159 } 160 ASSERT_EQ(read_line_count, line_count); 161 162 // The last read should have set the end-of-file indicator for the stream. 163 ASSERT_TRUE(feof(fp)); 164 clearerr(fp); 165 166 // getline returns -1 but doesn't set errno if we're already at EOF. 167 // It should set the end-of-file indicator for the stream, though. 168 errno = 0; 169 ASSERT_EQ(getline(&line_read, &allocated_length, fp), -1); 170 ASSERT_EQ(0, errno); 171 ASSERT_TRUE(feof(fp)); 172 173 free(line_read); 174 fclose(fp); 175} 176 177TEST(stdio, getline_invalid) { 178 FILE* fp = tmpfile(); 179 ASSERT_TRUE(fp != NULL); 180 181 char* buffer = NULL; 182 size_t buffer_length = 0; 183 184 // The first argument can't be NULL. 185 errno = 0; 186 ASSERT_EQ(getline(NULL, &buffer_length, fp), -1); 187 ASSERT_EQ(EINVAL, errno); 188 189 // The second argument can't be NULL. 190 errno = 0; 191 ASSERT_EQ(getline(&buffer, NULL, fp), -1); 192 ASSERT_EQ(EINVAL, errno); 193 194 // The underlying fd can't be closed. 195 ASSERT_EQ(0, close(fileno(fp))); 196 errno = 0; 197 ASSERT_EQ(getline(&buffer, &buffer_length, fp), -1); 198 ASSERT_EQ(EBADF, errno); 199 fclose(fp); 200} 201 202TEST(stdio, printf_ssize_t) { 203 // http://b/8253769 204 ASSERT_EQ(sizeof(ssize_t), sizeof(long int)); 205 ASSERT_EQ(sizeof(ssize_t), sizeof(size_t)); 206 // For our 32-bit ABI, we had a ssize_t definition that confuses GCC into saying: 207 // error: format '%zd' expects argument of type 'signed size_t', 208 // but argument 4 has type 'ssize_t {aka long int}' [-Werror=format] 209 ssize_t v = 1; 210 char buf[32]; 211 snprintf(buf, sizeof(buf), "%zd", v); 212} 213 214// https://code.google.com/p/android/issues/detail?id=64886 215TEST(stdio, snprintf_a) { 216 char buf[BUFSIZ]; 217 EXPECT_EQ(23, snprintf(buf, sizeof(buf), "<%a>", 9990.235)); 218 EXPECT_STREQ("<0x1.3831e147ae148p+13>", buf); 219} 220 221TEST(stdio, snprintf_lc) { 222 char buf[BUFSIZ]; 223 wint_t wc = L'a'; 224 EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", wc)); 225 EXPECT_STREQ("<a>", buf); 226} 227 228TEST(stdio, snprintf_ls) { 229 char buf[BUFSIZ]; 230 wchar_t* ws = NULL; 231 EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%ls>", ws)); 232 EXPECT_STREQ("<(null)>", buf); 233 234 wchar_t chars[] = { L'h', L'i', 0 }; 235 ws = chars; 236 EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%ls>", ws)); 237 EXPECT_STREQ("<hi>", buf); 238} 239 240TEST(stdio, snprintf_n) { 241#if defined(__BIONIC__) 242 // http://b/14492135 243 char buf[32]; 244 int i = 1234; 245 EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i)); 246 EXPECT_EQ(1234, i); 247 EXPECT_STREQ("a n b", buf); 248#else 249 GTEST_LOG_(INFO) << "This test does nothing.\n"; 250#endif 251} 252 253TEST(stdio, snprintf_smoke) { 254 char buf[BUFSIZ]; 255 256 snprintf(buf, sizeof(buf), "a"); 257 EXPECT_STREQ("a", buf); 258 259 snprintf(buf, sizeof(buf), "%%"); 260 EXPECT_STREQ("%", buf); 261 262 snprintf(buf, sizeof(buf), "01234"); 263 EXPECT_STREQ("01234", buf); 264 265 snprintf(buf, sizeof(buf), "a%sb", "01234"); 266 EXPECT_STREQ("a01234b", buf); 267 268 char* s = NULL; 269 snprintf(buf, sizeof(buf), "a%sb", s); 270 EXPECT_STREQ("a(null)b", buf); 271 272 snprintf(buf, sizeof(buf), "aa%scc", "bb"); 273 EXPECT_STREQ("aabbcc", buf); 274 275 snprintf(buf, sizeof(buf), "a%cc", 'b'); 276 EXPECT_STREQ("abc", buf); 277 278 snprintf(buf, sizeof(buf), "a%db", 1234); 279 EXPECT_STREQ("a1234b", buf); 280 281 snprintf(buf, sizeof(buf), "a%db", -8123); 282 EXPECT_STREQ("a-8123b", buf); 283 284 snprintf(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010)); 285 EXPECT_STREQ("a16b", buf); 286 287 snprintf(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10)); 288 EXPECT_STREQ("a16b", buf); 289 290 snprintf(buf, sizeof(buf), "a%lldb", 0x1000000000LL); 291 EXPECT_STREQ("a68719476736b", buf); 292 293 snprintf(buf, sizeof(buf), "a%ldb", 70000L); 294 EXPECT_STREQ("a70000b", buf); 295 296 snprintf(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234)); 297 EXPECT_STREQ("a0xb0001234b", buf); 298 299 snprintf(buf, sizeof(buf), "a%xz", 0x12ab); 300 EXPECT_STREQ("a12abz", buf); 301 302 snprintf(buf, sizeof(buf), "a%Xz", 0x12ab); 303 EXPECT_STREQ("a12ABz", buf); 304 305 snprintf(buf, sizeof(buf), "a%08xz", 0x123456); 306 EXPECT_STREQ("a00123456z", buf); 307 308 snprintf(buf, sizeof(buf), "a%5dz", 1234); 309 EXPECT_STREQ("a 1234z", buf); 310 311 snprintf(buf, sizeof(buf), "a%05dz", 1234); 312 EXPECT_STREQ("a01234z", buf); 313 314 snprintf(buf, sizeof(buf), "a%8dz", 1234); 315 EXPECT_STREQ("a 1234z", buf); 316 317 snprintf(buf, sizeof(buf), "a%-8dz", 1234); 318 EXPECT_STREQ("a1234 z", buf); 319 320 snprintf(buf, sizeof(buf), "A%-11sZ", "abcdef"); 321 EXPECT_STREQ("Aabcdef Z", buf); 322 323 snprintf(buf, sizeof(buf), "A%s:%dZ", "hello", 1234); 324 EXPECT_STREQ("Ahello:1234Z", buf); 325 326 snprintf(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5); 327 EXPECT_STREQ("a005:5:05z", buf); 328 329 void* p = NULL; 330 snprintf(buf, sizeof(buf), "a%d,%pz", 5, p); 331#if defined(__BIONIC__) 332 EXPECT_STREQ("a5,0x0z", buf); 333#else // __BIONIC__ 334 EXPECT_STREQ("a5,(nil)z", buf); 335#endif // __BIONIC__ 336 337 snprintf(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8); 338 EXPECT_STREQ("a68719476736,6,7,8z", buf); 339 340 snprintf(buf, sizeof(buf), "a_%f_b", 1.23f); 341 EXPECT_STREQ("a_1.230000_b", buf); 342 343 snprintf(buf, sizeof(buf), "a_%g_b", 3.14); 344 EXPECT_STREQ("a_3.14_b", buf); 345 346 snprintf(buf, sizeof(buf), "%1$s %1$s", "print_me_twice"); 347 EXPECT_STREQ("print_me_twice print_me_twice", buf); 348} 349 350TEST(stdio, snprintf_f_special) { 351 char buf[BUFSIZ]; 352 snprintf(buf, sizeof(buf), "%f", nanf("")); 353 EXPECT_STRCASEEQ("NaN", buf); 354 355 snprintf(buf, sizeof(buf), "%f", HUGE_VALF); 356 EXPECT_STRCASEEQ("Inf", buf); 357} 358 359TEST(stdio, snprintf_g_special) { 360 char buf[BUFSIZ]; 361 snprintf(buf, sizeof(buf), "%g", nan("")); 362 EXPECT_STRCASEEQ("NaN", buf); 363 364 snprintf(buf, sizeof(buf), "%g", HUGE_VAL); 365 EXPECT_STRCASEEQ("Inf", buf); 366} 367 368TEST(stdio, snprintf_d_INT_MAX) { 369 char buf[BUFSIZ]; 370 snprintf(buf, sizeof(buf), "%d", INT_MAX); 371 EXPECT_STREQ("2147483647", buf); 372} 373 374TEST(stdio, snprintf_d_INT_MIN) { 375 char buf[BUFSIZ]; 376 snprintf(buf, sizeof(buf), "%d", INT_MIN); 377 EXPECT_STREQ("-2147483648", buf); 378} 379 380TEST(stdio, snprintf_ld_LONG_MAX) { 381 char buf[BUFSIZ]; 382 snprintf(buf, sizeof(buf), "%ld", LONG_MAX); 383#if __LP64__ 384 EXPECT_STREQ("9223372036854775807", buf); 385#else 386 EXPECT_STREQ("2147483647", buf); 387#endif 388} 389 390TEST(stdio, snprintf_ld_LONG_MIN) { 391 char buf[BUFSIZ]; 392 snprintf(buf, sizeof(buf), "%ld", LONG_MIN); 393#if __LP64__ 394 EXPECT_STREQ("-9223372036854775808", buf); 395#else 396 EXPECT_STREQ("-2147483648", buf); 397#endif 398} 399 400TEST(stdio, snprintf_lld_LLONG_MAX) { 401 char buf[BUFSIZ]; 402 snprintf(buf, sizeof(buf), "%lld", LLONG_MAX); 403 EXPECT_STREQ("9223372036854775807", buf); 404} 405 406TEST(stdio, snprintf_lld_LLONG_MIN) { 407 char buf[BUFSIZ]; 408 snprintf(buf, sizeof(buf), "%lld", LLONG_MIN); 409 EXPECT_STREQ("-9223372036854775808", buf); 410} 411 412TEST(stdio, snprintf_e) { 413 char buf[BUFSIZ]; 414 415 snprintf(buf, sizeof(buf), "%e", 1.5); 416 EXPECT_STREQ("1.500000e+00", buf); 417 418 snprintf(buf, sizeof(buf), "%Le", 1.5l); 419 EXPECT_STREQ("1.500000e+00", buf); 420} 421 422TEST(stdio, snprintf_negative_zero_5084292) { 423 char buf[BUFSIZ]; 424 425 snprintf(buf, sizeof(buf), "%f", -0.0); 426 EXPECT_STREQ("-0.000000", buf); 427} 428 429TEST(stdio, snprintf_utf8_15439554) { 430 // http://b/15439554 431 char buf[BUFSIZ]; 432 433 // 1-byte character. 434 snprintf(buf, sizeof(buf), "%dx%d", 1, 2); 435 EXPECT_STREQ("1x2", buf); 436 // 2-byte character. 437 snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2); 438 EXPECT_STREQ("1¢2", buf); 439 // 3-byte character. 440 snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2); 441 EXPECT_STREQ("1€2", buf); 442 // 4-byte character. 443 snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2); 444 EXPECT_STREQ("12", buf); 445} 446 447TEST(stdio, fprintf_failures_7229520) { 448 // http://b/7229520 449 FILE* fp; 450 451 // Unbuffered case where the fprintf(3) itself fails. 452 ASSERT_NE(nullptr, fp = tmpfile()); 453 setbuf(fp, NULL); 454 ASSERT_EQ(4, fprintf(fp, "epic")); 455 ASSERT_EQ(0, close(fileno(fp))); 456 ASSERT_EQ(-1, fprintf(fp, "fail")); 457 ASSERT_EQ(-1, fclose(fp)); 458 459 // Buffered case where we won't notice until the fclose(3). 460 // It's likely this is what was actually seen in http://b/7229520, 461 // and that expecting fprintf to fail is setting yourself up for 462 // disappointment. Remember to check fclose(3)'s return value, kids! 463 ASSERT_NE(nullptr, fp = tmpfile()); 464 ASSERT_EQ(4, fprintf(fp, "epic")); 465 ASSERT_EQ(0, close(fileno(fp))); 466 ASSERT_EQ(4, fprintf(fp, "fail")); 467 ASSERT_EQ(-1, fclose(fp)); 468} 469 470TEST(stdio, popen) { 471 FILE* fp = popen("cat /proc/version", "r"); 472 ASSERT_TRUE(fp != NULL); 473 474 char buf[16]; 475 char* s = fgets(buf, sizeof(buf), fp); 476 buf[13] = '\0'; 477 ASSERT_STREQ("Linux version", s); 478 479 ASSERT_EQ(0, pclose(fp)); 480} 481 482TEST(stdio, getc) { 483 FILE* fp = fopen("/proc/version", "r"); 484 ASSERT_TRUE(fp != NULL); 485 ASSERT_EQ('L', getc(fp)); 486 ASSERT_EQ('i', getc(fp)); 487 ASSERT_EQ('n', getc(fp)); 488 ASSERT_EQ('u', getc(fp)); 489 ASSERT_EQ('x', getc(fp)); 490 fclose(fp); 491} 492 493TEST(stdio, putc) { 494 FILE* fp = fopen("/proc/version", "r"); 495 ASSERT_TRUE(fp != NULL); 496 ASSERT_EQ(EOF, putc('x', fp)); 497 fclose(fp); 498} 499 500TEST(stdio, sscanf) { 501 char s1[123]; 502 int i1; 503 double d1; 504 char s2[123]; 505 ASSERT_EQ(3, sscanf(" hello 123 1.23 ", "%s %i %lf %s", s1, &i1, &d1, s2)); 506 ASSERT_STREQ("hello", s1); 507 ASSERT_EQ(123, i1); 508 ASSERT_DOUBLE_EQ(1.23, d1); 509} 510 511TEST(stdio, cantwrite_EBADF) { 512 // If we open a file read-only... 513 FILE* fp = fopen("/proc/version", "r"); 514 515 // ...all attempts to write to that file should return failure. 516 517 // They should also set errno to EBADF. This isn't POSIX, but it's traditional. 518 // glibc gets the wide-character functions wrong. 519 520 errno = 0; 521 EXPECT_EQ(EOF, putc('x', fp)); 522 EXPECT_EQ(EBADF, errno); 523 524 errno = 0; 525 EXPECT_EQ(EOF, fprintf(fp, "hello")); 526 EXPECT_EQ(EBADF, errno); 527 528 errno = 0; 529 EXPECT_EQ(EOF, fwprintf(fp, L"hello")); 530#if defined(__BIONIC__) 531 EXPECT_EQ(EBADF, errno); 532#endif 533 534 errno = 0; 535 EXPECT_EQ(EOF, putw(1234, fp)); 536 EXPECT_EQ(EBADF, errno); 537 538 errno = 0; 539 EXPECT_EQ(0U, fwrite("hello", 1, 2, fp)); 540 EXPECT_EQ(EBADF, errno); 541 542 errno = 0; 543 EXPECT_EQ(EOF, fputs("hello", fp)); 544 EXPECT_EQ(EBADF, errno); 545 546 errno = 0; 547 EXPECT_EQ(WEOF, fputwc(L'x', fp)); 548#if defined(__BIONIC__) 549 EXPECT_EQ(EBADF, errno); 550#endif 551} 552 553// Tests that we can only have a consistent and correct fpos_t when using 554// f*pos functions (i.e. fpos doesn't get inside a multi byte character). 555TEST(stdio, consistent_fpos_t) { 556 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 557 uselocale(LC_GLOBAL_LOCALE); 558 559 FILE* fp = tmpfile(); 560 ASSERT_TRUE(fp != NULL); 561 562 wchar_t mb_one_bytes = L'h'; 563 wchar_t mb_two_bytes = 0x00a2; 564 wchar_t mb_three_bytes = 0x20ac; 565 wchar_t mb_four_bytes = 0x24b62; 566 567 // Write to file. 568 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp))); 569 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp))); 570 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp))); 571 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp))); 572 573 rewind(fp); 574 575 // Record each character position. 576 fpos_t pos1; 577 fpos_t pos2; 578 fpos_t pos3; 579 fpos_t pos4; 580 fpos_t pos5; 581 EXPECT_EQ(0, fgetpos(fp, &pos1)); 582 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp))); 583 EXPECT_EQ(0, fgetpos(fp, &pos2)); 584 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp))); 585 EXPECT_EQ(0, fgetpos(fp, &pos3)); 586 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp))); 587 EXPECT_EQ(0, fgetpos(fp, &pos4)); 588 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp))); 589 EXPECT_EQ(0, fgetpos(fp, &pos5)); 590 591#if defined(__BIONIC__) 592 // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD 593 // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In 594 // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE 595 // structure. 596 ASSERT_EQ(0, static_cast<off_t>(pos1)); 597 ASSERT_EQ(1, static_cast<off_t>(pos2)); 598 ASSERT_EQ(3, static_cast<off_t>(pos3)); 599 ASSERT_EQ(6, static_cast<off_t>(pos4)); 600 ASSERT_EQ(10, static_cast<off_t>(pos5)); 601#endif 602 603 // Exercise back and forth movements of the position. 604 ASSERT_EQ(0, fsetpos(fp, &pos2)); 605 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp))); 606 ASSERT_EQ(0, fsetpos(fp, &pos1)); 607 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp))); 608 ASSERT_EQ(0, fsetpos(fp, &pos4)); 609 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp))); 610 ASSERT_EQ(0, fsetpos(fp, &pos3)); 611 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp))); 612 ASSERT_EQ(0, fsetpos(fp, &pos5)); 613 ASSERT_EQ(WEOF, fgetwc(fp)); 614 615 fclose(fp); 616} 617 618// Exercise the interaction between fpos and seek. 619TEST(stdio, fpos_t_and_seek) { 620 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 621 uselocale(LC_GLOBAL_LOCALE); 622 623 // In glibc-2.16 fseek doesn't work properly in wide mode 624 // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is 625 // to close and re-open the file. We do it in order to make the test pass 626 // with all glibcs. 627 628 TemporaryFile tf; 629 FILE* fp = fdopen(tf.fd, "w+"); 630 ASSERT_TRUE(fp != NULL); 631 632 wchar_t mb_two_bytes = 0x00a2; 633 wchar_t mb_three_bytes = 0x20ac; 634 wchar_t mb_four_bytes = 0x24b62; 635 636 // Write to file. 637 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp))); 638 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp))); 639 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp))); 640 641 fflush(fp); 642 fclose(fp); 643 644 fp = fopen(tf.filename, "r"); 645 ASSERT_TRUE(fp != NULL); 646 647 // Store a valid position. 648 fpos_t mb_two_bytes_pos; 649 ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos)); 650 651 // Move inside mb_four_bytes with fseek. 652 long offset_inside_mb = 6; 653 ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET)); 654 655 // Store the "inside multi byte" position. 656 fpos_t pos_inside_mb; 657 ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb)); 658#if defined(__BIONIC__) 659 ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb)); 660#endif 661 662 // Reading from within a byte should produce an error. 663 ASSERT_EQ(WEOF, fgetwc(fp)); 664 ASSERT_EQ(EILSEQ, errno); 665 666 // Reverting to a valid position should work. 667 ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos)); 668 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp))); 669 670 // Moving withing a multi byte with fsetpos should work but reading should 671 // produce an error. 672 ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb)); 673 ASSERT_EQ(WEOF, fgetwc(fp)); 674 ASSERT_EQ(EILSEQ, errno); 675 676 fclose(fp); 677} 678