blob: 890e86edc09e48937b6c4d31a4f86ad6bd8a0e36 [file] [log] [blame]
Elliott Hughes91875dc2012-09-24 17:55:15 -07001/*
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>
Elliott Hughesc9244bd2014-05-14 13:31:35 -070020#include <fcntl.h>
Elliott Hughes1d13c642013-09-23 16:02:39 -070021#include <limits.h>
Elliott Hughes7823f322014-04-14 12:11:28 -070022#include <math.h>
Elliott Hughes91875dc2012-09-24 17:55:15 -070023#include <stdio.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
Elliott Hughes05493712014-04-17 17:30:03 -070027#include <wchar.h>
Calin Juravle03e4ebe2014-05-08 14:42:06 +010028#include <locale.h>
29
Elliott Hughese6bb5a22015-01-23 17:48:15 -080030#include <vector>
31
Calin Juravle03e4ebe2014-05-08 14:42:06 +010032#include "TemporaryFile.h"
Elliott Hughes91875dc2012-09-24 17:55:15 -070033
Elliott Hughes6a03abc2014-11-03 12:32:17 -080034TEST(stdio, flockfile_18208568_stderr) {
35 // Check that we have a _recursive_ mutex for flockfile.
36 flockfile(stderr);
37 feof(stderr); // We don't care about the result, but this needs to take the lock.
38 funlockfile(stderr);
39}
40
41TEST(stdio, flockfile_18208568_regular) {
42 // We never had a bug for streams other than stdin/stdout/stderr, but test anyway.
43 FILE* fp = fopen("/dev/null", "w");
44 ASSERT_TRUE(fp != NULL);
45 flockfile(fp);
46 feof(fp);
47 funlockfile(fp);
48 fclose(fp);
49}
50
Elliott Hughes91875dc2012-09-24 17:55:15 -070051TEST(stdio, tmpfile_fileno_fprintf_rewind_fgets) {
52 FILE* fp = tmpfile();
53 ASSERT_TRUE(fp != NULL);
54
55 int fd = fileno(fp);
56 ASSERT_NE(fd, -1);
57
58 struct stat sb;
59 int rc = fstat(fd, &sb);
60 ASSERT_NE(rc, -1);
61 ASSERT_EQ(sb.st_mode & 0777, 0600U);
62
63 rc = fprintf(fp, "hello\n");
64 ASSERT_EQ(rc, 6);
65
66 rewind(fp);
67
68 char buf[16];
69 char* s = fgets(buf, sizeof(buf), fp);
70 ASSERT_TRUE(s != NULL);
71 ASSERT_STREQ("hello\n", s);
72
73 fclose(fp);
74}
Irina Tirdeaeac9eb42012-09-08 09:28:30 +030075
Calin Juravle6afb2a92014-05-22 11:47:47 +010076TEST(stdio, dprintf) {
77 TemporaryFile tf;
78
79 int rc = dprintf(tf.fd, "hello\n");
80 ASSERT_EQ(rc, 6);
81
Yabin Cui5ca4a9e2014-11-06 19:55:09 -080082 lseek(tf.fd, 0, SEEK_SET);
Christopher Ferris9e01ea62014-05-29 12:49:35 -070083 FILE* tfile = fdopen(tf.fd, "r");
84 ASSERT_TRUE(tfile != NULL);
Calin Juravle6afb2a92014-05-22 11:47:47 +010085
Christopher Ferris9e01ea62014-05-29 12:49:35 -070086 char buf[7];
87 ASSERT_EQ(buf, fgets(buf, sizeof(buf), tfile));
Calin Juravle6afb2a92014-05-22 11:47:47 +010088 ASSERT_STREQ("hello\n", buf);
Christopher Ferris9e01ea62014-05-29 12:49:35 -070089 // Make sure there isn't anything else in the file.
90 ASSERT_EQ(NULL, fgets(buf, sizeof(buf), tfile));
91 fclose(tfile);
Calin Juravle6afb2a92014-05-22 11:47:47 +010092}
93
Irina Tirdeaeac9eb42012-09-08 09:28:30 +030094TEST(stdio, getdelim) {
95 FILE* fp = tmpfile();
96 ASSERT_TRUE(fp != NULL);
97
98 const char* line_written = "This is a test";
99 int rc = fprintf(fp, "%s", line_written);
100 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
101
102 rewind(fp);
103
104 char* word_read = NULL;
105 size_t allocated_length = 0;
106
107 const char* expected[] = { "This ", " ", "is ", "a ", "test" };
108 for (size_t i = 0; i < 5; ++i) {
109 ASSERT_FALSE(feof(fp));
110 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), static_cast<int>(strlen(expected[i])));
111 ASSERT_GE(allocated_length, strlen(expected[i]));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800112 ASSERT_STREQ(expected[i], word_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300113 }
114 // The last read should have set the end-of-file indicator for the stream.
115 ASSERT_TRUE(feof(fp));
116 clearerr(fp);
117
118 // getdelim returns -1 but doesn't set errno if we're already at EOF.
119 // It should set the end-of-file indicator for the stream, though.
120 errno = 0;
121 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800122 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300123 ASSERT_TRUE(feof(fp));
124
125 free(word_read);
126 fclose(fp);
127}
128
129TEST(stdio, getdelim_invalid) {
130 FILE* fp = tmpfile();
Elliott Hughes6ad8f762013-12-19 14:56:17 -0800131 ASSERT_TRUE(fp != NULL);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300132
133 char* buffer = NULL;
134 size_t buffer_length = 0;
135
136 // The first argument can't be NULL.
137 errno = 0;
138 ASSERT_EQ(getdelim(NULL, &buffer_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800139 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300140
141 // The second argument can't be NULL.
142 errno = 0;
143 ASSERT_EQ(getdelim(&buffer, NULL, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800144 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300145
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700146 // The underlying fd can't be closed.
147 ASSERT_EQ(0, close(fileno(fp)));
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300148 errno = 0;
149 ASSERT_EQ(getdelim(&buffer, &buffer_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800150 ASSERT_EQ(EBADF, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700151 fclose(fp);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300152}
153
154TEST(stdio, getline) {
155 FILE* fp = tmpfile();
156 ASSERT_TRUE(fp != NULL);
157
158 const char* line_written = "This is a test for getline\n";
159 const size_t line_count = 5;
160
161 for (size_t i = 0; i < line_count; ++i) {
162 int rc = fprintf(fp, "%s", line_written);
163 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
164 }
165
166 rewind(fp);
167
168 char* line_read = NULL;
169 size_t allocated_length = 0;
170
171 size_t read_line_count = 0;
172 ssize_t read_char_count;
173 while ((read_char_count = getline(&line_read, &allocated_length, fp)) != -1) {
174 ASSERT_EQ(read_char_count, static_cast<int>(strlen(line_written)));
175 ASSERT_GE(allocated_length, strlen(line_written));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800176 ASSERT_STREQ(line_written, line_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300177 ++read_line_count;
178 }
179 ASSERT_EQ(read_line_count, line_count);
180
181 // The last read should have set the end-of-file indicator for the stream.
182 ASSERT_TRUE(feof(fp));
183 clearerr(fp);
184
185 // getline returns -1 but doesn't set errno if we're already at EOF.
186 // It should set the end-of-file indicator for the stream, though.
187 errno = 0;
188 ASSERT_EQ(getline(&line_read, &allocated_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800189 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300190 ASSERT_TRUE(feof(fp));
191
192 free(line_read);
193 fclose(fp);
194}
195
196TEST(stdio, getline_invalid) {
197 FILE* fp = tmpfile();
Elliott Hughes6ad8f762013-12-19 14:56:17 -0800198 ASSERT_TRUE(fp != NULL);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300199
200 char* buffer = NULL;
201 size_t buffer_length = 0;
202
203 // The first argument can't be NULL.
204 errno = 0;
205 ASSERT_EQ(getline(NULL, &buffer_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800206 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300207
208 // The second argument can't be NULL.
209 errno = 0;
210 ASSERT_EQ(getline(&buffer, NULL, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800211 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300212
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700213 // The underlying fd can't be closed.
214 ASSERT_EQ(0, close(fileno(fp)));
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300215 errno = 0;
216 ASSERT_EQ(getline(&buffer, &buffer_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800217 ASSERT_EQ(EBADF, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700218 fclose(fp);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300219}
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000220
221TEST(stdio, printf_ssize_t) {
Elliott Hughese2556422013-02-28 10:51:14 -0800222 // http://b/8253769
Elliott Hughese2556422013-02-28 10:51:14 -0800223 ASSERT_EQ(sizeof(ssize_t), sizeof(long int));
Elliott Hughesb6e22482013-03-08 15:28:52 -0800224 ASSERT_EQ(sizeof(ssize_t), sizeof(size_t));
225 // For our 32-bit ABI, we had a ssize_t definition that confuses GCC into saying:
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000226 // error: format '%zd' expects argument of type 'signed size_t',
227 // but argument 4 has type 'ssize_t {aka long int}' [-Werror=format]
228 ssize_t v = 1;
229 char buf[32];
230 snprintf(buf, sizeof(buf), "%zd", v);
231}
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800232
Elliott Hughes05493712014-04-17 17:30:03 -0700233// https://code.google.com/p/android/issues/detail?id=64886
234TEST(stdio, snprintf_a) {
235 char buf[BUFSIZ];
236 EXPECT_EQ(23, snprintf(buf, sizeof(buf), "<%a>", 9990.235));
237 EXPECT_STREQ("<0x1.3831e147ae148p+13>", buf);
238}
239
240TEST(stdio, snprintf_lc) {
241 char buf[BUFSIZ];
242 wint_t wc = L'a';
243 EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", wc));
244 EXPECT_STREQ("<a>", buf);
245}
246
247TEST(stdio, snprintf_ls) {
248 char buf[BUFSIZ];
249 wchar_t* ws = NULL;
250 EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%ls>", ws));
251 EXPECT_STREQ("<(null)>", buf);
252
253 wchar_t chars[] = { L'h', L'i', 0 };
254 ws = chars;
255 EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%ls>", ws));
256 EXPECT_STREQ("<hi>", buf);
257}
258
259TEST(stdio, snprintf_n) {
Elliott Hughes063525c2014-05-13 11:19:57 -0700260#if defined(__BIONIC__)
Elliott Hughese2341d02014-05-02 18:16:32 -0700261 // http://b/14492135
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700262 char buf[32];
Elliott Hughese2341d02014-05-02 18:16:32 -0700263 int i = 1234;
264 EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i));
265 EXPECT_EQ(1234, i);
266 EXPECT_STREQ("a n b", buf);
267#else
268 GTEST_LOG_(INFO) << "This test does nothing.\n";
269#endif
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700270}
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700271
Elliott Hughes1d13c642013-09-23 16:02:39 -0700272TEST(stdio, snprintf_smoke) {
273 char buf[BUFSIZ];
274
275 snprintf(buf, sizeof(buf), "a");
276 EXPECT_STREQ("a", buf);
277
278 snprintf(buf, sizeof(buf), "%%");
279 EXPECT_STREQ("%", buf);
280
281 snprintf(buf, sizeof(buf), "01234");
282 EXPECT_STREQ("01234", buf);
283
284 snprintf(buf, sizeof(buf), "a%sb", "01234");
285 EXPECT_STREQ("a01234b", buf);
286
287 char* s = NULL;
288 snprintf(buf, sizeof(buf), "a%sb", s);
289 EXPECT_STREQ("a(null)b", buf);
290
291 snprintf(buf, sizeof(buf), "aa%scc", "bb");
292 EXPECT_STREQ("aabbcc", buf);
293
294 snprintf(buf, sizeof(buf), "a%cc", 'b');
295 EXPECT_STREQ("abc", buf);
296
297 snprintf(buf, sizeof(buf), "a%db", 1234);
298 EXPECT_STREQ("a1234b", buf);
299
300 snprintf(buf, sizeof(buf), "a%db", -8123);
301 EXPECT_STREQ("a-8123b", buf);
302
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700303 snprintf(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010));
Elliott Hughes1d13c642013-09-23 16:02:39 -0700304 EXPECT_STREQ("a16b", buf);
305
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700306 snprintf(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10));
Elliott Hughes1d13c642013-09-23 16:02:39 -0700307 EXPECT_STREQ("a16b", buf);
308
309 snprintf(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
310 EXPECT_STREQ("a68719476736b", buf);
311
312 snprintf(buf, sizeof(buf), "a%ldb", 70000L);
313 EXPECT_STREQ("a70000b", buf);
314
315 snprintf(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
316 EXPECT_STREQ("a0xb0001234b", buf);
317
318 snprintf(buf, sizeof(buf), "a%xz", 0x12ab);
319 EXPECT_STREQ("a12abz", buf);
320
321 snprintf(buf, sizeof(buf), "a%Xz", 0x12ab);
322 EXPECT_STREQ("a12ABz", buf);
323
324 snprintf(buf, sizeof(buf), "a%08xz", 0x123456);
325 EXPECT_STREQ("a00123456z", buf);
326
327 snprintf(buf, sizeof(buf), "a%5dz", 1234);
328 EXPECT_STREQ("a 1234z", buf);
329
330 snprintf(buf, sizeof(buf), "a%05dz", 1234);
331 EXPECT_STREQ("a01234z", buf);
332
333 snprintf(buf, sizeof(buf), "a%8dz", 1234);
334 EXPECT_STREQ("a 1234z", buf);
335
336 snprintf(buf, sizeof(buf), "a%-8dz", 1234);
337 EXPECT_STREQ("a1234 z", buf);
338
339 snprintf(buf, sizeof(buf), "A%-11sZ", "abcdef");
340 EXPECT_STREQ("Aabcdef Z", buf);
341
342 snprintf(buf, sizeof(buf), "A%s:%dZ", "hello", 1234);
343 EXPECT_STREQ("Ahello:1234Z", buf);
344
345 snprintf(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
346 EXPECT_STREQ("a005:5:05z", buf);
347
348 void* p = NULL;
349 snprintf(buf, sizeof(buf), "a%d,%pz", 5, p);
Christopher Ferris13613132013-10-28 15:24:04 -0700350#if defined(__BIONIC__)
Elliott Hughes1d13c642013-09-23 16:02:39 -0700351 EXPECT_STREQ("a5,0x0z", buf);
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800352#else // __BIONIC__
Christopher Ferris13613132013-10-28 15:24:04 -0700353 EXPECT_STREQ("a5,(nil)z", buf);
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800354#endif // __BIONIC__
Elliott Hughes1d13c642013-09-23 16:02:39 -0700355
356 snprintf(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
357 EXPECT_STREQ("a68719476736,6,7,8z", buf);
358
359 snprintf(buf, sizeof(buf), "a_%f_b", 1.23f);
360 EXPECT_STREQ("a_1.230000_b", buf);
361
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700362 snprintf(buf, sizeof(buf), "a_%g_b", 3.14);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700363 EXPECT_STREQ("a_3.14_b", buf);
Alexander Ivchenkoedd7c2e2014-04-01 17:01:39 +0400364
365 snprintf(buf, sizeof(buf), "%1$s %1$s", "print_me_twice");
366 EXPECT_STREQ("print_me_twice print_me_twice", buf);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700367}
368
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800369template <typename T>
370void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...),
371 const T* fmt, const T* fmt_plus,
372 const T* minus_inf, const T* inf_, const T* plus_inf,
373 const T* minus_nan, const T* nan_, const T* plus_nan) {
374 T buf[BUFSIZ];
Elliott Hughes7823f322014-04-14 12:11:28 -0700375
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800376 snprintf_fn(buf, sizeof(buf), fmt, nan(""));
377 EXPECT_STREQ(nan_, buf) << fmt;
378 snprintf_fn(buf, sizeof(buf), fmt, -nan(""));
379 EXPECT_STREQ(minus_nan, buf) << fmt;
380 snprintf_fn(buf, sizeof(buf), fmt_plus, nan(""));
381 EXPECT_STREQ(plus_nan, buf) << fmt_plus;
382 snprintf_fn(buf, sizeof(buf), fmt_plus, -nan(""));
383 EXPECT_STREQ(minus_nan, buf) << fmt_plus;
384
385 snprintf_fn(buf, sizeof(buf), fmt, HUGE_VAL);
386 EXPECT_STREQ(inf_, buf) << fmt;
387 snprintf_fn(buf, sizeof(buf), fmt, -HUGE_VAL);
388 EXPECT_STREQ(minus_inf, buf) << fmt;
389 snprintf_fn(buf, sizeof(buf), fmt_plus, HUGE_VAL);
390 EXPECT_STREQ(plus_inf, buf) << fmt_plus;
391 snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VAL);
392 EXPECT_STREQ(minus_inf, buf) << fmt_plus;
Elliott Hughes7823f322014-04-14 12:11:28 -0700393}
394
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800395TEST(stdio, snprintf_inf_nan) {
396 CheckInfNan(snprintf, "%a", "%+a", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
397 CheckInfNan(snprintf, "%A", "%+A", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
398 CheckInfNan(snprintf, "%e", "%+e", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
399 CheckInfNan(snprintf, "%E", "%+E", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
400 CheckInfNan(snprintf, "%f", "%+f", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
401 CheckInfNan(snprintf, "%F", "%+F", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
402 CheckInfNan(snprintf, "%g", "%+g", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
403 CheckInfNan(snprintf, "%G", "%+G", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
404}
Elliott Hughes7823f322014-04-14 12:11:28 -0700405
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800406TEST(stdio, wsprintf_inf_nan) {
407 CheckInfNan(swprintf, L"%a", L"%+a", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
408 CheckInfNan(swprintf, L"%A", L"%+A", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
409 CheckInfNan(swprintf, L"%e", L"%+e", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
410 CheckInfNan(swprintf, L"%E", L"%+E", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
411 CheckInfNan(swprintf, L"%f", L"%+f", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
412 CheckInfNan(swprintf, L"%F", L"%+F", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
413 CheckInfNan(swprintf, L"%g", L"%+g", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
414 CheckInfNan(swprintf, L"%G", L"%+G", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
Elliott Hughes7823f322014-04-14 12:11:28 -0700415}
416
Elliott Hughes1d13c642013-09-23 16:02:39 -0700417TEST(stdio, snprintf_d_INT_MAX) {
418 char buf[BUFSIZ];
419 snprintf(buf, sizeof(buf), "%d", INT_MAX);
420 EXPECT_STREQ("2147483647", buf);
421}
422
423TEST(stdio, snprintf_d_INT_MIN) {
424 char buf[BUFSIZ];
425 snprintf(buf, sizeof(buf), "%d", INT_MIN);
426 EXPECT_STREQ("-2147483648", buf);
427}
428
429TEST(stdio, snprintf_ld_LONG_MAX) {
430 char buf[BUFSIZ];
431 snprintf(buf, sizeof(buf), "%ld", LONG_MAX);
Elliott Hughes925753a2013-10-18 13:17:18 -0700432#if __LP64__
433 EXPECT_STREQ("9223372036854775807", buf);
434#else
Elliott Hughes1d13c642013-09-23 16:02:39 -0700435 EXPECT_STREQ("2147483647", buf);
Elliott Hughes925753a2013-10-18 13:17:18 -0700436#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700437}
438
439TEST(stdio, snprintf_ld_LONG_MIN) {
440 char buf[BUFSIZ];
441 snprintf(buf, sizeof(buf), "%ld", LONG_MIN);
Elliott Hughes925753a2013-10-18 13:17:18 -0700442#if __LP64__
443 EXPECT_STREQ("-9223372036854775808", buf);
444#else
Elliott Hughes1d13c642013-09-23 16:02:39 -0700445 EXPECT_STREQ("-2147483648", buf);
Elliott Hughes925753a2013-10-18 13:17:18 -0700446#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700447}
448
449TEST(stdio, snprintf_lld_LLONG_MAX) {
450 char buf[BUFSIZ];
451 snprintf(buf, sizeof(buf), "%lld", LLONG_MAX);
452 EXPECT_STREQ("9223372036854775807", buf);
453}
454
455TEST(stdio, snprintf_lld_LLONG_MIN) {
456 char buf[BUFSIZ];
457 snprintf(buf, sizeof(buf), "%lld", LLONG_MIN);
458 EXPECT_STREQ("-9223372036854775808", buf);
459}
460
Elliott Hughes4bd97ce2014-04-10 17:48:14 -0700461TEST(stdio, snprintf_e) {
462 char buf[BUFSIZ];
463
464 snprintf(buf, sizeof(buf), "%e", 1.5);
465 EXPECT_STREQ("1.500000e+00", buf);
466
467 snprintf(buf, sizeof(buf), "%Le", 1.5l);
468 EXPECT_STREQ("1.500000e+00", buf);
469}
470
Elliott Hughese77f38f2014-05-14 12:39:12 -0700471TEST(stdio, snprintf_negative_zero_5084292) {
472 char buf[BUFSIZ];
473
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800474 snprintf(buf, sizeof(buf), "%e", -0.0);
475 EXPECT_STREQ("-0.000000e+00", buf);
476 snprintf(buf, sizeof(buf), "%E", -0.0);
477 EXPECT_STREQ("-0.000000E+00", buf);
Elliott Hughese77f38f2014-05-14 12:39:12 -0700478 snprintf(buf, sizeof(buf), "%f", -0.0);
479 EXPECT_STREQ("-0.000000", buf);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800480 snprintf(buf, sizeof(buf), "%F", -0.0);
481 EXPECT_STREQ("-0.000000", buf);
482 snprintf(buf, sizeof(buf), "%g", -0.0);
483 EXPECT_STREQ("-0", buf);
484 snprintf(buf, sizeof(buf), "%G", -0.0);
485 EXPECT_STREQ("-0", buf);
486 snprintf(buf, sizeof(buf), "%a", -0.0);
487 EXPECT_STREQ("-0x0p+0", buf);
488 snprintf(buf, sizeof(buf), "%A", -0.0);
489 EXPECT_STREQ("-0X0P+0", buf);
Elliott Hughese77f38f2014-05-14 12:39:12 -0700490}
491
Elliott Hughes69f05d22014-06-05 20:10:09 -0700492TEST(stdio, snprintf_utf8_15439554) {
Dan Albert1aec7c12014-07-30 10:53:48 -0700493 locale_t cloc = newlocale(LC_ALL, "C.UTF-8", 0);
Wally Yaua40fdbd2014-08-26 09:47:23 -0700494 locale_t old_locale = uselocale(cloc);
Dan Albert1aec7c12014-07-30 10:53:48 -0700495
Elliott Hughes69f05d22014-06-05 20:10:09 -0700496 // http://b/15439554
497 char buf[BUFSIZ];
498
499 // 1-byte character.
500 snprintf(buf, sizeof(buf), "%dx%d", 1, 2);
501 EXPECT_STREQ("1x2", buf);
502 // 2-byte character.
503 snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2);
504 EXPECT_STREQ("1¢2", buf);
505 // 3-byte character.
506 snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2);
507 EXPECT_STREQ("1€2", buf);
508 // 4-byte character.
509 snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2);
510 EXPECT_STREQ("1𤭢2", buf);
Dan Albert1aec7c12014-07-30 10:53:48 -0700511
Wally Yaua40fdbd2014-08-26 09:47:23 -0700512 uselocale(old_locale);
Dan Albert1aec7c12014-07-30 10:53:48 -0700513 freelocale(cloc);
Elliott Hughes69f05d22014-06-05 20:10:09 -0700514}
515
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700516TEST(stdio, fprintf_failures_7229520) {
Elliott Hughes69f05d22014-06-05 20:10:09 -0700517 // http://b/7229520
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700518 FILE* fp;
519
520 // Unbuffered case where the fprintf(3) itself fails.
521 ASSERT_NE(nullptr, fp = tmpfile());
522 setbuf(fp, NULL);
523 ASSERT_EQ(4, fprintf(fp, "epic"));
524 ASSERT_EQ(0, close(fileno(fp)));
525 ASSERT_EQ(-1, fprintf(fp, "fail"));
526 ASSERT_EQ(-1, fclose(fp));
527
528 // Buffered case where we won't notice until the fclose(3).
529 // It's likely this is what was actually seen in http://b/7229520,
530 // and that expecting fprintf to fail is setting yourself up for
531 // disappointment. Remember to check fclose(3)'s return value, kids!
532 ASSERT_NE(nullptr, fp = tmpfile());
533 ASSERT_EQ(4, fprintf(fp, "epic"));
534 ASSERT_EQ(0, close(fileno(fp)));
535 ASSERT_EQ(4, fprintf(fp, "fail"));
536 ASSERT_EQ(-1, fclose(fp));
537}
538
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800539TEST(stdio, popen) {
540 FILE* fp = popen("cat /proc/version", "r");
541 ASSERT_TRUE(fp != NULL);
542
543 char buf[16];
544 char* s = fgets(buf, sizeof(buf), fp);
545 buf[13] = '\0';
546 ASSERT_STREQ("Linux version", s);
547
548 ASSERT_EQ(0, pclose(fp));
549}
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700550
551TEST(stdio, getc) {
552 FILE* fp = fopen("/proc/version", "r");
553 ASSERT_TRUE(fp != NULL);
554 ASSERT_EQ('L', getc(fp));
555 ASSERT_EQ('i', getc(fp));
556 ASSERT_EQ('n', getc(fp));
557 ASSERT_EQ('u', getc(fp));
558 ASSERT_EQ('x', getc(fp));
559 fclose(fp);
560}
561
562TEST(stdio, putc) {
563 FILE* fp = fopen("/proc/version", "r");
564 ASSERT_TRUE(fp != NULL);
565 ASSERT_EQ(EOF, putc('x', fp));
566 fclose(fp);
567}
Elliott Hughes603332f2014-03-12 17:10:41 -0700568
569TEST(stdio, sscanf) {
570 char s1[123];
571 int i1;
572 double d1;
573 char s2[123];
574 ASSERT_EQ(3, sscanf(" hello 123 1.23 ", "%s %i %lf %s", s1, &i1, &d1, s2));
575 ASSERT_STREQ("hello", s1);
576 ASSERT_EQ(123, i1);
Christopher Ferrisf171b342014-03-17 16:40:26 -0700577 ASSERT_DOUBLE_EQ(1.23, d1);
Elliott Hughes603332f2014-03-12 17:10:41 -0700578}
Elliott Hughes53b24382014-05-02 18:29:25 -0700579
580TEST(stdio, cantwrite_EBADF) {
581 // If we open a file read-only...
582 FILE* fp = fopen("/proc/version", "r");
583
584 // ...all attempts to write to that file should return failure.
585
586 // They should also set errno to EBADF. This isn't POSIX, but it's traditional.
587 // glibc gets the wide-character functions wrong.
588
589 errno = 0;
590 EXPECT_EQ(EOF, putc('x', fp));
591 EXPECT_EQ(EBADF, errno);
592
593 errno = 0;
594 EXPECT_EQ(EOF, fprintf(fp, "hello"));
595 EXPECT_EQ(EBADF, errno);
596
597 errno = 0;
598 EXPECT_EQ(EOF, fwprintf(fp, L"hello"));
Elliott Hughes063525c2014-05-13 11:19:57 -0700599#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -0700600 EXPECT_EQ(EBADF, errno);
601#endif
602
603 errno = 0;
Elliott Hughes53b24382014-05-02 18:29:25 -0700604 EXPECT_EQ(0U, fwrite("hello", 1, 2, fp));
605 EXPECT_EQ(EBADF, errno);
606
607 errno = 0;
608 EXPECT_EQ(EOF, fputs("hello", fp));
609 EXPECT_EQ(EBADF, errno);
610
611 errno = 0;
612 EXPECT_EQ(WEOF, fputwc(L'x', fp));
Elliott Hughes063525c2014-05-13 11:19:57 -0700613#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -0700614 EXPECT_EQ(EBADF, errno);
615#endif
616}
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100617
618// Tests that we can only have a consistent and correct fpos_t when using
619// f*pos functions (i.e. fpos doesn't get inside a multi byte character).
620TEST(stdio, consistent_fpos_t) {
621 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
622 uselocale(LC_GLOBAL_LOCALE);
623
624 FILE* fp = tmpfile();
625 ASSERT_TRUE(fp != NULL);
626
627 wchar_t mb_one_bytes = L'h';
628 wchar_t mb_two_bytes = 0x00a2;
629 wchar_t mb_three_bytes = 0x20ac;
630 wchar_t mb_four_bytes = 0x24b62;
631
632 // Write to file.
633 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp)));
634 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
635 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
636 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
637
638 rewind(fp);
639
640 // Record each character position.
641 fpos_t pos1;
642 fpos_t pos2;
643 fpos_t pos3;
644 fpos_t pos4;
645 fpos_t pos5;
646 EXPECT_EQ(0, fgetpos(fp, &pos1));
647 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
648 EXPECT_EQ(0, fgetpos(fp, &pos2));
649 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
650 EXPECT_EQ(0, fgetpos(fp, &pos3));
651 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
652 EXPECT_EQ(0, fgetpos(fp, &pos4));
653 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
654 EXPECT_EQ(0, fgetpos(fp, &pos5));
655
Elliott Hughes063525c2014-05-13 11:19:57 -0700656#if defined(__BIONIC__)
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100657 // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD
658 // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In
659 // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE
660 // structure.
661 ASSERT_EQ(0, static_cast<off_t>(pos1));
662 ASSERT_EQ(1, static_cast<off_t>(pos2));
663 ASSERT_EQ(3, static_cast<off_t>(pos3));
664 ASSERT_EQ(6, static_cast<off_t>(pos4));
665 ASSERT_EQ(10, static_cast<off_t>(pos5));
666#endif
667
668 // Exercise back and forth movements of the position.
669 ASSERT_EQ(0, fsetpos(fp, &pos2));
670 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
671 ASSERT_EQ(0, fsetpos(fp, &pos1));
672 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
673 ASSERT_EQ(0, fsetpos(fp, &pos4));
674 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
675 ASSERT_EQ(0, fsetpos(fp, &pos3));
676 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
677 ASSERT_EQ(0, fsetpos(fp, &pos5));
678 ASSERT_EQ(WEOF, fgetwc(fp));
679
680 fclose(fp);
681}
682
683// Exercise the interaction between fpos and seek.
684TEST(stdio, fpos_t_and_seek) {
685 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
686 uselocale(LC_GLOBAL_LOCALE);
687
Calin Juravle9b95ea92014-05-14 17:07:10 +0100688 // In glibc-2.16 fseek doesn't work properly in wide mode
689 // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is
690 // to close and re-open the file. We do it in order to make the test pass
691 // with all glibcs.
692
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100693 TemporaryFile tf;
694 FILE* fp = fdopen(tf.fd, "w+");
695 ASSERT_TRUE(fp != NULL);
696
697 wchar_t mb_two_bytes = 0x00a2;
698 wchar_t mb_three_bytes = 0x20ac;
699 wchar_t mb_four_bytes = 0x24b62;
700
701 // Write to file.
702 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
703 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
704 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
705
706 fflush(fp);
707 fclose(fp);
708
709 fp = fopen(tf.filename, "r");
710 ASSERT_TRUE(fp != NULL);
711
712 // Store a valid position.
713 fpos_t mb_two_bytes_pos;
714 ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos));
715
716 // Move inside mb_four_bytes with fseek.
717 long offset_inside_mb = 6;
718 ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET));
719
720 // Store the "inside multi byte" position.
721 fpos_t pos_inside_mb;
722 ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb));
Elliott Hughes063525c2014-05-13 11:19:57 -0700723#if defined(__BIONIC__)
724 ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb));
725#endif
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100726
727 // Reading from within a byte should produce an error.
728 ASSERT_EQ(WEOF, fgetwc(fp));
729 ASSERT_EQ(EILSEQ, errno);
730
731 // Reverting to a valid position should work.
732 ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos));
733 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
734
735 // Moving withing a multi byte with fsetpos should work but reading should
736 // produce an error.
737 ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb));
738 ASSERT_EQ(WEOF, fgetwc(fp));
739 ASSERT_EQ(EILSEQ, errno);
740
741 fclose(fp);
742}
Elliott Hughes6b841db2014-08-20 16:10:49 -0700743
744TEST(stdio, fmemopen) {
745 char buf[16];
746 memset(buf, 0, sizeof(buf));
747 FILE* fp = fmemopen(buf, sizeof(buf), "r+");
748 ASSERT_EQ('<', fputc('<', fp));
749 ASSERT_NE(EOF, fputs("abc>\n", fp));
750 fflush(fp);
751
752 ASSERT_STREQ("<abc>\n", buf);
753
754 rewind(fp);
755
756 char line[16];
757 char* s = fgets(line, sizeof(line), fp);
758 ASSERT_TRUE(s != NULL);
759 ASSERT_STREQ("<abc>\n", s);
760
761 fclose(fp);
762}
763
764TEST(stdio, fmemopen_NULL) {
765 FILE* fp = fmemopen(nullptr, 128, "r+");
766 ASSERT_NE(EOF, fputs("xyz\n", fp));
767
768 rewind(fp);
769
770 char line[16];
771 char* s = fgets(line, sizeof(line), fp);
772 ASSERT_TRUE(s != NULL);
773 ASSERT_STREQ("xyz\n", s);
774
775 fclose(fp);
776}
777
778TEST(stdio, fmemopen_EINVAL) {
779 char buf[16];
780
781 // Invalid size.
782 errno = 0;
783 ASSERT_EQ(nullptr, fmemopen(buf, 0, "r+"));
784 ASSERT_EQ(EINVAL, errno);
785
786 // No '+' with NULL buffer.
787 errno = 0;
788 ASSERT_EQ(nullptr, fmemopen(nullptr, 0, "r"));
789 ASSERT_EQ(EINVAL, errno);
790}
791
792TEST(stdio, open_memstream) {
793 char* p = nullptr;
794 size_t size = 0;
795 FILE* fp = open_memstream(&p, &size);
796 ASSERT_NE(EOF, fputs("hello, world!", fp));
797 fclose(fp);
798
799 ASSERT_STREQ("hello, world!", p);
800 ASSERT_EQ(strlen("hello, world!"), size);
801 free(p);
802}
803
804TEST(stdio, open_memstream_EINVAL) {
805#if defined(__BIONIC__)
806 char* p;
807 size_t size;
808
809 // Invalid buffer.
810 errno = 0;
811 ASSERT_EQ(nullptr, open_memstream(nullptr, &size));
812 ASSERT_EQ(EINVAL, errno);
813
814 // Invalid size.
815 errno = 0;
816 ASSERT_EQ(nullptr, open_memstream(&p, nullptr));
817 ASSERT_EQ(EINVAL, errno);
818#else
819 GTEST_LOG_(INFO) << "This test does nothing.\n";
820#endif
821}
Elliott Hughes31165ed2014-09-23 17:34:29 -0700822
823TEST(stdio, fdopen_CLOEXEC) {
824 int fd = open("/proc/version", O_RDONLY);
825 ASSERT_TRUE(fd != -1);
826
827 // This fd doesn't have O_CLOEXEC...
828 int flags = fcntl(fd, F_GETFD);
829 ASSERT_TRUE(flags != -1);
830 ASSERT_EQ(0, flags & FD_CLOEXEC);
831
832 FILE* fp = fdopen(fd, "re");
833 ASSERT_TRUE(fp != NULL);
834
835 // ...but the new one does.
836 flags = fcntl(fileno(fp), F_GETFD);
837 ASSERT_TRUE(flags != -1);
838 ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
839
840 fclose(fp);
841 close(fd);
842}
843
844TEST(stdio, freopen_CLOEXEC) {
845 FILE* fp = fopen("/proc/version", "r");
846 ASSERT_TRUE(fp != NULL);
847
848 // This FILE* doesn't have O_CLOEXEC...
849 int flags = fcntl(fileno(fp), F_GETFD);
850 ASSERT_TRUE(flags != -1);
851 ASSERT_EQ(0, flags & FD_CLOEXEC);
852
853 fp = freopen("/proc/version", "re", fp);
854
855 // ...but the new one does.
856 flags = fcntl(fileno(fp), F_GETFD);
857 ASSERT_TRUE(flags != -1);
858 ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
859
860 fclose(fp);
861}
Elliott Hughes20841a12014-12-01 16:13:30 -0800862
863// https://code.google.com/p/android/issues/detail?id=81155
864// http://b/18556607
865TEST(stdio, fread_unbuffered_pathological_performance) {
866 FILE* fp = fopen("/dev/zero", "r");
867 ASSERT_TRUE(fp != NULL);
868
869 // Make this stream unbuffered.
870 setvbuf(fp, 0, _IONBF, 0);
871
872 char buf[65*1024];
873 memset(buf, 0xff, sizeof(buf));
874
875 time_t t0 = time(NULL);
876 for (size_t i = 0; i < 1024; ++i) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -0800877 ASSERT_EQ(1U, fread(buf, 64*1024, 1, fp));
Elliott Hughes20841a12014-12-01 16:13:30 -0800878 }
879 time_t t1 = time(NULL);
880
881 fclose(fp);
882
883 // 1024 64KiB reads should have been very quick.
884 ASSERT_LE(t1 - t0, 1);
885
886 for (size_t i = 0; i < 64*1024; ++i) {
887 ASSERT_EQ('\0', buf[i]);
888 }
889 for (size_t i = 64*1024; i < 65*1024; ++i) {
890 ASSERT_EQ('\xff', buf[i]);
891 }
892}
Elliott Hughes75b99382015-01-20 11:23:50 -0800893
Elliott Hughesbcb378d2015-01-22 14:18:35 -0800894TEST(stdio, fread_EOF) {
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800895 std::string digits("0123456789");
896 FILE* fp = fmemopen(&digits[0], digits.size(), "r");
Elliott Hughes75b99382015-01-20 11:23:50 -0800897
898 // Try to read too much, but little enough that it still fits in the FILE's internal buffer.
899 char buf1[4 * 4];
900 memset(buf1, 0, sizeof(buf1));
901 ASSERT_EQ(2U, fread(buf1, 4, 4, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800902 ASSERT_STREQ("0123456789", buf1);
Elliott Hughes75b99382015-01-20 11:23:50 -0800903 ASSERT_TRUE(feof(fp));
904
905 rewind(fp);
906
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800907 // Try to read way too much so stdio tries to read more direct from the stream.
908 char buf2[4 * 4096];
Elliott Hughes75b99382015-01-20 11:23:50 -0800909 memset(buf2, 0, sizeof(buf2));
910 ASSERT_EQ(2U, fread(buf2, 4, 4096, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800911 ASSERT_STREQ("0123456789", buf2);
Elliott Hughes75b99382015-01-20 11:23:50 -0800912 ASSERT_TRUE(feof(fp));
913
914 fclose(fp);
915}
Elliott Hughese6bb5a22015-01-23 17:48:15 -0800916
917static void test_fread_from_write_only_stream(size_t n) {
918 FILE* fp = fopen("/dev/null", "w");
919 std::vector<char> buf(n, 0);
920 errno = 0;
921 ASSERT_EQ(0U, fread(&buf[0], n, 1, fp));
922 ASSERT_EQ(EBADF, errno);
923 ASSERT_TRUE(ferror(fp));
924 ASSERT_FALSE(feof(fp));
925 fclose(fp);
926}
927
928TEST(stdio, fread_from_write_only_stream_slow_path) {
929 test_fread_from_write_only_stream(1);
930}
931
932TEST(stdio, fread_from_write_only_stream_fast_path) {
933 test_fread_from_write_only_stream(64*1024);
934}
935
936static void test_fwrite_after_fread(size_t n) {
937 TemporaryFile tf;
938
939 FILE* fp = fdopen(tf.fd, "w+");
940 ASSERT_EQ(1U, fwrite("1", 1, 1, fp));
941 fflush(fp);
942
943 // We've flushed but not rewound, so there's nothing to read.
944 std::vector<char> buf(n, 0);
945 ASSERT_EQ(0U, fread(&buf[0], 1, buf.size(), fp));
946 ASSERT_TRUE(feof(fp));
947
948 // But hitting EOF doesn't prevent us from writing...
949 errno = 0;
950 ASSERT_EQ(1U, fwrite("2", 1, 1, fp)) << errno;
951
952 // And if we rewind, everything's there.
953 rewind(fp);
954 ASSERT_EQ(2U, fread(&buf[0], 1, buf.size(), fp));
955 ASSERT_EQ('1', buf[0]);
956 ASSERT_EQ('2', buf[1]);
957
958 fclose(fp);
959}
960
961TEST(stdio, fwrite_after_fread_slow_path) {
962 test_fwrite_after_fread(16);
963}
964
965TEST(stdio, fwrite_after_fread_fast_path) {
966 test_fwrite_after_fread(64*1024);
967}