Skip to content

test(critical): Add Mock Relay to verify crash envelope #3811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 50 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a7b38d4
Add New UI Tests App for critical tests
krystofwoldrich Oct 17, 2024
855903a
Format code
getsentry-bot Oct 17, 2024
835d432
Return proguard rules file
krystofwoldrich Oct 17, 2024
339a8d7
Add CI build and test jobs
krystofwoldrich Oct 18, 2024
4dc470d
Merge remote-tracking branch 'origin/kw/test/add-critical-ui-tests' i…
krystofwoldrich Oct 18, 2024
26ff65e
Fix maestro install and emulator boot
krystofwoldrich Oct 18, 2024
d675e3f
Fix apk install
krystofwoldrich Oct 18, 2024
8049612
fix apk name when testing
krystofwoldrich Oct 18, 2024
304f261
use maestro action
krystofwoldrich Oct 18, 2024
069f17d
fix the action name
krystofwoldrich Oct 18, 2024
7fc41c1
fix path
krystofwoldrich Oct 18, 2024
eab8424
Fix java and server tests
krystofwoldrich Oct 18, 2024
bba38d6
ref and fix server build
krystofwoldrich Oct 18, 2024
32c0ab6
fix maybe
krystofwoldrich Oct 18, 2024
9cbfacf
Update Makefile
stefanosiano Oct 21, 2024
88c7396
Update sentry-android-integration-tests/sentry-uitest-android-critica…
krystofwoldrich Oct 21, 2024
76a5eff
test(critical): Add API Level matrix
krystofwoldrich Oct 21, 2024
88f290b
fix maestro version
krystofwoldrich Oct 21, 2024
57cc5d8
Merge branch 'kw/test/add-critical-ui-tests' into kw/test/extend-crit…
krystofwoldrich Oct 21, 2024
229409c
Fix atd only runs on api level 30
krystofwoldrich Oct 21, 2024
85326e8
update 31 and newer runners
krystofwoldrich Oct 21, 2024
c332e7d
tmp: list available images
krystofwoldrich Oct 21, 2024
1e560ea
tmp: fix path
krystofwoldrich Oct 21, 2024
d4b00cb
change default arch for 31 and higher
krystofwoldrich Oct 21, 2024
0cf0a0c
tmp: remove images list
krystofwoldrich Oct 21, 2024
a99c02f
remove api level 29, the test would succeed but the runner timeout on…
krystofwoldrich Oct 22, 2024
5dda9c3
Merge branch 'main' into kw/test/extend-critical-tests-matrix
krystofwoldrich Oct 22, 2024
837a64f
test(critical): Add Mock Relay to verify crash envelope
krystofwoldrich Oct 22, 2024
d03418e
Format code
getsentry-bot Oct 22, 2024
a18acf3
Revert "Format code"
krystofwoldrich Oct 22, 2024
aa01a76
Revert "test(critical): Add Mock Relay to verify crash envelope"
krystofwoldrich Oct 22, 2024
679961e
Merge branch 'kw/test/extend-critical-tests-matrix' into kw/test/chec…
krystofwoldrich Oct 22, 2024
d9ac076
test(critical): Add Mock Relay to verify crash envelope
krystofwoldrich Oct 22, 2024
31876fe
Format code
getsentry-bot Oct 22, 2024
29d3166
fix envs
krystofwoldrich Oct 22, 2024
bb05b58
fix java runtime version
krystofwoldrich Oct 22, 2024
bfad2ba
fix kill mock relay
krystofwoldrich Oct 22, 2024
090ec5c
fix pkill
krystofwoldrich Oct 22, 2024
c055466
try different kill
krystofwoldrich Oct 22, 2024
935df7c
try kill script
krystofwoldrich Oct 22, 2024
cbe2e92
another try
krystofwoldrich Oct 22, 2024
f577ae8
try pgrep and kill
krystofwoldrich Oct 22, 2024
84a09ab
Merge remote-tracking branch 'origin/main' into kw/test/extend-critic…
krystofwoldrich Oct 24, 2024
cf86c10
Merge branch 'kw/test/extend-critical-tests-matrix' into kw/test/chec…
krystofwoldrich Oct 24, 2024
f6e5bcf
fix server exit code
krystofwoldrich Oct 24, 2024
0e20749
use graceful exit
krystofwoldrich Oct 24, 2024
e015905
respond ok to stop call
krystofwoldrich Oct 24, 2024
2ee6559
Merge branch 'main' into kw/test/check-crash-envelope
krystofwoldrich Oct 29, 2024
ede0953
Merge branch 'main' into kw/test/check-crash-envelope
krystofwoldrich Nov 21, 2024
35ac99f
Merge branch 'main' into kw/test/check-crash-envelope
krystofwoldrich Feb 11, 2025
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
32 changes: 32 additions & 0 deletions .github/workflows/integration-tests-ui-critical.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ concurrency:
cancel-in-progress: true

