diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Android.mk | 2 | ||||
-rw-r--r-- | tests/dlfcn_test.cpp | 65 | ||||
-rw-r--r-- | tests/libs/Android.mk | 24 | ||||
-rw-r--r-- | tests/libs/dlsym_from_this_functions.cpp | 52 | ||||
-rw-r--r-- | tests/libs/dlsym_from_this_symbol.cpp (renamed from tests/libs/dlsym_from_this.cpp) | 15 | ||||
-rw-r--r-- | tests/libs/dlsym_from_this_symbol2.cpp | 18 | ||||
-rw-r--r-- | tests/pthread_dlfcn_test.cpp | 83 | ||||
-rw-r--r-- | tests/pthread_test.cpp | 93 |
8 files changed, 235 insertions, 117 deletions
diff --git a/tests/Android.mk b/tests/Android.mk index cd65c10..14f0d32 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -269,6 +269,7 @@ bionic-unit-tests_src_files := \ dlext_test.cpp \ __cxa_thread_atexit_test.cpp \ dlfcn_test.cpp \ + pthread_dlfcn_test.cpp \ bionic-unit-tests_cflags := $(test_cflags) @@ -346,6 +347,7 @@ bionic-unit-tests-glibc_src_files := \ atexit_test.cpp \ dlfcn_test.cpp \ dl_test.cpp \ + pthread_dlfcn_test.cpp \ bionic-unit-tests-glibc_shared_libraries := \ libdl_preempt_test_1 \ diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp index 6b1f109..a5abda7 100644 --- a/tests/dlfcn_test.cpp +++ b/tests/dlfcn_test.cpp @@ -71,21 +71,78 @@ TEST(dlfcn, dlsym_from_sofile) { void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_LAZY | RTLD_LOCAL); ASSERT_TRUE(handle != nullptr) << dlerror(); - // check that we cant find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT) + // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT) void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol"); ASSERT_TRUE(symbol == nullptr); ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror()); typedef int* (*fn_t)(); - fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT")); + fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT = + reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT")); + ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror(); - ASSERT_TRUE(fn != nullptr) << dlerror(); + int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT(); + ASSERT_TRUE(ptr != nullptr) << dlerror(); + ASSERT_EQ(42, *ptr); + + fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT = + reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT")); + ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror(); + + ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT(); + ASSERT_TRUE(ptr != nullptr) << dlerror(); + ASSERT_EQ(44, *ptr); + + fn_t lookup_dlsym_symbol_using_RTLD_NEXT = + reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT")); + ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror(); - int* ptr = fn(); + ptr = lookup_dlsym_symbol_using_RTLD_NEXT(); + ASSERT_TRUE(ptr != nullptr) << dlerror(); + ASSERT_EQ(43, *ptr); + + dlclose(handle); +} + +TEST(dlfcn, dlsym_from_sofile_with_preload) { + void* preload = dlopen("libtest_dlsym_from_this_grandchild.so", RTLD_NOW | RTLD_LOCAL); + ASSERT_TRUE(preload != nullptr) << dlerror(); + + void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL); + ASSERT_TRUE(handle != nullptr) << dlerror(); + + // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT) + void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol"); + ASSERT_TRUE(symbol == nullptr); + ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror()); + + typedef int* (*fn_t)(); + fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT = + reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT")); + ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror(); + + int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT(); ASSERT_TRUE(ptr != nullptr) << dlerror(); ASSERT_EQ(42, *ptr); + fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT = + reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT")); + ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror(); + + ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT(); + ASSERT_TRUE(ptr != nullptr) << dlerror(); + ASSERT_EQ(44, *ptr); + + fn_t lookup_dlsym_symbol_using_RTLD_NEXT = + reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT")); + ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror(); + + ptr = lookup_dlsym_symbol_using_RTLD_NEXT(); + ASSERT_TRUE(ptr != nullptr) << dlerror(); + ASSERT_EQ(43, *ptr); + dlclose(handle); + dlclose(preload); } TEST(dlfcn, dlsym_with_dependencies) { diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk index c432c2e..15fa55c 100644 --- a/tests/libs/Android.mk +++ b/tests/libs/Android.mk @@ -355,10 +355,7 @@ include $(LOCAL_PATH)/Android.build.testlib.mk # ----------------------------------------------------------------------------- libdl_test_df_1_global_src_files := dl_df_1_global.cpp libdl_test_df_1_global_ldflags := -Wl,-z,global -# TODO (dimitry): x86* toolchain does not support -z global - switch to bfd -ifeq ($(filter $(TARGET_ARCH),x86 x86_64),$(TARGET_ARCH)) -libdl_test_df_1_global_ldflags_target := -fuse-ld=bfd -endif + # TODO (dimitry): host ld.gold does not yet support -z global # remove this line once it is updated. libdl_test_df_1_global_ldflags_host := -fuse-ld=bfd @@ -385,11 +382,26 @@ include $(LOCAL_PATH)/Android.build.testlib.mk # ----------------------------------------------------------------------------- # Library to check RTLD_LOCAL with dlsym in 'this' # ----------------------------------------------------------------------------- -libtest_dlsym_from_this_src_files := dlsym_from_this.cpp +libtest_dlsym_from_this_src_files := dlsym_from_this_symbol.cpp -module := libtest_dlsym_from_this libtest_dlsym_from_this_shared_libraries_target := libdl +libtest_dlsym_from_this_shared_libraries := libtest_dlsym_from_this_child + +module := libtest_dlsym_from_this +include $(LOCAL_PATH)/Android.build.testlib.mk + +# ----------------------------------------------------------------------------- +libtest_dlsym_from_this_child_src_files := dlsym_from_this_functions.cpp + +libtest_dlsym_from_this_child_shared_libraries := libtest_dlsym_from_this_grandchild + +module := libtest_dlsym_from_this_child +include $(LOCAL_PATH)/Android.build.testlib.mk + +# ----------------------------------------------------------------------------- +libtest_dlsym_from_this_grandchild_src_files := dlsym_from_this_symbol2.cpp +module := libtest_dlsym_from_this_grandchild include $(LOCAL_PATH)/Android.build.testlib.mk # ----------------------------------------------------------------------------- diff --git a/tests/libs/dlsym_from_this_functions.cpp b/tests/libs/dlsym_from_this_functions.cpp new file mode 100644 index 0000000..1f357e0 --- /dev/null +++ b/tests/libs/dlsym_from_this_functions.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 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 <dlfcn.h> +#include <stdio.h> + +extern int test_dlsym_symbol; + +int test_dlsym_symbol = -1; + +extern "C" int* lookup_dlsym_symbol_using_RTLD_DEFAULT() { + dlerror(); + int* result = static_cast<int*>(dlsym(RTLD_DEFAULT, "test_dlsym_symbol")); + // TODO: remove this once b/20049306 is fixed + if (result == nullptr) { + printf("Cannot find the answer\n"); + } + return result; +} + +extern "C" int* lookup_dlsym_symbol2_using_RTLD_DEFAULT() { + dlerror(); + int* result = static_cast<int*>(dlsym(RTLD_DEFAULT, "test_dlsym_symbol2")); + // TODO: remove this once b/20049306 is fixed + if (result == nullptr) { + printf("Cannot find the answer\n"); + } + return result; +} + +extern "C" int* lookup_dlsym_symbol_using_RTLD_NEXT() { + dlerror(); + int* result = static_cast<int*>(dlsym(RTLD_NEXT, "test_dlsym_symbol")); + // TODO: remove this once b/20049306 is fixed + if (result == nullptr) { + printf("Cannot find the answer\n"); + } + return result; +} + diff --git a/tests/libs/dlsym_from_this.cpp b/tests/libs/dlsym_from_this_symbol.cpp index b5215c9..c3ec255 100644 --- a/tests/libs/dlsym_from_this.cpp +++ b/tests/libs/dlsym_from_this_symbol.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2015 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. @@ -13,18 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include <dlfcn.h> -#include <stdio.h> int test_dlsym_symbol = 42; - -extern "C" int* lookup_dlsym_symbol_using_RTLD_DEFAULT() { - dlerror(); - int* result = static_cast<int*>(dlsym(RTLD_DEFAULT, "test_dlsym_symbol")); - // TODO: remove this once b/20049306 is fixed - if (result == nullptr) { - printf("Cannot find the answer\n"); - } - return result; -} - diff --git a/tests/libs/dlsym_from_this_symbol2.cpp b/tests/libs/dlsym_from_this_symbol2.cpp new file mode 100644 index 0000000..20da1d5 --- /dev/null +++ b/tests/libs/dlsym_from_this_symbol2.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2015 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. + */ + +int test_dlsym_symbol = 43; +int test_dlsym_symbol2 = 44; diff --git a/tests/pthread_dlfcn_test.cpp b/tests/pthread_dlfcn_test.cpp new file mode 100644 index 0000000..5e8b206 --- /dev/null +++ b/tests/pthread_dlfcn_test.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015 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 <dlfcn.h> + +static int g_atfork_prepare_calls = 0; +static void AtForkPrepare1() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 1; } +static void AtForkPrepare2() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 2; } +static void AtForkPrepare3() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 3; } +static void AtForkPrepare4() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 4; } + +static int g_atfork_parent_calls = 0; +static void AtForkParent1() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 1; } +static void AtForkParent2() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 2; } +static void AtForkParent3() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 3; } +static void AtForkParent4() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 4; } + +static int g_atfork_child_calls = 0; +static void AtForkChild1() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 1; } +static void AtForkChild2() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 2; } +static void AtForkChild3() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 3; } +static void AtForkChild4() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 4; } + +TEST(pthread, pthread_atfork_with_dlclose) { + ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1)); + + void* handle = dlopen("libtest_pthread_atfork.so", RTLD_NOW | RTLD_LOCAL); + ASSERT_TRUE(handle != nullptr) << dlerror(); + typedef int (*fn_t)(void (*)(void), void (*)(void), void (*)(void)); + fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "proxy_pthread_atfork")); + ASSERT_TRUE(fn != nullptr) << dlerror(); + // the library registers 2 additional atfork handlers in a constructor + ASSERT_EQ(0, fn(AtForkPrepare2, AtForkParent2, AtForkChild2)); + ASSERT_EQ(0, fn(AtForkPrepare3, AtForkParent3, AtForkChild3)); + + ASSERT_EQ(0, pthread_atfork(AtForkPrepare4, AtForkParent4, AtForkChild4)); + + int pid = fork(); + + ASSERT_NE(-1, pid) << strerror(errno); + + if (pid == 0) { + ASSERT_EQ(1234, g_atfork_child_calls); + _exit(0); + } + + ASSERT_EQ(1234, g_atfork_parent_calls); + ASSERT_EQ(4321, g_atfork_prepare_calls); + + EXPECT_EQ(0, dlclose(handle)); + g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0; + + int status; + ASSERT_EQ(pid, waitpid(pid, &status, 0)); + + pid = fork(); + + ASSERT_NE(-1, pid) << strerror(errno); + + if (pid == 0) { + ASSERT_EQ(14, g_atfork_child_calls); + _exit(0); + } + + ASSERT_EQ(14, g_atfork_parent_calls); + ASSERT_EQ(41, g_atfork_prepare_calls); + + ASSERT_EQ(pid, waitpid(pid, &status, 0)); +} diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index cb5e818..201b8a9 100644 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -16,7 +16,6 @@ #include <gtest/gtest.h> -#include <dlfcn.h> #include <errno.h> #include <inttypes.h> #include <limits.h> @@ -459,42 +458,6 @@ TEST(pthread, pthread_detach__no_such_thread) { ASSERT_EQ(ESRCH, pthread_detach(dead_thread)); } -TEST(pthread, pthread_detach_no_leak) { - size_t initial_bytes = 0; - // Run this loop more than once since the first loop causes some memory - // to be allocated permenantly. Run an extra loop to help catch any subtle - // memory leaks. - for (size_t loop = 0; loop < 3; loop++) { - // Set the initial bytes on the second loop since the memory in use - // should have stabilized. - if (loop == 1) { - initial_bytes = mallinfo().uordblks; - } - - pthread_attr_t attr; - ASSERT_EQ(0, pthread_attr_init(&attr)); - ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)); - - std::vector<pthread_t> threads; - for (size_t i = 0; i < 32; ++i) { - pthread_t t; - ASSERT_EQ(0, pthread_create(&t, &attr, IdFn, NULL)); - threads.push_back(t); - } - - sleep(1); - - for (size_t i = 0; i < 32; ++i) { - ASSERT_EQ(0, pthread_detach(threads[i])) << i; - } - } - - size_t final_bytes = mallinfo().uordblks; - int leaked_bytes = (final_bytes - initial_bytes); - - ASSERT_EQ(0, leaked_bytes); -} - TEST(pthread, pthread_getcpuclockid__clock_gettime) { SpinFunctionHelper spinhelper; @@ -1019,62 +982,6 @@ TEST(pthread, pthread_atfork_smoke) { ASSERT_EQ(pid, waitpid(pid, &status, 0)); } -static void AtForkPrepare3() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 3; } -static void AtForkPrepare4() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 4; } - -static void AtForkParent3() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 3; } -static void AtForkParent4() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 4; } - -static void AtForkChild3() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 3; } -static void AtForkChild4() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 4; } - -TEST(pthread, pthread_atfork_with_dlclose) { - ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1)); - - void* handle = dlopen("libtest_pthread_atfork.so", RTLD_NOW | RTLD_LOCAL); - ASSERT_TRUE(handle != nullptr) << dlerror(); - typedef int (*fn_t)(void (*)(void), void (*)(void), void (*)(void)); - fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "proxy_pthread_atfork")); - ASSERT_TRUE(fn != nullptr) << dlerror(); - // the library registers 2 additional atfork handlers in a constructor - ASSERT_EQ(0, fn(AtForkPrepare2, AtForkParent2, AtForkChild2)); - ASSERT_EQ(0, fn(AtForkPrepare3, AtForkParent3, AtForkChild3)); - - ASSERT_EQ(0, pthread_atfork(AtForkPrepare4, AtForkParent4, AtForkChild4)); - - int pid = fork(); - - ASSERT_NE(-1, pid) << strerror(errno); - - if (pid == 0) { - ASSERT_EQ(1234, g_atfork_child_calls); - _exit(0); - } - - ASSERT_EQ(1234, g_atfork_parent_calls); - ASSERT_EQ(4321, g_atfork_prepare_calls); - - EXPECT_EQ(0, dlclose(handle)); - g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0; - - int status; - ASSERT_EQ(pid, waitpid(pid, &status, 0)); - - pid = fork(); - - ASSERT_NE(-1, pid) << strerror(errno); - - if (pid == 0) { - ASSERT_EQ(14, g_atfork_child_calls); - _exit(0); - } - - ASSERT_EQ(14, g_atfork_parent_calls); - ASSERT_EQ(41, g_atfork_prepare_calls); - - ASSERT_EQ(pid, waitpid(pid, &status, 0)); -} - TEST(pthread, pthread_attr_getscope) { pthread_attr_t attr; ASSERT_EQ(0, pthread_attr_init(&attr)); |