Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2014 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 <stdio_ext.h>
     18 
     19 #include <gtest/gtest.h>
     20 
     21 #include <errno.h>
     22 #include <fcntl.h>
     23 #include <limits.h>
     24 #include <math.h>
     25 #include <stdio.h>
     26 #include <sys/types.h>
     27 #include <sys/stat.h>
     28 #include <unistd.h>
     29 #include <wchar.h>
     30 #include <locale.h>
     31 
     32 #include <android-base/file.h>
     33 
     34 #include "utils.h"
     35 
     36 TEST(stdio_ext, __fbufsize) {
     37   FILE* fp = fopen("/proc/version", "r");
     38 
     39   // Initially, there's no buffer in case the first thing you do is disable buffering.
     40   ASSERT_EQ(0U, __fbufsize(fp));
     41 
     42   // A read forces a buffer to be created.
     43   char buf[128];
     44   fgets(buf, sizeof(buf), fp);
     45   ASSERT_EQ(1024U, __fbufsize(fp));
     46 
     47   ASSERT_EQ(0, setvbuf(fp, buf, _IOFBF, 1));
     48   ASSERT_EQ(1U, __fbufsize(fp));
     49 
     50   ASSERT_EQ(0, setvbuf(fp, buf, _IOFBF, 8));
     51   ASSERT_EQ(8U, __fbufsize(fp));
     52 
     53   fclose(fp);
     54 }
     55 
     56 TEST(stdio_ext, __flbf) {
     57   FILE* fp = fopen("/proc/version", "r");
     58 
     59   ASSERT_FALSE(__flbf(fp));
     60 
     61   char buf[128];
     62   ASSERT_EQ(0, setvbuf(fp, buf, _IOLBF, sizeof(buf)));
     63 
     64   ASSERT_TRUE(__flbf(fp));
     65 
     66   fclose(fp);
     67 }
     68 
     69 TEST(stdio_ext, __fpending) {
     70   FILE* fp = fopen("/dev/null", "w");
     71   ASSERT_EQ(0U, __fpending(fp));
     72   ASSERT_EQ('x', fputc('x', fp));
     73   ASSERT_EQ(1U, __fpending(fp));
     74   ASSERT_EQ('y', fputc('y', fp));
     75   ASSERT_EQ(2U, __fpending(fp));
     76   fflush(fp);
     77   ASSERT_EQ(0U, __fpending(fp));
     78   fclose(fp);
     79 }
     80 
     81 TEST(stdio_ext, __fpurge) {
     82   FILE* fp = tmpfile();
     83 
     84   ASSERT_EQ('a', fputc('a', fp));
     85   ASSERT_EQ(1U, __fpending(fp));
     86   __fpurge(fp);
     87   ASSERT_EQ(0U, __fpending(fp));
     88 
     89   ASSERT_EQ('b', fputc('b', fp));
     90   ASSERT_EQ('\n', fputc('\n', fp));
     91   ASSERT_EQ(2U, __fpending(fp));
     92 
     93   rewind(fp);
     94 
     95   char buf[16];
     96   char* s = fgets(buf, sizeof(buf), fp);
     97   ASSERT_TRUE(s != nullptr);
     98   ASSERT_STREQ("b\n", s);
     99 
    100   fclose(fp);
    101 }
    102 
    103 TEST(stdio_ext, _flushlbf) {
    104   FILE* fp = fopen("/dev/null", "w");
    105 
    106   char buf[128];
    107   ASSERT_EQ(0, setvbuf(fp, buf, _IOLBF, sizeof(buf)));
    108 
    109   ASSERT_EQ('a', fputc('a', fp));
    110   ASSERT_EQ(1U, __fpending(fp));
    111 
    112   _flushlbf();
    113 
    114   ASSERT_EQ(0U, __fpending(fp));
    115 
    116   fclose(fp);
    117 }
    118 
    119 TEST(stdio_ext, __freadable__fwritable) {
    120   FILE* fp;
    121 
    122   // Read-only.
    123   fp = fopen("/dev/null", "r");
    124   ASSERT_TRUE(__freadable(fp));
    125   ASSERT_FALSE(__fwritable(fp));
    126   fclose(fp);
    127 
    128   // Write-only.
    129   fp = fopen("/dev/null", "w");
    130   ASSERT_FALSE(__freadable(fp));
    131   ASSERT_TRUE(__fwritable(fp));
    132   fclose(fp);
    133 
    134   // Append (aka write-only).
    135   fp = fopen("/dev/null", "a");
    136   ASSERT_FALSE(__freadable(fp));
    137   ASSERT_TRUE(__fwritable(fp));
    138   fclose(fp);
    139 
    140   // The three read-write modes.
    141   for (auto read_write_mode : {"r+", "w+", "a+"}) {
    142     fp = fopen("/dev/null", read_write_mode);
    143     ASSERT_TRUE(__freadable(fp));
    144     ASSERT_TRUE(__fwritable(fp));
    145     fclose(fp);
    146   }
    147 }
    148 
    149 TEST(stdio_ext, __freading__fwriting) {
    150   FILE* fp;
    151 
    152   // Append (aka write-only). Never reading. Always writing.
    153   fp = fopen("/dev/zero", "a");
    154   ASSERT_FALSE(__freading(fp)); // Not reading initially.
    155   ASSERT_TRUE(__fwriting(fp)); // Writing initially.
    156   ASSERT_TRUE(fputc('x', fp) != EOF);
    157   ASSERT_FALSE(__freading(fp)); // Not reading after write.
    158   ASSERT_TRUE(__fwriting(fp)); // Still writing after write.
    159   fclose(fp);
    160 
    161   // Write-only. Never reading. Always writing.
    162   fp = fopen("/dev/zero", "w");
    163   ASSERT_FALSE(__freading(fp)); // Not reading initially.
    164   ASSERT_TRUE(__fwriting(fp)); // Writing initially.
    165   ASSERT_TRUE(fputc('x', fp) != EOF);
    166   ASSERT_FALSE(__freading(fp)); // Not reading after write.
    167   ASSERT_TRUE(__fwriting(fp)); // Still writing after write.
    168   fclose(fp);
    169 
    170   // Read-only. Always reading. Never writing.
    171   fp = fopen("/dev/zero", "r");
    172   ASSERT_TRUE(__freading(fp)); // Reading initially.
    173   ASSERT_FALSE(__fwriting(fp)); // Not writing initially.
    174   ASSERT_TRUE(fgetc(fp) == 0);
    175   ASSERT_TRUE(__freading(fp)); // Still reading after read.
    176   ASSERT_FALSE(__fwriting(fp)); // Still not writing after read.
    177   fclose(fp);
    178 
    179   // The three read-write modes.
    180   for (auto read_write_mode : {"r+", "w+", "a+"}) {
    181     fp = fopen("/dev/zero", read_write_mode);
    182     ASSERT_FALSE(__freading(fp)); // Not reading initially.
    183     ASSERT_FALSE(__fwriting(fp)); // Not writing initially.
    184     ASSERT_TRUE(fgetc(fp) == 0);
    185     ASSERT_TRUE(__freading(fp)); // Reading after read.
    186     ASSERT_FALSE(__fwriting(fp)); // Not writing after read.
    187     ASSERT_TRUE(fputc('x', fp) != EOF);
    188     ASSERT_FALSE(__freading(fp)); // Not reading after write.
    189     ASSERT_TRUE(__fwriting(fp)); // Writing after write.
    190     fclose(fp);
    191   }
    192 }
    193 
    194 TEST(stdio_ext, __fseterr) {
    195 #if defined(__GLIBC__)
    196   GTEST_SKIP() << "glibc doesn't have __fseterr, but gnulib will use it";
    197 #else
    198   FILE* fp = fopen("/dev/null", "w");
    199 
    200   ASSERT_FALSE(ferror(fp));
    201   __fseterr(fp);
    202   ASSERT_TRUE(ferror(fp));
    203   clearerr(fp);
    204   ASSERT_FALSE(ferror(fp));
    205 
    206   fclose(fp);
    207 #endif
    208 }
    209 
    210 TEST(stdio_ext, __fsetlocking) {
    211   FILE* fp = fopen("/proc/version", "r");
    212   ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
    213   ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_BYCALLER));
    214   ASSERT_EQ(FSETLOCKING_BYCALLER, __fsetlocking(fp, FSETLOCKING_QUERY));
    215   ASSERT_EQ(FSETLOCKING_BYCALLER, __fsetlocking(fp, FSETLOCKING_INTERNAL));
    216   ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
    217   fclose(fp);
    218 }
    219 
    220 static void LockingByCallerHelper(std::atomic<pid_t>* pid) {
    221   *pid = gettid();
    222   flockfile(stdout);
    223   funlockfile(stdout);
    224 }
    225 
    226 TEST(stdio_ext, __fsetlocking_BYCALLER) {
    227   // Check if users can use flockfile/funlockfile to protect stdio operations.
    228   int old_state = __fsetlocking(stdout, FSETLOCKING_BYCALLER);
    229   flockfile(stdout);
    230   pthread_t thread;
    231   std::atomic<pid_t> pid(0);
    232   ASSERT_EQ(0, pthread_create(&thread, nullptr,
    233                               reinterpret_cast<void* (*)(void*)>(LockingByCallerHelper), &pid));
    234   WaitUntilThreadSleep(pid);
    235   funlockfile(stdout);
    236 
    237   ASSERT_EQ(0, pthread_join(thread, nullptr));
    238   __fsetlocking(stdout, old_state);
    239 }
    240