env:
INTEGRATION_TESTS_PATH: "sentry-android-integration-tests"
BASE_PATH: "sentry-android-integration-tests/sentry-uitest-android-critical"
BUILD_PATH: "build/outputs/apk/release"
APK_NAME: "sentry-uitest-android-critical-release.apk"
APK_ARTIFACT_NAME: "sentry-uitest-android-critical-release"
MAESTRO_VERSION: "1.39.0"
MOCK_RELAY_ARTIFACT_NAME: "sentry-mock-relay"
MOCK_RELAY_PATH: "sentry-mock-relay-0.0.1.zip"

jobs:
build:
Expand All @@ -41,6 +44,16 @@ jobs:
gradle-home-cache-cleanup: true
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

- name: Build mock relay
run: make buildMockRelay

- name: Upload Mock Relay
uses: actions/upload-artifact@v4
with:
name: ${{env.MOCK_RELAY_ARTIFACT_NAME}}
path: "${{env.INTEGRATION_TESTS_PATH}}/sentry-mock-relay/build/distributions/${{env.MOCK_RELAY_PATH}}"
retention-days: 1

- name: Build debug APK
run: make assembleUiTestCriticalRelease

Expand Down Expand Up @@ -91,11 +104,25 @@ jobs:
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Set up Java 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Download APK artifact
uses: actions/download-artifact@v4
with:
name: ${{env.APK_ARTIFACT_NAME}}

- name: Download Mock Relay
uses: actions/download-artifact@v4
with:
name: ${{env.MOCK_RELAY_ARTIFACT_NAME}}

- name: Unzip Mock Relay
run: unzip -o ${{env.MOCK_RELAY_PATH}}

- name: Install Maestro
uses: dniHze/maestro-test-action@bda8a93211c86d0a05b7a4597c5ad134566fbde4 # [email protected]
with:
Expand All @@ -122,8 +149,13 @@ jobs:
-timezone US/Pacific
script: |
adb install -r -d "${{env.APK_NAME}}"
./sentry-mock-relay-0.0.1/bin/sentry-mock-relay > /dev/null &

maestro test "${{env.BASE_PATH}}/maestro" --debug-output "${{env.BASE_PATH}}/maestro-logs"

curl --fail http://localhost:8961/assertReceivedAtLeastOneCrashReport
curl --fail http://localhost:8961/stop

- name: Upload Maestro test results
if: failure()
uses: actions/upload-artifact@v4
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/system-tests-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ jobs:
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' \
-e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' \
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-critical",/d' \
-e '/.*"sentry-android-integration-tests:sentry-mock-relay",/d' \
-e '/.*"sentry-android-integration-tests:test-app-sentry",/d' \
-e '/.*"sentry-samples:sentry-samples-android",/d' \
-e '/.*"sentry-android-replay",/d' \
Expand All @@ -85,6 +86,7 @@ jobs:
-e '/.*"sentry-uitest-android",/d' \
-e '/.*"sentry-uitest-android-benchmark",/d' \
-e '/.*"sentry-uitest-android-critical",/d' \
-e '/.*"sentry-mock-relay",/d' \
-e '/.*"test-app-sentry",/d' \
-e '/.*"sentry-samples-android",/d' \
build.gradle.kts
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: all clean compile javadocs dryRelease update stop checkFormat format api assembleBenchmarkTestRelease assembleUiTestRelease assembleUiTestCriticalRelease createCoverageReports runUiTestCritical check preMerge publish
.PHONY: all clean compile javadocs dryRelease update stop checkFormat format api assembleBenchmarkTestRelease assembleUiTestRelease assembleUiTestCriticalRelease createCoverageReports runUiTestCritical buildMockRelay check preMerge publish

