Skip to content

Commit

Permalink
Create test case.
Browse files Browse the repository at this point in the history
Repro case for android/ndk#533 that is
isolated from gradle and the JVM.
  • Loading branch information
DanAlbert committed Oct 3, 2017
1 parent 8136d67 commit 549261e
Show file tree
Hide file tree
Showing 12 changed files with 190 additions and 0 deletions.
25 changes: 25 additions & 0 deletions jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := first
LOCAL_SRC_FILES := firstImpl.cpp
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := second
LOCAL_SRC_FILES := second.cpp
LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := first
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := test.cpp
LOCAL_SHARED_LIBRARIES := first second
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_EXECUTABLE)
4 changes: 4 additions & 0 deletions jni/Application.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
APP_STL := c++_shared
APP_CPPFLAGS := -frtti
APP_PLATFORM := android-16
APP_ABI := armeabi-v7a
15 changes: 15 additions & 0 deletions jni/first.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef TWO_LIBS_FIRST_H
#define TWO_LIBS_FIRST_H

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

virtual void init() = 0;

virtual void prepare() = 0;

virtual void run() = 0;
};

#endif // TWO_LIBS_FIRST_H
9 changes: 9 additions & 0 deletions jni/firstImpl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "firstImpl.h"

firstImpl::firstImpl() {}

void firstImpl::init() {}

void firstImpl::prepare() {}

void firstImpl::run() {}
17 changes: 17 additions & 0 deletions jni/firstImpl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef TWO_LIBS_FIRSTIMPL_H
#define TWO_LIBS_FIRSTIMPL_H

#include "first.h"

class firstImpl : public first {
public:
firstImpl();

void init() override;

void prepare() override;

void run() override;
};

#endif // TWO_LIBS_FIRSTIMPL_H
54 changes: 54 additions & 0 deletions jni/foo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#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() {
test_func test_dynamic;
test_func test_static;

// Commenting out these two lines makes both tests pass.
void *libfirst = load_library("libfirst.so");
void *libsecond = load_library("libsecond.so");

void *libtest = load_library("libtest.so");

test_dynamic = load_func(libtest, "test_dynamic");
test_static = load_func(libtest, "test_static");

if (!test_static()) {
std::cout << "test_static() failed!" << std::endl;
return EXIT_FAILURE;
} else {
std::cout << "test_static() passed!" << std::endl;
}

if (!test_dynamic()) {
std::cout << "test_dynamic() failed!" << std::endl;
return EXIT_FAILURE;
} else {
std::cout << "test_dynamic() passed!" << std::endl;
}

return EXIT_SUCCESS;
}
25 changes: 25 additions & 0 deletions jni/second.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "second.h"
#include "firstImpl.h"

second::second(const std::shared_ptr<first> &firstSRef)
: _firstSRef(firstSRef) {}

bool second::validateDynamicPointerCast() const {
if (_firstSRef != nullptr) {
auto firstImplSRef = std::dynamic_pointer_cast<firstImpl>(_firstSRef);
if (firstImplSRef != nullptr) {
return true;
}
}
return false;
}

bool second::validateStaticPointerCast() const {
if (_firstSRef != nullptr) {
auto firstImplSRef = std::static_pointer_cast<firstImpl>(_firstSRef);
if (firstImplSRef != nullptr) {
return true;
}
}
return false;
}
20 changes: 20 additions & 0 deletions jni/second.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef TWO_LIBS_SECOND_H
#define TWO_LIBS_SECOND_H

#include <memory>

#include "first.h"

class second {
public:
second(const std::shared_ptr<first> &firstSRef);

bool validateDynamicPointerCast() const;

bool validateStaticPointerCast() const;

private:
std::shared_ptr<first> _firstSRef;
};

#endif // TWO_LIBS_SECOND_H
17 changes: 17 additions & 0 deletions jni/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <memory>

#include "first.h"
#include "firstImpl.h"
#include "second.h"

extern "C" bool test_dynamic() {
std::shared_ptr<first> firstSRef = std::make_shared<firstImpl>();
std::shared_ptr<second> secondSRef = std::make_shared<second>(firstSRef);
return secondSRef->validateDynamicPointerCast();
}

extern "C" bool test_static() {
std::shared_ptr<first> firstSRef = std::make_shared<firstImpl>();
std::shared_ptr<second> secondSRef = std::make_shared<second>(firstSRef);
return secondSRef->validateStaticPointerCast();
}
Binary file added libs/armeabi-v7a/foo
Binary file not shown.
Binary file added obj/local/armeabi-v7a/foo
Binary file not shown.
4 changes: 4 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
$NDK/ndk-build
adb push libs/armeabi-v7a/* /data/local/tmp/ && \
adb shell 'LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/foo'

0 comments on commit 549261e

Please sign in to comment.