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