Skip to content

Commit 67abf6e

Browse files
authored
Write adb logcat results and screenshots to FLUTTER_LOGS_DIR if able. (flutter#50722)
Fixes flutter/flutter#143586. This should make it easier to understand what is/isn't happening, and will unblock flutter/flutter#143458, and make flutter/flutter#143459 potentially easier to debug.
1 parent 8ae2321 commit 67abf6e

File tree

6 files changed

+83
-14
lines changed

6 files changed

+83
-14
lines changed

testing/scenario_app/android/README.md

+33-6
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,50 @@ $ ./testing/scenario_app/run_android_tests.sh android_debug_unopt
1616
$ ./testing/scenario_app/run_android_tests.sh android_debug_unopt_arm64
1717
```
1818

19+
## Debugging
20+
21+
Debugging the tests on CI is not straightforward but is being improved:
22+
23+
- <https://github.com/flutter/flutter/issues/143458>
24+
- <https://github.com/flutter/flutter/issues/143459>
25+
26+
Locally (or on a temporary PR for CI), you can run the tests with the
27+
`--smoke-test` argument to run a single test by class name, which can be useful
28+
to verify the setup:
29+
30+
```sh
31+
# From the root of the engine repository
32+
$ ./testing/scenario_app/run_android_tests.sh android_debug_unopt_arm64 --smoke-test dev.flutter.scenarios.EngineLaunchE2ETest
33+
```
34+
35+
The result of `adb logcat` and screenshots taken during the test will be stored
36+
in a logs directory, which is either `FLUTTER_LOGS_DIR` (if set, such as on CI)
37+
or locally in `out/.../scenario_app/logs`.
38+
39+
You can then view the logs and screenshots on LUCI. [For example](https://ci.chromium.org/ui/p/flutter/builders/try/Linux%20Engine%20Drone/2003164/overview):
40+
41+
![Screenshot of the Logs on LUCI](https://github.com/flutter/engine/assets/168174/79dc864c-c18b-4df9-a733-fd55301cc69c).
42+
1943
## CI Configuration
2044

2145
See [`ci/builders/linux_android_emulator.json`](../../../ci/builders/linux_android_emulator.json)
2246
, and grep for `run_android_tests.sh`.
2347

2448
The following matrix of configurations is tested on the CI:
2549

26-
| API Version | Graphics Backend | Skia Gold | Rationale |
27-
| ----------- | ------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------- |
50+
<!-- TODO(matanlurey): Blocked by https://github.com/flutter/flutter/issues/143471.
2851
| 28 | Skia | [Android 28 + Skia][skia-gold-skia-28] | Older Android devices (without `ImageReader`) on Skia. |
2952
| 28 | Impeller (OpenGLES) | [Android 28 + Impeller OpenGLES][skia-gold-impeller-opengles-28] | Older Android devices (without `ImageReader`) on Impeller. |
30-
| 34 | Skia | [Android 34 + Skia][skia-gold-skia-34] | Newer Android devices on Skia. |
31-
| 34 | Impeller (OpenGLES) | [Android 34 + Impeller OpenGLES][skia-gold-impeller-opengles-34] | Newer Android devices on Impeller with OpenGLES. |
32-
| 34 | Impeller (Vulkan) | [Android 34 + Impeller Vulkan][skia-gold-impeller-vulkan-34] | Newer Android devices on Impeller. |
33-
3453
[skia-gold-skia-28]: https://flutter-engine-gold.skia.org/search?left_filter=AndroidAPILevel%3D28%26GraphicsBackend%3Dskia&negative=true&positive=true&right_filter=AndroidAPILevel%3D28%26GraphicsBackend%3Dskia
3554
[skia-gold-impeller-opengles-28]: https://flutter-engine-gold.skia.org/search?left_filter=AndroidAPILevel%3D28%26GraphicsBackend%3Dimpeller-opengles&negative=true&positive=true&right_filter=AndroidAPILevel%3D28%26GraphicsBackend%3Dimpeller-opengles
55+
-->
56+
57+
| API Version | Graphics Backend | Skia Gold | Rationale |
58+
| ----------- | ------------------- | ---------------------------------------------------------------- | ------------------------------------------------ |
59+
| 34 | Skia | [Android 34 + Skia][skia-gold-skia-34] | Newer Android devices on Skia. |
60+
| 34 | Impeller (OpenGLES) | [Android 34 + Impeller OpenGLES][skia-gold-impeller-opengles-34] | Newer Android devices on Impeller with OpenGLES. |
61+
| 34 | Impeller (Vulkan) | [Android 34 + Impeller Vulkan][skia-gold-impeller-vulkan-34] | Newer Android devices on Impeller. |
62+
3663
[skia-gold-skia-34]: https://flutter-engine-gold.skia.org/search?left_filter=AndroidAPILevel%3D34%26GraphicsBackend%3Dskia&negative=true&positive=true&right_filter=AndroidAPILevel%3D34%26GraphicsBackend%3Dskia
3764
[skia-gold-impeller-opengles-34]: https://flutter-engine-gold.skia.org/search?left_filter=AndroidAPILevel%3D34%26GraphicsBackend%3Dimpeller-opengles&negative=true&positive=true&right_filter=AndroidAPILevel%3D34%26GraphicsBackend%3Dimpeller-opengles
3865
[skia-gold-impeller-vulkan-34]: https://flutter-engine-gold.skia.org/search?left_filter=AndroidAPILevel%3D34%26GraphicsBackend%3Dimpeller-vulkan&negative=true&positive=true&right_filter=AndroidAPILevel%3D34%26GraphicsBackend%3Dimpeller-vulkan

testing/scenario_app/bin/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ dart bin/android_integration_tests.dart --smoke-test dev.flutter.scenarios.Engin
3030
- `--out-dir`: The directory containing the build artifacts. Defaults to the
3131
last updated build directory in `out/` that starts with `android_`.
3232

33+
- `--logs-dir`: The directory to store logs and screenshots. Defaults to
34+
`FLUTTER_LOGS_DIR` if set, or `out/.../scenario_app/logs` otherwise.
35+
3336
- `--use-skia-gold`: Use Skia Gold to compare screenshots. Defaults to true
3437
when running on CI, and false otherwise (i.e. when running locally). If
3538
set to true, `isSkiaGoldClientAvailable` must be true.

testing/scenario_app/bin/android_integration_tests.dart

+17-4
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ void main(List<String> args) async {
8181
help: 'The Impeller backend to use for the Android app.',
8282
allowed: <String>['vulkan', 'opengles'],
8383
defaultsTo: 'vulkan',
84+
)
85+
..addOption(
86+
'logs-dir',
87+
help: 'The directory to store the logs and screenshots. Defaults to '
88+
'the value of the FLUTTER_LOGS_DIR environment variable, if set, '
89+
'otherwise it defaults to a path within out-dir.',
90+
defaultsTo: Platform.environment['FLUTTER_LOGS_DIR'],
8491
);
8592

8693
runZonedGuarded(
@@ -108,13 +115,15 @@ void main(List<String> args) async {
108115
if (enableImpeller && impellerBackend == null) {
109116
panic(<String>['invalid graphics-backend', results['impeller-backend'] as String? ?? '<null>']);
110117
}
118+
final Directory logsDir = Directory(results['logs-dir'] as String? ?? join(outDir.path, 'scenario_app', 'logs'));
111119
await _run(
112120
outDir: outDir,
113121
adb: adb,
114122
smokeTestFullPath: smokeTest,
115123
useSkiaGold: useSkiaGold,
116124
enableImpeller: enableImpeller,
117125
impellerBackend: impellerBackend,
126+
logsDir: logsDir,
118127
contentsGolden: contentsGolden,
119128
);
120129
exit(0);
@@ -152,6 +161,7 @@ Future<void> _run({
152161
required bool useSkiaGold,
153162
required bool enableImpeller,
154163
required _ImpellerBackend? impellerBackend,
164+
required Directory logsDir,
155165
required String? contentsGolden,
156166
}) async {
157167
const ProcessManager pm = LocalProcessManager();
@@ -165,11 +175,14 @@ Future<void> _run({
165175
}
166176

167177
final String scenarioAppPath = join(outDir.path, 'scenario_app');
168-
final String logcatPath = join(scenarioAppPath, 'logcat.txt');
169-
final String screenshotPath = join(scenarioAppPath, 'screenshots');
178+
final String logcatPath = join(logsDir.path, 'logcat.txt');
179+
180+
// TODO(matanlurey): Use screenshots/ sub-directory (https://github.com/flutter/flutter/issues/143604).
181+
final String screenshotPath = logsDir.path;
170182
final String apkOutPath = join(scenarioAppPath, 'app', 'outputs', 'apk');
171183
final File testApk = File(join(apkOutPath, 'androidTest', 'debug', 'app-debug-androidTest.apk'));
172184
final File appApk = File(join(apkOutPath, 'debug', 'app-debug.apk'));
185+
log('writing logs and screenshots to ${logsDir.path}');
173186

174187
if (!testApk.existsSync()) {
175188
panic(<String>['test apk does not exist: ${testApk.path}', 'make sure to build the selected engine variant']);
@@ -347,14 +360,14 @@ Future<void> _run({
347360
}
348361
});
349362

350-
await step('Uinstalling app APK...', () async {
363+
await step('Uninstalling app APK...', () async {
351364
final int exitCode = await pm.runAndForward(<String>[adb.path, 'uninstall', 'dev.flutter.scenarios']);
352365
if (exitCode != 0) {
353366
panic(<String>['could not uninstall app apk']);
354367
}
355368
});
356369

357-
await step('Uinstalling test APK...', () async {
370+
await step('Uninstalling test APK...', () async {
358371
final int exitCode = await pm.runAndForward(<String>[adb.path, 'uninstall', 'dev.flutter.scenarios.test']);
359372
if (exitCode != 0) {
360373
panic(<String>['could not uninstall app apk']);

testing/scenario_app/bin/utils/logs.dart

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ Future<void> step(String msg, Future<void> Function() fn) async {
1414
stdout.writeln('-> $_green$msg$_reset');
1515
try {
1616
await fn();
17+
} catch (_) {
18+
stderr.writeln('~~ ${_red}Failed$_reset');
19+
rethrow;
1720
} finally {
1821
stdout.writeln('<- ${_gray}Done$_reset');
1922
}

testing/scenario_app/run_android_tests.sh

+24-3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ SRC_DIR="$(
4646
OUT_DIR="$SRC_DIR/out/$BUILD_VARIANT"
4747
CONTENTS_GOLDEN="$SRC_DIR/flutter/testing/scenario_app_android_output.txt"
4848

49+
# TODO(matanlurey): If the test runner was purely in Dart, this would not have
50+
# been necesesary to repeat. However my best guess is the Dart script was seen
51+
# as potentially crashing, so it was wrapped in a shell script. If we can change
52+
# this, we should.
53+
#
54+
# Define a logs directory for ADB and screenshots.
55+
# By default, it should be the environment variable FLUTTER_LOGS_DIR, but if
56+
# it's not set, use the output directory and append "scenario_app/logs".
57+
LOGS_DIR=${FLUTTER_LOGS_DIR:-"$OUT_DIR/scenario_app/logs"}
58+
59+
# Create the logs directory if it doesn't exist.
60+
mkdir -p "$LOGS_DIR"
61+
4962
# Dump the logcat and symbolize stack traces before exiting.
5063
function dumpLogcat {
5164
ndkstack="windows-x86_64"
@@ -55,18 +68,25 @@ function dumpLogcat {
5568
ndkstack="linux-x86_64"
5669
fi
5770

71+
# Get the expected location of logcat.txt.
72+
logcat_file="$LOGS_DIR/logcat.txt"
73+
5874
echo "-> Symbolize stack traces"
5975
"$SRC_DIR"/third_party/android_tools/ndk/prebuilt/"$ndkstack"/bin/ndk-stack \
6076
-sym "$OUT_DIR" \
61-
-dump "$OUT_DIR"/scenario_app/logcat.txt
77+
-dump "$logcat_file"
6278
echo "<- Done"
6379

6480
echo "-> Dump full logcat"
65-
cat "$OUT_DIR"/scenario_app/logcat.txt
81+
cat "$logcat_file"
6682
echo "<- Done"
83+
84+
# Output the directory for the logs.
85+
echo "TIP: Full logs are in $LOGS_DIR"
6786
}
6887

69-
trap dumpLogcat EXIT
88+
# On error, dump the logcat and symbolize stack traces.
89+
trap dumpLogcat ERR
7090

7191
cd $SCRIPT_DIR
7292

@@ -75,5 +95,6 @@ cd $SCRIPT_DIR
7595
"$SRC_DIR"/third_party/dart/tools/sdks/dart-sdk/bin/dart run \
7696
"$SCRIPT_DIR"/bin/android_integration_tests.dart \
7797
--out-dir="$OUT_DIR" \
98+
--logs-dir="$LOGS_DIR" \
7899
--output-contents-golden="$CONTENTS_GOLDEN" \
79100
"$@"

testing/scenario_app_android_output.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,6 @@ PlatformViewWithTextureViewUiTest_testPlatformViewRotate.png
5757
PlatformViewWithTextureViewUiTest_testPlatformViewTransform.png
5858
PlatformViewWithTextureViewUiTest_testPlatformViewTwoIntersectingOverlays.png
5959
PlatformViewWithTextureViewUiTest_testPlatformViewWithoutOverlayIntersection.png
60-
SpawnEngineTests_testSpawnedEngine.png
60+
SpawnEngineTests_testSpawnedEngine.png
61+
logcat.txt
62+
noop.txt

0 commit comments

Comments
 (0)