]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/platform-bionic.git/blobdiff - tests/stdio_test.cpp
Fix nan output in the printf family.
[android-sdk/platform-bionic.git] / tests / stdio_test.cpp
index c01ab683ca25ac049fba32d8a680c4391d53aee7..de5eea347f4251aae68044ef01307ea2782375ed 100644 (file)
 
 #include "TemporaryFile.h"
 
+TEST(stdio, flockfile_18208568_stderr) {
+  // Check that we have a _recursive_ mutex for flockfile.
+  flockfile(stderr);
+  feof(stderr); // We don't care about the result, but this needs to take the lock.
+  funlockfile(stderr);
+}
+
+TEST(stdio, flockfile_18208568_regular) {
+  // We never had a bug for streams other than stdin/stdout/stderr, but test anyway.
+  FILE* fp = fopen("/dev/null", "w");
+  ASSERT_TRUE(fp != NULL);
+  flockfile(fp);
+  feof(fp);
+  funlockfile(fp);
+  fclose(fp);
+}
+
 TEST(stdio, tmpfile_fileno_fprintf_rewind_fgets) {
   FILE* fp = tmpfile();
   ASSERT_TRUE(fp != NULL);
@@ -60,7 +77,7 @@ TEST(stdio, dprintf) {
   int rc = dprintf(tf.fd, "hello\n");
   ASSERT_EQ(rc, 6);
 
-  lseek(tf.fd, SEEK_SET, 0);
+  lseek(tf.fd, 0, SEEK_SET);
   FILE* tfile = fdopen(tf.fd, "r");
   ASSERT_TRUE(tfile != NULL);
 
@@ -347,22 +364,52 @@ TEST(stdio, snprintf_smoke) {
   EXPECT_STREQ("print_me_twice print_me_twice", buf);
 }
 
-TEST(stdio, snprintf_f_special) {
-  char buf[BUFSIZ];
-  snprintf(buf, sizeof(buf), "%f", nanf(""));
-  EXPECT_STRCASEEQ("NaN", buf);
-
-  snprintf(buf, sizeof(buf), "%f", HUGE_VALF);
-  EXPECT_STRCASEEQ("Inf", buf);
-}
-
-TEST(stdio, snprintf_g_special) {
-  char buf[BUFSIZ];
-  snprintf(buf, sizeof(buf), "%g", nan(""));
-  EXPECT_STRCASEEQ("NaN", buf);
-
-  snprintf(buf, sizeof(buf), "%g", HUGE_VAL);
-  EXPECT_STRCASEEQ("Inf", buf);
+template <typename T>
+void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...),
+                 const T* fmt, const T* fmt_plus,
+                 const T* minus_inf, const T* inf_, const T* plus_inf,
+                 const T* minus_nan, const T* nan_, const T* plus_nan) {
+  T buf[BUFSIZ];
+
+  snprintf_fn(buf, sizeof(buf), fmt, nan(""));
+  EXPECT_STREQ(nan_, buf) << fmt;
+  snprintf_fn(buf, sizeof(buf), fmt, -nan(""));
+  EXPECT_STREQ(minus_nan, buf) << fmt;
+  snprintf_fn(buf, sizeof(buf), fmt_plus, nan(""));
+  EXPECT_STREQ(plus_nan, buf) << fmt_plus;
+  snprintf_fn(buf, sizeof(buf), fmt_plus, -nan(""));
+  EXPECT_STREQ(minus_nan, buf) << fmt_plus;
+
+  snprintf_fn(buf, sizeof(buf), fmt, HUGE_VAL);
+  EXPECT_STREQ(inf_, buf) << fmt;
+  snprintf_fn(buf, sizeof(buf), fmt, -HUGE_VAL);
+  EXPECT_STREQ(minus_inf, buf) << fmt;
+  snprintf_fn(buf, sizeof(buf), fmt_plus, HUGE_VAL);
+  EXPECT_STREQ(plus_inf, buf) << fmt_plus;
+  snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VAL);
+  EXPECT_STREQ(minus_inf, buf) << fmt_plus;
+}
+
+TEST(stdio, snprintf_inf_nan) {
+  CheckInfNan(snprintf, "%a", "%+a", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
+  CheckInfNan(snprintf, "%A", "%+A", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
+  CheckInfNan(snprintf, "%e", "%+e", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
+  CheckInfNan(snprintf, "%E", "%+E", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
+  CheckInfNan(snprintf, "%f", "%+f", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
+  CheckInfNan(snprintf, "%F", "%+F", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
+  CheckInfNan(snprintf, "%g", "%+g", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
+  CheckInfNan(snprintf, "%G", "%+G", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
+}
+
+TEST(stdio, wsprintf_inf_nan) {
+  CheckInfNan(swprintf, L"%a", L"%+a", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
+  CheckInfNan(swprintf, L"%A", L"%+A", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
+  CheckInfNan(swprintf, L"%e", L"%+e", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
+  CheckInfNan(swprintf, L"%E", L"%+E", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
+  CheckInfNan(swprintf, L"%f", L"%+f", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
+  CheckInfNan(swprintf, L"%F", L"%+F", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
+  CheckInfNan(swprintf, L"%g", L"%+g", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
+  CheckInfNan(swprintf, L"%G", L"%+G", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
 }
 
 TEST(stdio, snprintf_d_INT_MAX) {
@@ -422,8 +469,22 @@ TEST(stdio, snprintf_e) {
 TEST(stdio, snprintf_negative_zero_5084292) {
   char buf[BUFSIZ];
 
+  snprintf(buf, sizeof(buf), "%e", -0.0);
+  EXPECT_STREQ("-0.000000e+00", buf);
+  snprintf(buf, sizeof(buf), "%E", -0.0);
+  EXPECT_STREQ("-0.000000E+00", buf);
   snprintf(buf, sizeof(buf), "%f", -0.0);
   EXPECT_STREQ("-0.000000", buf);
+  snprintf(buf, sizeof(buf), "%F", -0.0);
+  EXPECT_STREQ("-0.000000", buf);
+  snprintf(buf, sizeof(buf), "%g", -0.0);
+  EXPECT_STREQ("-0", buf);
+  snprintf(buf, sizeof(buf), "%G", -0.0);
+  EXPECT_STREQ("-0", buf);
+  snprintf(buf, sizeof(buf), "%a", -0.0);
+  EXPECT_STREQ("-0x0p+0", buf);
+  snprintf(buf, sizeof(buf), "%A", -0.0);
+  EXPECT_STREQ("-0X0P+0", buf);
 }
 
 TEST(stdio, snprintf_utf8_15439554) {
@@ -756,3 +817,74 @@ TEST(stdio, open_memstream_EINVAL) {
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
+
+TEST(stdio, fdopen_CLOEXEC) {
+  int fd = open("/proc/version", O_RDONLY);
+  ASSERT_TRUE(fd != -1);
+
+  // This fd doesn't have O_CLOEXEC...
+  int flags = fcntl(fd, F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(0, flags & FD_CLOEXEC);
+
+  FILE* fp = fdopen(fd, "re");
+  ASSERT_TRUE(fp != NULL);
+
+  // ...but the new one does.
+  flags = fcntl(fileno(fp), F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+
+  fclose(fp);
+  close(fd);
+}
+
+TEST(stdio, freopen_CLOEXEC) {
+  FILE* fp = fopen("/proc/version", "r");
+  ASSERT_TRUE(fp != NULL);
+
+  // This FILE* doesn't have O_CLOEXEC...
+  int flags = fcntl(fileno(fp), F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(0, flags & FD_CLOEXEC);
+
+  fp = freopen("/proc/version", "re", fp);
+
+  // ...but the new one does.
+  flags = fcntl(fileno(fp), F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+
+  fclose(fp);
+}
+
+// https://code.google.com/p/android/issues/detail?id=81155
+// http://b/18556607
+TEST(stdio, fread_unbuffered_pathological_performance) {
+  FILE* fp = fopen("/dev/zero", "r");
+  ASSERT_TRUE(fp != NULL);
+
+  // Make this stream unbuffered.
+  setvbuf(fp, 0, _IONBF, 0);
+
+  char buf[65*1024];
+  memset(buf, 0xff, sizeof(buf));
+
+  time_t t0 = time(NULL);
+  for (size_t i = 0; i < 1024; ++i) {
+    fread(buf, 64*1024, 1, fp);
+  }
+  time_t t1 = time(NULL);
+
+  fclose(fp);
+
+  // 1024 64KiB reads should have been very quick.
+  ASSERT_LE(t1 - t0, 1);
+
+  for (size_t i = 0; i < 64*1024; ++i) {
+    ASSERT_EQ('\0', buf[i]);
+  }
+  for (size_t i = 64*1024; i < 65*1024; ++i) {
+    ASSERT_EQ('\xff', buf[i]);
+  }
+}