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