Skip to content

Commit bbc2975

Browse files
vlussenburgKrzaQ
andauthored
Feature/cmake crashpad (#53)
* Added UI tests to daily CI scripts on the Sauce Labs device farm * Use Backtrace's CMake Crashpad repository * Add scripts to set Backtrace submission URL and upload built AAR and APKs * Removed java.nio since it's not supported on old Android versions. * added espresso test + modified test script Co-authored-by: krzaq <krzaq@krzaq.cc>
1 parent d4b90b2 commit bbc2975

File tree

11 files changed

+228
-90
lines changed

11 files changed

+228
-90
lines changed

.github/workflows/test.yml

Lines changed: 115 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,118 @@ on:
1010

1111
jobs:
1212
build:
13-
env:
14-
ANDROID_API_LEVEL: 23
15-
ANDROID_EMULATOR_LEVEL: 23
16-
ANDROID_BUILD_TOOLS_VERSION: 28.0.3
17-
ANDROID_ABI: armeabi-v7a
18-
ANDROID_TAG: google_apis
19-
ADB_INSTALL_TIMEOUT: 20
20-
21-
runs-on: macos-latest # necessary for reactivecircus/android-emulator-runner@v2
22-
23-
steps:
24-
- name: Checkout submodules
25-
uses: actions/checkout@v2
26-
with:
27-
fetch-depth: 2
28-
submodules: recursive
29-
token: ${{ secrets.ACCESS_TOKEN }}
30-
persist-credentials: false
31-
32-
- name: set up JDK 11
33-
uses: actions/setup-java@v2
34-
with:
35-
java-version: 11.0.10
36-
distribution: 'adopt'
37-
cache: gradle
38-
39-
- name: Grant execute permission for gradlew
40-
run: chmod +x gradlew
41-
- name: Test
42-
uses: reactivecircus/android-emulator-runner@v2
43-
with:
44-
target: google_apis
45-
api-level: 30
46-
arch: x86_64
47-
script: ./gradlew assembleDebug && ./gradlew test --info && ./gradlew connectedCheck
48-
49-
- name: Code coverage
50-
run: bash <(curl -s https://codecov.io/bash)
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout submodules
17+
uses: actions/checkout@v2
18+
with:
19+
fetch-depth: 2
20+
submodules: recursive
21+
token: ${{ secrets.ACCESS_TOKEN }}
22+
persist-credentials: false
23+
24+
- name: set up JDK 11
25+
uses: actions/setup-java@v2
26+
with:
27+
java-version: 11.0.10
28+
distribution: 'adopt'
29+
cache: gradle
30+
31+
- name: Write to local.properties
32+
run: |
33+
echo BACKTRACE_SUBMISSION_URL=\"https://submit.backtrace.io/yolo/2dd86e8e779d1fc7e22e7b19a9489abeedec3b1426abe7e2209888e92362fba4/json\" > ./local.properties
34+
35+
- name: Build and check
36+
run: ./gradlew assembleDebug assembleDebugAndroidTest check
37+
38+
- name: Upload example-app APK
39+
uses: actions/upload-artifact@v3
40+
with:
41+
name: example-app-debug.apk
42+
path: example-app/build/outputs/apk/debug/example-app-debug.apk
43+
44+
- name: Upload example-app Test APK
45+
uses: actions/upload-artifact@v3
46+
with:
47+
name: example-app-debug-androidTest.apk
48+
path: example-app/build/outputs/apk/androidTest/debug/example-app-debug-androidTest.apk
49+
50+
- name: Upload backtrace-library AAR
51+
uses: actions/upload-artifact@v3
52+
with:
53+
name: backtrace-library-debug.aar
54+
path: backtrace-library/build/outputs/aar/backtrace-library-debug.aar
55+
56+
- name: Upload backtrace-library Test APK
57+
uses: actions/upload-artifact@v3
58+
with:
59+
name: backtrace-library-debug-androidTest.apk
60+
path: backtrace-library/build/outputs/apk/androidTest/debug/backtrace-library-debug-androidTest.apk
61+
62+
test:
63+
runs-on: ubuntu-latest
64+
needs: build
65+
66+
strategy:
67+
fail-fast: false
68+
matrix:
69+
test-apk: [example-app-debug-androidTest.apk, backtrace-library-debug-androidTest.apk]
70+
71+
steps:
72+
- name: Download APK
73+
uses: actions/download-artifact@v3
74+
with:
75+
name: example-app-debug.apk
76+
77+
- name: Download Test APK
78+
uses: actions/download-artifact@v3
79+
with:
80+
name: ${{ matrix.test-apk }}
81+
82+
- name: Get Saucectl
83+
run: curl -L https://saucelabs.github.io/saucectl/install | bash
84+
85+
- name: Install saucectl
86+
uses: saucelabs/saucectl-run-action@v1
87+
with:
88+
skip-run: true
89+
90+
- name: Run Saucectl
91+
run: |
92+
saucectl configure --username ${{ secrets.SAUCE_USERNAME }} --accessKey ${{ secrets.SAUCE_ACCESS_KEY }}
93+
# newest Android version
94+
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"
95+
# oldest Android version
96+
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"
97+
# real device
98+
saucectl run espresso -c "" --name "From Github Actions" --app example-app-debug.apk --testApp ${{ matrix.test-apk }} --device name="Samsung_Galaxy_S20_FE_5G_backtrace_us"
99+
# --device name=".*,platformVersion=6.0.1"
100+
# --device name="Samsung_Galaxy_S20_FE_5G_backtrace_us"
101+
# --device name="Samsung_Galaxy_S22_Ultra_5G_backtrace_us"
102+
103+
- name: Run morgue
104+
run: |
105+
npm install backtrace-morgue --location=global
106+
morgue --version || true
107+
# Todo: currently just looks 15 minutes in the past and doesn't filter at all.
108+
# --csv=crash.csv
109+
morgue --token=${{ secrets.BACKTRACE_API_TOKEN }} --endpoint="https://yolo.sp.backtrace.io" list yolo/android-library --select timestamp --filter=timestamp,greater-than,`date +%s%3N -d "15 minutes ago"` || true
110+
111+
# if [ $(wc -l < crash.csv) -gt 0 ]; then
112+
# echo "Success"
113+
# else
114+
# exit 1
115+
# fi
116+
117+
# runs-on: macos-latest # necessary for reactivecircus/android-emulator-runner@v2
118+
# - name: Emulator test
119+
# uses: reactivecircus/android-emulator-runner@v2
120+
# with:
121+
# target: google_apis
122+
# api-level: ${{ matrix.api-level }}
123+
# arch: x86_64
124+
# script: ./gradlew connectedCheck
125+
126+
# - name: Code coverage
127+
# run: bash <(curl -s https://codecov.io/bash)

.gitmodules

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
[submodule "backtrace-library/src/main/cpp/crashpad-builds"]
2-
path = backtrace-library/src/main/cpp/crashpad-builds
3-
url = https://github.com/backtrace-labs/crashpad-builds.git
41
[submodule "backtrace-library/src/main/cpp/libbun"]
52
path = backtrace-library/src/main/cpp/libbun
63
url = git@github.com:backtrace-labs/libbun.git
74
[submodule "backtrace-library/src/main/cpp/breakpad-builds"]
85
path = backtrace-library/src/main/cpp/breakpad-builds
96
url = git@github.com:backtrace-labs/breakpad-builds.git
7+
[submodule "backtrace-library/src/main/cpp/crashpad"]
8+
path = backtrace-library/src/main/cpp/crashpad
9+
url = git@github.com:backtrace-labs/crashpad.git

backtrace-library/build.gradle

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ android {
1616
externalNativeBuild {
1717
cmake {
1818
cppFlags ""
19+
arguments "-DCMAKE_BUILD_TYPE=Release"
1920
}
2021
}
2122
ndk {
@@ -38,13 +39,10 @@ android {
3839
externalNativeBuild {
3940
cmake {
4041
path file('src/main/cpp/CMakeLists.txt')
41-
version "3.10.2"
4242
}
4343
}
4444
sourceSets {
4545
main {
46-
jniLibs.srcDirs = ['src/main/cpp/crashpad-builds']
47-
jniLibs.includes = ['src/main/cpp/crashpad-builds/crashpad_handler']
4846
}
4947
}
5048

@@ -69,4 +67,4 @@ dependencies {
6967
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
7068
}
7169

72-
apply from: 'publish.gradle'
70+
apply from: 'publish.gradle'

backtrace-library/src/androidTest/java/backtraceio/library/breadcrumbs/BacktraceBreadcrumbsTest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
import java.io.File;
2020
import java.io.FileInputStream;
2121
import java.io.IOException;
22-
import java.nio.file.Files;
23-
import java.nio.file.Paths;
2422
import java.util.ArrayList;
2523
import java.util.HashMap;
2624
import java.util.LinkedHashMap;
@@ -324,7 +322,7 @@ public void testQueueFileRollover() {
324322
backtraceBreadcrumbs.addBreadcrumb("I am a breadcrumb", attributes);
325323
}
326324

327-
long breadcrumbsFileSize = Files.size(Paths.get(backtraceBreadcrumbs.getBreadcrumbLogPath()));
325+
long breadcrumbsFileSize = new File(backtraceBreadcrumbs.getBreadcrumbLogPath()).length();
328326
assertTrue(String.format("Size of breadcrumbs file (%s) not close enough to a full breadcrumb file (%s)", breadcrumbsFileSize, 64 * 1024),
329327
breadcrumbsFileSize > 63 * 1024);
330328

backtrace-library/src/main/cpp/CMakeLists.txt

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,6 @@ target_compile_features(backtrace-native PRIVATE cxx_std_17)
5454
if(BACKEND STREQUAL "CRASHPAD_BACKEND")
5555
target_compile_definitions(backtrace-native PRIVATE -DCRASHPAD_BACKEND)
5656

57-
# Crashpad Libraries
58-
add_library(crashpad_client STATIC IMPORTED)
59-
set_property(TARGET crashpad_client PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/crashpad-builds/${ANDROID_ABI}/client/libcrashpad_client.a)
60-
61-
add_library(crashpad_util STATIC IMPORTED)
62-
set_property(TARGET crashpad_util PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/crashpad-builds/${ANDROID_ABI}/util/libcrashpad_util.a)
63-
64-
add_library(base STATIC IMPORTED)
65-
set_property(TARGET base PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/crashpad-builds/${ANDROID_ABI}/third_party/mini_chromium/mini_chromium/base/libbase.a)
66-
67-
# Crashpad Headers
68-
include_directories(${PROJECT_SOURCE_DIR}/crashpad-builds/headers/ ${PROJECT_SOURCE_DIR}/crashpad-builds/headers/third_party/mini_chromium/mini_chromium/)
6957
elseif(BACKEND STREQUAL "BREAKPAD_BACKEND")
7058
target_compile_definitions(backtrace-native PRIVATE -DBREAKPAD_BACKEND)
7159

@@ -116,9 +104,10 @@ list(APPEND LIBS backtrace-native)
116104
list(APPEND LIBS ${log-lib})
117105

118106
if(BACKEND STREQUAL "CRASHPAD_BACKEND")
119-
list(APPEND LIBS crashpad_client)
120-
list(APPEND LIBS crashpad_util)
121-
list(APPEND LIBS base)
107+
set(CUSTOM_CRASHPAD_HANDLER_DESTINATION
108+
${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libcrashpad_handler.so)
109+
add_subdirectory(crashpad)
110+
target_link_libraries(backtrace-native client)
122111
elseif(BACKEND STREQUAL "BREAKPAD_BACKEND")
123112
list(APPEND LIBS breakpad_client)
124113
list(APPEND LIBS curl)
Submodule crashpad added at 3ce0e54
Lines changed: 0 additions & 1 deletion
This file was deleted.

backtrace-library/src/main/java/backtraceio/library/services/BacktraceHandlerThread.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ SummedEventsHandler createSummedEventsHandler(BacktraceMetrics backtraceMetrics,
4040
@Override
4141
protected void onLooperPrepared() {
4242
super.onLooperPrepared();
43-
mHandler = new BacktraceHandler(this.getLooper(), this.url);
43+
if (mHandler == null) {
44+
mHandler = new BacktraceHandler(this.getLooper(), this.url);
45+
}
4446
}
4547

4648
Message createMessage(BacktraceHandlerInput data) {
@@ -50,6 +52,11 @@ Message createMessage(BacktraceHandlerInput data) {
5052
}
5153

5254
void sendReport(BacktraceHandlerInputReport data) {
55+
// Sometimes, sendReport gets called before the Looper is ready.
56+
// getLooper will wait for the Looper to be ready: https://stackoverflow.com/questions/30300555/android-what-happens-after-a-handlerthread-is-started
57+
if (mHandler == null) {
58+
mHandler = new BacktraceHandler(this.getLooper(), this.url);
59+
}
5360
mHandler.sendMessage(createMessage(data));
5461
}
5562

example-app/build.gradle

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,26 @@ android {
3232
lintOptions {
3333
abortOnError false
3434
}
35+
defaultConfig {
36+
buildConfigField ("String", "BACKTRACE_SUBMISSION_URL", getSubmissionUrl())
37+
}
3538
}
3639
}
3740

41+
String getSubmissionUrl() {
42+
def propFile = rootProject.file("./local.properties")
43+
def properties = new Properties()
44+
properties.load(new FileInputStream(propFile))
45+
return properties.containsKey('BACKTRACE_SUBMISSION_URL') ? properties['BACKTRACE_SUBMISSION_URL'] : "null"
46+
}
47+
3848
dependencies {
3949
implementation fileTree(include: ['*.jar'], dir: 'libs')
4050
implementation 'com.android.support:appcompat-v7:28.0.0'
4151
implementation 'com.android.support.constraint:constraint-layout:2.0.1'
4252
testImplementation 'junit:junit:4.12'
4353
androidTestImplementation 'com.android.support.test:runner:1.0.2'
54+
androidTestImplementation 'com.android.support.test:rules:1.0.2'
4455
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
4556
implementation project(':backtrace-library')
4657
}

example-app/src/androidTest/java/backtraceio/backtraceio/ExampleInstrumentedTest.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
package backtraceio.backtraceio;
22

3+
import static android.support.test.espresso.Espresso.onView;
4+
import static android.support.test.espresso.action.ViewActions.click;
5+
import static android.support.test.espresso.matcher.ViewMatchers.withId;
6+
37
import android.content.Context;
48
import android.support.test.InstrumentationRegistry;
9+
import android.support.test.espresso.PerformException;
10+
import android.support.test.rule.ActivityTestRule;
511
import android.support.test.runner.AndroidJUnit4;
612

13+
import org.junit.Before;
14+
import org.junit.Rule;
715
import org.junit.Test;
816
import org.junit.runner.RunWith;
917

@@ -16,11 +24,46 @@
1624
*/
1725
@RunWith(AndroidJUnit4.class)
1826
public class ExampleInstrumentedTest {
27+
28+
@Rule
29+
public ActivityTestRule<MainActivity> mActivityRule =
30+
new ActivityTestRule<>(MainActivity.class);
31+
32+
@Before
33+
public void enableMetricsAndBreadcrumbs() {
34+
onView(withId(R.id.enableBreadcrumbs)).perform(click());
35+
}
36+
1937
@Test
2038
public void useAppContext() {
2139
// Context of the app under test.
2240
Context appContext = InstrumentationRegistry.getTargetContext();
23-
2441
assertEquals("backtraceio.backtraceio", appContext.getPackageName());
2542
}
43+
44+
@Test
45+
public void dumpWithoutCrash() {
46+
onView(withId(R.id.dumpWithoutCrash)).perform(click());
47+
}
48+
49+
@Test(expected = PerformException.class)
50+
public void unhandledException() {
51+
onView(withId(R.id.unhandledException)).perform(click());
52+
}
53+
54+
@Test
55+
public void handledException() {
56+
onView(withId(R.id.handledException)).perform(click());
57+
}
58+
59+
@Test
60+
public void anr() {
61+
onView(withId(R.id.anr)).perform(click());
62+
}
63+
64+
// Will break build, obviously.
65+
//@Test
66+
public void nativeCrash() {
67+
onView(withId(R.id.nativeCrash)).perform(click());
68+
}
2669
}

0 commit comments

Comments
 (0)