From 44fa74b7a526e0a13c82cd5c23a8f6b774ccbe05 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 09:21:59 +0200 Subject: [PATCH 01/10] Revert "test(ui): Add critical tests run by Maestro (#3802)" This reverts commit 4988d5bf9e0a5be708853cf53d07b8503e4c77be. --- .../integration-tests-ui-critical.yml | 106 ------------------ .github/workflows/system-tests-backend.yml | 33 +----- Makefile | 10 +- build.gradle.kts | 1 - scripts/test-ui-critical.sh | 35 ------ .../sentry-uitest-android-critical/.gitignore | 2 - .../build.gradle.kts | 69 ------------ .../maestro/corruptEnvelope.yaml | 11 -- .../maestro/crash.yaml | 6 - .../proguard-rules.pro | 21 ---- .../src/main/AndroidManifest.xml | 21 ---- .../uitest/android/critical/MainActivity.kt | 51 --------- settings.gradle.kts | 1 - 13 files changed, 4 insertions(+), 363 deletions(-) delete mode 100644 .github/workflows/integration-tests-ui-critical.yml delete mode 100755 scripts/test-ui-critical.sh delete mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/.gitignore delete mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts delete mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/maestro/corruptEnvelope.yaml delete mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/maestro/crash.yaml delete mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/proguard-rules.pro delete mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/src/main/AndroidManifest.xml delete mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/src/main/java/io/sentry/uitest/android/critical/MainActivity.kt diff --git a/.github/workflows/integration-tests-ui-critical.yml b/.github/workflows/integration-tests-ui-critical.yml deleted file mode 100644 index 6729e40ca5..0000000000 --- a/.github/workflows/integration-tests-ui-critical.yml +++ /dev/null @@ -1,106 +0,0 @@ -name: UI Tests Critical - -on: - push: - branches: - - main - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - 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" - -jobs: - build: - name: Build sentry-uitest-android-critical - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Java 17 - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@bb0c460cbf5354b0cddd15bacdf0d6aaa3e5a32b # pin@v3 - with: - gradle-home-cache-cleanup: true - - - name: Build debug APK - run: make assembleUiTestCriticalRelease - - - name: Upload APK artifact - uses: actions/upload-artifact@v4 - with: - name: ${{env.APK_ARTIFACT_NAME}} - path: "${{env.BASE_PATH}}/${{env.BUILD_PATH}}/${{env.APK_NAME}}" - retention-days: 1 - - run-maestro-tests: - name: Run Maestro Tests - needs: build - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup KVM - shell: bash - run: | - # check if virtualization is supported... - sudo apt install -y --no-install-recommends cpu-checker coreutils && echo "CPUs=$(nproc --all)" && kvm-ok - # allow access to KVM to run the emulator - echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \ - | sudo tee /etc/udev/rules.d/99-kvm4all.rules - sudo udevadm control --reload-rules - sudo udevadm trigger --name-match=kvm - - - name: Download APK artifact - uses: actions/download-artifact@v4 - with: - name: ${{env.APK_ARTIFACT_NAME}} - - - name: Install Maestro - uses: dniHze/maestro-test-action@bda8a93211c86d0a05b7a4597c5ad134566fbde4 # pin@v1.0.0 - with: - version: ${{env.MAESTRO_VERSION}} - - - name: Run tests - uses: reactivecircus/android-emulator-runner@f0d1ed2dcad93c7479e8b2f2226c83af54494915 # pin@v2.32.0 - with: - api-level: 30 - force-avd-creation: false - disable-animations: true - disable-spellchecker: true - target: 'aosp_atd' - channel: canary # Necessary for ATDs - emulator-options: > - -no-window - -no-snapshot-save - -gpu swiftshader_indirect - -noaudio - -no-boot-anim - -camera-back none - -camera-front none - -timezone US/Pacific - script: | - adb install -r -d "${{env.APK_NAME}}" - maestro test "${{env.BASE_PATH}}/maestro" --debug-output "${{env.BASE_PATH}}/maestro-logs" - - - name: Upload Maestro test results - if: failure() - uses: actions/upload-artifact@v4 - with: - name: maestro-logs - path: "${{env.BASE_PATH}}/maestro-logs" - retention-days: 1 diff --git a/.github/workflows/system-tests-backend.yml b/.github/workflows/system-tests-backend.yml index 2222f910ad..0098644d97 100644 --- a/.github/workflows/system-tests-backend.yml +++ b/.github/workflows/system-tests-backend.yml @@ -46,33 +46,11 @@ jobs: - name: Exclude android modules from build run: | - sed -i \ - -e '/.*"sentry-android-ndk",/d' \ - -e '/.*"sentry-android",/d' \ - -e '/.*"sentry-compose",/d' \ - -e '/.*"sentry-android-core",/d' \ - -e '/.*"sentry-android-fragment",/d' \ - -e '/.*"sentry-android-navigation",/d' \ - -e '/.*"sentry-android-okhttp",/d' \ - -e '/.*"sentry-android-sqlite",/d' \ - -e '/.*"sentry-android-timber",/d' \ - -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:test-app-sentry",/d' \ - -e '/.*"sentry-samples:sentry-samples-android",/d' \ - -e '/.*"sentry-android-replay",/d' \ - settings.gradle.kts + sed -i -e '/.*"sentry-android-ndk",/d' -e '/.*"sentry-android",/d' -e '/.*"sentry-compose",/d' -e '/.*"sentry-android-core",/d' -e '/.*"sentry-android-fragment",/d' -e '/.*"sentry-android-navigation",/d' -e '/.*"sentry-android-okhttp",/d' -e '/.*"sentry-android-sqlite",/d' -e '/.*"sentry-android-timber",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' -e '/.*"sentry-android-integration-tests:test-app-sentry",/d' -e '/.*"sentry-samples:sentry-samples-android",/d' -e '/.*"sentry-android-replay",/d' settings.gradle.kts - name: Exclude android modules from ignore list run: | - sed -i \ - -e '/.*"sentry-uitest-android",/d' \ - -e '/.*"sentry-uitest-android-benchmark",/d' \ - -e '/.*"sentry-uitest-android-critical",/d' \ - -e '/.*"test-app-sentry",/d' \ - -e '/.*"sentry-samples-android",/d' \ - build.gradle.kts + sed -i -e '/.*"sentry-uitest-android",/d' -e '/.*"sentry-uitest-android-benchmark",/d' -e '/.*"test-app-sentry",/d' -e '/.*"sentry-samples-android",/d' build.gradle.kts - name: Build server jar run: | @@ -80,12 +58,7 @@ jobs: - name: Start server and run integration test for sentry-cli commands run: | - test/system-test-sentry-server-start.sh \ - > sentry-mock-server.txt 2>&1 & \ - test/system-test-spring-server-start.sh "${{ matrix.sample }}" \ - > spring-server.txt 2>&1 & \ - test/wait-for-spring.sh && \ - ./gradlew :sentry-samples:${{ matrix.sample }}:systemTest + test/system-test-sentry-server-start.sh > sentry-mock-server.txt 2>&1 & test/system-test-spring-server-start.sh "${{ matrix.sample }}" > spring-server.txt 2>&1 & test/wait-for-spring.sh && ./gradlew :sentry-samples:${{ matrix.sample }}:systemTest - name: Upload test results if: always() diff --git a/Makefile b/Makefile index 62e6e258f3..2117e6da21 100644 --- a/Makefile +++ b/Makefile @@ -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 createCoverageReports check preMerge publish all: stop clean javadocs compile createCoverageReports assembleBenchmarks: assembleBenchmarkTestRelease @@ -53,14 +53,6 @@ assembleUiTestRelease: ./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleRelease ./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleAndroidTest -DtestBuildType=release -# Assemble release of the uitest-android-critical module -assembleUiTestCriticalRelease: - ./gradlew :sentry-android-integration-tests:sentry-uitest-android-critical:assembleRelease - -# Run Maestro tests for the uitest-android-critical module -runUiTestCritical: - ./scripts/test-ui-critical.sh - # Create coverage reports # - Jacoco for Java & Android modules # - Kover for KMP modules e.g sentry-compose diff --git a/build.gradle.kts b/build.gradle.kts index 9d53252562..7985a55486 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -68,7 +68,6 @@ apiValidation { "sentry-samples-spring-boot-webflux-jakarta", "sentry-uitest-android", "sentry-uitest-android-benchmark", - "sentry-uitest-android-critical", "test-app-plain", "test-app-sentry", "sentry-samples-netflix-dgs" diff --git a/scripts/test-ui-critical.sh b/scripts/test-ui-critical.sh deleted file mode 100755 index 7bb36eebec..0000000000 --- a/scripts/test-ui-critical.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -set -e - -echo "Checking if ADB is installed..." -if ! command -v adb &> /dev/null; then - echo "ADB is not installed or not in PATH. Please install Android SDK platform tools and ensure ADB is in your PATH." - exit 1 -fi - -echo "Checking if an Android emulator is running..." -if ! adb devices | grep -q "emulator"; then - echo "No Android emulator is currently running. Please start an emulator before running this script." - exit 1 -fi - -echo "Checking if Maestro is installed..." -if ! command -v maestro &> /dev/null; then - echo "Maestro is not installed. Please install Maestro before running this script." - exit 1 -fi - -echo "Building the UI Test Critical app..." -make assembleUiTestCriticalRelease - -echo "Installing the UI Test Critical app on the emulator..." -baseDir="sentry-android-integration-tests/sentry-uitest-android-critical" -buildDir="build/outputs/apk/release" -apkName="sentry-uitest-android-critical-release.apk" -appPath="${baseDir}/${buildDir}/${apkName}" -adb install -r -d "$appPath" - -echo "Running the Maestro tests..." -maestro test \ - "${baseDir}/maestro" \ - --debug-output "${baseDir}/maestro-logs" diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/.gitignore b/sentry-android-integration-tests/sentry-uitest-android-critical/.gitignore deleted file mode 100644 index 48fc28dcf5..0000000000 --- a/sentry-android-integration-tests/sentry-uitest-android-critical/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/build -/maestro-logs diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts deleted file mode 100644 index cebf744a24..0000000000 --- a/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts +++ /dev/null @@ -1,69 +0,0 @@ -import io.gitlab.arturbosch.detekt.Detekt - -plugins { - id("com.android.application") - kotlin("android") -} - -android { - compileSdk = Config.Android.compileSdkVersion - namespace = "io.sentry.uitest.android.critical" - - signingConfigs { - getByName("debug") { - // Debug config remains unchanged - } - } - - defaultConfig { - applicationId = "io.sentry.uitest.android.critical" - minSdk = Config.Android.minSdkVersionCompose - targetSdk = Config.Android.targetSdkVersion - versionCode = 1 - versionName = "1.0" - } - - buildTypes { - release { - isMinifyEnabled = false - signingConfig = signingConfigs.getByName("debug") - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8.toString() - } - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = Config.androidComposeCompilerVersion - } - variantFilter { - if (Config.Android.shouldSkipDebugVariant(buildType.name)) { - ignore = true - } - } -} - -dependencies { - implementation(kotlin(Config.kotlinStdLib, org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)) - implementation(Config.Libs.androidxCore) - implementation(Config.Libs.composeActivity) - implementation(Config.Libs.composeFoundation) - implementation(Config.Libs.composeMaterial) - implementation(Config.Libs.constraintLayout) - implementation(projects.sentryAndroidCore) -} - -tasks.withType { - // Target version of the generated JVM bytecode. It is used for type resolution. - jvmTarget = JavaVersion.VERSION_1_8.toString() -} - -kotlin { - explicitApi() -} diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/corruptEnvelope.yaml b/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/corruptEnvelope.yaml deleted file mode 100644 index dec889731b..0000000000 --- a/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/corruptEnvelope.yaml +++ /dev/null @@ -1,11 +0,0 @@ -appId: io.sentry.uitest.android.critical ---- -- launchApp -- tapOn: "Write Corrupted Envelope" -# The close here ensures the next corrupted envelope -# will be present on the next app launch -- tapOn: "Close SDK" -- tapOn: "Write Corrupted Envelope" -- stopApp -- launchApp -- assertVisible: "Welcome!" diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/crash.yaml b/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/crash.yaml deleted file mode 100644 index f9543f365c..0000000000 --- a/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/crash.yaml +++ /dev/null @@ -1,6 +0,0 @@ -appId: io.sentry.uitest.android.critical ---- -- launchApp -- tapOn: "Crash" -- launchApp -- assertVisible: "Welcome!" diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/proguard-rules.pro b/sentry-android-integration-tests/sentry-uitest-android-critical/proguard-rules.pro deleted file mode 100644 index f1b424510d..0000000000 --- a/sentry-android-integration-tests/sentry-uitest-android-critical/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/AndroidManifest.xml b/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/AndroidManifest.xml deleted file mode 100644 index 0ab5e6052d..0000000000 --- a/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/AndroidManifest.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/java/io/sentry/uitest/android/critical/MainActivity.kt b/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/java/io/sentry/uitest/android/critical/MainActivity.kt deleted file mode 100644 index 8802f3dca2..0000000000 --- a/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/java/io/sentry/uitest/android/critical/MainActivity.kt +++ /dev/null @@ -1,51 +0,0 @@ -package io.sentry.uitest.android.critical - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Column -import androidx.compose.material3.Button -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import io.sentry.Sentry -import java.io.File - -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val outboxPath = Sentry.getCurrentHub().options.outboxPath - ?: throw RuntimeException("Outbox path is not set.") - - setContent { - MaterialTheme { - Surface() { - Column() { - Text(text = "Welcome!") - Button(onClick = { - throw RuntimeException("Crash the test app.") - }) { - Text("Crash") - } - Button(onClick = { - Sentry.close() - }) { - Text("Close SDK") - } - Button(onClick = { - val file = File(outboxPath, "corrupted.envelope") - val corruptedEnvelopeContent = """ - {"event_id":"1990b5bc31904b7395fd07feb72daf1c","sdk":{"name":"sentry.java.android","version":"7.21.0"}} - {"type":"test","length":50} - """.trimIndent() - file.writeText(corruptedEnvelopeContent) - println("Wrote corrupted envelope to: ${file.absolutePath}") - }) { - Text("Write Corrupted Envelope") - } - } - } - } - } - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 77b3be021d..760c6e6905 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -61,7 +61,6 @@ include( "sentry-samples:sentry-samples-spring-boot-webflux", "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-uitest-android-benchmark", "sentry-android-integration-tests:sentry-uitest-android", "sentry-android-integration-tests:test-app-plain", From 47b7f6cbe7bd5d1ed03d220164161e7f0634805b Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 09:47:26 +0200 Subject: [PATCH 02/10] test(ui): Re-Add critical tests run by Maestro --- .../integration-tests-ui-critical.yml | 106 ++++++++++++++++++ .github/workflows/system-tests-backend.yml | 33 +++++- Makefile | 10 +- build.gradle.kts | 1 + scripts/test-ui-critical.sh | 35 ++++++ .../sentry-uitest-android-critical/.gitignore | 2 + .../build.gradle.kts | 69 ++++++++++++ .../maestro/corruptEnvelope.yaml | 11 ++ .../maestro/crash.yaml | 6 + .../proguard-rules.pro | 21 ++++ .../src/main/AndroidManifest.xml | 21 ++++ .../uitest/android/critical/MainActivity.kt | 51 +++++++++ settings.gradle.kts | 1 + 13 files changed, 363 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/integration-tests-ui-critical.yml create mode 100755 scripts/test-ui-critical.sh create mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/.gitignore create mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts create mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/maestro/corruptEnvelope.yaml create mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/maestro/crash.yaml create mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/proguard-rules.pro create mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/src/main/AndroidManifest.xml create mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/src/main/java/io/sentry/uitest/android/critical/MainActivity.kt diff --git a/.github/workflows/integration-tests-ui-critical.yml b/.github/workflows/integration-tests-ui-critical.yml new file mode 100644 index 0000000000..6729e40ca5 --- /dev/null +++ b/.github/workflows/integration-tests-ui-critical.yml @@ -0,0 +1,106 @@ +name: UI Tests Critical + +on: + push: + branches: + - main + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + 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" + +jobs: + build: + name: Build sentry-uitest-android-critical + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Java 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@bb0c460cbf5354b0cddd15bacdf0d6aaa3e5a32b # pin@v3 + with: + gradle-home-cache-cleanup: true + + - name: Build debug APK + run: make assembleUiTestCriticalRelease + + - name: Upload APK artifact + uses: actions/upload-artifact@v4 + with: + name: ${{env.APK_ARTIFACT_NAME}} + path: "${{env.BASE_PATH}}/${{env.BUILD_PATH}}/${{env.APK_NAME}}" + retention-days: 1 + + run-maestro-tests: + name: Run Maestro Tests + needs: build + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup KVM + shell: bash + run: | + # check if virtualization is supported... + sudo apt install -y --no-install-recommends cpu-checker coreutils && echo "CPUs=$(nproc --all)" && kvm-ok + # allow access to KVM to run the emulator + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \ + | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Download APK artifact + uses: actions/download-artifact@v4 + with: + name: ${{env.APK_ARTIFACT_NAME}} + + - name: Install Maestro + uses: dniHze/maestro-test-action@bda8a93211c86d0a05b7a4597c5ad134566fbde4 # pin@v1.0.0 + with: + version: ${{env.MAESTRO_VERSION}} + + - name: Run tests + uses: reactivecircus/android-emulator-runner@f0d1ed2dcad93c7479e8b2f2226c83af54494915 # pin@v2.32.0 + with: + api-level: 30 + force-avd-creation: false + disable-animations: true + disable-spellchecker: true + target: 'aosp_atd' + channel: canary # Necessary for ATDs + emulator-options: > + -no-window + -no-snapshot-save + -gpu swiftshader_indirect + -noaudio + -no-boot-anim + -camera-back none + -camera-front none + -timezone US/Pacific + script: | + adb install -r -d "${{env.APK_NAME}}" + maestro test "${{env.BASE_PATH}}/maestro" --debug-output "${{env.BASE_PATH}}/maestro-logs" + + - name: Upload Maestro test results + if: failure() + uses: actions/upload-artifact@v4 + with: + name: maestro-logs + path: "${{env.BASE_PATH}}/maestro-logs" + retention-days: 1 diff --git a/.github/workflows/system-tests-backend.yml b/.github/workflows/system-tests-backend.yml index 0098644d97..2222f910ad 100644 --- a/.github/workflows/system-tests-backend.yml +++ b/.github/workflows/system-tests-backend.yml @@ -46,11 +46,33 @@ jobs: - name: Exclude android modules from build run: | - sed -i -e '/.*"sentry-android-ndk",/d' -e '/.*"sentry-android",/d' -e '/.*"sentry-compose",/d' -e '/.*"sentry-android-core",/d' -e '/.*"sentry-android-fragment",/d' -e '/.*"sentry-android-navigation",/d' -e '/.*"sentry-android-okhttp",/d' -e '/.*"sentry-android-sqlite",/d' -e '/.*"sentry-android-timber",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' -e '/.*"sentry-android-integration-tests:test-app-sentry",/d' -e '/.*"sentry-samples:sentry-samples-android",/d' -e '/.*"sentry-android-replay",/d' settings.gradle.kts + sed -i \ + -e '/.*"sentry-android-ndk",/d' \ + -e '/.*"sentry-android",/d' \ + -e '/.*"sentry-compose",/d' \ + -e '/.*"sentry-android-core",/d' \ + -e '/.*"sentry-android-fragment",/d' \ + -e '/.*"sentry-android-navigation",/d' \ + -e '/.*"sentry-android-okhttp",/d' \ + -e '/.*"sentry-android-sqlite",/d' \ + -e '/.*"sentry-android-timber",/d' \ + -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:test-app-sentry",/d' \ + -e '/.*"sentry-samples:sentry-samples-android",/d' \ + -e '/.*"sentry-android-replay",/d' \ + settings.gradle.kts - name: Exclude android modules from ignore list run: | - sed -i -e '/.*"sentry-uitest-android",/d' -e '/.*"sentry-uitest-android-benchmark",/d' -e '/.*"test-app-sentry",/d' -e '/.*"sentry-samples-android",/d' build.gradle.kts + sed -i \ + -e '/.*"sentry-uitest-android",/d' \ + -e '/.*"sentry-uitest-android-benchmark",/d' \ + -e '/.*"sentry-uitest-android-critical",/d' \ + -e '/.*"test-app-sentry",/d' \ + -e '/.*"sentry-samples-android",/d' \ + build.gradle.kts - name: Build server jar run: | @@ -58,7 +80,12 @@ jobs: - name: Start server and run integration test for sentry-cli commands run: | - test/system-test-sentry-server-start.sh > sentry-mock-server.txt 2>&1 & test/system-test-spring-server-start.sh "${{ matrix.sample }}" > spring-server.txt 2>&1 & test/wait-for-spring.sh && ./gradlew :sentry-samples:${{ matrix.sample }}:systemTest + test/system-test-sentry-server-start.sh \ + > sentry-mock-server.txt 2>&1 & \ + test/system-test-spring-server-start.sh "${{ matrix.sample }}" \ + > spring-server.txt 2>&1 & \ + test/wait-for-spring.sh && \ + ./gradlew :sentry-samples:${{ matrix.sample }}:systemTest - name: Upload test results if: always() diff --git a/Makefile b/Makefile index 2117e6da21..62e6e258f3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all clean compile javadocs dryRelease update stop checkFormat format api assembleBenchmarkTestRelease assembleUiTestRelease createCoverageReports check preMerge publish +.PHONY: all clean compile javadocs dryRelease update stop checkFormat format api assembleBenchmarkTestRelease assembleUiTestRelease assembleUiTestCriticalRelease createCoverageReports runUiTestCritical check preMerge publish all: stop clean javadocs compile createCoverageReports assembleBenchmarks: assembleBenchmarkTestRelease @@ -53,6 +53,14 @@ assembleUiTestRelease: ./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleRelease ./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleAndroidTest -DtestBuildType=release +# Assemble release of the uitest-android-critical module +assembleUiTestCriticalRelease: + ./gradlew :sentry-android-integration-tests:sentry-uitest-android-critical:assembleRelease + +# Run Maestro tests for the uitest-android-critical module +runUiTestCritical: + ./scripts/test-ui-critical.sh + # Create coverage reports # - Jacoco for Java & Android modules # - Kover for KMP modules e.g sentry-compose diff --git a/build.gradle.kts b/build.gradle.kts index 7985a55486..9d53252562 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -68,6 +68,7 @@ apiValidation { "sentry-samples-spring-boot-webflux-jakarta", "sentry-uitest-android", "sentry-uitest-android-benchmark", + "sentry-uitest-android-critical", "test-app-plain", "test-app-sentry", "sentry-samples-netflix-dgs" diff --git a/scripts/test-ui-critical.sh b/scripts/test-ui-critical.sh new file mode 100755 index 0000000000..7bb36eebec --- /dev/null +++ b/scripts/test-ui-critical.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -e + +echo "Checking if ADB is installed..." +if ! command -v adb &> /dev/null; then + echo "ADB is not installed or not in PATH. Please install Android SDK platform tools and ensure ADB is in your PATH." + exit 1 +fi + +echo "Checking if an Android emulator is running..." +if ! adb devices | grep -q "emulator"; then + echo "No Android emulator is currently running. Please start an emulator before running this script." + exit 1 +fi + +echo "Checking if Maestro is installed..." +if ! command -v maestro &> /dev/null; then + echo "Maestro is not installed. Please install Maestro before running this script." + exit 1 +fi + +echo "Building the UI Test Critical app..." +make assembleUiTestCriticalRelease + +echo "Installing the UI Test Critical app on the emulator..." +baseDir="sentry-android-integration-tests/sentry-uitest-android-critical" +buildDir="build/outputs/apk/release" +apkName="sentry-uitest-android-critical-release.apk" +appPath="${baseDir}/${buildDir}/${apkName}" +adb install -r -d "$appPath" + +echo "Running the Maestro tests..." +maestro test \ + "${baseDir}/maestro" \ + --debug-output "${baseDir}/maestro-logs" diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/.gitignore b/sentry-android-integration-tests/sentry-uitest-android-critical/.gitignore new file mode 100644 index 0000000000..48fc28dcf5 --- /dev/null +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/.gitignore @@ -0,0 +1,2 @@ +/build +/maestro-logs diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts new file mode 100644 index 0000000000..cebf744a24 --- /dev/null +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts @@ -0,0 +1,69 @@ +import io.gitlab.arturbosch.detekt.Detekt + +plugins { + id("com.android.application") + kotlin("android") +} + +android { + compileSdk = Config.Android.compileSdkVersion + namespace = "io.sentry.uitest.android.critical" + + signingConfigs { + getByName("debug") { + // Debug config remains unchanged + } + } + + defaultConfig { + applicationId = "io.sentry.uitest.android.critical" + minSdk = Config.Android.minSdkVersionCompose + targetSdk = Config.Android.targetSdkVersion + versionCode = 1 + versionName = "1.0" + } + + buildTypes { + release { + isMinifyEnabled = false + signingConfig = signingConfigs.getByName("debug") + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8.toString() + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = Config.androidComposeCompilerVersion + } + variantFilter { + if (Config.Android.shouldSkipDebugVariant(buildType.name)) { + ignore = true + } + } +} + +dependencies { + implementation(kotlin(Config.kotlinStdLib, org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)) + implementation(Config.Libs.androidxCore) + implementation(Config.Libs.composeActivity) + implementation(Config.Libs.composeFoundation) + implementation(Config.Libs.composeMaterial) + implementation(Config.Libs.constraintLayout) + implementation(projects.sentryAndroidCore) +} + +tasks.withType { + // Target version of the generated JVM bytecode. It is used for type resolution. + jvmTarget = JavaVersion.VERSION_1_8.toString() +} + +kotlin { + explicitApi() +} diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/corruptEnvelope.yaml b/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/corruptEnvelope.yaml new file mode 100644 index 0000000000..dec889731b --- /dev/null +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/corruptEnvelope.yaml @@ -0,0 +1,11 @@ +appId: io.sentry.uitest.android.critical +--- +- launchApp +- tapOn: "Write Corrupted Envelope" +# The close here ensures the next corrupted envelope +# will be present on the next app launch +- tapOn: "Close SDK" +- tapOn: "Write Corrupted Envelope" +- stopApp +- launchApp +- assertVisible: "Welcome!" diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/crash.yaml b/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/crash.yaml new file mode 100644 index 0000000000..f9543f365c --- /dev/null +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/maestro/crash.yaml @@ -0,0 +1,6 @@ +appId: io.sentry.uitest.android.critical +--- +- launchApp +- tapOn: "Crash" +- launchApp +- assertVisible: "Welcome!" diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/proguard-rules.pro b/sentry-android-integration-tests/sentry-uitest-android-critical/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/AndroidManifest.xml b/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..0ab5e6052d --- /dev/null +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/java/io/sentry/uitest/android/critical/MainActivity.kt b/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/java/io/sentry/uitest/android/critical/MainActivity.kt new file mode 100644 index 0000000000..8802f3dca2 --- /dev/null +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/src/main/java/io/sentry/uitest/android/critical/MainActivity.kt @@ -0,0 +1,51 @@ +package io.sentry.uitest.android.critical + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import io.sentry.Sentry +import java.io.File + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val outboxPath = Sentry.getCurrentHub().options.outboxPath + ?: throw RuntimeException("Outbox path is not set.") + + setContent { + MaterialTheme { + Surface() { + Column() { + Text(text = "Welcome!") + Button(onClick = { + throw RuntimeException("Crash the test app.") + }) { + Text("Crash") + } + Button(onClick = { + Sentry.close() + }) { + Text("Close SDK") + } + Button(onClick = { + val file = File(outboxPath, "corrupted.envelope") + val corruptedEnvelopeContent = """ + {"event_id":"1990b5bc31904b7395fd07feb72daf1c","sdk":{"name":"sentry.java.android","version":"7.21.0"}} + {"type":"test","length":50} + """.trimIndent() + file.writeText(corruptedEnvelopeContent) + println("Wrote corrupted envelope to: ${file.absolutePath}") + }) { + Text("Write Corrupted Envelope") + } + } + } + } + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 760c6e6905..77b3be021d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -61,6 +61,7 @@ include( "sentry-samples:sentry-samples-spring-boot-webflux", "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-uitest-android-benchmark", "sentry-android-integration-tests:sentry-uitest-android", "sentry-android-integration-tests:test-app-plain", From 8f17ffeeda53637c7953b8cb171f1d13eb2e32b0 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 10:54:27 +0200 Subject: [PATCH 03/10] use new gc --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 73dc376308..23643cf722 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Daemons heap size -org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC +org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC org.gradle.caching=true org.gradle.parallel=true From 63fbb87a9c84b81952aeb7286e754c5b699d45c2 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 10:59:16 +0200 Subject: [PATCH 04/10] remove UseConcMarkSweepGC --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 23643cf722..b05dab76d1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Daemons heap size -org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC +org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParNewGC org.gradle.caching=true org.gradle.parallel=true From 1dc9ea7fe824084f2436894291f1d0830ee961b7 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 11:12:23 +0200 Subject: [PATCH 05/10] UseG1GC --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index b05dab76d1..e084fd1978 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Daemons heap size -org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParNewGC +org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseG1GC org.gradle.caching=true org.gradle.parallel=true From 7cac0954062096e9c8726dffe1898a35fea4e629 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 11:19:45 +0200 Subject: [PATCH 06/10] return parallel gc and limit workers to 4 --- gradle.properties | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e084fd1978..d6bfa9101d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,11 @@ # Daemons heap size -org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseG1GC +org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC org.gradle.caching=true org.gradle.parallel=true +# Daemons workers +org.gradle.workers.max=4 + # AndroidX required by AGP >= 3.6.x android.useAndroidX=true From c429881cb0d64f948034037952e89e8f3e685f39 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 11:43:33 +0200 Subject: [PATCH 07/10] remove workers limit, add swap space 10g --- .github/workflows/build.yml | 5 +++++ gradle.properties | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b885942e9..bd92d1b528 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,6 +20,11 @@ jobs: with: submodules: 'recursive' + - name: Set Swap Space + uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # pin@v1 + with: + swap-size-gb: 10 + - name: Setup Java Version uses: actions/setup-java@v4 with: diff --git a/gradle.properties b/gradle.properties index d6bfa9101d..73dc376308 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,9 +3,6 @@ org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError org.gradle.caching=true org.gradle.parallel=true -# Daemons workers -org.gradle.workers.max=4 - # AndroidX required by AGP >= 3.6.x android.useAndroidX=true From a91e8977cbe258f867ed39d7c174980ac6fb40e3 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 11:58:45 +0200 Subject: [PATCH 08/10] revert swap, try large runner --- .github/workflows/build.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bd92d1b528..7d282084da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ concurrency: jobs: build: name: Build Job ubuntu-latest - Java 17 - runs-on: ubuntu-latest + runs-on: ubuntu-latest-4-cores steps: - name: Checkout Repo @@ -20,11 +20,6 @@ jobs: with: submodules: 'recursive' - - name: Set Swap Space - uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # pin@v1 - with: - swap-size-gb: 10 - - name: Setup Java Version uses: actions/setup-java@v4 with: From 5add1daa963000c881890d591118010f9129b33e Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 12:07:17 +0200 Subject: [PATCH 09/10] revert runner, 4-cores does not exist --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7d282084da..6b885942e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ concurrency: jobs: build: name: Build Job ubuntu-latest - Java 17 - runs-on: ubuntu-latest-4-cores + runs-on: ubuntu-latest steps: - name: Checkout Repo From 4767848dca7ee663c117cfda02976657f7cb1699 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 23 Oct 2024 12:07:56 +0200 Subject: [PATCH 10/10] try only two workers --- gradle.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gradle.properties b/gradle.properties index 73dc376308..b333f4b906 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,9 @@ org.gradle.jvmargs=-Xmx12g -XX:MaxMetaspaceSize=4g -XX:+CrashOnOutOfMemoryError org.gradle.caching=true org.gradle.parallel=true +# Daemons workers +org.gradle.workers.max=2 + # AndroidX required by AGP >= 3.6.x android.useAndroidX=true