Use icu4c to implement <wctype.h>.

Pretty useless, because the POSIX APIs are useless for actually
internationalization, but it lets us put this to bed for good.

Bug: http://b/18492914
Test: bionic tests
Change-Id: I4dd0aff66c44b5547039be3ffea806c865b9014a
diff --git a/tests/Android.bp b/tests/Android.bp
index 3e1e13b..643b295 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -385,6 +385,12 @@
     name: "bionic-unit-tests",
     defaults: ["bionic_unit_tests_defaults", "bionic_tests_defaults"],
     clang: true,
+
+    target: {
+        android: {
+            shared_libs: ["libicuuc"],
+        },
+    },
 }
 
 cc_test {
diff --git a/tests/wctype_test.cpp b/tests/wctype_test.cpp
index fe2e374..84a0e65 100644
--- a/tests/wctype_test.cpp
+++ b/tests/wctype_test.cpp
@@ -16,6 +16,8 @@
 
 #include <wctype.h>
 
+#include <dlfcn.h>
+
 #include <gtest/gtest.h>
 
 class UtfLocale {
@@ -25,63 +27,75 @@
   locale_t l;
 };
 
+// bionic's dlsym doesn't work in static binaries, so we can't access icu,
+// so any unicode test case will fail.
+static bool have_dl = (dlopen("libc.so", 0) != nullptr);
+
 static void TestIsWideFn(int fn(wint_t),
                          int fn_l(wint_t, locale_t),
                          const wchar_t* trues,
                          const wchar_t* falses) {
   UtfLocale l;
   for (const wchar_t* p = trues; *p; ++p) {
+    if (!have_dl && *p > 0x7f) {
+      GTEST_LOG_(INFO) << "skipping unicode test " << *p;
+      continue;
+    }
     EXPECT_TRUE(fn(*p)) << *p;
     EXPECT_TRUE(fn_l(*p, l.l)) << *p;
   }
   for (const wchar_t* p = falses; *p; ++p) {
+    if (!have_dl && *p > 0x7f) {
+      GTEST_LOG_(INFO) << "skipping unicode test " << *p;
+      continue;
+    }
     EXPECT_FALSE(fn(*p)) << *p;
     EXPECT_FALSE(fn_l(*p, l.l)) << *p;
   }
 }
 
 TEST(wctype, iswalnum) {
-  TestIsWideFn(iswalnum, iswalnum_l, L"1aA", L"! \b");
+  TestIsWideFn(iswalnum, iswalnum_l, L"1aAÇçΔδ", L"! \b");
 }
 
 TEST(wctype, iswalpha) {
-  TestIsWideFn(iswalpha, iswalpha_l, L"aA", L"1! \b");
+  TestIsWideFn(iswalpha, iswalpha_l, L"aAÇçΔδ", L"1! \b");
 }
 
 TEST(wctype, iswblank) {
-  TestIsWideFn(iswblank, iswblank_l, L" \t", L"1aA!\b");
+  TestIsWideFn(iswblank, iswblank_l, L" \t", L"1aA!\bÇçΔδ");
 }
 
 TEST(wctype, iswcntrl) {
-  TestIsWideFn(iswcntrl, iswcntrl_l, L"\b", L"1aA! ");
+  TestIsWideFn(iswcntrl, iswcntrl_l, L"\b\u009f", L"1aA! ÇçΔδ");
 }
 
 TEST(wctype, iswdigit) {
-  TestIsWideFn(iswdigit, iswdigit_l, L"1", L"aA! \b");
+  TestIsWideFn(iswdigit, iswdigit_l, L"1", L"aA! \bÇçΔδ");
 }
 
 TEST(wctype, iswgraph) {
-  TestIsWideFn(iswgraph, iswgraph_l, L"1aA!", L" \b");
+  TestIsWideFn(iswgraph, iswgraph_l, L"1aA!ÇçΔδ", L" \b");
 }
 
 TEST(wctype, iswlower) {
-  TestIsWideFn(iswlower, iswlower_l, L"a", L"1A! \b");
+  TestIsWideFn(iswlower, iswlower_l, L"açδ", L"1A! \bÇΔ");
 }
 
 TEST(wctype, iswprint) {
-  TestIsWideFn(iswprint, iswprint_l, L"1aA! ", L"\b");
+  TestIsWideFn(iswprint, iswprint_l, L"1aA! ÇçΔδ", L"\b");
 }
 
 TEST(wctype, iswpunct) {
-  TestIsWideFn(iswpunct, iswpunct_l, L"!", L"1aA \b");
+  TestIsWideFn(iswpunct, iswpunct_l, L"!", L"1aA \bÇçΔδ");
 }
 
 TEST(wctype, iswspace) {
-  TestIsWideFn(iswspace, iswspace_l, L" \f\t", L"1aA!\b");
+  TestIsWideFn(iswspace, iswspace_l, L" \f\t", L"1aA!\bÇçΔδ");
 }
 
 TEST(wctype, iswupper) {
-  TestIsWideFn(iswupper, iswupper_l, L"A", L"1a! \b");
+  TestIsWideFn(iswupper, iswupper_l, L"AÇΔ", L"1a! \bçδ");
 }
 
 TEST(wctype, iswxdigit) {
@@ -89,29 +103,65 @@
 }
 
 TEST(wctype, towlower) {
+  EXPECT_EQ(WEOF, towlower(WEOF));
   EXPECT_EQ(wint_t('!'), towlower(L'!'));
   EXPECT_EQ(wint_t('a'), towlower(L'a'));
   EXPECT_EQ(wint_t('a'), towlower(L'A'));
+  if (have_dl) {
+    EXPECT_EQ(wint_t(L'ç'), towlower(L'ç'));
+    EXPECT_EQ(wint_t(L'ç'), towlower(L'Ç'));
+    EXPECT_EQ(wint_t(L'δ'), towlower(L'δ'));
+    EXPECT_EQ(wint_t(L'δ'), towlower(L'Δ'));
+  } else {
+    GTEST_LOG_(INFO) << "skipping unicode towlower tests";
+  }
 }
 
 TEST(wctype, towlower_l) {
   UtfLocale l;
+  EXPECT_EQ(WEOF, towlower(WEOF));
   EXPECT_EQ(wint_t('!'), towlower_l(L'!', l.l));
   EXPECT_EQ(wint_t('a'), towlower_l(L'a', l.l));
   EXPECT_EQ(wint_t('a'), towlower_l(L'A', l.l));
+  if (have_dl) {
+    EXPECT_EQ(wint_t(L'ç'), towlower_l(L'ç', l.l));
+    EXPECT_EQ(wint_t(L'ç'), towlower_l(L'Ç', l.l));
+    EXPECT_EQ(wint_t(L'δ'), towlower_l(L'δ', l.l));
+    EXPECT_EQ(wint_t(L'δ'), towlower_l(L'Δ', l.l));
+  } else {
+    GTEST_LOG_(INFO) << "skipping unicode towlower_l tests";
+  }
 }
 
 TEST(wctype, towupper) {
+  EXPECT_EQ(WEOF, towupper(WEOF));
   EXPECT_EQ(wint_t('!'), towupper(L'!'));
   EXPECT_EQ(wint_t('A'), towupper(L'a'));
   EXPECT_EQ(wint_t('A'), towupper(L'A'));
+  if (have_dl) {
+    EXPECT_EQ(wint_t(L'Ç'), towupper(L'ç'));
+    EXPECT_EQ(wint_t(L'Ç'), towupper(L'Ç'));
+    EXPECT_EQ(wint_t(L'Δ'), towupper(L'δ'));
+    EXPECT_EQ(wint_t(L'Δ'), towupper(L'Δ'));
+  } else {
+    GTEST_LOG_(INFO) << "skipping unicode towupper tests";
+  }
 }
 
 TEST(wctype, towupper_l) {
   UtfLocale l;
+  EXPECT_EQ(WEOF, towupper_l(WEOF, l.l));
   EXPECT_EQ(wint_t('!'), towupper_l(L'!', l.l));
   EXPECT_EQ(wint_t('A'), towupper_l(L'a', l.l));
   EXPECT_EQ(wint_t('A'), towupper_l(L'A', l.l));
+  if (have_dl) {
+    EXPECT_EQ(wint_t(L'Ç'), towupper_l(L'ç', l.l));
+    EXPECT_EQ(wint_t(L'Ç'), towupper_l(L'Ç', l.l));
+    EXPECT_EQ(wint_t(L'Δ'), towupper_l(L'δ', l.l));
+    EXPECT_EQ(wint_t(L'Δ'), towupper_l(L'Δ', l.l));
+  } else {
+    GTEST_LOG_(INFO) << "skipping unicode towupper_l tests";
+  }
 }
 
 TEST(wctype, wctype) {