blob: c946cca63c7178c4a892859a403e7d8f280a8176 [file] [log] [blame]
// 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