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