Add ifunc for variable test-case
Also move ifunc tests to clang and c++.
Test: bionic-unit-tests --gtest_filter=dlfcn.ifunc*
Change-Id: I008c4fc01470c8e4d314003c03a2b63ff9bf7fd8
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 4ff324e..0ec4663 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -247,6 +247,40 @@
// mips doesn't support ifuncs
#if !defined(__mips__)
+TEST(dlfcn, ifunc_variable) {
+ typedef const char* (*fn_ptr)();
+
+ // ifunc's choice depends on whether IFUNC_CHOICE has a value
+ // first check the set case
+ setenv("IFUNC_CHOICE", "set", 1);
+ // preload libtest_ifunc_variable_impl.so
+ void* handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW);
+ void* handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ const char** foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo"));
+ fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
+ ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
+ ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
+ ASSERT_EQ(strncmp("set", *foo_ptr, 3), 0);
+ ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
+ dlclose(handle);
+ dlclose(handle_impl);
+
+ // then check the unset case
+ unsetenv("IFUNC_CHOICE");
+ handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW);
+ handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo"));
+ foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
+ ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
+ ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
+ ASSERT_EQ(strncmp("unset", *foo_ptr, 5), 0);
+ ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0);
+ dlclose(handle);
+ dlclose(handle_impl);
+}
+
TEST(dlfcn, ifunc) {
typedef const char* (*fn_ptr)();
@@ -254,11 +288,11 @@
// first check the set case
setenv("IFUNC_CHOICE", "set", 1);
void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
- ASSERT_TRUE(handle != nullptr);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
- ASSERT_TRUE(foo_ptr != nullptr);
- ASSERT_TRUE(foo_library_ptr != nullptr);
+ ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
+ ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0);
ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
dlclose(handle);
@@ -266,13 +300,13 @@
// then check the unset case
unsetenv("IFUNC_CHOICE");
handle = dlopen("libtest_ifunc.so", RTLD_NOW);
- ASSERT_TRUE(handle != nullptr);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
- ASSERT_TRUE(foo_ptr != nullptr);
- ASSERT_TRUE(foo_library_ptr != nullptr);
+ ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
+ ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0);
- ASSERT_EQ(strncmp("unset", foo_library_ptr(), 3), 0);
+ ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0);
dlclose(handle);
}