Skip to content
Merged
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
40 changes: 38 additions & 2 deletions build-tools/automation/yaml-templates/apk-instrumentation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ parameters:
steps:
# Build and install the APK to the device first, so that ComputeRunArguments
# can resolve the package name from AndroidManifest.xml.
#
# Retry the install up to 3 times: the emulator/ADB connection occasionally
# drops mid-install (XAGCPU7000 "device offline") and a retry usually recovers.
# If every attempt fails, continueOnError: false fails the lane immediately -
# there is no point running the tests against a device where the app was never
# installed (that only wastes CI time and produces a misleading
# INSTRUMENTATION_FAILED). See dotnet/android#11830.
- template: /build-tools/automation/yaml-templates/run-dotnet-preview.yaml
parameters:
configuration: ${{ parameters.buildConfiguration }}
Expand All @@ -24,7 +31,30 @@ steps:
-bl:${{ parameters.xaSourcePath }}/bin/Test${{ parameters.configuration }}/build-${{ parameters.testName }}.binlog
-c ${{ parameters.configuration }} ${{ parameters.extraBuildArgs }}
condition: ${{ parameters.condition }}
continueOnError: true
retryCountOnTaskFailure: 3
continueOnError: false

# If the install above failed, snapshot device state so we can classify WHY on
# the next iteration instead of guessing: connectivity (adb devices/get-state),
# disk pressure (df), storage-service readiness (the StorageStatsManager NPE
# from install-create), boot completion, and how many test apps have piled up.
# Best-effort and time-bounded so it never hangs or fails the lane itself.
- script: |
set +e
echo "===== adb devices -l ====="; adb devices -l
echo "===== adb get-state ====="; adb get-state
echo "===== boot completion ====="; adb shell getprop sys.boot_completed; adb shell getprop dev.bootcomplete
echo "===== df /data ====="; adb shell df /data
echo "===== df /storage/emulated/0 ====="; adb shell df /storage/emulated/0
echo "===== dumpsys diskstats ====="; adb shell dumpsys diskstats
echo "===== storaged (storage stats service) ====="; adb shell dumpsys storaged
echo "===== installed 3rd-party packages ====="; adb shell pm list packages -3
echo "===== end device state ====="
exit 0
displayName: diagnose install failure ${{ parameters.testName }}
condition: failed()
continueOnError: true
timeoutInMinutes: 3

# Run dotnet test from the project directory so it finds the project-local
# global.json with "test": { "runner": "Microsoft.Testing.Platform" }.
Expand Down Expand Up @@ -63,13 +93,19 @@ steps:
# failures, JNI crashes, instrumentation errors, etc. The Android-side
# instrumentation output (Log.Info/Log.Error from TestInstrumentation) and
# any UnsatisfiedLinkError / dlopen messages only appear in logcat.
#
# Use always() (not the default succeeded()) so we still capture logcat when an
# earlier step failed or the job was canceled - in particular a failed -t:Install
# (which now fails the lane fast) or a hung/timed-out test run. Losing logcat in
# exactly those cases would defeat the diagnostics this template exists for; the
# capture is best-effort (continueOnError + '|| echo'). See dotnet/android#11830.
- script: >
DEST="$(Build.StagingDirectory)/Test${{ parameters.configuration }}/${{ parameters.artifactFolder }}/" &&
mkdir -p "$DEST" &&
adb logcat -d > "$DEST/logcat-${{ parameters.testName }}.txt" ||
echo "logcat capture failed"
displayName: capture logcat ${{ parameters.testName }}
condition: ${{ parameters.condition }}
condition: always()
continueOnError: true

- task: PublishTestResults@2
Expand Down
Loading