| // Copyright (C) 2014 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 "emugl/common/shared_library.h" |
| |
| #include <gtest/gtest.h> |
| |
| #include <string> |
| |
| #include <limits.h> |
| #include <string.h> |
| |
| // Hack to get the current executable's full path. |
| namespace testing { |
| namespace internal { |
| |
| extern std::string g_executable_path; |
| |
| } // namespace internal |
| } // namespace testing |
| |
| namespace emugl { |
| |
| namespace { |
| |
| // Return the name/path of the test shared library to load. |
| // Note that this doesn't include a platform-specific extension. |
| // This assumes that the test shared library is under the lib/ sub-directory |
| // of the current executable's path! |
| std::string GetTestLibraryName() { |
| #ifdef __x86_64__ |
| static const char kLibraryPrefix[] = "lib64"; |
| static const char kSubDir[] = "lib64/"; |
| #else |
| static const char kLibraryPrefix[] = "lib"; |
| static const char kSubDir[] = "lib/"; |
| #endif |
| static const char kTestLibrarySuffix[] = "emugl_test_shared_library"; |
| |
| const char* exec_path = testing::internal::g_executable_path.c_str(); |
| |
| #ifdef _WIN32 |
| const char* p = strrchr(exec_path, '/'); |
| const char* p2 = strrchr(exec_path, '\\'); |
| if (p2) { |
| if (!p || p2 > p) { |
| p = p2; |
| } |
| } |
| #else |
| const char* p = strrchr(exec_path, '/'); |
| #endif |
| |
| std::string path; |
| |
| if (!p) { |
| path = "./"; |
| } else { |
| path = std::string(exec_path, p - exec_path + 1U); |
| } |
| path += kSubDir; |
| path += kLibraryPrefix; |
| path += kTestLibrarySuffix; |
| printf("Library path: %s\n", path.c_str()); |
| return path; |
| } |
| |
| class SharedLibraryTest : public testing::Test { |
| public: |
| SharedLibraryTest() { |
| // Locate the shared library |
| mLibraryPath = GetTestLibraryName(); |
| } |
| |
| ~SharedLibraryTest() {} |
| |
| const char* library_path() const { return mLibraryPath.c_str(); } |
| |
| private: |
| std::string mLibraryPath; |
| }; |
| |
| class ScopedSharedLibrary { |
| public: |
| explicit ScopedSharedLibrary(const SharedLibrary* lib) : mLib(lib) {} |
| ~ScopedSharedLibrary() { |
| delete mLib; |
| } |
| const SharedLibrary* get() const { return mLib; } |
| |
| const SharedLibrary* operator->() { return mLib; } |
| |
| void release() { |
| delete mLib; |
| mLib = NULL; |
| } |
| |
| private: |
| const SharedLibrary* mLib; |
| }; |
| |
| } // namespace |
| |
| TEST_F(SharedLibraryTest, Open) { |
| ScopedSharedLibrary lib(SharedLibrary::open(library_path())); |
| EXPECT_TRUE(lib.get()); |
| } |
| |
| TEST_F(SharedLibraryTest, OpenFailureWithError) { |
| char error[256]; |
| error[0] = '\0'; |
| SharedLibrary* lib = SharedLibrary::open("/tmp/does/not/exists", |
| error, |
| sizeof(error)); |
| EXPECT_FALSE(lib); |
| EXPECT_TRUE(error[0]) |
| << "Could not get error string when failing to load library"; |
| printf("Expected library load failure: [%s]\n", error); |
| } |
| |
| TEST_F(SharedLibraryTest, OpenLibraryWithExtension) { |
| std::string path = library_path(); |
| |
| // test extension append |
| ScopedSharedLibrary libNoExtension(SharedLibrary::open(path.c_str())); |
| EXPECT_TRUE(libNoExtension.get()); |
| libNoExtension.release(); |
| |
| #ifdef _WIN32 |
| path += ".dll"; |
| #elif defined(__APPLE__) |
| // try to open the library without an extension |
| |
| path += ".dylib"; |
| #else |
| path += ".so"; |
| #endif |
| |
| // test open with prepended extension |
| ScopedSharedLibrary lib(SharedLibrary::open(path.c_str())); |
| EXPECT_TRUE(lib.get()); |
| } |
| |
| #ifdef __APPLE__ |
| TEST_F(SharedLibraryTest, OpenLibraryWithoutExtension) { |
| const char* library = "/System/Library/Frameworks/OpenGL.framework/OpenGL"; |
| ScopedSharedLibrary lib(SharedLibrary::open(library)); |
| EXPECT_TRUE(lib.get()); |
| } |
| #endif |
| |
| TEST_F(SharedLibraryTest, FindSymbol) { |
| ScopedSharedLibrary lib(SharedLibrary::open(library_path())); |
| EXPECT_TRUE(lib.get()); |
| |
| if (lib.get()) { |
| typedef int (*FooFunction)(void); |
| |
| FooFunction foo_func = reinterpret_cast<FooFunction>( |
| lib->findSymbol("foo_function")); |
| EXPECT_TRUE(foo_func); |
| EXPECT_EQ(42, (*foo_func)()); |
| } |
| } |
| |
| } // namespace emugl |