diff options
author | Elliott Hughes <enh@google.com> | 2012-10-11 16:08:51 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2012-10-11 16:08:51 -0700 |
commit | 3b297c40794b23d50cb5240f9b03f6ef25fd98db (patch) | |
tree | ebcb95b3cd9f249f08257e8654307f88c98e6dbb /tests/dlopen_test.cpp | |
parent | 417fd2334a694cf6a831b81cd672b4ca31ff2f54 (diff) | |
download | android_bionic-3b297c40794b23d50cb5240f9b03f6ef25fd98db.tar.gz android_bionic-3b297c40794b23d50cb5240f9b03f6ef25fd98db.tar.bz2 android_bionic-3b297c40794b23d50cb5240f9b03f6ef25fd98db.zip |
Fix dlerror(3).
Add unit tests for dlerror(3) in various situations. I think We're at least
as good as glibc now.
Also factor out the ScopedPthreadMutexLock and use it here too.
Bug: http://code.google.com/p/android/issues/detail?id=38398
Change-Id: I040938b4366ab836e3df46d1d8055b92f4ea6ed8
Diffstat (limited to 'tests/dlopen_test.cpp')
-rw-r--r-- | tests/dlopen_test.cpp | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/tests/dlopen_test.cpp b/tests/dlopen_test.cpp index 2fcfa0c85..5ef32ad29 100644 --- a/tests/dlopen_test.cpp +++ b/tests/dlopen_test.cpp @@ -24,14 +24,19 @@ #include <string> +#define ASSERT_SUBSTR(needle, haystack) \ + ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack) + static bool gCalled = false; extern "C" void DlSymTestFunction() { gCalled = true; } TEST(dlopen, dlsym_in_self) { + dlerror(); // Clear any pending errors. void* self = dlopen(NULL, RTLD_NOW); ASSERT_TRUE(self != NULL); + ASSERT_TRUE(dlerror() == NULL); void* sym = dlsym(self, "DlSymTestFunction"); ASSERT_TRUE(sym != NULL); @@ -43,9 +48,52 @@ TEST(dlopen, dlsym_in_self) { ASSERT_TRUE(gCalled); } +TEST(dlopen, dlopen_failure) { + void* self = dlopen("/does/not/exist", RTLD_NOW); + ASSERT_TRUE(self == NULL); +#if __BIONIC__ + ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror()); +#else + ASSERT_STREQ("/does/not/exist: cannot open shared object file: No such file or directory", dlerror()); +#endif +} + +TEST(dlopen, dlsym_failures) { + dlerror(); // Clear any pending errors. + void* self = dlopen(NULL, RTLD_NOW); + ASSERT_TRUE(self != NULL); + ASSERT_TRUE(dlerror() == NULL); + + void* sym; + + // NULL handle. + sym = dlsym(NULL, "test"); + ASSERT_TRUE(sym == NULL); +#if __BIONIC__ + ASSERT_SUBSTR("dlsym library handle is null", dlerror()); +#else + ASSERT_SUBSTR("undefined symbol: test", dlerror()); // glibc isn't specific about the failure. +#endif + + // NULL symbol name. +#if __BIONIC__ + // glibc marks this parameter non-null and SEGVs if you cheat. + sym = dlsym(self, NULL); + ASSERT_TRUE(sym == NULL); + ASSERT_SUBSTR("", dlerror()); +#endif + + // Symbol that doesn't exist. + sym = dlsym(self, "ThisSymbolDoesNotExist"); + ASSERT_TRUE(sym == NULL); + ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror()); +} + TEST(dlopen, dladdr) { + dlerror(); // Clear any pending errors. void* self = dlopen(NULL, RTLD_NOW); ASSERT_TRUE(self != NULL); + ASSERT_TRUE(dlerror() == NULL); void* sym = dlsym(self, "DlSymTestFunction"); ASSERT_TRUE(sym != NULL); @@ -102,9 +150,13 @@ TEST(dlopen, dladdr) { TEST(dlopen, dladdr_invalid) { Dl_info info; + dlerror(); // Clear any pending errors. + // No symbol corresponding to NULL. ASSERT_EQ(dladdr(NULL, &info), 0); // Zero on error, non-zero on success. + ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3). // No symbol corresponding to a stack address. ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success. + ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3). } |