Skip to content

Commit

Permalink
Add test for dynamic_cast across dlopen boundaries.
Browse files Browse the repository at this point in the history
Test: ./run_tests.py --filter dynamic_cast_dlopen
Bug: android/ndk#533
Change-Id: I345ae21639d7ab16ae3487b5ba633b66940b6bb6
  • Loading branch information
DanAlbert committed Oct 5, 2017
1 parent cce70b9 commit 8c28ddd
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 0 deletions.
17 changes: 17 additions & 0 deletions tests/device/dynamic_cast_dlopen/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libtypes
LOCAL_SRC_FILES := types.cpp
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libtypestest
LOCAL_SRC_FILES := types_test.cpp
LOCAL_SHARED_LIBRARIES := libtypes
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_EXECUTABLE)
2 changes: 2 additions & 0 deletions tests/device/dynamic_cast_dlopen/jni/Application.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
APP_STL := c++_shared
APP_CPPFLAGS := -frtti -std=c++11
41 changes: 41 additions & 0 deletions tests/device/dynamic_cast_dlopen/jni/foo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <dlfcn.h>
#include <stdlib.h>

#include <iostream>

typedef bool (*test_func)();

void *load_library(const char *name) {
void *lib = dlopen(name, RTLD_NOW);
if (lib == nullptr) {
std::cerr << dlerror() << std::endl;
abort();
}
return lib;
}

test_func load_func(void *lib, const char *name) {
test_func sym = reinterpret_cast<test_func>(dlsym(lib, name));
if (sym == nullptr) {
std::cerr << dlerror() << std::endl;
abort();
}
return sym;
}

int main(int argc, char**) {
// Explicitly loading libtypes.so before libtypestest.so so the type_infos it
// contains are resolved with RTLD_LOCAL, which causes the address-only
// type_info comparison to fail.
load_library("libtypes.so");

void *libtest = load_library("libtypestest.so");
test_func do_test = load_func(libtest, "do_test");
if (!do_test()) {
std::cout << "do_test() failed!" << std::endl;
return EXIT_FAILURE;
}

std::cout << "do_test() passed!" << std::endl;
return EXIT_SUCCESS;
}
3 changes: 3 additions & 0 deletions tests/device/dynamic_cast_dlopen/jni/types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "types.h"

MyTypeImpl::MyTypeImpl() {}
11 changes: 11 additions & 0 deletions tests/device/dynamic_cast_dlopen/jni/types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

class MyType {
public:
virtual ~MyType(){};
};

class MyTypeImpl : public MyType {
public:
MyTypeImpl();
};
7 changes: 7 additions & 0 deletions tests/device/dynamic_cast_dlopen/jni/types_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "types.h"

extern "C" bool do_test() {
MyTypeImpl impl;
MyType* base = &impl;
return dynamic_cast<MyTypeImpl*>(base) != nullptr;
}

0 comments on commit 8c28ddd

Please sign in to comment.