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 32 TEST(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 57 TEST(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 75 TEST(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 110 TEST(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 135 TEST(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 177 TEST(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 202 TEST(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 215 TEST(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 221 TEST(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 228 TEST(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 240 TEST(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 253 TEST(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 350 TEST(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 359 TEST(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 368 TEST(stdio, snprintf_d_INT_MAX) { 369 char buf[BUFSIZ]; 370 snprintf(buf, sizeof(buf), "%d", INT_MAX); 371 EXPECT_STREQ("2147483647", buf); 372 } 373 374 TEST(stdio, snprintf_d_INT_MIN) { 375 char buf[BUFSIZ]; 376 snprintf(buf, sizeof(buf), "%d", INT_MIN); 377 EXPECT_STREQ("-2147483648", buf); 378 } 379 380 TEST(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 390 TEST(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 400 TEST(stdio, snprintf_lld_LLONG_MAX) { 401 char buf[BUFSIZ]; 402 snprintf(buf, sizeof(buf), "%lld", LLONG_MAX); 403 EXPECT_STREQ("9223372036854775807", buf); 404 } 405 406 TEST(stdio, snprintf_lld_LLONG_MIN) { 407 char buf[BUFSIZ]; 408 snprintf(buf, sizeof(buf), "%lld", LLONG_MIN); 409 EXPECT_STREQ("-9223372036854775808", buf); 410 } 411 412 TEST(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 422 TEST(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 429 TEST(stdio, snprintf_utf8_15439554) { 430 locale_t cloc = newlocale(LC_ALL, "C.UTF-8", 0); 431 locale_t old_locale = uselocale(cloc); 432 433 // http://b/15439554 434 char buf[BUFSIZ]; 435 436 // 1-byte character. 437 snprintf(buf, sizeof(buf), "%dx%d", 1, 2); 438 EXPECT_STREQ("1x2", buf); 439 // 2-byte character. 440 snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2); 441 EXPECT_STREQ("12", buf); 442 // 3-byte character. 443 snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2); 444 EXPECT_STREQ("12", buf); 445 // 4-byte character. 446 snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2); 447 EXPECT_STREQ("12", buf); 448 449 uselocale(old_locale); 450 freelocale(cloc); 451 } 452 453 TEST(stdio, fprintf_failures_7229520) { 454 // http://b/7229520 455 FILE* fp; 456 457 // Unbuffered case where the fprintf(3) itself fails. 458 ASSERT_NE(nullptr, fp = tmpfile()); 459 setbuf(fp, NULL); 460 ASSERT_EQ(4, fprintf(fp, "epic")); 461 ASSERT_EQ(0, close(fileno(fp))); 462 ASSERT_EQ(-1, fprintf(fp, "fail")); 463 ASSERT_EQ(-1, fclose(fp)); 464 465 // Buffered case where we won't notice until the fclose(3). 466 // It's likely this is what was actually seen in http://b/7229520, 467 // and that expecting fprintf to fail is setting yourself up for 468 // disappointment. Remember to check fclose(3)'s return value, kids! 469 ASSERT_NE(nullptr, fp = tmpfile()); 470 ASSERT_EQ(4, fprintf(fp, "epic")); 471 ASSERT_EQ(0, close(fileno(fp))); 472 ASSERT_EQ(4, fprintf(fp, "fail")); 473 ASSERT_EQ(-1, fclose(fp)); 474 } 475 476 TEST(stdio, popen) { 477 FILE* fp = popen("cat /proc/version", "r"); 478 ASSERT_TRUE(fp != NULL); 479 480 char buf[16]; 481 char* s = fgets(buf, sizeof(buf), fp); 482 buf[13] = '\0'; 483 ASSERT_STREQ("Linux version", s); 484 485 ASSERT_EQ(0, pclose(fp)); 486 } 487 488 TEST(stdio, getc) { 489 FILE* fp = fopen("/proc/version", "r"); 490 ASSERT_TRUE(fp != NULL); 491 ASSERT_EQ('L', getc(fp)); 492 ASSERT_EQ('i', getc(fp)); 493 ASSERT_EQ('n', getc(fp)); 494 ASSERT_EQ('u', getc(fp)); 495 ASSERT_EQ('x', getc(fp)); 496 fclose(fp); 497 } 498 499 TEST(stdio, putc) { 500 FILE* fp = fopen("/proc/version", "r"); 501 ASSERT_TRUE(fp != NULL); 502 ASSERT_EQ(EOF, putc('x', fp)); 503 fclose(fp); 504 } 505 506 TEST(stdio, sscanf) { 507 char s1[123]; 508 int i1; 509 double d1; 510 char s2[123]; 511 ASSERT_EQ(3, sscanf(" hello 123 1.23 ", "%s %i %lf %s", s1, &i1, &d1, s2)); 512 ASSERT_STREQ("hello", s1); 513 ASSERT_EQ(123, i1); 514 ASSERT_DOUBLE_EQ(1.23, d1); 515 } 516 517 TEST(stdio, cantwrite_EBADF) { 518 // If we open a file read-only... 519 FILE* fp = fopen("/proc/version", "r"); 520 521 // ...all attempts to write to that file should return failure. 522 523 // They should also set errno to EBADF. This isn't POSIX, but it's traditional. 524 // glibc gets the wide-character functions wrong. 525 526 errno = 0; 527 EXPECT_EQ(EOF, putc('x', fp)); 528 EXPECT_EQ(EBADF, errno); 529 530 errno = 0; 531 EXPECT_EQ(EOF, fprintf(fp, "hello")); 532 EXPECT_EQ(EBADF, errno); 533 534 errno = 0; 535 EXPECT_EQ(EOF, fwprintf(fp, L"hello")); 536 #if defined(__BIONIC__) 537 EXPECT_EQ(EBADF, errno); 538 #endif 539 540 errno = 0; 541 EXPECT_EQ(0U, fwrite("hello", 1, 2, fp)); 542 EXPECT_EQ(EBADF, errno); 543 544 errno = 0; 545 EXPECT_EQ(EOF, fputs("hello", fp)); 546 EXPECT_EQ(EBADF, errno); 547 548 errno = 0; 549 EXPECT_EQ(WEOF, fputwc(L'x', fp)); 550 #if defined(__BIONIC__) 551 EXPECT_EQ(EBADF, errno); 552 #endif 553 } 554 555 // Tests that we can only have a consistent and correct fpos_t when using 556 // f*pos functions (i.e. fpos doesn't get inside a multi byte character). 557 TEST(stdio, consistent_fpos_t) { 558 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 559 uselocale(LC_GLOBAL_LOCALE); 560 561 FILE* fp = tmpfile(); 562 ASSERT_TRUE(fp != NULL); 563 564 wchar_t mb_one_bytes = L'h'; 565 wchar_t mb_two_bytes = 0x00a2; 566 wchar_t mb_three_bytes = 0x20ac; 567 wchar_t mb_four_bytes = 0x24b62; 568 569 // Write to file. 570 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp))); 571 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp))); 572 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp))); 573 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp))); 574 575 rewind(fp); 576 577 // Record each character position. 578 fpos_t pos1; 579 fpos_t pos2; 580 fpos_t pos3; 581 fpos_t pos4; 582 fpos_t pos5; 583 EXPECT_EQ(0, fgetpos(fp, &pos1)); 584 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp))); 585 EXPECT_EQ(0, fgetpos(fp, &pos2)); 586 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp))); 587 EXPECT_EQ(0, fgetpos(fp, &pos3)); 588 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp))); 589 EXPECT_EQ(0, fgetpos(fp, &pos4)); 590 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp))); 591 EXPECT_EQ(0, fgetpos(fp, &pos5)); 592 593 #if defined(__BIONIC__) 594 // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD 595 // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In 596 // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE 597 // structure. 598 ASSERT_EQ(0, static_cast<off_t>(pos1)); 599 ASSERT_EQ(1, static_cast<off_t>(pos2)); 600 ASSERT_EQ(3, static_cast<off_t>(pos3)); 601 ASSERT_EQ(6, static_cast<off_t>(pos4)); 602 ASSERT_EQ(10, static_cast<off_t>(pos5)); 603 #endif 604 605 // Exercise back and forth movements of the position. 606 ASSERT_EQ(0, fsetpos(fp, &pos2)); 607 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp))); 608 ASSERT_EQ(0, fsetpos(fp, &pos1)); 609 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp))); 610 ASSERT_EQ(0, fsetpos(fp, &pos4)); 611 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp))); 612 ASSERT_EQ(0, fsetpos(fp, &pos3)); 613 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp))); 614 ASSERT_EQ(0, fsetpos(fp, &pos5)); 615 ASSERT_EQ(WEOF, fgetwc(fp)); 616 617 fclose(fp); 618 } 619 620 // Exercise the interaction between fpos and seek. 621 TEST(stdio, fpos_t_and_seek) { 622 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 623 uselocale(LC_GLOBAL_LOCALE); 624 625 // In glibc-2.16 fseek doesn't work properly in wide mode 626 // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is 627 // to close and re-open the file. We do it in order to make the test pass 628 // with all glibcs. 629 630 TemporaryFile tf; 631 FILE* fp = fdopen(tf.fd, "w+"); 632 ASSERT_TRUE(fp != NULL); 633 634 wchar_t mb_two_bytes = 0x00a2; 635 wchar_t mb_three_bytes = 0x20ac; 636 wchar_t mb_four_bytes = 0x24b62; 637 638 // Write to file. 639 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp))); 640 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp))); 641 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp))); 642 643 fflush(fp); 644 fclose(fp); 645 646 fp = fopen(tf.filename, "r"); 647 ASSERT_TRUE(fp != NULL); 648 649 // Store a valid position. 650 fpos_t mb_two_bytes_pos; 651 ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos)); 652 653 // Move inside mb_four_bytes with fseek. 654 long offset_inside_mb = 6; 655 ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET)); 656 657 // Store the "inside multi byte" position. 658 fpos_t pos_inside_mb; 659 ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb)); 660 #if defined(__BIONIC__) 661 ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb)); 662 #endif 663 664 // Reading from within a byte should produce an error. 665 ASSERT_EQ(WEOF, fgetwc(fp)); 666 ASSERT_EQ(EILSEQ, errno); 667 668 // Reverting to a valid position should work. 669 ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos)); 670 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp))); 671 672 // Moving withing a multi byte with fsetpos should work but reading should 673 // produce an error. 674 ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb)); 675 ASSERT_EQ(WEOF, fgetwc(fp)); 676 ASSERT_EQ(EILSEQ, errno); 677 678 fclose(fp); 679 } 680