Skip to content

Commit e9b531d

Browse files
[3.13] gh-116622: Android test script improvements (GH-124012) (#124034)
gh-116622: Android test script improvements (GH-124012) * Set Android test script stdout to line-buffered * Print warning logcat messages on stderr * Add a -vv option to display high-volume messages which are rarely useful * Documentation and comment improvements (cherry picked from commit 1f9d163) Co-authored-by: Malcolm Smith <[email protected]>
1 parent d4225b6 commit e9b531d

File tree

2 files changed

+34
-17
lines changed

2 files changed

+34
-17
lines changed

Android/README.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ experience.
88

99
## Prerequisites
1010

11-
Export the `ANDROID_HOME` environment variable to point at your Android SDK. If
12-
you don't already have the SDK, here's how to install it:
11+
First, make sure you have all the usual tools and libraries needed to build
12+
Python for your development machine.
13+
14+
Second, you'll need an Android SDK. If you already have the SDK installed,
15+
export the `ANDROID_HOME` environment variable to point at its location.
16+
Otherwise, here's how to install it:
1317

1418
* Download the "Command line tools" from <https://developer.android.com/studio>.
1519
* Create a directory `android-sdk/cmdline-tools`, and unzip the command line
@@ -33,11 +37,6 @@ development tools, which currently means Linux or macOS. This involves doing a
3337
cross-build where you use a "build" Python (for your development machine) to
3438
help produce a "host" Python for Android.
3539

36-
First, make sure you have all the usual tools and libraries needed to build
37-
Python for your development machine. The only Android tool you need to install
38-
is the command line tools package above: the build script will download the
39-
rest.
40-
4140
The easiest way to do a build is to use the `android.py` script. You can either
4241
have it perform the entire build process from start to finish in one step, or
4342
you can do it in discrete steps that mirror running `configure` and `make` for
@@ -76,12 +75,15 @@ call. For example, if you want a pydebug build that also caches the results from
7675

7776
## Testing
7877

79-
The tests can be run on Linux, macOS, or Windows, although on Windows you'll
80-
have to build the `cross-build/HOST` subdirectory on one of the other platforms
81-
and copy it over.
78+
The test suite can be run on Linux, macOS, or Windows:
79+
80+
* On Linux, the emulator needs access to the KVM virtualization interface, and
81+
a DISPLAY environment variable pointing at an X server.
82+
* On Windows, you won't be able to do the build on the same machine, so you'll
83+
have to copy the `cross-build/HOST` directory from somewhere else.
8284

83-
The test suite can usually be run on a device with 2 GB of RAM, though for some
84-
configurations or test orders you may need to increase this. As of Android
85+
The test suite can usually be run on a device with 2 GB of RAM, but this is
86+
borderline, so you may need to increase it to 4 GB. As of Android
8587
Studio Koala, 2 GB is the default for all emulators, although the user interface
8688
may indicate otherwise. Locate the emulator's directory under `~/.android/avd`,
8789
and find `hw.ramSize` in both config.ini and hardware-qemu.ini. Either set these

Android/android.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,8 @@ def setup_testbed():
259259
f"{temp_dir}/{outer_jar}", "gradle-wrapper.jar"])
260260

261261

262-
# run_testbed will build the app automatically, but it hides the Gradle output
263-
# by default, so it's useful to have this as a separate command for the buildbot.
262+
# run_testbed will build the app automatically, but it's useful to have this as
263+
# a separate command to allow running the app outside of this script.
264264
def build_testbed(context):
265265
setup_sdk()
266266
setup_testbed()
@@ -376,6 +376,8 @@ async def find_pid(serial):
376376
shown_error = False
377377
while True:
378378
try:
379+
# `pidof` requires API level 24 or higher. The level 23 emulator
380+
# includes it, but it doesn't work (it returns all processes).
379381
pid = (await async_check_output(
380382
adb, "-s", serial, "shell", "pidof", "-s", APP_ID
381383
)).strip()
@@ -407,6 +409,7 @@ async def logcat_task(context, initial_devices):
407409
serial = await wait_for(find_device(context, initial_devices), startup_timeout)
408410
pid = await wait_for(find_pid(serial), startup_timeout)
409411

412+
# `--pid` requires API level 24 or higher.
410413
args = [adb, "-s", serial, "logcat", "--pid", pid, "--format", "tag"]
411414
hidden_output = []
412415
async with async_process(
@@ -421,11 +424,15 @@ async def logcat_task(context, initial_devices):
421424
# such messages, but other components might.
422425
level, message = None, line
423426

427+
# Exclude high-volume messages which are rarely useful.
428+
if context.verbose < 2 and "from python test_syslog" in message:
429+
continue
430+
424431
# Put high-level messages on stderr so they're highlighted in the
425432
# buildbot logs. This will include Python's own stderr.
426433
stream = (
427434
sys.stderr
428-
if level in ["E", "F"] # ERROR and FATAL (aka ASSERT)
435+
if level in ["W", "E", "F"] # WARNING, ERROR, FATAL (aka ASSERT)
429436
else sys.stdout
430437
)
431438

@@ -573,8 +580,9 @@ def parse_args():
573580
test = subcommands.add_parser(
574581
"test", help="Run the test suite")
575582
test.add_argument(
576-
"-v", "--verbose", action="store_true",
577-
help="Show Gradle output, and non-Python logcat messages")
583+
"-v", "--verbose", action="count", default=0,
584+
help="Show Gradle output, and non-Python logcat messages. "
585+
"Use twice to include high-volume messages which are rarely useful.")
578586
device_group = test.add_mutually_exclusive_group(required=True)
579587
device_group.add_argument(
580588
"--connected", metavar="SERIAL", help="Run on a connected device. "
@@ -591,6 +599,13 @@ def parse_args():
591599

592600
def main():
593601
install_signal_handler()
602+
603+
# Under the buildbot, stdout is not a TTY, but we must still flush after
604+
# every line to make sure our output appears in the correct order relative
605+
# to the output of our subprocesses.
606+
for stream in [sys.stdout, sys.stderr]:
607+
stream.reconfigure(line_buffering=True)
608+
594609
context = parse_args()
595610
dispatch = {"configure-build": configure_build_python,
596611
"make-build": make_build_python,

0 commit comments

Comments
 (0)