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 = fopen("/dev/null", "r");
    120   ASSERT_TRUE(__freadable(fp));
    121   ASSERT_FALSE(__fwritable(fp));
    122   fclose(fp);
    123 
    124   fp = fopen("/dev/null", "w");
    125   ASSERT_FALSE(__freadable(fp));
    126   ASSERT_TRUE(__fwritable(fp));
    127   fclose(fp);
    128 
    129   fp = fopen("/dev/null", "w+");
    130   ASSERT_TRUE(__freadable(fp));
    131   ASSERT_TRUE(__fwritable(fp));
    132   fclose(fp);
    133 }
    134 
    135 TEST(stdio_ext, __fsetlocking) {
    136   FILE* fp = fopen("/proc/version", "r");
    137   ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
    138   ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_BYCALLER));
    139   ASSERT_EQ(FSETLOCKING_BYCALLER, __fsetlocking(fp, FSETLOCKING_QUERY));
    140   ASSERT_EQ(FSETLOCKING_BYCALLER, __fsetlocking(fp, FSETLOCKING_INTERNAL));
    141   ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
    142   fclose(fp);
    143 }
    144 
    145 static void LockingByCallerHelper(std::atomic<pid_t>* pid) {
    146   *pid = gettid();
    147   flockfile(stdout);
    148   funlockfile(stdout);
    149 }
    150 
    151 TEST(stdio_ext, __fsetlocking_BYCALLER) {
    152   // Check if users can use flockfile/funlockfile to protect stdio operations.
    153   int old_state = __fsetlocking(stdout, FSETLOCKING_BYCALLER);
    154   flockfile(stdout);
    155   pthread_t thread;
    156   std::atomic<pid_t> pid(0);
    157   ASSERT_EQ(0, pthread_create(&thread, nullptr,
    158                               reinterpret_cast<void* (*)(void*)>(LockingByCallerHelper), &pid));
    159   WaitUntilThreadSleep(pid);
    160   funlockfile(stdout);
    161 
    162   ASSERT_EQ(0, pthread_join(thread, nullptr));
    163   __fsetlocking(stdout, old_state);
    164 }
    165