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