Merge "check invalid file offset when loading library"
diff --git a/libc/Android.mk b/libc/Android.mk
index 694c642..d044145 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -784,7 +784,6 @@
 
 LOCAL_CFLAGS := \
     $(libc_common_cflags) \
-    -Wno-missing-field-initializers \
     -Wno-sign-compare \
     -Wno-uninitialized \
     -Wno-unused-parameter \
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index ddb49ce..b4a3472 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -123,8 +123,8 @@
 }
 
 locale_t newlocale(int category_mask, const char* locale_name, locale_t /*base*/) {
-  // Is 'category_mask' valid?
-  if ((category_mask & ~LC_ALL_MASK) != 0) {
+  // Are 'category_mask' and 'locale_name' valid?
+  if ((category_mask & ~LC_ALL_MASK) != 0 || locale_name == NULL) {
     errno = EINVAL;
     return NULL;
   }
diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c
index 35d028e..ef8e9e6 100644
--- a/libc/stdio/findfp.c
+++ b/libc/stdio/findfp.c
@@ -49,8 +49,8 @@
 #define	NDYNAMIC 10		/* add ten more whenever necessary */
 
 #define	std(flags, file) \
-	{0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
-	    {(unsigned char *)(__sFext+file), 0},NULL,0,{0},{0},{0},0,0}
+	{0,0,0,flags,file,{0,0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
+	    {(unsigned char *)(__sFext+file), 0},NULL,0,{0},{0},{0,0},0,0}
 
 				/* the usual - (stdin + stdout + stderr) */
 static FILE usual[FOPEN_MAX - 3];
diff --git a/tests/Android.mk b/tests/Android.mk
index 66b1655..1a7a5e0 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -67,20 +67,6 @@
     libgen_test.cpp \
     locale_test.cpp \
     malloc_test.cpp \
-    math_cos_test.cpp \
-    math_cosf_test.cpp \
-    math_exp_test.cpp \
-    math_expf_test.cpp \
-    math_log_test.cpp \
-    math_logf_test.cpp \
-    math_pow_test.cpp \
-    math_powf_test.cpp \
-    math_sin_test.cpp \
-    math_sinf_test.cpp \
-    math_sincos_test.cpp \
-    math_sincosf_test.cpp \
-    math_tan_test.cpp \
-    math_tanf_test.cpp \
     math_test.cpp \
     mntent_test.cpp \
     netdb_test.cpp \
diff --git a/tests/locale_test.cpp b/tests/locale_test.cpp
index 7ec607a..f308af5 100644
--- a/tests/locale_test.cpp
+++ b/tests/locale_test.cpp
@@ -71,20 +71,30 @@
   EXPECT_EQ(ENOENT, errno); // POSIX specified, not an implementation detail!
 }
 
-TEST(locale, newlocale) {
+TEST(locale, newlocale_invalid_category_mask) {
   errno = 0;
   EXPECT_EQ(0, newlocale(1 << 20, "C", 0));
   EXPECT_EQ(EINVAL, errno);
+}
 
-  locale_t l = newlocale(LC_ALL, "C", 0);
-  ASSERT_TRUE(l != NULL);
-  freelocale(l);
+TEST(locale, newlocale_NULL_locale_name) {
+  errno = 0;
+  EXPECT_EQ(0, newlocale(LC_ALL, NULL, 0));
+  EXPECT_EQ(EINVAL, errno);
+}
 
+TEST(locale, newlocale_bad_locale_name) {
   errno = 0;
   EXPECT_EQ(0, newlocale(LC_ALL, "this-is-not-a-locale", 0));
   EXPECT_EQ(ENOENT, errno); // POSIX specified, not an implementation detail!
 }
 
+TEST(locale, newlocale) {
+  locale_t l = newlocale(LC_ALL, "C", 0);
+  ASSERT_TRUE(l != NULL);
+  freelocale(l);
+}
+
 TEST(locale, duplocale) {
   locale_t cloned_global = duplocale(LC_GLOBAL_LOCALE);
   ASSERT_TRUE(cloned_global != NULL);
diff --git a/tests/math_cos_test.cpp b/tests/math_cos_intel_data.h
similarity index 99%
rename from tests/math_cos_test.cpp
rename to tests/math_cos_intel_data.h
index 4917e87..22ec0bc 100644
--- a/tests/math_cos_test.cpp
+++ b/tests/math_cos_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  double expected;
-  double call_data;
-} cos_intel_data_t;
-
-static cos_intel_data_t g_cos_intel_data[] = {
+static data_1_1_t<double, double> g_cos_intel_data[] = {
   { // Entry 0
     0x1.c1a27ae836f128000000000000504e9bp-1,
     0x1.feb1f7920e248p-2
@@ -5632,15 +5620,3 @@
     -0.0
   },
 };
-#endif // __BIONIC__
-
-TEST(math_cos, cos_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_cos_intel_data)/sizeof(cos_intel_data_t); i++) {
-    EXPECT_DOUBLE_EQ(g_cos_intel_data[i].expected, cos(g_cos_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_cosf_test.cpp b/tests/math_cosf_intel_data.h
similarity index 98%
rename from tests/math_cosf_test.cpp
rename to tests/math_cosf_intel_data.h
index 8520c1d..d606021 100644
--- a/tests/math_cosf_test.cpp
+++ b/tests/math_cosf_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  float expected;
-  float call_data;
-} cosf_intel_data_t;
-
-static cosf_intel_data_t g_cosf_intel_data[] = {
+static data_1_1_t<float, float> g_cosf_intel_data[] = {
   { // Entry 0
     0x1.bc7b66ffb7689d646dd1af83e9661d2dp-1,
     -0x1.09ebacp-1
@@ -4344,15 +4332,3 @@
     -0.0f
   },
 };
-#endif // __BIONIC__
-
-TEST(math_cosf, cosf_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_cosf_intel_data)/sizeof(cosf_intel_data_t); i++) {
-    EXPECT_FLOAT_EQ(g_cosf_intel_data[i].expected, cosf(g_cosf_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_data_test.h b/tests/math_data_test.h
new file mode 100644
index 0000000..f3d25ef
--- /dev/null
+++ b/tests/math_data_test.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <fenv.h>
+
+template <typename RT, typename T1>
+struct data_1_1_t {
+  RT expected;
+  T1 input;
+};
+
+template <typename RT, typename T1, typename T2>
+struct data_1_2_t {
+  RT expected;
+  T1 input1;
+  T2 input2;
+};
+
+template <typename RT1, typename RT2, typename T>
+struct data_2_1_t {
+  RT1 expected1;
+  RT2 expected2;
+  T input;
+};
+
+template <typename T> union fp_u;
+
+template <> union fp_u<float> {
+  float value;
+  struct {
+    unsigned frac:23;
+    unsigned exp:8;
+    unsigned sign:1;
+  } bits;
+  uint32_t sign_magnitude;
+};
+
+template <> union fp_u<double> {
+  double value;
+  struct {
+    unsigned fracl;
+    unsigned frach:20;
+    unsigned exp:11;
+    unsigned sign:1;
+  } bits;
+  uint64_t sign_magnitude;
+};
+
+// TODO: long double.
+
+template <typename T>
+static inline auto SignAndMagnitudeToBiased(const T& value) -> decltype(fp_u<T>::sign_magnitude) {
+  fp_u<T> u;
+  u.value = value;
+  if (u.bits.sign) {
+    return ~u.sign_magnitude + 1;
+  } else {
+    u.bits.sign = 1;
+    return u.sign_magnitude;
+  }
+}
+
+// Based on the existing googletest implementation, which uses a fixed 4 ulp bound.
+template <typename T>
+size_t UlpDistance(T lhs, T rhs) {
+  const auto biased1 = SignAndMagnitudeToBiased(lhs);
+  const auto biased2 = SignAndMagnitudeToBiased(rhs);
+  return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+}
+
+template <size_t ULP, typename T>
+struct FpUlpEq {
+  ::testing::AssertionResult operator()(const char* /* expected_expression */,
+                                        const char* /* actual_expression */,
+                                        T expected,
+                                        T actual) {
+    if (!isnan(expected) && !isnan(actual) && UlpDistance(expected, actual) <= ULP) {
+      return ::testing::AssertionSuccess();
+    }
+
+    // Output the actual and expected values as hex floating point.
+    char expected_str[64];
+    char actual_str[64];
+    snprintf(expected_str, sizeof(expected_str), "%a", expected);
+    snprintf(actual_str, sizeof(actual_str), "%a", actual);
+
+    return ::testing::AssertionFailure()
+        << "expected (" << expected_str << ") != actual (" << actual_str << ")";
+  }
+};
+
+// Runs through the array 'data' applying 'f' to each of the input values
+// and asserting that the result is within ULP ulps of the expected value.
+// For testing a (double) -> double function like sin(3).
+template <size_t ULP, typename RT, typename T, size_t N>
+void DoMathDataTest(data_1_1_t<RT, T> (&data)[N], RT f(T)) {
+  fesetenv(FE_DFL_ENV);
+  FpUlpEq<ULP, RT> predicate;
+  for (size_t i = 0; i < N; ++i) {
+    EXPECT_PRED_FORMAT2(predicate,
+                        data[i].expected, f(data[i].input)) << "Failed on element " << i;
+  }
+}
+
+// Runs through the array 'data' applying 'f' to each of the pairs of input values
+// and asserting that the result is within ULP ulps of the expected value.
+// For testing a (double, double) -> double function like pow(3).
+template <size_t ULP, typename RT, typename T1, typename T2, size_t N>
+void DoMathDataTest(data_1_2_t<RT, T1, T2> (&data)[N], RT f(T1, T2)) {
+  fesetenv(FE_DFL_ENV);
+  FpUlpEq<ULP, RT> predicate;
+  for (size_t i = 0; i < N; ++i) {
+    EXPECT_PRED_FORMAT2(predicate,
+                        data[i].expected, f(data[i].input1, data[i].input2)) << "Failed on element " << i;
+  }
+}
+
+// Runs through the array 'data' applying 'f' to each of the input values
+// and asserting that the results are within ULP ulps of the expected values.
+// For testing a (double, double*, double*) -> void function like sincos(3).
+template <size_t ULP, typename RT1, typename RT2, typename T1, size_t N>
+void DoMathDataTest(data_2_1_t<RT1, RT2, T1> (&data)[N], void f(T1, RT1*, RT2*)) {
+  fesetenv(FE_DFL_ENV);
+  FpUlpEq<ULP, RT1> predicate1;
+  FpUlpEq<ULP, RT2> predicate2;
+  for (size_t i = 0; i < N; ++i) {
+    RT1 out1;
+    RT2 out2;
+    f(data[i].input, &out1, &out2);
+    EXPECT_PRED_FORMAT2(predicate1, data[i].expected1, out1) << "Failed on element " << i;
+    EXPECT_PRED_FORMAT2(predicate2, data[i].expected2, out2) << "Failed on element " << i;
+  }
+}
diff --git a/tests/math_exp_test.cpp b/tests/math_exp_intel_data.h
similarity index 98%
rename from tests/math_exp_test.cpp
rename to tests/math_exp_intel_data.h
index c9c6ad5..0ca3813 100644
--- a/tests/math_exp_test.cpp
+++ b/tests/math_exp_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  double expected;
-  double call_data;
-} exp_intel_data_t;
-
-static exp_intel_data_t g_exp_intel_data[] = {
+static data_1_1_t<double, double> g_exp_intel_data[] = {
   { // Entry 0
     0x1.0000000000001fffffffffffffffffffp0,
     0x1.ffffffffffffep-52
@@ -1964,15 +1952,3 @@
     -0x1.6232bdd7abcd3p9
   },
 };
-#endif // __BIONIC__
-
-TEST(math_exp, exp_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_exp_intel_data)/sizeof(exp_intel_data_t); i++) {
-    EXPECT_DOUBLE_EQ(g_exp_intel_data[i].expected, exp(g_exp_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_expf_test.cpp b/tests/math_expf_intel_data.h
similarity index 97%
rename from tests/math_expf_test.cpp
rename to tests/math_expf_intel_data.h
index 30bc946..7007458 100644
--- a/tests/math_expf_test.cpp
+++ b/tests/math_expf_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  float expected;
-  float call_data;
-} expf_intel_data_t;
-
-static expf_intel_data_t g_expf_intel_data[] = {
+static data_1_1_t<float, float> g_expf_intel_data[] = {
   { // Entry 0
     0x1.e0fabf081222780d74c00fda30aa3943p-1,
     -0x1.000006p-4
@@ -1428,15 +1416,3 @@
     -0x1.5d58a0p6
   },
 };
-#endif // __BIONIC__
-
-TEST(math_expf, expf_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_expf_intel_data)/sizeof(expf_intel_data_t); i++) {
-    EXPECT_FLOAT_EQ(g_expf_intel_data[i].expected, expf(g_expf_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_log_test.cpp b/tests/math_log_intel_data.h
similarity index 97%
rename from tests/math_log_test.cpp
rename to tests/math_log_intel_data.h
index 4f136a7..95ae60e 100644
--- a/tests/math_log_test.cpp
+++ b/tests/math_log_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  double expected;
-  double call_data;
-} log_intel_data_t;
-
-static log_intel_data_t g_log_intel_data[] = {
+static data_1_1_t<double, double> g_log_intel_data[] = {
   { // Entry 0
     0x1.d77fd13d27ffefffffffffffb5ed9843p-11,
     0x1.003af6c37c1d3p0
@@ -1664,15 +1652,3 @@
     -0.0
   },
 };
-#endif // __BIONIC__
-
-TEST(math_log, log_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_log_intel_data)/sizeof(log_intel_data_t); i++) {
-    EXPECT_DOUBLE_EQ(g_log_intel_data[i].expected, log(g_log_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_logf_test.cpp b/tests/math_logf_intel_data.h
similarity index 97%
rename from tests/math_logf_test.cpp
rename to tests/math_logf_intel_data.h
index ca02095..b69776c 100644
--- a/tests/math_logf_test.cpp
+++ b/tests/math_logf_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  float expected;
-  float call_data;
-} logf_intel_data_t;
-
-static logf_intel_data_t g_logf_intel_data[] = {
+static data_1_1_t<float, float> g_logf_intel_data[] = {
   { // Entry 0
     -0x1.bb9d3aeb8c87b02d7763eba8b48a102dp1,
     0x1.000002p-5
@@ -1316,15 +1304,3 @@
     -0.0f
   },
 };
-#endif // __BIONIC__
-
-TEST(math_logf, logf_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_logf_intel_data)/sizeof(logf_intel_data_t); i++) {
-    EXPECT_FLOAT_EQ(g_logf_intel_data[i].expected, logf(g_logf_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_pow_test.cpp b/tests/math_pow_intel_data.h
similarity index 98%
rename from tests/math_pow_test.cpp
rename to tests/math_pow_intel_data.h
index a4caa36..ac9f5af 100644
--- a/tests/math_pow_test.cpp
+++ b/tests/math_pow_intel_data.h
@@ -14,20 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  double expected;
-  double x_call_data;
-  double y_call_data;
-} pow_intel_data_t;
-
-static pow_intel_data_t g_pow_intel_data[] = {
+static data_1_2_t<double, double, double> g_pow_intel_data[] = {
   { // Entry 0
     0x1.p0,
     -0x1.0p-10, 0.0
@@ -3289,15 +3276,3 @@
     0x1.4p3, 0x1.4p3
   },
 };
-#endif // __BIONIC__
-
-TEST(math_pow, pow_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_pow_intel_data)/sizeof(pow_intel_data_t); i++) {
-    EXPECT_DOUBLE_EQ(g_pow_intel_data[i].expected, pow(g_pow_intel_data[i].x_call_data, g_pow_intel_data[i].y_call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_powf_test.cpp b/tests/math_powf_intel_data.h
similarity index 98%
rename from tests/math_powf_test.cpp
rename to tests/math_powf_intel_data.h
index 7272644..3a1765b 100644
--- a/tests/math_powf_test.cpp
+++ b/tests/math_powf_intel_data.h
@@ -14,20 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  float expected;
-  float x_call_data;
-  float y_call_data;
-} powf_intel_data_t;
-
-static powf_intel_data_t g_powf_intel_data[] = {
+static data_1_2_t<float, float, float> g_powf_intel_data[] = {
   { // Entry 0
     HUGE_VALF,
     -0.0, -0x1.000002p-1
@@ -2777,15 +2764,3 @@
     0x1.40p3, 0x1.40p3
   },
 };
-#endif // __BIONIC__
-
-TEST(math_powf, powf_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_powf_intel_data)/sizeof(powf_intel_data_t); i++) {
-    EXPECT_FLOAT_EQ(g_powf_intel_data[i].expected, powf(g_powf_intel_data[i].x_call_data, g_powf_intel_data[i].y_call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_sin_test.cpp b/tests/math_sin_intel_data.h
similarity index 99%
rename from tests/math_sin_test.cpp
rename to tests/math_sin_intel_data.h
index 509642c..c341cfe 100644
--- a/tests/math_sin_test.cpp
+++ b/tests/math_sin_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  double expected;
-  double call_data;
-} sin_intel_data_t;
-
-static sin_intel_data_t g_sin_intel_data[] = {
+static data_1_1_t<double, double> g_sin_intel_data[] = {
   { // Entry 0
     0x1.9259e3708bd39ffffffffffffff1bdbep-5,
     0x1.9283586503fe0p-5
@@ -5784,15 +5772,3 @@
     -0.0
   },
 };
-#endif // __BIONIC__
-
-TEST(math_sin, sin_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_sin_intel_data)/sizeof(sin_intel_data_t); i++) {
-    EXPECT_DOUBLE_EQ(g_sin_intel_data[i].expected, sin(g_sin_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_sincos_test.cpp b/tests/math_sincos_intel_data.h
similarity index 98%
rename from tests/math_sincos_test.cpp
rename to tests/math_sincos_intel_data.h
index 4093fb9..71ba6b1 100644
--- a/tests/math_sincos_test.cpp
+++ b/tests/math_sincos_intel_data.h
@@ -14,22 +14,7 @@
  * limitations under the License.
  */
 
-#define _GNU_SOURCE 1
-
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  double sin_expected;
-  double cos_expected;
-  double call_data;
-} sincos_intel_data_t;
-
-static sincos_intel_data_t g_sincos_intel_data[] = {
+static data_2_1_t<double, double, double> g_sincos_intel_data[] = {
   { // Entry 0
     -0x1.ce9a94ea9c2ad95597b1193b2300d19ap-1,
     -0x1.b6d3057776dc38335b16745f2d756ab6p-2,
@@ -4776,18 +4761,3 @@
     -0.0,
   },
 };
-#endif // __BIONIC__
-
-TEST(math_sincos, sincos_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_sincos_intel_data)/sizeof(sincos_intel_data_t); i++) {
-   double dsin, dcos;
-   sincos(g_sincos_intel_data[i].call_data, &dsin, &dcos);
-   EXPECT_DOUBLE_EQ(g_sincos_intel_data[i].sin_expected, dsin) << "Failed on element " << i;
-   EXPECT_DOUBLE_EQ(g_sincos_intel_data[i].cos_expected, dcos) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_sincosf_test.cpp b/tests/math_sincosf_intel_data.h
similarity index 98%
rename from tests/math_sincosf_test.cpp
rename to tests/math_sincosf_intel_data.h
index d30f72e..5b1b535 100644
--- a/tests/math_sincosf_test.cpp
+++ b/tests/math_sincosf_intel_data.h
@@ -14,20 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  float sin_expected;
-  float cos_expected;
-  float call_data;
-} sincosf_intel_data_t;
-
-static sincosf_intel_data_t g_sincosf_intel_data[] = {
+static data_2_1_t<float, float, float> g_sincosf_intel_data[] = {
   { // Entry 0
     -0x1.b6a7abffaf59a5ac181e3e1abf961698p-1,
     0x1.080e74c116863cfab82a0fd59c71b363p-1,
@@ -4644,18 +4631,3 @@
     -0.0f,
   },
 };
-#endif // __BIONIC__
-
-TEST(math_sincosf, sincosf_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_sincosf_intel_data)/sizeof(sincosf_intel_data_t); i++) {
-   float fsin, fcos;
-   sincosf(g_sincosf_intel_data[i].call_data, &fsin, &fcos);
-   EXPECT_FLOAT_EQ(g_sincosf_intel_data[i].sin_expected, fsin) << "Failed on element " << i;
-   EXPECT_FLOAT_EQ(g_sincosf_intel_data[i].cos_expected, fcos) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_sinf_test.cpp b/tests/math_sinf_intel_data.h
similarity index 98%
rename from tests/math_sinf_test.cpp
rename to tests/math_sinf_intel_data.h
index 0c2e6f1..9cda0fd 100644
--- a/tests/math_sinf_test.cpp
+++ b/tests/math_sinf_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  float expected;
-  float call_data;
-} sinf_intel_data_t;
-
-static sinf_intel_data_t g_sinf_intel_data[] = {
+static data_1_1_t<float, float> g_sinf_intel_data[] = {
   { // Entry 0
     -0x1.0003fffffff554d5535552cccf778ccdp-21,
     -0x1.0004p-21
@@ -4384,15 +4372,3 @@
     -0.0f
   },
 };
-#endif // __BIONIC__
-
-TEST(math_sinf, sinf_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_sinf_intel_data)/sizeof(sinf_intel_data_t); i++) {
-    EXPECT_FLOAT_EQ(g_sinf_intel_data[i].expected, sinf(g_sinf_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_tan_test.cpp b/tests/math_tan_intel_data.h
similarity index 98%
rename from tests/math_tan_test.cpp
rename to tests/math_tan_intel_data.h
index e555ef3..32d733e 100644
--- a/tests/math_tan_test.cpp
+++ b/tests/math_tan_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  double expected;
-  double call_data;
-} tan_intel_data_t;
-
-static tan_intel_data_t g_tan_intel_data[] = {
+static data_1_1_t<double, double> g_tan_intel_data[] = {
   { // Entry 0
     0x1.5078cebff9c728000000000000024df8p-5,
     0x1.50486b2f87014p-5
@@ -5192,15 +5180,3 @@
     -0.0
   },
 };
-#endif // __BIONIC__
-
-TEST(math_tan, tan_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_tan_intel_data)/sizeof(tan_intel_data_t); i++) {
-    EXPECT_DOUBLE_EQ(g_tan_intel_data[i].expected, tan(g_tan_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_tanf_test.cpp b/tests/math_tanf_intel_data.h
similarity index 98%
rename from tests/math_tanf_test.cpp
rename to tests/math_tanf_intel_data.h
index db04116..0669115 100644
--- a/tests/math_tanf_test.cpp
+++ b/tests/math_tanf_intel_data.h
@@ -14,19 +14,7 @@
  * limitations under the License.
  */
 
-#include <math.h>
-
-#include <fenv.h>
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-typedef struct {
-  float expected;
-  float call_data;
-} tanf_intel_data_t;
-
-static tanf_intel_data_t g_tanf_intel_data[] = {
+static data_1_1_t<float, float> g_tanf_intel_data[] = {
   { // Entry 0
     -0x1.00000000001555555555577777777777p-21,
     -0x1.p-21
@@ -4448,15 +4436,3 @@
     -0.0f
   },
 };
-#endif // __BIONIC__
-
-TEST(math_tanf, tanf_intel) {
-#if defined(__BIONIC__)
-  fesetenv(FE_DFL_ENV);
-  for (size_t i = 0; i < sizeof(g_tanf_intel_data)/sizeof(tanf_intel_data_t); i++) {
-    EXPECT_FLOAT_EQ(g_tanf_intel_data[i].expected, tanf(g_tanf_intel_data[i].call_data)) << "Failed on element " << i;
-  }
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.";
-#endif // __BIONIC__
-}
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index 538ebb1..e14d3dd 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#define _GNU_SOURCE 1
+#include <math.h>
+
 // This include (and the associated definition of __test_capture_signbit)
 // must be placed before any files that include <cmath> (gtest.h in this case).
 //
@@ -29,7 +32,6 @@
 // sure that we're testing the bionic version of signbit. The C++ libraries
 // are free to reimplement signbit or delegate to compiler builtins if they
 // please.
-#include <math.h>
 
 namespace {
 template<typename T> inline int test_capture_signbit(const T in) {
@@ -46,6 +48,8 @@
 }
 }
 
+#include "math_data_test.h"
+
 #include <gtest/gtest.h>
 
 #include <fenv.h>
@@ -167,39 +171,30 @@
 }
 
 TEST(math, __fpclassifyd) {
-#if defined(__BIONIC__)
+#if defined(__GLIBC__)
+#define __fpclassifyd __fpclassify
+#endif
   ASSERT_EQ(FP_INFINITE, __fpclassifyd(HUGE_VAL));
   ASSERT_EQ(FP_NAN, __fpclassifyd(nan("")));
   ASSERT_EQ(FP_NORMAL, __fpclassifyd(1.0));
   ASSERT_EQ(FP_SUBNORMAL, __fpclassifyd(double_subnormal()));
   ASSERT_EQ(FP_ZERO, __fpclassifyd(0.0));
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
 }
 
 TEST(math, __fpclassifyf) {
-#if defined(__BIONIC__)
   ASSERT_EQ(FP_INFINITE, __fpclassifyf(HUGE_VALF));
   ASSERT_EQ(FP_NAN, __fpclassifyf(nanf("")));
   ASSERT_EQ(FP_NORMAL, __fpclassifyf(1.0f));
   ASSERT_EQ(FP_SUBNORMAL, __fpclassifyf(float_subnormal()));
   ASSERT_EQ(FP_ZERO, __fpclassifyf(0.0f));
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
 }
 
 TEST(math, __fpclassifyl) {
-#if defined(__BIONIC__)
   EXPECT_EQ(FP_INFINITE, __fpclassifyl(HUGE_VALL));
   EXPECT_EQ(FP_NAN, __fpclassifyl(nanl("")));
   EXPECT_EQ(FP_NORMAL, __fpclassifyl(1.0L));
   EXPECT_EQ(FP_SUBNORMAL, __fpclassifyl(ldouble_subnormal()));
   EXPECT_EQ(FP_ZERO, __fpclassifyl(0.0L));
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
 }
 
 TEST(math, finitef) {
@@ -208,30 +203,27 @@
 }
 
 TEST(math, __isfinite) {
-#if defined(__BIONIC__)
+#if defined(__GLIBC__)
+#define __isfinite __finite
+#endif
   ASSERT_TRUE(__isfinite(123.0));
   ASSERT_FALSE(__isfinite(HUGE_VAL));
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
 }
 
 TEST(math, __isfinitef) {
-#if defined(__BIONIC__)
+#if defined(__GLIBC__)
+#define __isfinitef __finitef
+#endif
   ASSERT_TRUE(__isfinitef(123.0f));
   ASSERT_FALSE(__isfinitef(HUGE_VALF));
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
 }
 
 TEST(math, __isfinitel) {
-#if defined(__BIONIC__)
+#if defined(__GLIBC__)
+#define __isfinitel __finitel
+#endif
   ASSERT_TRUE(__isfinitel(123.0L));
   ASSERT_FALSE(__isfinitel(HUGE_VALL));
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
 }
 
 TEST(math, finite) {
@@ -281,7 +273,7 @@
   ASSERT_TRUE(__isnormal(123.0));
   ASSERT_FALSE(__isnormal(double_subnormal()));
 #else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
+  GTEST_LOG_(INFO) << "glibc doesn't have __isnormal.\n";
 #endif // __BIONIC__
 }
 
@@ -290,7 +282,7 @@
   ASSERT_TRUE(__isnormalf(123.0f));
   ASSERT_FALSE(__isnormalf(float_subnormal()));
 #else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
+  GTEST_LOG_(INFO) << "glibc doesn't have __isnormalf.\n";
 #endif // __BIONIC__
 }
 
@@ -299,7 +291,7 @@
   ASSERT_TRUE(__isnormall(123.0L));
   ASSERT_FALSE(__isnormall(ldouble_subnormal()));
 #else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
+  GTEST_LOG_(INFO) << "glibc doesn't have __isnormall.\n";
 #endif // __BIONIC__
 }
 
@@ -1156,7 +1148,7 @@
   ASSERT_DOUBLE_EQ(log(24.0), gamma_r(5.0, &sign));
   ASSERT_EQ(1, sign);
 #else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
+  GTEST_LOG_(INFO) << "glibc doesn't have gamma_r.\n";
 #endif // __BIONIC__
 }
 
@@ -1166,7 +1158,7 @@
   ASSERT_FLOAT_EQ(logf(24.0f), gammaf_r(5.0f, &sign));
   ASSERT_EQ(1, sign);
 #else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
+  GTEST_LOG_(INFO) << "glibc doesn't have gammaf_r.\n";
 #endif // __BIONIC__
 }
 
@@ -1386,3 +1378,73 @@
   ASSERT_TRUE(nextafterf(1.0f, 0.0f) - 1.0f < 0.0f);
   ASSERT_TRUE(nextafterl(1.0L, 0.0L) - 1.0L < 0.0L);
 }
+
+#include "math_cos_intel_data.h"
+TEST(math, cos_intel) {
+  DoMathDataTest<1>(g_cos_intel_data, cos);
+}
+
+#include "math_cosf_intel_data.h"
+TEST(math, cosf_intel) {
+  DoMathDataTest<1>(g_cosf_intel_data, cosf);
+}
+
+#include "math_exp_intel_data.h"
+TEST(math, exp_intel) {
+  DoMathDataTest<1>(g_exp_intel_data, exp);
+}
+
+#include "math_expf_intel_data.h"
+TEST(math, expf_intel) {
+  DoMathDataTest<1>(g_expf_intel_data, expf);
+}
+
+#include "math_log_intel_data.h"
+TEST(math, log_intel) {
+  DoMathDataTest<1>(g_log_intel_data, log);
+}
+
+#include "math_logf_intel_data.h"
+TEST(math, logf_intel) {
+  DoMathDataTest<1>(g_logf_intel_data, logf);
+}
+
+#include "math_pow_intel_data.h"
+TEST(math, pow_intel) {
+  DoMathDataTest<1>(g_pow_intel_data, pow);
+}
+
+#include "math_powf_intel_data.h"
+TEST(math, powf_intel) {
+  DoMathDataTest<1>(g_powf_intel_data, powf);
+}
+
+#include "math_sin_intel_data.h"
+TEST(math, sin_intel) {
+  DoMathDataTest<1>(g_sin_intel_data, sin);
+}
+
+#include "math_sincos_intel_data.h"
+TEST(math, sincos_intel) {
+  DoMathDataTest<1>(g_sincos_intel_data, sincos);
+}
+
+#include "math_sincosf_intel_data.h"
+TEST(math, sincosf_intel) {
+  DoMathDataTest<1>(g_sincosf_intel_data, sincosf);
+}
+
+#include "math_sinf_intel_data.h"
+TEST(math, sinf_intel) {
+  DoMathDataTest<1>(g_sinf_intel_data, sinf);
+}
+
+#include "math_tan_intel_data.h"
+TEST(math, tan_intel) {
+  DoMathDataTest<1>(g_tan_intel_data, tan);
+}
+
+#include "math_tanf_intel_data.h"
+TEST(math, tanf_intel) {
+  DoMathDataTest<1>(g_tanf_intel_data, tanf);
+}