all: stop clean javadocs compile createCoverageReports
assembleBenchmarks: assembleBenchmarkTestRelease
Expand Down Expand Up @@ -61,6 +61,10 @@ assembleUiTestCriticalRelease:
runUiTestCritical:
./scripts/test-ui-critical.sh

# Build the mock relay for critical tests
buildMockRelay:
./gradlew :sentry-android-integration-tests:sentry-mock-relay:build

# Create coverage reports
# - Jacoco for Java & Android modules
# - Kover for KMP modules e.g sentry-compose
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ apiValidation {
"sentry-uitest-android",
"sentry-uitest-android-benchmark",
"sentry-uitest-android-critical",
"sentry-mock-relay",
"test-app-plain",
"test-app-sentry",
"sentry-samples-netflix-dgs"
Expand Down
4 changes: 4 additions & 0 deletions buildSrc/src/main/java/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ object Config {
val javaFaker = "com.github.javafaker:javafaker:1.0.2"
val msgpack = "org.msgpack:msgpack-core:0.9.8"
val leakCanaryInstrumentation = "com.squareup.leakcanary:leakcanary-android-instrumentation:2.14"
val kotlinxSerializationJson = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1"
val pluginSerializationVersion = "1.5.0"
val logbackClassic = "ch.qos.logback:logback-classic:1.4.14"
val ktorVersion = "2.3.12"
val composeUiTestJunit4 = "androidx.compose.ui:ui-test-junit4:1.6.8"
}

Expand Down
20 changes: 20 additions & 0 deletions scripts/test-ui-critical.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ if ! command -v maestro &> /dev/null; then
exit 1
fi

echo "Building the mock relay..."
make buildMockRelay

echo "Building the UI Test Critical app..."
make assembleUiTestCriticalRelease

Expand All @@ -29,7 +32,24 @@ apkName="sentry-uitest-android-critical-release.apk"
appPath="${baseDir}/${buildDir}/${apkName}"
adb install -r -d "$appPath"

echo "Starting the mock relay..."
cd sentry-android-integration-tests/sentry-mock-relay/build/distributions
unzip -o sentry-mock-relay-0.0.1.zip
./sentry-mock-relay-0.0.1/bin/sentry-mock-relay > /dev/null & MOCK_RELAY_PID=$!
echo "Mock relay PID: $MOCK_RELAY_PID"

set +e
echo "Running the Maestro tests..."
maestro test \
"${baseDir}/maestro" \
--debug-output "${baseDir}/maestro-logs"
MAESTRO_EXIT_CODE=$?

echo "Checking mock relay results..."
curl --fail http://localhost:8961/assertReceivedAtLeastOneCrashReport
MOCK_RELAY_EXIT_CODE=$?

echo "Stopping the mock relay..."
kill $MOCK_RELAY_PID

exit $(($MAESTRO_EXIT_CODE || $MOCK_RELAY_EXIT_CODE))
36 changes: 36 additions & 0 deletions sentry-android-integration-tests/sentry-mock-relay/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

plugins {
kotlin("jvm")
id("io.ktor.plugin") version Config.TestLibs.ktorVersion
kotlin("plugin.serialization") version Config.TestLibs.pluginSerializationVersion
}

group = "io.sentry.mock-relay"
version = "0.0.1"

application {
mainClass.set("io.ktor.server.netty.EngineMain")

val isDevelopment: Boolean = project.ext.has("development")
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment")
}

repositories {
mavenCentral()
}

dependencies {
implementation(Config.TestLibs.kotlinxSerializationJson)
implementation("io.ktor:ktor-server-core-jvm")
implementation("io.ktor:ktor-server-netty-jvm")
implementation(Config.TestLibs.logbackClassic)
implementation("io.ktor:ktor-server-config-yaml")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

pkill -9 -f "sentry-mock-relay" || true
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package io.sentry

import io.ktor.server.application.Application
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.request.receiveText
import io.ktor.server.request.uri
import io.ktor.server.response.respondText
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.routing
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import java.util.zip.GZIPInputStream

fun main(args: Array<String>) {
io.ktor.server.netty.EngineMain.main(args)
}

fun Application.module() {
configureRouting()
}

fun Application.configureRouting() {
val receivedEnvelopes = mutableListOf<List<JsonElement>>()

routing {
post("/{...}") {
println("Received request: ${call.request.uri}")
val textBody: String = if (call.request.headers["Content-Encoding"] == "gzip") {
call.receive<ByteArray>().let {
GZIPInputStream(it.inputStream()).bufferedReader().use { reader ->
reader.readText()
}
}
} else {
call.receiveText()
}

val jsonItems = textBody.split('\n').mapNotNull { line ->
try {
Json.parseToJsonElement(line)
} catch (e: Exception) {
null
}
}

receivedEnvelopes.add(jsonItems)

call.respondText("{}")
}
get("/healthCheck") {
call.respondText("OK")
}
get("/assertReceivedAtLeastOneCrashReport") {
if (receivedEnvelopes.isEmpty()) {
call.respondText("Mocked Replay have not received any envelopes\n", status = io.ktor.http.HttpStatusCode.BadRequest)
}

val hasCrashReport = receivedEnvelopes.any { envelope ->
envelope.any { item ->
try {
if (item.jsonObject.containsKey("exception")) {
val exception = item.jsonObject["exception"]?.jsonObject
val values = exception?.get("values")?.jsonArray
values?.any { value ->
val message = value.jsonObject["value"]?.jsonPrimitive?.content
message == "Crash the test app."
} ?: false
} else {
false
}
} catch (e: Exception) {
false
}
}
}

if (hasCrashReport) {
call.respondText("Received at least one crash report\n")
} else {
call.respondText("No crash report received\n", status = io.ktor.http.HttpStatusCode.BadRequest)
}
}
get("/stop") {
call.respondText("OK")

launch {
delay(1000)
Runtime.getRuntime().halt(0)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ktor:
application:
modules:
- io.sentry.ApplicationKt.module
deployment:
port: 8961
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="INFO"/>
<logger name="io.netty" level="INFO"/>
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ android {

dependencies {
implementation(kotlin(Config.kotlinStdLib, org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION))
implementation(Config.Libs.okhttp)
implementation(Config.TestLibs.mockWebserver)
implementation(Config.Libs.androidxCore)
implementation(Config.Libs.composeActivity)
implementation(Config.Libs.composeFoundation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
<application
android:label="Sentry UI Tests Critical"
android:supportsRtl="true"
tools:targetApi="31">
<meta-data android:name="io.sentry.dsn" android:value="https://[email protected]/5428559" />
tools:targetApi="31"
android:networkSecurityConfig="@xml/network"
>
<meta-data android:name="io.sentry.dsn" android:value="http://[email protected]:8961/dsn" />
<meta-data android:name="io.sentry.debug" android:value="true" />
<activity
android:name=".MainActivity"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<!-- Allow cleartext traffic from the emulator to the host machine -->
<!-- See https://developer.android.com/studio/run/emulator-networking for more details -->
<domain includeSubdomains="true">10.0.2.2</domain>
</domain-config>
</network-security-config>
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ include(
"sentry-samples:sentry-samples-spring-boot-webflux-jakarta",
"sentry-samples:sentry-samples-netflix-dgs",
"sentry-android-integration-tests:sentry-uitest-android-critical",
"sentry-android-integration-tests:sentry-mock-relay",
"sentry-android-integration-tests:sentry-uitest-android-benchmark",
"sentry-android-integration-tests:sentry-uitest-android",
"sentry-android-integration-tests:test-app-plain",
Expand Down
Loading