summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2009-05-28 17:37:31 +0200
committerDavid 'Digit' Turner <digit@google.com>2009-05-28 17:37:31 +0200
commit611cdccd9690a9083816f6d4746e998d58250a86 (patch)
tree8c5876982da79ba2d0d319a14a00b6bbf30916fc
parentd7f225b7ebf3bcb9af9df7ecda38125f6e429774 (diff)
downloadextras-611cdccd9690a9083816f6d4746e998d58250a86.tar.gz
Add a new unit test that checks that the static C++ constructors of
shared libraries and dynamic executables are called only once, and in the correct order.
-rw-r--r--tests/bionic/libc/Android.mk19
-rw-r--r--tests/bionic/libc/bionic/lib_static_init.cpp18
-rw-r--r--tests/bionic/libc/bionic/lib_static_init.h15
-rw-r--r--tests/bionic/libc/bionic/test_static_init.cpp30
4 files changed, 82 insertions, 0 deletions
diff --git a/tests/bionic/libc/Android.mk b/tests/bionic/libc/Android.mk
index c7e7305d..4e4bcc64 100644
--- a/tests/bionic/libc/Android.mk
+++ b/tests/bionic/libc/Android.mk
@@ -30,6 +30,7 @@ define device-test
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_MODULE := $(notdir $(file:%.c=%))) \
+ $(eval LOCAL_MODULE := $(LOCAL_MODULE:%.cpp=%)) \
$(eval $(info LOCAL_MODULE=$(LOCAL_MODULE))) \
$(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \
$(eval LOCAL_MODULE_TAGS := tests) \
@@ -46,6 +47,7 @@ define host-test
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_MODULE := $(notdir $(file:%.c=%))) \
+ $(eval LOCAL_MODULE := $(LOCAL_MODULE:%.cpp=%)) \
$(eval $(info LOCAL_MODULE=$(LOCAL_MODULE) file=$(file))) \
$(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \
$(eval LOCAL_LDLIBS += $(EXTRA_LDLIBS)) \
@@ -128,6 +130,23 @@ LOCAL_MODULE := test_relocs
LOCAL_SHARED_LIBRARIES := libtest_relocs
include $(BUILD_EXECUTABLE)
+# This test tries to see if the static constructors in a
+# shared library are only called once. We thus need to
+# build a shared library, then call it from another
+# program.
+#
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := bionic/lib_static_init.cpp
+LOCAL_MODULE := libtest_static_init
+LOCAL_PRELINK_MODULE := false
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := bionic/test_static_init.cpp
+LOCAL_MODULE := test_static_init
+LOCAL_SHARED_LIBRARIES := libtest_static_init
+include $(BUILD_EXECUTABLE)
+
# TODO: Add a variety of GLibc test programs too...
# Hello World to test libstdc++ support
diff --git a/tests/bionic/libc/bionic/lib_static_init.cpp b/tests/bionic/libc/bionic/lib_static_init.cpp
new file mode 100644
index 00000000..d847110a
--- /dev/null
+++ b/tests/bionic/libc/bionic/lib_static_init.cpp
@@ -0,0 +1,18 @@
+#include "lib_static_init.h"
+#include <stdio.h>
+
+Foo::Foo()
+{
+ /* increment the static variable */
+ value = ++Foo::counter;
+ fprintf(stderr, "Foo::Foo for this=%p called (counter = %d)\n", this, counter);
+}
+
+int Foo::getValue()
+{
+ return value;
+}
+
+int Foo::counter;
+
+Foo theFoo;
diff --git a/tests/bionic/libc/bionic/lib_static_init.h b/tests/bionic/libc/bionic/lib_static_init.h
new file mode 100644
index 00000000..f455de8e
--- /dev/null
+++ b/tests/bionic/libc/bionic/lib_static_init.h
@@ -0,0 +1,15 @@
+#ifndef _lib_static_init_h
+#define _lib_static_init_h
+
+class Foo {
+private:
+ int value;
+ static int counter;
+public:
+ virtual int getValue();
+ Foo();
+};
+
+extern Foo theFoo;
+
+#endif /* _lib_static_init_h */
diff --git a/tests/bionic/libc/bionic/test_static_init.cpp b/tests/bionic/libc/bionic/test_static_init.cpp
new file mode 100644
index 00000000..cbc4a59d
--- /dev/null
+++ b/tests/bionic/libc/bionic/test_static_init.cpp
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "lib_static_init.h"
+
+Foo theFoo2;
+
+int main(int argc, char** argv)
+{
+ int c = theFoo.getValue();
+
+ /* check the counter on the library object
+ * it must have been called first, and only once
+ */
+ if (c != 1) {
+ printf("KO (counter(shared) == %d, expected 1)\n", c);
+ return 1;
+ }
+
+ /* check the counter on the executable object,
+ * it must have been called second, and only once
+ */
+ c = theFoo2.getValue();
+ if (c != 2) {
+ printf("KO (counter(executable) == %d, expected 2)\n", c);
+ return 1;
+ }
+
+ printf("OK\n");
+ return 0;
+}