177 lines
4.6 KiB
C++
177 lines
4.6 KiB
C++
// 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
|