Home | History | Annotate | Download | only in tests
      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