stdio_test.cpp revision 8200e55d941305f6f24f1745492b90271aa417e9
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 <vector> 31 32#include "TemporaryFile.h" 33 34#if defined(NOFORTIFY) 35#define STDIO_TEST stdio_nofortify 36#else 37#define STDIO_TEST stdio 38#endif 39 40TEST(STDIO_TEST, flockfile_18208568_stderr) { 41 // Check that we have a _recursive_ mutex for flockfile. 42 flockfile(stderr); 43 feof(stderr); // We don't care about the result, but this needs to take the lock. 44 funlockfile(stderr); 45} 46 47TEST(STDIO_TEST, flockfile_18208568_regular) { 48 // We never had a bug for streams other than stdin/stdout/stderr, but test anyway. 49 FILE* fp = fopen("/dev/null", "w"); 50 ASSERT_TRUE(fp != NULL); 51 flockfile(fp); 52 feof(fp); 53 funlockfile(fp); 54 fclose(fp); 55} 56 57TEST(STDIO_TEST, tmpfile_fileno_fprintf_rewind_fgets) { 58 FILE* fp = tmpfile(); 59 ASSERT_TRUE(fp != NULL); 60 61 int fd = fileno(fp); 62 ASSERT_NE(fd, -1); 63 64 struct stat sb; 65 int rc = fstat(fd, &sb); 66 ASSERT_NE(rc, -1); 67 ASSERT_EQ(sb.st_mode & 0777, 0600U); 68 69 rc = fprintf(fp, "hello\n"); 70 ASSERT_EQ(rc, 6); 71 72 rewind(fp); 73 74 char buf[16]; 75 char* s = fgets(buf, sizeof(buf), fp); 76 ASSERT_TRUE(s != NULL); 77 ASSERT_STREQ("hello\n", s); 78 79 fclose(fp); 80} 81 82TEST(STDIO_TEST, tmpfile64) { 83 FILE* fp = tmpfile64(); 84 ASSERT_TRUE(fp != nullptr); 85 fclose(fp); 86} 87 88TEST(STDIO_TEST, dprintf) { 89 TemporaryFile tf; 90 91 int rc = dprintf(tf.fd, "hello\n"); 92 ASSERT_EQ(rc, 6); 93 94 lseek(tf.fd, 0, SEEK_SET); 95 FILE* tfile = fdopen(tf.fd, "r"); 96 ASSERT_TRUE(tfile != NULL); 97 98 char buf[7]; 99 ASSERT_EQ(buf, fgets(buf, sizeof(buf), tfile)); 100 ASSERT_STREQ("hello\n", buf); 101 // Make sure there isn't anything else in the file. 102 ASSERT_EQ(NULL, fgets(buf, sizeof(buf), tfile)); 103 fclose(tfile); 104} 105 106TEST(STDIO_TEST, getdelim) { 107 FILE* fp = tmpfile(); 108 ASSERT_TRUE(fp != NULL); 109 110 const char* line_written = "This is a test"; 111 int rc = fprintf(fp, "%s", line_written); 112 ASSERT_EQ(rc, static_cast<int>(strlen(line_written))); 113 114 rewind(fp); 115 116 char* word_read = NULL; 117 size_t allocated_length = 0; 118 119 const char* expected[] = { "This ", " ", "is ", "a ", "test" }; 120 for (size_t i = 0; i < 5; ++i) { 121 ASSERT_FALSE(feof(fp)); 122 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), static_cast<int>(strlen(expected[i]))); 123 ASSERT_GE(allocated_length, strlen(expected[i])); 124 ASSERT_STREQ(expected[i], word_read); 125 } 126 // The last read should have set the end-of-file indicator for the stream. 127 ASSERT_TRUE(feof(fp)); 128 clearerr(fp); 129 130 // getdelim returns -1 but doesn't set errno if we're already at EOF. 131 // It should set the end-of-file indicator for the stream, though. 132 errno = 0; 133 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), -1); 134 ASSERT_EQ(0, errno); 135 ASSERT_TRUE(feof(fp)); 136 137 free(word_read); 138 fclose(fp); 139} 140 141TEST(STDIO_TEST, getdelim_invalid) { 142 FILE* fp = tmpfile(); 143 ASSERT_TRUE(fp != NULL); 144 145 char* buffer = NULL; 146 size_t buffer_length = 0; 147 148 // The first argument can't be NULL. 149 errno = 0; 150 ASSERT_EQ(getdelim(NULL, &buffer_length, ' ', fp), -1); 151 ASSERT_EQ(EINVAL, errno); 152 153 // The second argument can't be NULL. 154 errno = 0; 155 ASSERT_EQ(getdelim(&buffer, NULL, ' ', fp), -1); 156 ASSERT_EQ(EINVAL, errno); 157 158 // The underlying fd can't be closed. 159 ASSERT_EQ(0, close(fileno(fp))); 160 errno = 0; 161 ASSERT_EQ(getdelim(&buffer, &buffer_length, ' ', fp), -1); 162 ASSERT_EQ(EBADF, errno); 163 fclose(fp); 164} 165 166TEST(STDIO_TEST, getdelim_directory) { 167 FILE* fp = fopen("/proc", "r"); 168 ASSERT_TRUE(fp != NULL); 169 char* word_read; 170 size_t allocated_length; 171 ASSERT_EQ(-1, getdelim(&word_read, &allocated_length, ' ', fp)); 172 fclose(fp); 173} 174 175TEST(STDIO_TEST, getline) { 176 FILE* fp = tmpfile(); 177 ASSERT_TRUE(fp != NULL); 178 179 const char* line_written = "This is a test for getline\n"; 180 const size_t line_count = 5; 181 182 for (size_t i = 0; i < line_count; ++i) { 183 int rc = fprintf(fp, "%s", line_written); 184 ASSERT_EQ(rc, static_cast<int>(strlen(line_written))); 185 } 186 187 rewind(fp); 188 189 char* line_read = NULL; 190 size_t allocated_length = 0; 191 192 size_t read_line_count = 0; 193 ssize_t read_char_count; 194 while ((read_char_count = getline(&line_read, &allocated_length, fp)) != -1) { 195 ASSERT_EQ(read_char_count, static_cast<int>(strlen(line_written))); 196 ASSERT_GE(allocated_length, strlen(line_written)); 197 ASSERT_STREQ(line_written, line_read); 198 ++read_line_count; 199 } 200 ASSERT_EQ(read_line_count, line_count); 201 202 // The last read should have set the end-of-file indicator for the stream. 203 ASSERT_TRUE(feof(fp)); 204 clearerr(fp); 205 206 // getline returns -1 but doesn't set errno if we're already at EOF. 207 // It should set the end-of-file indicator for the stream, though. 208 errno = 0; 209 ASSERT_EQ(getline(&line_read, &allocated_length, fp), -1); 210 ASSERT_EQ(0, errno); 211 ASSERT_TRUE(feof(fp)); 212 213 free(line_read); 214 fclose(fp); 215} 216 217TEST(STDIO_TEST, getline_invalid) { 218 FILE* fp = tmpfile(); 219 ASSERT_TRUE(fp != NULL); 220 221 char* buffer = NULL; 222 size_t buffer_length = 0; 223 224 // The first argument can't be NULL. 225 errno = 0; 226 ASSERT_EQ(getline(NULL, &buffer_length, fp), -1); 227 ASSERT_EQ(EINVAL, errno); 228 229 // The second argument can't be NULL. 230 errno = 0; 231 ASSERT_EQ(getline(&buffer, NULL, fp), -1); 232 ASSERT_EQ(EINVAL, errno); 233 234 // The underlying fd can't be closed. 235 ASSERT_EQ(0, close(fileno(fp))); 236 errno = 0; 237 ASSERT_EQ(getline(&buffer, &buffer_length, fp), -1); 238 ASSERT_EQ(EBADF, errno); 239 fclose(fp); 240} 241 242TEST(STDIO_TEST, printf_ssize_t) { 243 // http://b/8253769 244 ASSERT_EQ(sizeof(ssize_t), sizeof(long int)); 245 ASSERT_EQ(sizeof(ssize_t), sizeof(size_t)); 246 // For our 32-bit ABI, we had a ssize_t definition that confuses GCC into saying: 247 // error: format '%zd' expects argument of type 'signed size_t', 248 // but argument 4 has type 'ssize_t {aka long int}' [-Werror=format] 249 ssize_t v = 1; 250 char buf[32]; 251 snprintf(buf, sizeof(buf), "%zd", v); 252} 253 254// https://code.google.com/p/android/issues/detail?id=64886 255TEST(STDIO_TEST, snprintf_a) { 256 char buf[BUFSIZ]; 257 EXPECT_EQ(23, snprintf(buf, sizeof(buf), "<%a>", 9990.235)); 258 EXPECT_STREQ("<0x1.3831e147ae148p+13>", buf); 259} 260 261TEST(STDIO_TEST, snprintf_lc) { 262 char buf[BUFSIZ]; 263 wint_t wc = L'a'; 264 EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", wc)); 265 EXPECT_STREQ("<a>", buf); 266} 267 268TEST(STDIO_TEST, snprintf_ls) { 269 char buf[BUFSIZ]; 270 wchar_t* ws = NULL; 271 EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%ls>", ws)); 272 EXPECT_STREQ("<(null)>", buf); 273 274 wchar_t chars[] = { L'h', L'i', 0 }; 275 ws = chars; 276 EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%ls>", ws)); 277 EXPECT_STREQ("<hi>", buf); 278} 279 280TEST(STDIO_TEST, snprintf_n) { 281#if defined(__BIONIC__) 282 // http://b/14492135 283 char buf[32]; 284 int i = 1234; 285 EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i)); 286 EXPECT_EQ(1234, i); 287 EXPECT_STREQ("a n b", buf); 288#else 289 GTEST_LOG_(INFO) << "This test does nothing on glibc.\n"; 290#endif 291} 292 293TEST(STDIO_TEST, snprintf_smoke) { 294 char buf[BUFSIZ]; 295 296 snprintf(buf, sizeof(buf), "a"); 297 EXPECT_STREQ("a", buf); 298 299 snprintf(buf, sizeof(buf), "%%"); 300 EXPECT_STREQ("%", buf); 301 302 snprintf(buf, sizeof(buf), "01234"); 303 EXPECT_STREQ("01234", buf); 304 305 snprintf(buf, sizeof(buf), "a%sb", "01234"); 306 EXPECT_STREQ("a01234b", buf); 307 308 char* s = NULL; 309 snprintf(buf, sizeof(buf), "a%sb", s); 310 EXPECT_STREQ("a(null)b", buf); 311 312 snprintf(buf, sizeof(buf), "aa%scc", "bb"); 313 EXPECT_STREQ("aabbcc", buf); 314 315 snprintf(buf, sizeof(buf), "a%cc", 'b'); 316 EXPECT_STREQ("abc", buf); 317 318 snprintf(buf, sizeof(buf), "a%db", 1234); 319 EXPECT_STREQ("a1234b", buf); 320 321 snprintf(buf, sizeof(buf), "a%db", -8123); 322 EXPECT_STREQ("a-8123b", buf); 323 324 snprintf(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010)); 325 EXPECT_STREQ("a16b", buf); 326 327 snprintf(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10)); 328 EXPECT_STREQ("a16b", buf); 329 330 snprintf(buf, sizeof(buf), "a%lldb", 0x1000000000LL); 331 EXPECT_STREQ("a68719476736b", buf); 332 333 snprintf(buf, sizeof(buf), "a%ldb", 70000L); 334 EXPECT_STREQ("a70000b", buf); 335 336 snprintf(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234)); 337 EXPECT_STREQ("a0xb0001234b", buf); 338 339 snprintf(buf, sizeof(buf), "a%xz", 0x12ab); 340 EXPECT_STREQ("a12abz", buf); 341 342 snprintf(buf, sizeof(buf), "a%Xz", 0x12ab); 343 EXPECT_STREQ("a12ABz", buf); 344 345 snprintf(buf, sizeof(buf), "a%08xz", 0x123456); 346 EXPECT_STREQ("a00123456z", buf); 347 348 snprintf(buf, sizeof(buf), "a%5dz", 1234); 349 EXPECT_STREQ("a 1234z", buf); 350 351 snprintf(buf, sizeof(buf), "a%05dz", 1234); 352 EXPECT_STREQ("a01234z", buf); 353 354 snprintf(buf, sizeof(buf), "a%8dz", 1234); 355 EXPECT_STREQ("a 1234z", buf); 356 357 snprintf(buf, sizeof(buf), "a%-8dz", 1234); 358 EXPECT_STREQ("a1234 z", buf); 359 360 snprintf(buf, sizeof(buf), "A%-11sZ", "abcdef"); 361 EXPECT_STREQ("Aabcdef Z", buf); 362 363 snprintf(buf, sizeof(buf), "A%s:%dZ", "hello", 1234); 364 EXPECT_STREQ("Ahello:1234Z", buf); 365 366 snprintf(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5); 367 EXPECT_STREQ("a005:5:05z", buf); 368 369 void* p = NULL; 370 snprintf(buf, sizeof(buf), "a%d,%pz", 5, p); 371#if defined(__BIONIC__) 372 EXPECT_STREQ("a5,0x0z", buf); 373#else // __BIONIC__ 374 EXPECT_STREQ("a5,(nil)z", buf); 375#endif // __BIONIC__ 376 377 snprintf(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8); 378 EXPECT_STREQ("a68719476736,6,7,8z", buf); 379 380 snprintf(buf, sizeof(buf), "a_%f_b", 1.23f); 381 EXPECT_STREQ("a_1.230000_b", buf); 382 383 snprintf(buf, sizeof(buf), "a_%g_b", 3.14); 384 EXPECT_STREQ("a_3.14_b", buf); 385 386 snprintf(buf, sizeof(buf), "%1$s %1$s", "print_me_twice"); 387 EXPECT_STREQ("print_me_twice print_me_twice", buf); 388} 389 390template <typename T> 391void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...), 392 const T* fmt, const T* fmt_plus, 393 const T* minus_inf, const T* inf_, const T* plus_inf, 394 const T* minus_nan, const T* nan_, const T* plus_nan) { 395 T buf[BUFSIZ]; 396 397 snprintf_fn(buf, sizeof(buf), fmt, nan("")); 398 EXPECT_STREQ(nan_, buf) << fmt; 399 snprintf_fn(buf, sizeof(buf), fmt, -nan("")); 400 EXPECT_STREQ(minus_nan, buf) << fmt; 401 snprintf_fn(buf, sizeof(buf), fmt_plus, nan("")); 402 EXPECT_STREQ(plus_nan, buf) << fmt_plus; 403 snprintf_fn(buf, sizeof(buf), fmt_plus, -nan("")); 404 EXPECT_STREQ(minus_nan, buf) << fmt_plus; 405 406 snprintf_fn(buf, sizeof(buf), fmt, HUGE_VAL); 407 EXPECT_STREQ(inf_, buf) << fmt; 408 snprintf_fn(buf, sizeof(buf), fmt, -HUGE_VAL); 409 EXPECT_STREQ(minus_inf, buf) << fmt; 410 snprintf_fn(buf, sizeof(buf), fmt_plus, HUGE_VAL); 411 EXPECT_STREQ(plus_inf, buf) << fmt_plus; 412 snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VAL); 413 EXPECT_STREQ(minus_inf, buf) << fmt_plus; 414} 415 416TEST(STDIO_TEST, snprintf_inf_nan) { 417 CheckInfNan(snprintf, "%a", "%+a", "-inf", "inf", "+inf", "-nan", "nan", "+nan"); 418 CheckInfNan(snprintf, "%A", "%+A", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN"); 419 CheckInfNan(snprintf, "%e", "%+e", "-inf", "inf", "+inf", "-nan", "nan", "+nan"); 420 CheckInfNan(snprintf, "%E", "%+E", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN"); 421 CheckInfNan(snprintf, "%f", "%+f", "-inf", "inf", "+inf", "-nan", "nan", "+nan"); 422 CheckInfNan(snprintf, "%F", "%+F", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN"); 423 CheckInfNan(snprintf, "%g", "%+g", "-inf", "inf", "+inf", "-nan", "nan", "+nan"); 424 CheckInfNan(snprintf, "%G", "%+G", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN"); 425} 426 427TEST(STDIO_TEST, wsprintf_inf_nan) { 428 CheckInfNan(swprintf, L"%a", L"%+a", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan"); 429 CheckInfNan(swprintf, L"%A", L"%+A", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN"); 430 CheckInfNan(swprintf, L"%e", L"%+e", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan"); 431 CheckInfNan(swprintf, L"%E", L"%+E", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN"); 432 CheckInfNan(swprintf, L"%f", L"%+f", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan"); 433 CheckInfNan(swprintf, L"%F", L"%+F", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN"); 434 CheckInfNan(swprintf, L"%g", L"%+g", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan"); 435 CheckInfNan(swprintf, L"%G", L"%+G", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN"); 436} 437 438TEST(STDIO_TEST, snprintf_d_INT_MAX) { 439 char buf[BUFSIZ]; 440 snprintf(buf, sizeof(buf), "%d", INT_MAX); 441 EXPECT_STREQ("2147483647", buf); 442} 443 444TEST(STDIO_TEST, snprintf_d_INT_MIN) { 445 char buf[BUFSIZ]; 446 snprintf(buf, sizeof(buf), "%d", INT_MIN); 447 EXPECT_STREQ("-2147483648", buf); 448} 449 450TEST(STDIO_TEST, snprintf_ld_LONG_MAX) { 451 char buf[BUFSIZ]; 452 snprintf(buf, sizeof(buf), "%ld", LONG_MAX); 453#if __LP64__ 454 EXPECT_STREQ("9223372036854775807", buf); 455#else 456 EXPECT_STREQ("2147483647", buf); 457#endif 458} 459 460TEST(STDIO_TEST, snprintf_ld_LONG_MIN) { 461 char buf[BUFSIZ]; 462 snprintf(buf, sizeof(buf), "%ld", LONG_MIN); 463#if __LP64__ 464 EXPECT_STREQ("-9223372036854775808", buf); 465#else 466 EXPECT_STREQ("-2147483648", buf); 467#endif 468} 469 470TEST(STDIO_TEST, snprintf_lld_LLONG_MAX) { 471 char buf[BUFSIZ]; 472 snprintf(buf, sizeof(buf), "%lld", LLONG_MAX); 473 EXPECT_STREQ("9223372036854775807", buf); 474} 475 476TEST(STDIO_TEST, snprintf_lld_LLONG_MIN) { 477 char buf[BUFSIZ]; 478 snprintf(buf, sizeof(buf), "%lld", LLONG_MIN); 479 EXPECT_STREQ("-9223372036854775808", buf); 480} 481 482TEST(STDIO_TEST, snprintf_e) { 483 char buf[BUFSIZ]; 484 485 snprintf(buf, sizeof(buf), "%e", 1.5); 486 EXPECT_STREQ("1.500000e+00", buf); 487 488 snprintf(buf, sizeof(buf), "%Le", 1.5l); 489 EXPECT_STREQ("1.500000e+00", buf); 490} 491 492TEST(STDIO_TEST, snprintf_negative_zero_5084292) { 493 char buf[BUFSIZ]; 494 495 snprintf(buf, sizeof(buf), "%e", -0.0); 496 EXPECT_STREQ("-0.000000e+00", buf); 497 snprintf(buf, sizeof(buf), "%E", -0.0); 498 EXPECT_STREQ("-0.000000E+00", buf); 499 snprintf(buf, sizeof(buf), "%f", -0.0); 500 EXPECT_STREQ("-0.000000", buf); 501 snprintf(buf, sizeof(buf), "%F", -0.0); 502 EXPECT_STREQ("-0.000000", buf); 503 snprintf(buf, sizeof(buf), "%g", -0.0); 504 EXPECT_STREQ("-0", buf); 505 snprintf(buf, sizeof(buf), "%G", -0.0); 506 EXPECT_STREQ("-0", buf); 507 snprintf(buf, sizeof(buf), "%a", -0.0); 508 EXPECT_STREQ("-0x0p+0", buf); 509 snprintf(buf, sizeof(buf), "%A", -0.0); 510 EXPECT_STREQ("-0X0P+0", buf); 511} 512 513TEST(STDIO_TEST, snprintf_utf8_15439554) { 514 locale_t cloc = newlocale(LC_ALL, "C.UTF-8", 0); 515 locale_t old_locale = uselocale(cloc); 516 517 // http://b/15439554 518 char buf[BUFSIZ]; 519 520 // 1-byte character. 521 snprintf(buf, sizeof(buf), "%dx%d", 1, 2); 522 EXPECT_STREQ("1x2", buf); 523 // 2-byte character. 524 snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2); 525 EXPECT_STREQ("1¢2", buf); 526 // 3-byte character. 527 snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2); 528 EXPECT_STREQ("1€2", buf); 529 // 4-byte character. 530 snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2); 531 EXPECT_STREQ("12", buf); 532 533 uselocale(old_locale); 534 freelocale(cloc); 535} 536 537static void* snprintf_small_stack_fn(void*) { 538 // Make life (realistically) hard for ourselves by allocating our own buffer for the result. 539 char buf[PATH_MAX]; 540 snprintf(buf, sizeof(buf), "/proc/%d", getpid()); 541 return nullptr; 542} 543 544TEST(STDIO_TEST, snprintf_small_stack) { 545 // Is it safe to call snprintf on a thread with a small stack? 546 // (The snprintf implementation puts some pretty large buffers on the stack.) 547 pthread_attr_t a; 548 ASSERT_EQ(0, pthread_attr_init(&a)); 549 ASSERT_EQ(0, pthread_attr_setstacksize(&a, PTHREAD_STACK_MIN)); 550 551 pthread_t t; 552 ASSERT_EQ(0, pthread_create(&t, &a, snprintf_small_stack_fn, nullptr)); 553 ASSERT_EQ(0, pthread_join(t, nullptr)); 554} 555 556TEST(STDIO_TEST, snprintf_asterisk_overflow) { 557 char buf[128]; 558 ASSERT_EQ(5, snprintf(buf, sizeof(buf), "%.*s%c", 4, "hello world", '!')); 559 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX/2, "hello world", '!')); 560 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX-1, "hello world", '!')); 561 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX, "hello world", '!')); 562 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", -1, "hello world", '!')); 563 564 // INT_MAX-1, INT_MAX, INT_MAX+1. 565 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483646s%c", "hello world", '!')); 566 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483647s%c", "hello world", '!')); 567 ASSERT_EQ(-1, snprintf(buf, sizeof(buf), "%.2147483648s%c", "hello world", '!')); 568 ASSERT_EQ(ENOMEM, errno); 569} 570 571TEST(STDIO_TEST, fprintf_failures_7229520) { 572 // http://b/7229520 573 FILE* fp; 574 575 // Unbuffered case where the fprintf(3) itself fails. 576 ASSERT_NE(nullptr, fp = tmpfile()); 577 setbuf(fp, NULL); 578 ASSERT_EQ(4, fprintf(fp, "epic")); 579 ASSERT_EQ(0, close(fileno(fp))); 580 ASSERT_EQ(-1, fprintf(fp, "fail")); 581 ASSERT_EQ(-1, fclose(fp)); 582 583 // Buffered case where we won't notice until the fclose(3). 584 // It's likely this is what was actually seen in http://b/7229520, 585 // and that expecting fprintf to fail is setting yourself up for 586 // disappointment. Remember to check fclose(3)'s return value, kids! 587 ASSERT_NE(nullptr, fp = tmpfile()); 588 ASSERT_EQ(4, fprintf(fp, "epic")); 589 ASSERT_EQ(0, close(fileno(fp))); 590 ASSERT_EQ(4, fprintf(fp, "fail")); 591 ASSERT_EQ(-1, fclose(fp)); 592} 593 594TEST(STDIO_TEST, popen) { 595 FILE* fp = popen("cat /proc/version", "r"); 596 ASSERT_TRUE(fp != NULL); 597 598 char buf[16]; 599 char* s = fgets(buf, sizeof(buf), fp); 600 buf[13] = '\0'; 601 ASSERT_STREQ("Linux version", s); 602 603 ASSERT_EQ(0, pclose(fp)); 604} 605 606TEST(STDIO_TEST, getc) { 607 FILE* fp = fopen("/proc/version", "r"); 608 ASSERT_TRUE(fp != NULL); 609 ASSERT_EQ('L', getc(fp)); 610 ASSERT_EQ('i', getc(fp)); 611 ASSERT_EQ('n', getc(fp)); 612 ASSERT_EQ('u', getc(fp)); 613 ASSERT_EQ('x', getc(fp)); 614 fclose(fp); 615} 616 617TEST(STDIO_TEST, putc) { 618 FILE* fp = fopen("/proc/version", "r"); 619 ASSERT_TRUE(fp != NULL); 620 ASSERT_EQ(EOF, putc('x', fp)); 621 fclose(fp); 622} 623 624TEST(STDIO_TEST, sscanf) { 625 char s1[123]; 626 int i1; 627 double d1; 628 char s2[123]; 629 ASSERT_EQ(3, sscanf(" hello 123 1.23 ", "%s %i %lf %s", s1, &i1, &d1, s2)); 630 ASSERT_STREQ("hello", s1); 631 ASSERT_EQ(123, i1); 632 ASSERT_DOUBLE_EQ(1.23, d1); 633} 634 635TEST(STDIO_TEST, cantwrite_EBADF) { 636 // If we open a file read-only... 637 FILE* fp = fopen("/proc/version", "r"); 638 639 // ...all attempts to write to that file should return failure. 640 641 // They should also set errno to EBADF. This isn't POSIX, but it's traditional. 642 // glibc gets the wide-character functions wrong. 643 644 errno = 0; 645 EXPECT_EQ(EOF, putc('x', fp)); 646 EXPECT_EQ(EBADF, errno); 647 648 errno = 0; 649 EXPECT_EQ(EOF, fprintf(fp, "hello")); 650 EXPECT_EQ(EBADF, errno); 651 652 errno = 0; 653 EXPECT_EQ(EOF, fwprintf(fp, L"hello")); 654#if defined(__BIONIC__) 655 EXPECT_EQ(EBADF, errno); 656#endif 657 658 errno = 0; 659 EXPECT_EQ(0U, fwrite("hello", 1, 2, fp)); 660 EXPECT_EQ(EBADF, errno); 661 662 errno = 0; 663 EXPECT_EQ(EOF, fputs("hello", fp)); 664 EXPECT_EQ(EBADF, errno); 665 666 errno = 0; 667 EXPECT_EQ(WEOF, fputwc(L'x', fp)); 668#if defined(__BIONIC__) 669 EXPECT_EQ(EBADF, errno); 670#endif 671} 672 673// Tests that we can only have a consistent and correct fpos_t when using 674// f*pos functions (i.e. fpos doesn't get inside a multi byte character). 675TEST(STDIO_TEST, consistent_fpos_t) { 676 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 677 uselocale(LC_GLOBAL_LOCALE); 678 679 FILE* fp = tmpfile(); 680 ASSERT_TRUE(fp != NULL); 681 682 wchar_t mb_one_bytes = L'h'; 683 wchar_t mb_two_bytes = 0x00a2; 684 wchar_t mb_three_bytes = 0x20ac; 685 wchar_t mb_four_bytes = 0x24b62; 686 687 // Write to file. 688 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp))); 689 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp))); 690 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp))); 691 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp))); 692 693 rewind(fp); 694 695 // Record each character position. 696 fpos_t pos1; 697 fpos_t pos2; 698 fpos_t pos3; 699 fpos_t pos4; 700 fpos_t pos5; 701 EXPECT_EQ(0, fgetpos(fp, &pos1)); 702 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp))); 703 EXPECT_EQ(0, fgetpos(fp, &pos2)); 704 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp))); 705 EXPECT_EQ(0, fgetpos(fp, &pos3)); 706 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp))); 707 EXPECT_EQ(0, fgetpos(fp, &pos4)); 708 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp))); 709 EXPECT_EQ(0, fgetpos(fp, &pos5)); 710 711#if defined(__BIONIC__) 712 // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD 713 // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In 714 // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE 715 // structure. 716 ASSERT_EQ(0, static_cast<off_t>(pos1)); 717 ASSERT_EQ(1, static_cast<off_t>(pos2)); 718 ASSERT_EQ(3, static_cast<off_t>(pos3)); 719 ASSERT_EQ(6, static_cast<off_t>(pos4)); 720 ASSERT_EQ(10, static_cast<off_t>(pos5)); 721#endif 722 723 // Exercise back and forth movements of the position. 724 ASSERT_EQ(0, fsetpos(fp, &pos2)); 725 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp))); 726 ASSERT_EQ(0, fsetpos(fp, &pos1)); 727 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp))); 728 ASSERT_EQ(0, fsetpos(fp, &pos4)); 729 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp))); 730 ASSERT_EQ(0, fsetpos(fp, &pos3)); 731 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp))); 732 ASSERT_EQ(0, fsetpos(fp, &pos5)); 733 ASSERT_EQ(WEOF, fgetwc(fp)); 734 735 fclose(fp); 736} 737 738// Exercise the interaction between fpos and seek. 739TEST(STDIO_TEST, fpos_t_and_seek) { 740 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 741 uselocale(LC_GLOBAL_LOCALE); 742 743 // In glibc-2.16 fseek doesn't work properly in wide mode 744 // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is 745 // to close and re-open the file. We do it in order to make the test pass 746 // with all glibcs. 747 748 TemporaryFile tf; 749 FILE* fp = fdopen(tf.fd, "w+"); 750 ASSERT_TRUE(fp != NULL); 751 752 wchar_t mb_two_bytes = 0x00a2; 753 wchar_t mb_three_bytes = 0x20ac; 754 wchar_t mb_four_bytes = 0x24b62; 755 756 // Write to file. 757 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp))); 758 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp))); 759 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp))); 760 761 fflush(fp); 762 fclose(fp); 763 764 fp = fopen(tf.filename, "r"); 765 ASSERT_TRUE(fp != NULL); 766 767 // Store a valid position. 768 fpos_t mb_two_bytes_pos; 769 ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos)); 770 771 // Move inside mb_four_bytes with fseek. 772 long offset_inside_mb = 6; 773 ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET)); 774 775 // Store the "inside multi byte" position. 776 fpos_t pos_inside_mb; 777 ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb)); 778#if defined(__BIONIC__) 779 ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb)); 780#endif 781 782 // Reading from within a byte should produce an error. 783 ASSERT_EQ(WEOF, fgetwc(fp)); 784 ASSERT_EQ(EILSEQ, errno); 785 786 // Reverting to a valid position should work. 787 ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos)); 788 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp))); 789 790 // Moving withing a multi byte with fsetpos should work but reading should 791 // produce an error. 792 ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb)); 793 ASSERT_EQ(WEOF, fgetwc(fp)); 794 ASSERT_EQ(EILSEQ, errno); 795 796 fclose(fp); 797} 798 799TEST(STDIO_TEST, fmemopen) { 800 char buf[16]; 801 memset(buf, 0, sizeof(buf)); 802 FILE* fp = fmemopen(buf, sizeof(buf), "r+"); 803 ASSERT_EQ('<', fputc('<', fp)); 804 ASSERT_NE(EOF, fputs("abc>\n", fp)); 805 fflush(fp); 806 807 ASSERT_STREQ("<abc>\n", buf); 808 809 rewind(fp); 810 811 char line[16]; 812 char* s = fgets(line, sizeof(line), fp); 813 ASSERT_TRUE(s != NULL); 814 ASSERT_STREQ("<abc>\n", s); 815 816 fclose(fp); 817} 818 819TEST(STDIO_TEST, fmemopen_NULL) { 820 FILE* fp = fmemopen(nullptr, 128, "r+"); 821 ASSERT_NE(EOF, fputs("xyz\n", fp)); 822 823 rewind(fp); 824 825 char line[16]; 826 char* s = fgets(line, sizeof(line), fp); 827 ASSERT_TRUE(s != NULL); 828 ASSERT_STREQ("xyz\n", s); 829 830 fclose(fp); 831} 832 833TEST(STDIO_TEST, fmemopen_EINVAL) { 834 char buf[16]; 835 836 // Invalid size. 837 errno = 0; 838 ASSERT_EQ(nullptr, fmemopen(buf, 0, "r+")); 839 ASSERT_EQ(EINVAL, errno); 840 841 // No '+' with NULL buffer. 842 errno = 0; 843 ASSERT_EQ(nullptr, fmemopen(nullptr, 0, "r")); 844 ASSERT_EQ(EINVAL, errno); 845} 846 847TEST(STDIO_TEST, open_memstream) { 848 char* p = nullptr; 849 size_t size = 0; 850 FILE* fp = open_memstream(&p, &size); 851 ASSERT_NE(EOF, fputs("hello, world!", fp)); 852 fclose(fp); 853 854 ASSERT_STREQ("hello, world!", p); 855 ASSERT_EQ(strlen("hello, world!"), size); 856 free(p); 857} 858 859TEST(STDIO_TEST, open_memstream_EINVAL) { 860#if defined(__BIONIC__) 861 char* p; 862 size_t size; 863 864 // Invalid buffer. 865 errno = 0; 866 ASSERT_EQ(nullptr, open_memstream(nullptr, &size)); 867 ASSERT_EQ(EINVAL, errno); 868 869 // Invalid size. 870 errno = 0; 871 ASSERT_EQ(nullptr, open_memstream(&p, nullptr)); 872 ASSERT_EQ(EINVAL, errno); 873#else 874 GTEST_LOG_(INFO) << "This test does nothing on glibc.\n"; 875#endif 876} 877 878TEST(STDIO_TEST, fdopen_CLOEXEC) { 879 int fd = open("/proc/version", O_RDONLY); 880 ASSERT_TRUE(fd != -1); 881 882 // This fd doesn't have O_CLOEXEC... 883 int flags = fcntl(fd, F_GETFD); 884 ASSERT_TRUE(flags != -1); 885 ASSERT_EQ(0, flags & FD_CLOEXEC); 886 887 FILE* fp = fdopen(fd, "re"); 888 ASSERT_TRUE(fp != NULL); 889 890 // ...but the new one does. 891 flags = fcntl(fileno(fp), F_GETFD); 892 ASSERT_TRUE(flags != -1); 893 ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC); 894 895 fclose(fp); 896 close(fd); 897} 898 899TEST(STDIO_TEST, freopen_CLOEXEC) { 900 FILE* fp = fopen("/proc/version", "r"); 901 ASSERT_TRUE(fp != NULL); 902 903 // This FILE* doesn't have O_CLOEXEC... 904 int flags = fcntl(fileno(fp), F_GETFD); 905 ASSERT_TRUE(flags != -1); 906 ASSERT_EQ(0, flags & FD_CLOEXEC); 907 908 fp = freopen("/proc/version", "re", fp); 909 910 // ...but the new one does. 911 flags = fcntl(fileno(fp), F_GETFD); 912 ASSERT_TRUE(flags != -1); 913 ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC); 914 915 fclose(fp); 916} 917 918TEST(STDIO_TEST, fopen64_freopen64) { 919 FILE* fp = fopen64("/proc/version", "r"); 920 ASSERT_TRUE(fp != nullptr); 921 fp = freopen64("/proc/version", "re", fp); 922 ASSERT_TRUE(fp != nullptr); 923 fclose(fp); 924} 925 926// https://code.google.com/p/android/issues/detail?id=81155 927// http://b/18556607 928TEST(STDIO_TEST, fread_unbuffered_pathological_performance) { 929 FILE* fp = fopen("/dev/zero", "r"); 930 ASSERT_TRUE(fp != NULL); 931 932 // Make this stream unbuffered. 933 setvbuf(fp, 0, _IONBF, 0); 934 935 char buf[65*1024]; 936 memset(buf, 0xff, sizeof(buf)); 937 938 time_t t0 = time(NULL); 939 for (size_t i = 0; i < 1024; ++i) { 940 ASSERT_EQ(1U, fread(buf, 64*1024, 1, fp)); 941 } 942 time_t t1 = time(NULL); 943 944 fclose(fp); 945 946 // 1024 64KiB reads should have been very quick. 947 ASSERT_LE(t1 - t0, 1); 948 949 for (size_t i = 0; i < 64*1024; ++i) { 950 ASSERT_EQ('\0', buf[i]); 951 } 952 for (size_t i = 64*1024; i < 65*1024; ++i) { 953 ASSERT_EQ('\xff', buf[i]); 954 } 955} 956 957TEST(STDIO_TEST, fread_EOF) { 958 std::string digits("0123456789"); 959 FILE* fp = fmemopen(&digits[0], digits.size(), "r"); 960 961 // Try to read too much, but little enough that it still fits in the FILE's internal buffer. 962 char buf1[4 * 4]; 963 memset(buf1, 0, sizeof(buf1)); 964 ASSERT_EQ(2U, fread(buf1, 4, 4, fp)); 965 ASSERT_STREQ("0123456789", buf1); 966 ASSERT_TRUE(feof(fp)); 967 968 rewind(fp); 969 970 // Try to read way too much so stdio tries to read more direct from the stream. 971 char buf2[4 * 4096]; 972 memset(buf2, 0, sizeof(buf2)); 973 ASSERT_EQ(2U, fread(buf2, 4, 4096, fp)); 974 ASSERT_STREQ("0123456789", buf2); 975 ASSERT_TRUE(feof(fp)); 976 977 fclose(fp); 978} 979 980static void test_fread_from_write_only_stream(size_t n) { 981 FILE* fp = fopen("/dev/null", "w"); 982 std::vector<char> buf(n, 0); 983 errno = 0; 984 ASSERT_EQ(0U, fread(&buf[0], n, 1, fp)); 985 ASSERT_EQ(EBADF, errno); 986 ASSERT_TRUE(ferror(fp)); 987 ASSERT_FALSE(feof(fp)); 988 fclose(fp); 989} 990 991TEST(STDIO_TEST, fread_from_write_only_stream_slow_path) { 992 test_fread_from_write_only_stream(1); 993} 994 995TEST(STDIO_TEST, fread_from_write_only_stream_fast_path) { 996 test_fread_from_write_only_stream(64*1024); 997} 998 999static void test_fwrite_after_fread(size_t n) { 1000 TemporaryFile tf; 1001 1002 FILE* fp = fdopen(tf.fd, "w+"); 1003 ASSERT_EQ(1U, fwrite("1", 1, 1, fp)); 1004 fflush(fp); 1005 1006 // We've flushed but not rewound, so there's nothing to read. 1007 std::vector<char> buf(n, 0); 1008 ASSERT_EQ(0U, fread(&buf[0], 1, buf.size(), fp)); 1009 ASSERT_TRUE(feof(fp)); 1010 1011 // But hitting EOF doesn't prevent us from writing... 1012 errno = 0; 1013 ASSERT_EQ(1U, fwrite("2", 1, 1, fp)) << strerror(errno); 1014 1015 // And if we rewind, everything's there. 1016 rewind(fp); 1017 ASSERT_EQ(2U, fread(&buf[0], 1, buf.size(), fp)); 1018 ASSERT_EQ('1', buf[0]); 1019 ASSERT_EQ('2', buf[1]); 1020 1021 fclose(fp); 1022} 1023 1024TEST(STDIO_TEST, fwrite_after_fread_slow_path) { 1025 test_fwrite_after_fread(16); 1026} 1027 1028TEST(STDIO_TEST, fwrite_after_fread_fast_path) { 1029 test_fwrite_after_fread(64*1024); 1030} 1031 1032// http://b/19172514 1033TEST(STDIO_TEST, fread_after_fseek) { 1034 TemporaryFile tf; 1035 1036 FILE* fp = fopen(tf.filename, "w+"); 1037 ASSERT_TRUE(fp != nullptr); 1038 1039 char file_data[12288]; 1040 for (size_t i = 0; i < 12288; i++) { 1041 file_data[i] = i; 1042 } 1043 ASSERT_EQ(12288U, fwrite(file_data, 1, 12288, fp)); 1044 fclose(fp); 1045 1046 fp = fopen(tf.filename, "r"); 1047 ASSERT_TRUE(fp != nullptr); 1048 1049 char buffer[8192]; 1050 size_t cur_location = 0; 1051 // Small read to populate internal buffer. 1052 ASSERT_EQ(100U, fread(buffer, 1, 100, fp)); 1053 ASSERT_EQ(memcmp(file_data, buffer, 100), 0); 1054 1055 cur_location = static_cast<size_t>(ftell(fp)); 1056 // Large read to force reading into the user supplied buffer and bypassing 1057 // the internal buffer. 1058 ASSERT_EQ(8192U, fread(buffer, 1, 8192, fp)); 1059 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 8192), 0); 1060 1061 // Small backwards seek to verify fseek does not reuse the internal buffer. 1062 ASSERT_EQ(0, fseek(fp, -22, SEEK_CUR)) << strerror(errno); 1063 cur_location = static_cast<size_t>(ftell(fp)); 1064 ASSERT_EQ(22U, fread(buffer, 1, 22, fp)); 1065 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 22), 0); 1066 1067 fclose(fp); 1068} 1069 1070// https://code.google.com/p/android/issues/detail?id=184847 1071TEST(STDIO_TEST, fread_EOF_184847) { 1072 TemporaryFile tf; 1073 char buf[6] = {0}; 1074 1075 FILE* fw = fopen(tf.filename, "w"); 1076 ASSERT_TRUE(fw != nullptr); 1077 1078 FILE* fr = fopen(tf.filename, "r"); 1079 ASSERT_TRUE(fr != nullptr); 1080 1081 fwrite("a", 1, 1, fw); 1082 fflush(fw); 1083 ASSERT_EQ(1U, fread(buf, 1, 1, fr)); 1084 ASSERT_STREQ("a", buf); 1085 1086 // 'fr' is now at EOF. 1087 ASSERT_EQ(0U, fread(buf, 1, 1, fr)); 1088 ASSERT_TRUE(feof(fr)); 1089 1090 // Write some more... 1091 fwrite("z", 1, 1, fw); 1092 fflush(fw); 1093 1094 // ...and check that we can read it back. 1095 // (BSD thinks that once a stream has hit EOF, it must always return EOF. SysV disagrees.) 1096 ASSERT_EQ(1U, fread(buf, 1, 1, fr)); 1097 ASSERT_STREQ("z", buf); 1098 1099 // But now we're done. 1100 ASSERT_EQ(0U, fread(buf, 1, 1, fr)); 1101 1102 fclose(fr); 1103 fclose(fw); 1104} 1105 1106TEST(STDIO_TEST, fclose_invalidates_fd) { 1107 // The typical error we're trying to help people catch involves accessing 1108 // memory after it's been freed. But we know that stdin/stdout/stderr are 1109 // special and don't get deallocated, so this test uses stdin. 1110 ASSERT_EQ(0, fclose(stdin)); 1111 1112 // Even though using a FILE* after close is undefined behavior, I've closed 1113 // this bug as "WAI" too many times. We shouldn't hand out stale fds, 1114 // especially because they might actually correspond to a real stream. 1115 errno = 0; 1116 ASSERT_EQ(-1, fileno(stdin)); 1117 ASSERT_EQ(EBADF, errno); 1118} 1119 1120TEST(STDIO_TEST, fseek_ftell_unseekable) { 1121#if defined(__BIONIC__) // glibc has fopencookie instead. 1122 auto read_fn = [](void*, char*, int) { return -1; }; 1123 FILE* fp = funopen(nullptr, read_fn, nullptr, nullptr, nullptr); 1124 ASSERT_TRUE(fp != nullptr); 1125 1126 // Check that ftell balks on an unseekable FILE*. 1127 errno = 0; 1128 ASSERT_EQ(-1, ftell(fp)); 1129 ASSERT_EQ(ESPIPE, errno); 1130 1131 // SEEK_CUR is rewritten as SEEK_SET internally... 1132 errno = 0; 1133 ASSERT_EQ(-1, fseek(fp, 0, SEEK_CUR)); 1134 ASSERT_EQ(ESPIPE, errno); 1135 1136 // ...so it's worth testing the direct seek path too. 1137 errno = 0; 1138 ASSERT_EQ(-1, fseek(fp, 0, SEEK_SET)); 1139 ASSERT_EQ(ESPIPE, errno); 1140 1141 fclose(fp); 1142#else 1143 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n"; 1144#endif 1145} 1146 1147TEST(STDIO_TEST, funopen_EINVAL) { 1148#if defined(__BIONIC__) 1149 errno = 0; 1150 ASSERT_EQ(nullptr, funopen(nullptr, nullptr, nullptr, nullptr, nullptr)); 1151 ASSERT_EQ(EINVAL, errno); 1152#else 1153 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n"; 1154#endif 1155} 1156 1157TEST(STDIO_TEST, funopen_seek) { 1158#if defined(__BIONIC__) 1159 auto read_fn = [](void*, char*, int) { return -1; }; 1160 1161 auto seek_fn = [](void*, fpos_t, int) -> fpos_t { return 0xfedcba12; }; 1162 auto seek64_fn = [](void*, fpos64_t, int) -> fpos64_t { return 0xfedcba12345678; }; 1163 1164 FILE* fp = funopen(nullptr, read_fn, nullptr, seek_fn, nullptr); 1165 ASSERT_TRUE(fp != nullptr); 1166 fpos_t pos; 1167#if defined(__LP64__) 1168 EXPECT_EQ(0, fgetpos(fp, &pos)) << strerror(errno); 1169 EXPECT_EQ(0xfedcba12LL, pos); 1170#else 1171 EXPECT_EQ(-1, fgetpos(fp, &pos)) << strerror(errno); 1172 EXPECT_EQ(EOVERFLOW, errno); 1173#endif 1174 1175 FILE* fp64 = funopen64(nullptr, read_fn, nullptr, seek64_fn, nullptr); 1176 ASSERT_TRUE(fp64 != nullptr); 1177 fpos64_t pos64; 1178 EXPECT_EQ(0, fgetpos64(fp64, &pos64)) << strerror(errno); 1179 EXPECT_EQ(0xfedcba12345678, pos64); 1180#else 1181 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n"; 1182#endif 1183} 1184 1185TEST(STDIO_TEST, lots_of_concurrent_files) { 1186 std::vector<TemporaryFile*> tfs; 1187 std::vector<FILE*> fps; 1188 1189 for (size_t i = 0; i < 256; ++i) { 1190 TemporaryFile* tf = new TemporaryFile; 1191 tfs.push_back(tf); 1192 FILE* fp = fopen(tf->filename, "w+"); 1193 fps.push_back(fp); 1194 fprintf(fp, "hello %zu!\n", i); 1195 fflush(fp); 1196 } 1197 1198 for (size_t i = 0; i < 256; ++i) { 1199 rewind(fps[i]); 1200 1201 char buf[BUFSIZ]; 1202 ASSERT_TRUE(fgets(buf, sizeof(buf), fps[i]) != nullptr); 1203 1204 char expected[BUFSIZ]; 1205 snprintf(expected, sizeof(expected), "hello %zu!\n", i); 1206 ASSERT_STREQ(expected, buf); 1207 1208 fclose(fps[i]); 1209 delete tfs[i]; 1210 } 1211} 1212 1213static void AssertFileOffsetAt(FILE* fp, off64_t offset) { 1214 EXPECT_EQ(offset, ftell(fp)); 1215 EXPECT_EQ(offset, ftello(fp)); 1216 EXPECT_EQ(offset, ftello64(fp)); 1217 fpos_t pos; 1218 fpos64_t pos64; 1219 EXPECT_EQ(0, fgetpos(fp, &pos)); 1220 EXPECT_EQ(0, fgetpos64(fp, &pos64)); 1221#if defined(__BIONIC__) 1222 EXPECT_EQ(offset, static_cast<off64_t>(pos)); 1223 EXPECT_EQ(offset, static_cast<off64_t>(pos64)); 1224#else 1225 GTEST_LOG_(INFO) << "glibc's fpos_t is opaque.\n"; 1226#endif 1227} 1228 1229TEST(STDIO_TEST, seek_tell_family_smoke) { 1230 TemporaryFile tf; 1231 FILE* fp = fdopen(tf.fd, "w+"); 1232 1233 // Initially we should be at 0. 1234 AssertFileOffsetAt(fp, 0); 1235 1236 // Seek to offset 8192. 1237 ASSERT_EQ(0, fseek(fp, 8192, SEEK_SET)); 1238 AssertFileOffsetAt(fp, 8192); 1239 fpos_t eight_k_pos; 1240 ASSERT_EQ(0, fgetpos(fp, &eight_k_pos)); 1241 1242 // Seek forward another 8192... 1243 ASSERT_EQ(0, fseek(fp, 8192, SEEK_CUR)); 1244 AssertFileOffsetAt(fp, 8192 + 8192); 1245 fpos64_t sixteen_k_pos64; 1246 ASSERT_EQ(0, fgetpos64(fp, &sixteen_k_pos64)); 1247 1248 // Seek back 8192... 1249 ASSERT_EQ(0, fseek(fp, -8192, SEEK_CUR)); 1250 AssertFileOffsetAt(fp, 8192); 1251 1252 // Since we haven't written anything, the end is also at 0. 1253 ASSERT_EQ(0, fseek(fp, 0, SEEK_END)); 1254 AssertFileOffsetAt(fp, 0); 1255 1256 // Check that our fpos64_t from 16KiB works... 1257 ASSERT_EQ(0, fsetpos64(fp, &sixteen_k_pos64)); 1258 AssertFileOffsetAt(fp, 8192 + 8192); 1259 // ...as does our fpos_t from 8192. 1260 ASSERT_EQ(0, fsetpos(fp, &eight_k_pos)); 1261 AssertFileOffsetAt(fp, 8192); 1262 1263 // Do fseeko and fseeko64 work too? 1264 ASSERT_EQ(0, fseeko(fp, 1234, SEEK_SET)); 1265 AssertFileOffsetAt(fp, 1234); 1266 ASSERT_EQ(0, fseeko64(fp, 5678, SEEK_SET)); 1267 AssertFileOffsetAt(fp, 5678); 1268 1269 fclose(fp); 1270} 1271 1272TEST(STDIO_TEST, fseek_fseeko_EINVAL) { 1273 TemporaryFile tf; 1274 FILE* fp = fdopen(tf.fd, "w+"); 1275 1276 // Bad whence. 1277 errno = 0; 1278 ASSERT_EQ(-1, fseek(fp, 0, 123)); 1279 ASSERT_EQ(EINVAL, errno); 1280 errno = 0; 1281 ASSERT_EQ(-1, fseeko(fp, 0, 123)); 1282 ASSERT_EQ(EINVAL, errno); 1283 errno = 0; 1284 ASSERT_EQ(-1, fseeko64(fp, 0, 123)); 1285 ASSERT_EQ(EINVAL, errno); 1286 1287 // Bad offset. 1288 errno = 0; 1289 ASSERT_EQ(-1, fseek(fp, -1, SEEK_SET)); 1290 ASSERT_EQ(EINVAL, errno); 1291 errno = 0; 1292 ASSERT_EQ(-1, fseeko(fp, -1, SEEK_SET)); 1293 ASSERT_EQ(EINVAL, errno); 1294 errno = 0; 1295 ASSERT_EQ(-1, fseeko64(fp, -1, SEEK_SET)); 1296 ASSERT_EQ(EINVAL, errno); 1297 1298 fclose(fp); 1299} 1300