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("1��2", 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