summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2010-06-28 14:04:20 -0700
committerDavid 'Digit' Turner <digit@google.com>2010-06-29 17:11:09 -0700
commit83b47ccbc4066ef19f5d95261d8a892567a7f0a7 (patch)
treeb158e88cd760c02129fe3ae8df26b92522ea3700
parent220a991976c5a029a6b8463c10040c322218934b (diff)
downloadextras-83b47ccbc4066ef19f5d95261d8a892567a7f0a7.tar.gz
bionic: add tests for sem_post() and static C++ destruction on dlclose().
Change-Id: I95e5608240881a3880874ea0ae8a24e716186e7f
-rw-r--r--tests/bionic/libc/Android.mk16
-rw-r--r--tests/bionic/libc/bionic/libdlclosetest1.cpp82
-rw-r--r--tests/bionic/libc/bionic/test_dlclose_destruction.c85
-rw-r--r--tests/bionic/libc/common/test_sem_post.c98
4 files changed, 281 insertions, 0 deletions
diff --git a/tests/bionic/libc/Android.mk b/tests/bionic/libc/Android.mk
index f68d68b9..48748508 100644
--- a/tests/bionic/libc/Android.mk
+++ b/tests/bionic/libc/Android.mk
@@ -68,6 +68,7 @@ sources := \
common/test_pthread_mutex.c \
common/test_pthread_once.c \
common/test_semaphore.c \
+ common/test_sem_post.c \
common/test_seteuid.c \
common/test_static_cpp_mutex.cpp \
common/test_strftime_2039.c \
@@ -150,6 +151,21 @@ LOCAL_MODULE := test_static_init
LOCAL_SHARED_LIBRARIES := libtest_static_init
include $(BUILD_EXECUTABLE)
+# This test tries to see if static destructors are called
+# on dlclose(). We thus need to generate a C++ shared library
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := bionic/libdlclosetest1.cpp
+LOCAL_MODULE := libdlclosetest1
+LOCAL_PRELINK_MODULE := false
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := bionic/test_dlclose_destruction.c
+LOCAL_MODULE := test_dlclose_destruction
+LOCAL_LDFLAGS := -ldl
+#LOCAL_SHARED_LIBRARIES := libdlclosetest1
+include $(BUILD_EXECUTABLE)
+
# Testing 'clone' is only possible on Linux systems
include $(CLEAR_VARS)
LOCAL_SRC_FILES := common/test_clone.c
diff --git a/tests/bionic/libc/bionic/libdlclosetest1.cpp b/tests/bionic/libc/bionic/libdlclosetest1.cpp
new file mode 100644
index 00000000..d19b6394
--- /dev/null
+++ b/tests/bionic/libc/bionic/libdlclosetest1.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+class Foo {
+public:
+ Foo();
+ virtual ~Foo();
+};
+
+
+/* This library is used to ensure that static C++ construction
+ * and destruction operate normally on dlopen() and dlclose().
+ *
+ * We use a global variable inside the DLL called "x"
+ * and initialize it to 1 in the static C++ constructor.
+ *
+ * The main program can access its address through dlsym()
+ * then later check that it was properly initialized.
+ */
+extern "C" int x;
+int x = 0;
+
+Foo::Foo()
+{
+ x = 1;
+ fprintf(stderr, "%s: setting x to 1\n", __FUNCTION__);
+}
+
+/* Similarly, the main program can provide the address of
+ * an integer, named "y", that will be set to 2 when the
+ * static C++ destructor is called on dlclose().
+ *
+ * This address must be provided through the "set_y" function
+ * that can also be resolved through dlsym() by the program.
+ */
+static int *to_y = NULL;
+
+Foo::~Foo()
+{
+ if (to_y == NULL) {
+ fprintf(stderr, "%s: to_y uinitialized !!\n", __FUNCTION__);
+ *(int *)NULL = 0; // crash
+ }
+ *to_y = 2;
+ fprintf(stderr, "%s: setting y(%p) to 2 !\n", __FUNCTION__, to_y);
+}
+
+static Foo f;
+
+extern "C"
+void set_y(int *y)
+{
+ to_y = y;
+ fprintf(stderr, "%s: setting to_y=%p\n", __FUNCTION__, y);
+}
diff --git a/tests/bionic/libc/bionic/test_dlclose_destruction.c b/tests/bionic/libc/bionic/test_dlclose_destruction.c
new file mode 100644
index 00000000..fac6a867
--- /dev/null
+++ b/tests/bionic/libc/bionic/test_dlclose_destruction.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* this program is used to check that static C++ destructors are
+ * properly called when dlclose() is called. We do this by using
+ * a helper C++ shared library.
+ *
+ * See libdlclosetest1.cpp for details.
+ */
+#include <dlfcn.h>
+#include <stdio.h>
+
+int main(void)
+{
+ void* lib = dlopen("libdlclosetest1.so", RTLD_NOW);
+ int* to_x;
+ void (*set_y)(int *);
+ int y = 0;
+
+ if (lib == NULL) {
+ fprintf(stderr, "Could not load shared library: %s\n", dlerror());
+ return 1;
+ }
+
+ fprintf(stderr, "Loaded !!\n");
+
+ to_x = dlsym(lib, "x");
+ if (to_x == NULL) {
+ fprintf(stderr, "Could not access global DLL variable (x): %s\n", dlerror());
+ return 10;
+ }
+
+ if (*to_x != 1) {
+ fprintf(stderr, "Static C++ constructor was not run on dlopen() !\n");
+ return 11;
+ }
+
+ set_y = dlsym(lib, "set_y");
+ if (set_y == NULL) {
+ fprintf(stderr, "Could not access global DLL function (set_y): %s\n", dlerror());
+ return 12;
+ }
+
+ y = 0;
+ (*set_y)(&y);
+
+ if (dlclose(lib) < 0) {
+ fprintf(stderr, "Could not unload shared library: %s\n", dlerror());
+ return 2;
+ }
+
+ fprintf(stderr, "Unloaded !!\n");
+
+ if (y != 2) {
+ fprintf(stderr, "Static C++ destructor was not run on dlclose() !\n");
+ return 11;
+ }
+
+ return 0;
+}
diff --git a/tests/bionic/libc/common/test_sem_post.c b/tests/bionic/libc/common/test_sem_post.c
new file mode 100644
index 00000000..adc0f859
--- /dev/null
+++ b/tests/bionic/libc/common/test_sem_post.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This program is used to test that sem_post() will wake up all
+ * threads that are waiting on a single semaphore, and not all of
+ * them.
+ */
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+static sem_t semaphore;
+
+/* Thread function, just wait for the semaphore */
+static void*
+thread_func(void* arg)
+{
+ sem_t *psem = (sem_t *)arg;
+ void *me = (void *)pthread_self();
+ printf("thread %p waiting\n", me);
+ sem_wait(psem);
+ printf("thread %p exiting\n", me);
+ return me;
+}
+
+#define MAX_THREADS 50
+
+int main(void)
+{
+ pthread_t t[MAX_THREADS];
+ int nn, value;
+
+ /* Initialize to 1, first thread will exit immediately.
+ * this is used to exercize more of the semaphore code path */
+ if ( sem_init( &semaphore, 0, 1 ) < 0 ) {
+ printf( "Could not initialize semaphore: %s\n", strerror(errno) );
+ return 1;
+ }
+
+ for ( nn = 0; nn < MAX_THREADS; nn++ ) {
+ if ( pthread_create( &t[nn], NULL, thread_func, &semaphore ) < 0 ) {
+ printf("Could not create thread %d: %s\n", nn+1, strerror(errno) );
+ return 2;
+ }
+ }
+ sleep( 1 );
+
+ for (nn = 0; nn < MAX_THREADS; nn++) {
+ sem_post(&semaphore);
+ }
+
+ for ( nn = 0; nn < MAX_THREADS; nn++) {
+ void* result;
+ pthread_join(t[nn], &result);
+ if (result != (void*)t[nn]) {
+ printf("Thread %p joined but returned %p\n", (void*)t[nn], result);
+ }
+ }
+
+ if (sem_getvalue(&semaphore, &value) < 0) {
+ printf("Could not get semaphore value: %s\n", strerror(errno));
+ return 3;
+ }
+ if (value != 1) {
+ printf("Error: Semaphore value = %d\n", value);
+ return 4;
+ }
+ return 0;
+}