Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ jobs:
token: ${{ secrets.ACCESS_TOKEN }}
persist-credentials: false

- name: set up JDK 11
- name: set up JDK 17
uses: actions/setup-java@v3
with:
java-version: 11.0.10
java-version: 17.0.10
distribution: "adopt"
cache: gradle

Expand Down Expand Up @@ -106,7 +106,7 @@ jobs:
# newest Android version
saucectl run espresso -c "" --name "From Github Actions" --app example-app-debug.apk --testApp ${{ matrix.test-apk }} --emulator name="Android GoogleApi Emulator,platformVersion=12.0" --region us-west-1
# oldest Android version
saucectl run espresso -c "" --name "From Github Actions" --app example-app-debug.apk --testApp ${{ matrix.test-apk }} --emulator name="Android GoogleApi Emulator,platformVersion=5.1" --region us-west-1
saucectl run espresso -c "" --name "From Github Actions" --app example-app-debug.apk --testApp ${{ matrix.test-apk }} --emulator name="Android GoogleApi Emulator,platformVersion=6.0" --region us-west-1
# oldest real device (aiming for armv7 / 32bit)
saucectl run espresso -c "" --name "From Github Actions" --app example-app-debug.apk --testApp ${{ matrix.test-apk }} --device name=".*,platformVersion=6.0.1" --region us-west-1
# --device name=".*,platformVersion=6.0.1"
Expand Down
9 changes: 7 additions & 2 deletions backtrace-library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ androidGitVersion {
android {

compileSdkVersion 33

namespace "backtraceio.library"
defaultConfig {
minSdkVersion 21
targetSdkVersion 33
Expand All @@ -32,6 +32,9 @@ android {
ndk {
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
buildFeatures {
buildConfig = true
}
}

buildTypes {
Expand All @@ -57,7 +60,7 @@ android {
}
androidTest.manifest.srcFile "src/androidTest/java/backtraceio/library/AndroidManifest.xml"
}

// Needed until we migrate to AndroidX
android {
lintOptions {
Expand All @@ -77,6 +80,8 @@ dependencies {
androidTestImplementation 'androidx.test:rules:1.5.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'org.mockito:mockito-core:2.28.2'
androidTestImplementation "org.mockito:mockito-android:2.28.2"
}

apply from: 'publish.gradle'
4 changes: 1 addition & 3 deletions backtrace-library/publish.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ afterEvaluate { project ->
publishing {
publications {
release(MavenPublication) {
from components.findByName('release')
groupId GROUP
artifactId POM_ARTIFACT_ID
version version
from components.release
}
}

Expand Down Expand Up @@ -111,12 +111,10 @@ afterEvaluate { project ->
}

task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}

task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.source
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="backtraceio.library">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package backtraceio.library.crashHandler;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import androidx.test.ext.junit.runners.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.List;
import java.util.Map;

import backtraceio.library.models.nativeHandler.CrashHandlerConfiguration;

@RunWith(AndroidJUnit4.class)
public class BacktraceCrashHandlerRunnerConfigurationTest {
@Test
public void unsupportedAbiVersion() {
CrashHandlerConfiguration crashHandlerConfiguration = new CrashHandlerConfiguration();
for (String unsupportedAbi :
CrashHandlerConfiguration.UNSUPPORTED_ABIS) {
assertFalse(crashHandlerConfiguration.isSupportedAbi(unsupportedAbi));
}
}

@Test
public void supportedAbiVersion() {
CrashHandlerConfiguration crashHandlerConfiguration = new CrashHandlerConfiguration();
for (String unsupportedAbi :
new String[]{"armeabi", "arm64", "arm64-v8", "x86-64"}) {
assertTrue(crashHandlerConfiguration.isSupportedAbi(unsupportedAbi));
}
}

@Test
public void environmentVariableHasCorrectPathToLibrary() {
CrashHandlerConfiguration crashHandlerConfiguration = new CrashHandlerConfiguration();
String fakePathToApk = "fake/path/to/apk/apk.apk";
String fakePathToLib = "fake/path/to/lib/arm64";
String fakeAbi = "fake-abi";
List<String> environmentVariables = crashHandlerConfiguration.getCrashHandlerEnvironmentVariables(fakePathToApk, fakePathToLib, fakeAbi);
for (String envVariable : environmentVariables) {
if (envVariable.startsWith(CrashHandlerConfiguration.BACKTRACE_CRASH_HANDLER)) {
assertEquals(envVariable, String.format("%s=%s!/lib/%s/libbacktrace-native.so", CrashHandlerConfiguration.BACKTRACE_CRASH_HANDLER, fakePathToApk, fakeAbi));
return;
}
}
fail("Cannot find Backtrace Crash Handler environment variable");
}

@Test
public void environmentVariableContainsJavaEnvVariables() {
CrashHandlerConfiguration crashHandlerConfiguration = new CrashHandlerConfiguration();
String fakePathToApk = "fake/path/to/apk/apk.apk";
String fakePathToLib = "fake/path/to/lib/arm64";
String fakeAbi = "fake-abi";
List<String> environmentVariables = crashHandlerConfiguration.getCrashHandlerEnvironmentVariables(fakePathToApk, fakePathToLib, fakeAbi);

Map<String, String> systemEnvVariables = System.getenv();

for (Map.Entry<String, String> envVariable : systemEnvVariables.entrySet()) {
assertTrue(environmentVariables.indexOf(String.format("%s=%s", envVariable.getKey(), envVariable.getValue())) != -1);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package backtraceio.library.crashHandler;


import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;

import java.util.HashMap;

import backtraceio.library.models.nativeHandler.CrashHandlerConfiguration;
import backtraceio.library.nativeCalls.BacktraceCrashHandlerWrapper;
import backtraceio.library.nativeCalls.SystemLoader;
import backtraceio.library.services.BacktraceCrashHandlerRunner;

@RunWith(MockitoJUnitRunner.class)
public class CrashHandlerRunnerInvocationTest {

private final static String fakePathLibrary = "path/to/lib";
@Mock
BacktraceCrashHandlerWrapper backtraceCrashHandlerWrapper;

@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}

@Test
public void failIfEnvVariablesAreNotDefined() {
BacktraceCrashHandlerRunner runner = new BacktraceCrashHandlerRunner();
assertFalse(runner.run(new String[]{}, null));
}

@Test
public void failIfEnvVariablesDontStoreHandlerPath() {
BacktraceCrashHandlerRunner runner = new BacktraceCrashHandlerRunner();
assertFalse(runner.run(new String[]{}, new HashMap<>()));
}

@Test
public void shouldExecuteCorrectlyCrashpadHandlerMethod() {
HashMap<String, String> envVariables = new HashMap<String, String>();
envVariables.put(CrashHandlerConfiguration.BACKTRACE_CRASH_HANDLER, fakePathLibrary);

when(backtraceCrashHandlerWrapper.handleCrash(any(String[].class))).thenReturn(true);

BacktraceCrashHandlerRunner runner = new BacktraceCrashHandlerRunner(backtraceCrashHandlerWrapper, mock(SystemLoader.class));
assertTrue(runner.run(new String[]{}, envVariables));
}

@Test
public void shouldReturnFalseWhenCrashpadFails() {
HashMap<String, String> envVariables = new HashMap<String, String>();
envVariables.put(CrashHandlerConfiguration.BACKTRACE_CRASH_HANDLER, fakePathLibrary);

when(backtraceCrashHandlerWrapper.handleCrash(any(String[].class))).thenReturn(true);

BacktraceCrashHandlerRunner runner = new BacktraceCrashHandlerRunner(backtraceCrashHandlerWrapper, mock(SystemLoader.class));
assertTrue(runner.run(new String[]{}, envVariables));
}
}
3 changes: 1 addition & 2 deletions backtrace-library/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="backtraceio.library">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<application/>
</manifest>
Expand Down
65 changes: 33 additions & 32 deletions backtrace-library/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@ cmake_minimum_required(VERSION 3.13)
# https://github.com/android/ndk/issues/596
if (ANDROID_ABI STREQUAL "x86")
message("Native crash reporting not supported for x86 emulator")
elseif(ANDROID_ABI STREQUAL "x86_64" AND (NOT ANDROID_NDK_MAJOR OR ANDROID_NDK_MAJOR LESS 17))
elseif (ANDROID_ABI STREQUAL "x86_64" AND (NOT ANDROID_NDK_MAJOR OR ANDROID_NDK_MAJOR LESS 17))
message("Breakpad not supported for x86_64 emulator")
elseif (NOT ANDROID_NDK_MAJOR)
set(BACKEND "BREAKPAD_BACKEND")
elseif(ANDROID_NDK_MAJOR LESS 17)
elseif (ANDROID_NDK_MAJOR LESS 17)
set(BACKEND "BREAKPAD_BACKEND")
elseif(ANDROID_NATIVE_API_LEVEL LESS 21)
elseif (ANDROID_NATIVE_API_LEVEL LESS 21)
set(BACKEND "CRASHPAD_BACKEND")
# 64 bit architectures will always have min API level 21
# https://stackoverflow.com/a/56467008
if (NOT ANDROID_ABI STREQUAL "armeabi-v7a")
set(CLIENT_SIDE_UNWINDING TRUE)
endif()
else()
endif ()
else ()
set(BACKEND "CRASHPAD_BACKEND")
set(CLIENT_SIDE_UNWINDING TRUE)
endif()
endif ()

cmake_policy(SET CMP0077 NEW)
set(ANDROID_SSL_MODE "OPENSSL")
Expand All @@ -35,29 +35,29 @@ set(ANDROID_SSL_MODE "OPENSSL")
list(APPEND SOURCES backtrace-native.cpp)
list(APPEND SOURCES backends/backend.cpp)
list(APPEND SOURCES client-side-unwinding.cpp)
if(BACKEND STREQUAL "CRASHPAD_BACKEND")
if (BACKEND STREQUAL "CRASHPAD_BACKEND")
list(APPEND SOURCES backends/crashpad-backend.cpp)
elseif(BACKEND STREQUAL "BREAKPAD_BACKEND")
elseif (BACKEND STREQUAL "BREAKPAD_BACKEND")
list(APPEND SOURCES backends/breakpad-backend.cpp)
else()
else ()
message("No native debugging backend selected")
endif()
endif ()

add_library(# Sets the name of the library.
backtrace-native
backtrace-native

# Sets the library as a shared library.
SHARED
# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
${SOURCES})
# Provides a relative path to your source file(s).
${SOURCES})

target_compile_features(backtrace-native PRIVATE cxx_std_17)

if(BACKEND STREQUAL "CRASHPAD_BACKEND")
if (BACKEND STREQUAL "CRASHPAD_BACKEND")
target_compile_definitions(backtrace-native PRIVATE -DCRASHPAD_BACKEND)

elseif(BACKEND STREQUAL "BREAKPAD_BACKEND")
elseif (BACKEND STREQUAL "BREAKPAD_BACKEND")
target_compile_definitions(backtrace-native PRIVATE -DBREAKPAD_BACKEND)

# Breakpad Libraries
Expand All @@ -70,9 +70,9 @@ elseif(BACKEND STREQUAL "BREAKPAD_BACKEND")

# Breakpad Headers
include_directories(${PROJECT_SOURCE_DIR}/breakpad-builds/${ANDROID_ABI} ${PROJECT_SOURCE_DIR}/breakpad-builds/${ANDROID_ABI}/src ${PROJECT_SOURCE_DIR}/breakpad-builds/${ANDROID_ABI}/src/common/android/include)
else()
else ()
message("No native debugging backend selected")
endif()
endif ()

# Includes
include_directories(${PROJECT_SOURCE_DIR}/include)
Expand All @@ -83,7 +83,7 @@ if (CLIENT_SIDE_UNWINDING)
# Bun Libraries
set(LIBUNWINDSTACK_ENABLED TRUE)
add_subdirectory(libbun)
endif()
endif ()

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
Expand All @@ -92,12 +92,12 @@ endif()
# completing its build.

find_library( # Sets the name of the path variable.
log-lib
log-lib

# Specifies the name of the NDK library that
# you want CMake to locate.
log
)
# Specifies the name of the NDK library that
# you want CMake to locate.
log
)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
Expand All @@ -106,21 +106,22 @@ find_library( # Sets the name of the path variable.
list(APPEND LIBS backtrace-native)
list(APPEND LIBS ${log-lib})

if(BACKEND STREQUAL "CRASHPAD_BACKEND")
set(CUSTOM_CRASHPAD_HANDLER_DESTINATION
${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libcrashpad_handler.so)
if (BACKEND STREQUAL "CRASHPAD_BACKEND")
set(CRASHPAD_HANDLER_GENERATE_STATIC_LIB true)
add_subdirectory(crashpad)
target_link_libraries(backtrace-native client)
elseif(BACKEND STREQUAL "BREAKPAD_BACKEND")
target_link_libraries(backtrace-native handlerlib)

elseif (BACKEND STREQUAL "BREAKPAD_BACKEND")
list(APPEND LIBS breakpad_client)
list(APPEND LIBS curl)
else()
else ()
message("No native debugging backend selected")
endif()
endif ()

if (CLIENT_SIDE_UNWINDING)
list(APPEND LIBS bun)
endif()
endif ()

target_link_libraries(${LIBS})

Expand Down
Loading