summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-05-09 16:34:50 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-05-09 16:34:50 +0000
commit71d6d9c582e1d2365a72b3a3a56dcce66f1cf468 (patch)
tree20d06cc9926650c2b659b19870100dacff75e6b1
parent5aa6a42b7b18f32c84ab85bb03a9985ec5c7a3be (diff)
parent7e6447c3d38923189ebc0442bad21e2878555074 (diff)
downloadadt-infra-emu-35-1-release.tar.gz
Snap for 11819808 from 7e6447c3d38923189ebc0442bad21e2878555074 to emu-35-1-releaseemu-35-1-release
Change-Id: I48cfca2cab46c2ef9248ec4777763192b86b7ded
-rwxr-xr-xemu_test/utils/run_sys_img_test.sh1
-rw-r--r--pytest/test_embedded/cfg/emulator_darwin_tests.json8
-rw-r--r--pytest/test_embedded/cfg/emulator_linux_tests.json8
-rw-r--r--pytest/test_embedded/cfg/emulator_windows_tests.json8
-rw-r--r--pytest/test_embedded/src/emu/console/emulator_connection.py8
-rw-r--r--pytest/test_embedded/src/emu/emulator.py49
-rw-r--r--pytest/test_embedded/tests/battery/test_battery.py2
-rw-r--r--pytest/test_embedded/tests/clipboard/test_clipboard.py6
-rw-r--r--pytest/test_embedded/tests/conftest.py29
-rw-r--r--pytest/test_embedded/tests/console/test_console_avd.py15
-rw-r--r--pytest/test_embedded/tests/console/test_multidisplay_console.py1
-rw-r--r--pytest/test_embedded/tests/console/test_screen_capture.py2
-rw-r--r--pytest/test_embedded/tests/console/test_sleep_awake.py3
-rw-r--r--pytest/test_embedded/tests/display/test_brightness.py1
-rw-r--r--pytest/test_embedded/tests/display/test_multi_display.py153
-rw-r--r--pytest/test_embedded/tests/display/test_rotation.py10
-rw-r--r--pytest/test_embedded/tests/display/test_screenshot.py2
-rw-r--r--pytest/test_embedded/tests/display/test_stream_screenshot.py1
-rw-r--r--pytest/test_embedded/tests/events/needs_debug_events/test_keys.py1
-rw-r--r--pytest/test_embedded/tests/events/test_input_events_in_animation.py3
-rw-r--r--pytest/test_embedded/tests/events/test_touch_event.py1
-rw-r--r--pytest/test_embedded/tests/foldable/test_foldable.py2
-rw-r--r--pytest/test_embedded/tests/foldable/test_new_foldable.py2
-rw-r--r--pytest/test_embedded/tests/graphics/test_app.py1
-rw-r--r--pytest/test_embedded/tests/graphics/test_chrome.py16
-rw-r--r--pytest/test_embedded/tests/recording/test_recording.py1
-rw-r--r--pytest/test_embedded/tests/resizable/test_new_resizable.py1
-rw-r--r--pytest/test_embedded/tests/resizable/test_resizable.py1
-rw-r--r--pytest/test_embedded/tests/test_boot.py12
29 files changed, 191 insertions, 157 deletions
diff --git a/emu_test/utils/run_sys_img_test.sh b/emu_test/utils/run_sys_img_test.sh
index d7eb0181..97905c47 100755
--- a/emu_test/utils/run_sys_img_test.sh
+++ b/emu_test/utils/run_sys_img_test.sh
@@ -38,6 +38,7 @@ function run_with_timeout () {
TARGET="$(echo $DIST_DIR | sed "s/.*git_devtools-test-.*-\(api.*\)\/.*/\1/g")"
export ADT_INFRA='/buildbot/src/android/emu-master-dev/external/adt-infra'
export ANDROID_SDK_ROOT="$SDK_EMULATOR"
+export JAVA_HOME="$PWD/prebuilts/studio/jdk/jdk17/linux/"
rm -rf "$ANDROID_SDK_ROOT/system-images"
ln -sf "/buildbot/src/android/emu-master-dev/prebuilts/android-emulator-build/system-images/linux/system-images" "$ANDROID_SDK_ROOT"
ls $SDK_EMULATOR
diff --git a/pytest/test_embedded/cfg/emulator_darwin_tests.json b/pytest/test_embedded/cfg/emulator_darwin_tests.json
index 780cf813..6be85eb4 100644
--- a/pytest/test_embedded/cfg/emulator_darwin_tests.json
+++ b/pytest/test_embedded/cfg/emulator_darwin_tests.json
@@ -323,14 +323,14 @@
},
"status": "enabled"
},
- "sanity_test_suite_api_25": {
+ "sanity_test_suite_api_28": {
"description": "Set of tests we want to run as a part of emulator sanity test suite",
"launch_flags": [],
"pytest_flags": [
"-m oldapiboot"
],
"avd_config": {
- "api": "25",
+ "api": "28",
"tag.id": "google_apis"
},
"status": "enabled"
@@ -375,7 +375,7 @@
"description": "Set of tests we want to run as part of presubmit, it merely boots the emulator and does some basic checks.",
"launch_flags": [],
"pytest_flags": [
- "-m boot and not slow"
+ "-m boot and not slow and not flaky"
],
"avd_config": {
"api": "31",
@@ -387,7 +387,7 @@
"description": "Set of tests we want to run as part of presubmit, it merely boots the emulator and does some basic checks.",
"launch_flags": [],
"pytest_flags": [
- "-m boot and not slow"
+ "-m boot and not slow and not flaky"
],
"avd_config": {
"api": "34",
diff --git a/pytest/test_embedded/cfg/emulator_linux_tests.json b/pytest/test_embedded/cfg/emulator_linux_tests.json
index 780cf813..6be85eb4 100644
--- a/pytest/test_embedded/cfg/emulator_linux_tests.json
+++ b/pytest/test_embedded/cfg/emulator_linux_tests.json
@@ -323,14 +323,14 @@
},
"status": "enabled"
},
- "sanity_test_suite_api_25": {
+ "sanity_test_suite_api_28": {
"description": "Set of tests we want to run as a part of emulator sanity test suite",
"launch_flags": [],
"pytest_flags": [
"-m oldapiboot"
],
"avd_config": {
- "api": "25",
+ "api": "28",
"tag.id": "google_apis"
},
"status": "enabled"
@@ -375,7 +375,7 @@
"description": "Set of tests we want to run as part of presubmit, it merely boots the emulator and does some basic checks.",
"launch_flags": [],
"pytest_flags": [
- "-m boot and not slow"
+ "-m boot and not slow and not flaky"
],
"avd_config": {
"api": "31",
@@ -387,7 +387,7 @@
"description": "Set of tests we want to run as part of presubmit, it merely boots the emulator and does some basic checks.",
"launch_flags": [],
"pytest_flags": [
- "-m boot and not slow"
+ "-m boot and not slow and not flaky"
],
"avd_config": {
"api": "34",
diff --git a/pytest/test_embedded/cfg/emulator_windows_tests.json b/pytest/test_embedded/cfg/emulator_windows_tests.json
index 8045cec4..bd396362 100644
--- a/pytest/test_embedded/cfg/emulator_windows_tests.json
+++ b/pytest/test_embedded/cfg/emulator_windows_tests.json
@@ -323,14 +323,14 @@
},
"status": "enabled"
},
- "sanity_test_suite_api_25": {
+ "sanity_test_suite_api_28": {
"description": "Set of tests we want to run as a part of emulator sanity test suite",
"launch_flags": [],
"pytest_flags": [
"-m oldapiboot"
],
"avd_config": {
- "api": "25",
+ "api": "28",
"tag.id": "google_apis"
},
"status": "enabled"
@@ -375,7 +375,7 @@
"description": "Set of tests we want to run as part of presubmit, it merely boots the emulator and does some basic checks.",
"launch_flags": [],
"pytest_flags": [
- "-m boot and not slow"
+ "-m boot and not slow and not flaky"
],
"avd_config": {
"api": "31",
@@ -387,7 +387,7 @@
"description": "Set of tests we want to run as part of presubmit, it merely boots the emulator and does some basic checks.",
"launch_flags": [],
"pytest_flags": [
- "-m boot and not slow"
+ "-m boot and not slow and not flaky"
],
"avd_config": {
"api": "34",
diff --git a/pytest/test_embedded/src/emu/console/emulator_connection.py b/pytest/test_embedded/src/emu/console/emulator_connection.py
index 9c3da43b..036a4eaf 100644
--- a/pytest/test_embedded/src/emu/console/emulator_connection.py
+++ b/pytest/test_embedded/src/emu/console/emulator_connection.py
@@ -55,6 +55,10 @@ class EmulatorClient:
await self.send(msg)
async def send(self, command) -> (bool, [str]):
+ if self._writer.is_closing() or self._reader.at_eof():
+ self.logger.info("-- Disconnected.. attempting to reconnect")
+ await self.login()
+
self.logger.info("-S-> %s", command)
self._writer.write(f"{command}\n".encode(encoding="utf-8"))
@@ -79,6 +83,10 @@ class EmulatorClient:
f"EOF before receiving complete emulator response: {msg}"
)
+ async def close(self):
+ self._writer.close()
+ await self._writer.wait_closed()
+
@staticmethod
async def connect(
port: int,
diff --git a/pytest/test_embedded/src/emu/emulator.py b/pytest/test_embedded/src/emu/emulator.py
index 62403c5d..33d03ca0 100644
--- a/pytest/test_embedded/src/emu/emulator.py
+++ b/pytest/test_embedded/src/emu/emulator.py
@@ -254,14 +254,21 @@ class BaseEmulator(object):
"""
count = 0
try:
- while not await self.adb.is_installed(package_name) and count < 10:
+ while not await self.adb.is_installed(package_name) and count < 3:
await self.adb.install(apk.absolute())
- await asyncio.sleep(1)
+ await asyncio.sleep(2)
count += 1
-
finally:
return await self.adb.is_installed(package_name)
+ async def pgrep(self, process_name: str) -> bool:
+ shell = await self.adb.shell(f"ps -A | grep {process_name}")
+ return process_name in shell
+
+ async def activity_is_running(self, activity: str):
+ """Returns true if the given activity is running."""
+ return await self.pgrep(activity[: activity.find("/")])
+
async def start_activity(self, activity: str, params=None) -> bool:
"""Attempts to start the given activity.
@@ -278,28 +285,19 @@ class BaseEmulator(object):
True if the activity was started successfully, False otherwise.
"""
- async def activity_is_running():
- """Returns true if the given activity is running."""
- return await self.pgrep(activity[: activity.find("/")])
-
shell = f"am start -n {activity}"
if params:
shell += f" {params}"
- await self.adb.shell(shell, timeout=2)
count = 0
- while count < 10:
- await self.adb.shell(shell, timeout=2)
- await asyncio.sleep(1)
- if await activity_is_running():
+ while count < 3:
+ await self.adb.shell(shell)
+ await asyncio.sleep(2)
+ if await self.activity_is_running(activity):
return True
count += 1
- return await activity_is_running()
-
- async def pgrep(self, process_name: str) -> bool:
- shell = await self.adb.shell(f"ps -A | grep {process_name}", timeout=2)
- return process_name in shell
+ return await self.activity_is_running(activity)
async def stop_activity(self, activity: str) -> bool:
"""Attempts to stop the given activity.
@@ -316,20 +314,17 @@ class BaseEmulator(object):
True if the activity is not running, False otherwise.
"""
- async def activity_is_running():
- """Returns true if the given activity is running."""
- return await self.pgrep(activity)
+ shell = f"am force-stop {activity}"
- await self.adb.shell(f"am force-stop {activity}", timeout=1)
count = 0
- running = await activity_is_running()
- while running and count < 10:
- await self.adb.shell(f"am force-stop {activity}", timeout=1)
- await asyncio.sleep(1)
- running = await activity_is_running()
+ while count < 3:
+ await self.adb.shell(shell)
+ await asyncio.sleep(2)
+ if not await self.activity_is_running(activity):
+ return True
count += 1
- return not running
+ return not await self.activity_is_running(activity)
async def reset_state(self):
"""Resets this emulator to a well known state.
diff --git a/pytest/test_embedded/tests/battery/test_battery.py b/pytest/test_embedded/tests/battery/test_battery.py
index 3b360c4f..330566ea 100644
--- a/pytest/test_embedded/tests/battery/test_battery.py
+++ b/pytest/test_embedded/tests/battery/test_battery.py
@@ -43,8 +43,6 @@ async def set_and_get_battery(emu_controller, battery_state):
@pytest.mark.e2e
@pytest.mark.hardware
-@pytest.mark.timeout_win(timeout=60)
-@pytest.mark.async_timeout(30)
@pytest.mark.parametrize(
"test_name, battery_status, battery_health",
[
diff --git a/pytest/test_embedded/tests/clipboard/test_clipboard.py b/pytest/test_embedded/tests/clipboard/test_clipboard.py
index 2f38b525..07df7c6e 100644
--- a/pytest/test_embedded/tests/clipboard/test_clipboard.py
+++ b/pytest/test_embedded/tests/clipboard/test_clipboard.py
@@ -56,7 +56,6 @@ async def set_clip_data(emulator_controller, clipboard_data="Hello there!"):
@pytest.mark.e2e
@pytest.mark.embedded
@pytest.mark.fast
-@pytest.mark.async_timeout(10)
@pytest.mark.skipos("win", "reason: b/303295516 - error at setup.")
@pytest.mark.parametrize(
"clipboard_data",
@@ -85,7 +84,6 @@ async def test_clipboard_data(emulator_controller, clipboard_data):
@pytest.mark.e2e
@pytest.mark.embedded
-@pytest.mark.async_timeout(10)
@pytest.mark.skipos("win", "reason=b/305040235 - error at setup.")
async def test_stream_clipboard_immediately_sends_data(emulator_controller):
"""Validate that the streaming call will immediately send the current clipboard status."""
@@ -104,7 +102,6 @@ async def test_stream_clipboard_immediately_sends_data(emulator_controller):
@pytest.mark.e2e
@pytest.mark.embedded
-@pytest.mark.async_timeout(10)
@pytest.mark.skipos("win", "reason=b/305040856 - error at setup.")
async def test_stream_clipboard_sends_updated_data(emulator_controller, avd):
"""Validate that the streaming call will immediately send the current clipboard status and
@@ -149,7 +146,6 @@ def get_test_channel(desc, max_length=4096):
@pytest.mark.e2e
@pytest.mark.embedded
-@pytest.mark.async_timeout(60)
async def test_stream_clipboard_sends_updated_data_to_other_channel(avd):
# We forcefully create 2 different channel configurations to make
# sure that python is not going to "cleverly" re-use an existing channel.
@@ -181,7 +177,6 @@ async def test_stream_clipboard_sends_updated_data_to_other_channel(avd):
@pytest.mark.e2e
@pytest.mark.embedded
-@pytest.mark.async_timeout(60)
async def test_stream_clipboard_sends_updated_data_to_other_channel_only_once(avd):
# We forcefully create 2 different channel configurations to make
# sure that python is not going to "cleverly" re-use an existing channel.
@@ -224,7 +219,6 @@ async def test_stream_clipboard_sends_updated_data_to_other_channel_only_once(av
@pytest.mark.e2e
@pytest.mark.embedded
-@pytest.mark.async_timeout(60)
async def test_stream_clipboard_from_android_immediately_sends_data(
avd, emulator_controller
):
diff --git a/pytest/test_embedded/tests/conftest.py b/pytest/test_embedded/tests/conftest.py
index 164d5958..b29aebd5 100644
--- a/pytest/test_embedded/tests/conftest.py
+++ b/pytest/test_embedded/tests/conftest.py
@@ -180,25 +180,6 @@ def pytest_runtest_setup(item: pytest.Item) -> None:
else:
pytest.skip()
- # Process the 'timeout_win' marker
- timeout_win = item.get_closest_marker("timeout_win")
- if timeout_win and pytest.os == "win":
- timeout_win_sec = (
- timeout_win.args[0]
- if timeout_win.args
- else timeout_win.kwargs.get("timeout")
- )
- # Remove existing timeout marker
- timeout = [
- m
- for m, marker in enumerate(item.iter_markers())
- if marker.name == "timeout"
- ]
- if timeout:
- item.own_markers.pop(timeout[0])
-
- item.add_marker(pytest.mark.async_timeout([timeout_win_sec]))
-
item.user_properties.append(("flaky", "flaky" in item.keywords))
logging.info("=============== Setup: %s ===============", item.name)
@@ -257,11 +238,11 @@ def pytest_configure(config):
# Current skipos platform
pytest.os = os_map.get(pytest.system, "unknown")
- # Register the 'timeout_win' marker
+ # Register the 'flaky' marker
config.addinivalue_line(
"markers",
- "timeout_win(timeout): "
- "Set a timeout for Windows platforms (overrides an existing timeout).",
+ "flaky: "
+ "Set a test as flaky, and exclude it from test failures on the dashboard.",
)
@@ -284,7 +265,6 @@ def get_crash_reporter(pytestconfig):
@pytest.fixture(autouse=True)
-@pytest.mark.async_timeout(5)
async def crash_reporter(pytestconfig):
"""A fixture to handle crash reports in the emulator.
@@ -490,7 +470,6 @@ async def emulator_log(avd: BaseEmulator):
return avd.log
-@pytest.mark.async_timeout(20)
async def launch_animiation_app(avd: BaseEmulator):
"""Launches the debug animation app.
@@ -502,8 +481,6 @@ async def launch_animiation_app(avd: BaseEmulator):
- Force stop any existing running animation app
- Start the activity
- Wait for the welcome message to appear on logcat.
-
- It will wait for at most 20 seconds before continuing.
"""
logging.info("--> launch_animiation_app")
assert avd.is_alive()
diff --git a/pytest/test_embedded/tests/console/test_console_avd.py b/pytest/test_embedded/tests/console/test_console_avd.py
index 52f92262..f7e91381 100644
--- a/pytest/test_embedded/tests/console/test_console_avd.py
+++ b/pytest/test_embedded/tests/console/test_console_avd.py
@@ -8,7 +8,6 @@ import emu.console.emulator_connection
@pytest.mark.console
@pytest.mark.fast
@pytest.mark.e2e
-@pytest.mark.async_timeout(10)
async def test_avd_canonical_path(avd, telnet):
"""Test adb emu avd path returns a canonical path"""
expected_path = Path(
@@ -22,7 +21,6 @@ async def test_avd_canonical_path(avd, telnet):
@pytest.mark.console
@pytest.mark.fast
@pytest.mark.e2e
-@pytest.mark.async_timeout(10)
async def test_avd_snapshots_path_has_no_dots(telnet):
"""Exposes b/299320133, paths should be normalized."""
path = await telnet.send("avd snapshotspath")
@@ -32,7 +30,6 @@ async def test_avd_snapshots_path_has_no_dots(telnet):
@pytest.mark.boot
@pytest.mark.console
@pytest.mark.e2e
-@pytest.mark.async_timeout(10)
async def test_avd_tracing_is_mounted(avd, telnet):
"""Test adb shell ls /sys/kernel/tracing/trace_marker valid"""
no_file = "No such file or directory"
@@ -58,7 +55,6 @@ def read_property_file(from_file) -> str:
@pytest.mark.boot
@pytest.mark.console
@pytest.mark.e2e
-@pytest.mark.async_timeout(10)
async def test_avd_dir_is_canonical_in_pid_xxx_ini(avd, telnet):
"""Test pid_xxx.ini contains canonical path for avd.dir
@@ -121,3 +117,14 @@ async def test_emulator_exit_console_command(telnet):
assert False, "Emulator client connection did not close as expected"
except emu.console.emulator_connection.EmulatorClientEOF:
pass # Connection closed successfully
+
+
+@pytest.mark.e2e
+@pytest.mark.sanity
+async def test_telnet_will_reconnect_after_exit(telnet):
+ try:
+ await telnet.send("exit")
+ assert False, "Emulator client connection did not close as expected"
+ except emu.console.emulator_connection.EmulatorClientEOF:
+ hello = await telnet.send("ping")
+ assert hello == ["I am alive!", "OK"]
diff --git a/pytest/test_embedded/tests/console/test_multidisplay_console.py b/pytest/test_embedded/tests/console/test_multidisplay_console.py
index 20f04ae3..2a8f0dc8 100644
--- a/pytest/test_embedded/tests/console/test_multidisplay_console.py
+++ b/pytest/test_embedded/tests/console/test_multidisplay_console.py
@@ -20,7 +20,6 @@ def ui_controller(service):
@pytest.mark.console
@pytest.mark.multidisplay
@pytest.mark.e2e
-@pytest.mark.async_timeout(10)
async def test_multidisplay_out_of_order_add_no_crash(avd, telnet, ui_controller):
"""Test adb emu multidisplay add 3 does not crash emulator"""
diff --git a/pytest/test_embedded/tests/console/test_screen_capture.py b/pytest/test_embedded/tests/console/test_screen_capture.py
index e22cb4ba..f27a9d32 100644
--- a/pytest/test_embedded/tests/console/test_screen_capture.py
+++ b/pytest/test_embedded/tests/console/test_screen_capture.py
@@ -27,7 +27,6 @@ def tmp_test_file(tmp_path):
@pytest.mark.adb
@pytest.mark.sanity
@pytest.mark.flaky
-@pytest.mark.async_timeout(30)
async def test_adb_screencapture_creates_a_file(
avd, log_adb_interactions, tmp_test_file
):
@@ -39,7 +38,6 @@ async def test_adb_screencapture_creates_a_file(
@pytest.mark.adb
@pytest.mark.flaky
-@pytest.mark.async_timeout(30)
async def test_adb_screencapture_is_a_png(avd, log_adb_interactions, tmp_test_file):
device_file = f"/sdcard/{tmp_test_file.name}"
await avd.adb.shell(f"rm {device_file}")
diff --git a/pytest/test_embedded/tests/console/test_sleep_awake.py b/pytest/test_embedded/tests/console/test_sleep_awake.py
index 46c9d55e..6782b20d 100644
--- a/pytest/test_embedded/tests/console/test_sleep_awake.py
+++ b/pytest/test_embedded/tests/console/test_sleep_awake.py
@@ -81,7 +81,6 @@ async def emulator_off(adb_shell):
@pytest.mark.adb
-@pytest.mark.async_timeout(60)
async def test_power_down_sleeps_the_device(adb_shell, emulator_on):
"""Test case to verify that sending the power-down command to an awake device will put the device to sleep."""
@@ -94,7 +93,6 @@ async def test_power_down_sleeps_the_device(adb_shell, emulator_on):
@pytest.mark.adb
-@pytest.mark.async_timeout(60)
async def test_wake_up_wakes_the_device(adb_shell, emulator_off):
"""Test case to verify that sending the wake-up command to a sleeping device will wake the device."""
@@ -108,7 +106,6 @@ async def test_wake_up_wakes_the_device(adb_shell, emulator_off):
@pytest.mark.e2e
@pytest.mark.adb
@pytest.mark.flaky # b/322557339
-@pytest.mark.async_timeout(60)
async def test_power_down_turns_off_the_screen(emulator_off, get_screenshot):
"""Test case to verify that a powered-down device has a black screen.
diff --git a/pytest/test_embedded/tests/display/test_brightness.py b/pytest/test_embedded/tests/display/test_brightness.py
index 411070f7..5823892a 100644
--- a/pytest/test_embedded/tests/display/test_brightness.py
+++ b/pytest/test_embedded/tests/display/test_brightness.py
@@ -34,7 +34,6 @@ async def set_and_get_brightness(emu_controller, brightness_value):
@pytest.mark.e2e
@pytest.mark.hardware
-@pytest.mark.async_timeout(10)
@pytest.mark.parametrize(
"test_name, brightness_value",
[
diff --git a/pytest/test_embedded/tests/display/test_multi_display.py b/pytest/test_embedded/tests/display/test_multi_display.py
index 4b16fc65..a9bf6301 100644
--- a/pytest/test_embedded/tests/display/test_multi_display.py
+++ b/pytest/test_embedded/tests/display/test_multi_display.py
@@ -15,6 +15,7 @@ import logging
import asyncio
import pytest
import re
+import json
from aemu.proto.emulator_controller_pb2 import (
DisplayConfiguration,
DisplayConfigurations,
@@ -88,7 +89,6 @@ async def emu_snapshot_service(avd, service):
@pytest.mark.e2e
-@pytest.mark.timeout_win(timeout=60)
@pytest.mark.graphics
@pytest.mark.multidisplay
async def test_multidisplay_none(avd, no_displays, emulator_controller, is_landscape):
@@ -360,22 +360,23 @@ async def test_multidisplay_error_too_many(
@pytest.mark.graphics
@pytest.mark.multidisplay
@pytest.mark.fast
-@pytest.mark.async_timeout(120)
-async def test_disable_multidisplay(avd, is_landscape):
+@pytest.mark.async_timeout(510)
+async def test_disable_multidisplay(avd, no_displays, is_landscape, emulator_controller):
"""Ensure an app is moved to the primary display when multidisplay is disabled.
Args:
- emulator (BaseEmulator): Fixture that gives access to the running emulator.
+ avd (BaseEmulator): Fixture that gives access to the running emulator.
+ no_displays (callable): Fixture to make sure the emulator has no multi displays configured.
is_landscape (bool): Fixture that indicates whether the emulator is in landscape orientation.
emulator_controller (EmulatorControllerStub): An instance of the emulator controller fixture.
Test UUID: d0114791-2781-45ee-b4fa-b496d767604e
Test Steps:
- 1. Configure the emulator to support multiple display resolutions.
- 2. Launch a dummy app (e.g., calendar) on the current display.
+ 1. Configure multiple display resolutions.
+ 2. Launch the animation APK on the current display.
3. Disable multidisplay functionality
- 4. confirm the dummy app moved to the primary display (Verify).
+ 4. Confirm the animation APK moved to the primary display (Verify).
5. Repeat the steps 2-4 for all display resolutions
Verify:
@@ -385,8 +386,6 @@ async def test_disable_multidisplay(avd, is_landscape):
if is_landscape:
pytest.skip("Cannot run multi display tests in landscape mode.")
- emulator_controller = EmulatorControllerStub(avd.channel)
-
# Displays configurations to be tested.
resolutions = [(720, 1280), (1080, 1920)]
displays = [
@@ -404,45 +403,135 @@ async def test_disable_multidisplay(avd, is_landscape):
return cfg
async def enable_multidisplay(displays):
- # Set the display configuration according to `displays`
+ # Set the display configuration from 'displays'.
to_set = DisplayConfigurations(displays=displays)
logging.info('Enabling multidisplay mode')
cfg = await emulator_controller.setDisplayConfigurations(to_set)
return cfg
async def get_display_id(package):
- # Get the display id where `package` is running
- windows_dump = await avd.adb.shell("dumpsys window", timeout=30)
+ # Get the id of the display where 'package' is running.
+ # Return 'None' if the package is not present in the window system dump.
+ windows_dump = await avd.adb.shell("dumpsys window", timeout=60)
display_lines = re.search(f"Window.*{package}.*mDisplayId=([0-9]*)", windows_dump)
+ if display_lines is None:
+ return None
return int(display_lines.groups()[0])
- dummy_pkg = "com.android.contacts"
- dummy_activity = f"{dummy_pkg}/.activities.PeopleActivity"
-
- # Make sure we start with the primary display only.
- cfg = await emulator_controller.getDisplayConfigurations(empty_pb2.Empty())
- if len(cfg.displays) > 1:
- await disable_multidisplay()
-
- for idx in range(len(resolutions)):
+ async def get_displays_ids():
+ # Get the displays ID's.
+ # Return None if there are no displays avaiable or if there is a single display.
+ windows_dump = await avd.adb.shell("dumpsys window", timeout=60)
+ display_ids = re.findall('displayId=([0-9]+)', windows_dump)
+ if display_ids is None:
+ return None
+ display_ids_list = sorted(set(display_ids))
+ if len(display_ids_list) == 1:
+ return None
+ return list(display_ids_list)
+
+ async def start_on_display(activity, id_):
+ # Start an activity on a given display.
+ return await avd.start_activity(activity, params=f"--display {id_}")
+
+ async def app_is_on_primary_display(pkg):
+ # Return True if 'pkg' is detected on the primary display.
+ display_id = await get_display_id(pkg)
+ return display_id == 0
+
+ dummy_pkg = "com.google.AnimateBox"
+ dummy_activity = f"{dummy_pkg}/com.google.emu.MainActivity"
+ pkg_name = dummy_pkg.split('.')[-1]
+ await avd.stop_activity(dummy_pkg)
+
+ for i in range(len(resolutions)):
# Enable multidisplay.
await enable_multidisplay(displays)
- await asyncio.sleep(10)
+ await asyncio.sleep(20)
+
+ # Get the current displays list.
+ assert await eventually(get_displays_ids,timeout=60), \
+ "Couldn't retrieve the displays Ids"
+ ids = await get_displays_ids()
- # Start app on current display.
- await avd.start_activity(dummy_activity, params=f"--display {idx + 1}")
- await asyncio.sleep(10)
+ # Start app on the display 'ids[i + 1]'.
+ assert await eventually(partial(start_on_display, dummy_activity, ids[i + 1]), timeout=60), \
+ f"Couldn't launch package '{pkg_name}' on display {ids[i + 1]}"
# Disable multidisplay.
- logging.info(f'Disable multidisplay while contacts app is on display {idx + 1}')
- cfg = await disable_multidisplay()
- await asyncio.sleep(10)
+ logging.info(f'Disable multidisplay while app {pkg_name} is on display {ids[i + 1]}')
+ await disable_multidisplay()
# Verify if the app is present in the primary display.
- display_id = await get_display_id(dummy_pkg)
- assert display_id == 0, f"Contacts app was detected in display {display_id}"
+ assert await eventually(partial(app_is_on_primary_display, dummy_pkg)), \
+ f"App {pkg_name} was not found on display 0"
# Stop the app.
- await avd.stop_activity("com.android.contacts")
- await asyncio.sleep(5)
+ await avd.stop_activity(dummy_pkg)
+
+
+@pytest.mark.graphics
+@pytest.mark.multidisplay
+@pytest.mark.fast
+@pytest.mark.async_timeout(510)
+async def test_add_multidisplay_from_config(emulator, tmp_path):
+ """Adding displays from config file should work
+
+ Args:
+ emulator (BaseEmulator): Fixture that gives access to the running emulator.
+ tmp_path (Path): Fixture that provides a temporary working folder.
+
+ Test UUID: ea5ede9a-8cdf-4e56-bae1-1b56c2d7ae71
+
+ Test Steps:
+ 1. Create an AVD with two secondary displays.
+ 2. Launch a new emulator based on the newly created AVD (Verify).
+
+ Verify:
+ Three logical displays should appear in the emulator display dump.
+ """
+ if emulator.is_alive():
+ await emulator.stop() # The test will configure its own emulator.
+
+ # Avd configuration containing two secondary displays.
+ config = {"abi": "x86",
+ "api": "29",
+ "tag.id":"google_apis",
+ "hw.display1.width": 800,
+ "hw.display1.height": 1200,
+ "hw.display1.density": 320,
+ "hw.display1.xOffset": -1,
+ "hw.display1.yOffset": -1,
+ "hw.display1.flag": 0,
+ "hw.display2.width": 800,
+ "hw.display2.height": 1200,
+ "hw.display2.density": 320,
+ "hw.display2.xOffset": -1,
+ "hw.display2.yOffset": -1,
+ "hw.display2.flag": 0}
+
+ n_displays = 3 # primary plus two secondary displays.
+
+ # Launch the emulator with the specificed multidisplay configuration.
+ logging.info("Launching emulator ...")
+ myflags = ["-no-snapshot-save"]
+ emulator = Emulator(
+ android_home=emulator.android_home,
+ android_avd_home=tmp_path,
+ exe=emulator.exe,
+ avd_config=config,
+ )
+ await emulator.launch(flags=myflags)
+ await emulator.wait_for_boot(timeout=180)
+
+ async def ensure_logical_displays(n_displays):
+ # Return True if 'n_displays' logical displays are present.
+ display_dump = await emulator.adb.shell("dumpsys display", timeout=30)
+ display_size_pattern = re.search('Logical Displays: size=([0-9]*).*', display_dump)
+ return display_size_pattern.groups()[0] == str(n_displays)
+
+ assert await eventually(partial(ensure_logical_displays, n_displays), timeout=180), \
+ 'Wrong number of displays detected'
+
+ await emulator.stop()
diff --git a/pytest/test_embedded/tests/display/test_rotation.py b/pytest/test_embedded/tests/display/test_rotation.py
index 7da0bd15..0a063e82 100644
--- a/pytest/test_embedded/tests/display/test_rotation.py
+++ b/pytest/test_embedded/tests/display/test_rotation.py
@@ -77,8 +77,6 @@ async def for_each_rotation(emulator_controller):
@pytest.mark.e2e
-@pytest.mark.async_timeout(10)
-@pytest.mark.timeout_win(timeout=60)
@pytest.mark.graphics
@pytest.mark.flaky
async def test_rotation_observable_through_screenshot(
@@ -125,7 +123,6 @@ async def test_rotation_observable_through_adbstream(
@pytest.mark.e2e
-@pytest.mark.async_timeout(10)
@pytest.mark.graphics
@pytest.mark.flaky
async def test_rotation_observable_through_stream_screenshot(
@@ -255,8 +252,6 @@ async def rotation_through_console_observable_through_stream_screenshot(
@pytest.mark.graphics
@pytest.mark.sanity
@pytest.mark.fast
-@pytest.mark.async_timeout(10)
-@pytest.mark.timeout_win(timeout=60)
@pytest.mark.parametrize(
"rotation, quadrant",
[(0, 1), (90, 2), (-180, 3), (-90, 4)],
@@ -294,7 +289,6 @@ async def test_rotation_pixels_in_the_right_place(
@pytest.mark.e2e
-@pytest.mark.async_timeout(10)
@pytest.mark.graphics
@pytest.mark.flaky
async def test_rotation_through_console_observable_through_physical_model(
@@ -324,7 +318,6 @@ async def test_rotation_through_console_observable_through_physical_model(
@pytest.mark.e2e
@pytest.mark.graphics
-@pytest.mark.async_timeout(10)
@pytest.mark.flaky
async def test_rotation_through_console_observable_through_screenshot(
at_home, emulator_controller, telnet
@@ -339,7 +332,6 @@ async def test_rotation_through_console_observable_through_screenshot(
@pytest.mark.e2e
@pytest.mark.graphics
-@pytest.mark.async_timeout(10)
@pytest.mark.flaky
async def test_rotation_through_console_observable_through_stream_screenshot(
at_home, animation_app, emulator_controller, telnet, stream_screenshot
@@ -356,7 +348,6 @@ async def test_rotation_through_console_observable_through_stream_screenshot(
@pytest.mark.e2e
@pytest.mark.embedded
@pytest.mark.sanity
-@pytest.mark.async_timeout(10)
@pytest.mark.flaky
async def test_rotation_observable_through_screenshot_embedded_mode(
emulator_controller, telnet, avd, at_home
@@ -368,7 +359,6 @@ async def test_rotation_observable_through_screenshot_embedded_mode(
@pytest.mark.e2e
@pytest.mark.embedded
-@pytest.mark.async_timeout(10)
@pytest.mark.flaky
async def test_rotation_observable_through_stream_screenshot_embedded_mode(
emulator_controller, telnet, avd, at_home, stream_screenshot
diff --git a/pytest/test_embedded/tests/display/test_screenshot.py b/pytest/test_embedded/tests/display/test_screenshot.py
index 70203e78..e2f62490 100644
--- a/pytest/test_embedded/tests/display/test_screenshot.py
+++ b/pytest/test_embedded/tests/display/test_screenshot.py
@@ -169,7 +169,7 @@ async def all_orientations(emulator_controller, request):
# bug 299344829
@pytest.mark.graphics
@pytest.mark.embedded
-@pytest.mark.timeout_win(timeout=120)
+@pytest.mark.async_timeout(120)
@pytest.mark.flaky
async def test_screenshot_valid_width_and_height(
avd, get_screenshot, default_display_config
diff --git a/pytest/test_embedded/tests/display/test_stream_screenshot.py b/pytest/test_embedded/tests/display/test_stream_screenshot.py
index 5767047f..f490f17d 100644
--- a/pytest/test_embedded/tests/display/test_stream_screenshot.py
+++ b/pytest/test_embedded/tests/display/test_stream_screenshot.py
@@ -35,7 +35,6 @@ def read_pixel(width, height, pack, arr):
"win", "reason: b/305252175 - error at setup. Only the parameter [2-1] fails."
)
@pytest.mark.flaky
-@pytest.mark.timeout_win(timeout=60)
@pytest.mark.parametrize(
"fmt,channel",
[
diff --git a/pytest/test_embedded/tests/events/needs_debug_events/test_keys.py b/pytest/test_embedded/tests/events/needs_debug_events/test_keys.py
index 5978f258..816134c1 100644
--- a/pytest/test_embedded/tests/events/needs_debug_events/test_keys.py
+++ b/pytest/test_embedded/tests/events/needs_debug_events/test_keys.py
@@ -66,7 +66,6 @@ async def keypress_expects(avd, log, jskey, expected_code):
@pytest.mark.e2e
@pytest.mark.hardware
-@pytest.mark.timeout_win(timeout=60)
async def test_hardware_keys(avd, at_home, emulator_log):
"""Checks that the hardware key events that studio sends are working."""
if not emulator_log:
diff --git a/pytest/test_embedded/tests/events/test_input_events_in_animation.py b/pytest/test_embedded/tests/events/test_input_events_in_animation.py
index cb042143..88c1086e 100644
--- a/pytest/test_embedded/tests/events/test_input_events_in_animation.py
+++ b/pytest/test_embedded/tests/events/test_input_events_in_animation.py
@@ -114,7 +114,6 @@ async def send_event(avd, emulator_controller):
return send_single_event
-@pytest.mark.async_timeout(10)
async def test_send_a_sequence_of_single_mouse_events(
animation_app, send_event, retrieve_events
):
@@ -129,7 +128,6 @@ async def test_send_a_sequence_of_single_mouse_events(
assert expected == retrieved
-@pytest.mark.async_timeout(10)
async def test_send_a_sequence_of_single_key_events(
animation_app, send_event, retrieve_events
):
@@ -146,7 +144,6 @@ async def test_send_a_sequence_of_single_key_events(
assert expected == retrieved
-@pytest.mark.async_timeout(10)
async def test_stream_a_sequence_of_key_events(
animation_app, emulator_controller, retrieve_events
):
diff --git a/pytest/test_embedded/tests/events/test_touch_event.py b/pytest/test_embedded/tests/events/test_touch_event.py
index c4ff5c29..25db9b95 100644
--- a/pytest/test_embedded/tests/events/test_touch_event.py
+++ b/pytest/test_embedded/tests/events/test_touch_event.py
@@ -41,7 +41,6 @@ async def test_touch_event_identifier_ranges(at_home, emulator_controller):
@pytest.mark.e2e
@pytest.mark.hardware
-@pytest.mark.timeout_win(timeout=60)
async def test_touch_event_identifier_to_many(at_home, emulator_controller):
"""Tests that we properly handle too many registered identifiers."""
x = 1
diff --git a/pytest/test_embedded/tests/foldable/test_foldable.py b/pytest/test_embedded/tests/foldable/test_foldable.py
index c766c3a9..73503c50 100644
--- a/pytest/test_embedded/tests/foldable/test_foldable.py
+++ b/pytest/test_embedded/tests/foldable/test_foldable.py
@@ -53,7 +53,6 @@ async def snapshot_service(avd, service):
@pytest.mark.parametrize(
"fmt,fold_angle,unfold_angle", [(ImageFormat.RGB888, 15.0, 180.0)]
)
-@pytest.mark.async_timeout(30)
async def test_foldable(emulator_controller, fmt, fold_angle, unfold_angle):
set_device_hinge_angle(emulator_controller, unfold_angle)
await asyncio.sleep(5)
@@ -186,7 +185,6 @@ async def test_unfolded_snapshot_sanity(
@pytest.mark.parametrize(
"fmt,fold_angle,unfold_angle", [(ImageFormat.RGB888, 5.0, 180.0)]
)
-@pytest.mark.async_timeout(30)
async def test_foldable_notifications(
emulator_controller, fmt, fold_angle, unfold_angle
):
diff --git a/pytest/test_embedded/tests/foldable/test_new_foldable.py b/pytest/test_embedded/tests/foldable/test_new_foldable.py
index 40641590..988c7c44 100644
--- a/pytest/test_embedded/tests/foldable/test_new_foldable.py
+++ b/pytest/test_embedded/tests/foldable/test_new_foldable.py
@@ -67,7 +67,6 @@ async def set_device_hinge_angle(emu, angle):
@pytest.mark.parametrize(
"fmt,fold_angle,unfold_angle", [(ImageFormat.RGB888, 15.0, 180.0)]
)
-@pytest.mark.async_timeout(60)
async def test_new_foldable(emulator_controller, fmt, fold_angle, unfold_angle):
await set_device_hinge_angle(emulator_controller, unfold_angle)
await asyncio.sleep(5)
@@ -108,7 +107,6 @@ async def test_new_foldable(emulator_controller, fmt, fold_angle, unfold_angle):
@pytest.mark.parametrize(
"fmt,fold_angle,unfold_angle", [(ImageFormat.RGB888, 5.0, 180.0)]
)
-@pytest.mark.async_timeout(60)
async def test_new_foldable_notifications(
emulator_controller, fmt, fold_angle, unfold_angle
):
diff --git a/pytest/test_embedded/tests/graphics/test_app.py b/pytest/test_embedded/tests/graphics/test_app.py
index 5764ddc6..d4bfbd56 100644
--- a/pytest/test_embedded/tests/graphics/test_app.py
+++ b/pytest/test_embedded/tests/graphics/test_app.py
@@ -22,7 +22,6 @@ from emu.timing import eventually
@pytest.mark.e2e
@pytest.mark.graphics
-@pytest.mark.async_timeout(60)
@pytest.mark.flaky
async def test_android_app_dialog_has_dimmed_background(avd, get_screenshot, log_adb_interactions):
"""
diff --git a/pytest/test_embedded/tests/graphics/test_chrome.py b/pytest/test_embedded/tests/graphics/test_chrome.py
index cf373de3..3bf09169 100644
--- a/pytest/test_embedded/tests/graphics/test_chrome.py
+++ b/pytest/test_embedded/tests/graphics/test_chrome.py
@@ -70,23 +70,23 @@ async def request_page_in_chrome(avd):
@pytest.mark.e2e
@pytest.mark.graphics
@pytest.mark.xpass
-@pytest.mark.flaky
+@pytest.mark.async_timeout(120)
async def test_launch_chrome_google(avd, get_screenshot):
"""
This test launches Chrome on an Android device, opens a html snippet,
- captures a screenshot, and verifies that at least 60% of the image pixels are purple.
+ captures a screenshot, and verifies that at least 40% of the image pixels are purple.
"""
- async def at_least_60_percent_of_image_is_purple():
+ async def at_least_40_percent_of_image_is_purple():
"""
- Helper function to check if at least 60% of the image pixels are purple.
+ Helper function to check if at least 40% of the image pixels are purple.
Returns:
- bool: True if at least 60% of the image pixels are blue, False otherwise.
+ bool: True if at least 40% of the image pixels are blue, False otherwise.
"""
_, rgb_image = await get_screenshot(ImageFormat())
rgb_image = rgb_image.convert("RGB")
- percent_purple = 60
+ percent_purple = 40
purple_count = 0
# Iterate over each pixel in the image
@@ -106,9 +106,9 @@ async def test_launch_chrome_google(avd, get_screenshot):
max_retries = 3
for _ in range(0, max_retries):
await request_page_in_chrome(avd)
- if await wait_until(at_least_60_percent_of_image_is_purple, timeout=5):
+ if await wait_until(at_least_40_percent_of_image_is_purple, timeout=20):
saw_purple = True
break
- assert (saw_purple), f"Did not see a screenshot with 60%% purple pixels"
+ assert (saw_purple), f"Did not see a screenshot with 40% purple pixels"
await avd.stop_activity(chrome_pkg)
diff --git a/pytest/test_embedded/tests/recording/test_recording.py b/pytest/test_embedded/tests/recording/test_recording.py
index dee9904c..81284038 100644
--- a/pytest/test_embedded/tests/recording/test_recording.py
+++ b/pytest/test_embedded/tests/recording/test_recording.py
@@ -24,7 +24,6 @@ from emu.timing import eventually
@pytest.fixture
-@pytest.mark.async_timeout(15)
async def screen_service(service):
"""A screen service fixture that will stop any active recording on test completion."""
screen_service: ScreenRecordingStub = service(ScreenRecordingStub)
diff --git a/pytest/test_embedded/tests/resizable/test_new_resizable.py b/pytest/test_embedded/tests/resizable/test_new_resizable.py
index 710fad4e..882679c7 100644
--- a/pytest/test_embedded/tests/resizable/test_new_resizable.py
+++ b/pytest/test_embedded/tests/resizable/test_new_resizable.py
@@ -93,7 +93,6 @@ async def set_display_mode(emulator_controller, mode, timeout=5):
(1920, 1080, DisplayModeValue.DESKTOP),
],
)
-@pytest.mark.timeout_win(timeout=60)
@pytest.mark.flaky
@pytest.mark.sanity
# @pytest.mark.skipos("all", "reason: b/309463427")
diff --git a/pytest/test_embedded/tests/resizable/test_resizable.py b/pytest/test_embedded/tests/resizable/test_resizable.py
index 0dfec498..7f9db787 100644
--- a/pytest/test_embedded/tests/resizable/test_resizable.py
+++ b/pytest/test_embedded/tests/resizable/test_resizable.py
@@ -58,7 +58,6 @@ async def set_display_mode(emulator_controller, mode, timeout=5):
(1920, 1080, DisplayModeValue.DESKTOP),
],
)
-@pytest.mark.timeout_win(timeout=60)
@pytest.mark.flaky
@pytest.mark.sanity
@pytest.mark.skipos("all", "reason: b/309463427")
diff --git a/pytest/test_embedded/tests/test_boot.py b/pytest/test_embedded/tests/test_boot.py
index 7250003e..168d2df5 100644
--- a/pytest/test_embedded/tests/test_boot.py
+++ b/pytest/test_embedded/tests/test_boot.py
@@ -145,8 +145,7 @@ def check_boot_from_snapshot(avdpath) -> bool:
@pytest.mark.boot
@pytest.mark.e2e
@pytest.mark.sanity
-@pytest.mark.timeout_win(timeout=120)
-@pytest.mark.skipos("all", "Test fails in presubmit")
+@pytest.mark.async_timeout(120)
async def test_snapshot_booted(emulator):
"""Make sure the emulator status is able to boot from snapshot.
@@ -222,7 +221,6 @@ async def test_emulator_should_idle(emulator):
@pytest.mark.boot
@pytest.mark.e2e
-@pytest.mark.timeout_win(timeout=60)
async def test_a_booted_emulator_immediately_notifies_it_has_booted(avd):
assert await avd.has_booted()
assert await asyncio.wait_for(get_booted_notification_time(avd), timeout=10)
@@ -293,11 +291,9 @@ async def test_first_time_booted_old_api(emulator):
assert await emulator.launch(flags=myflags)
logging.info("Waiting for it to boot up ...")
- logging.info("Booting up emulator ...")
- assert await emulator.wait_for_boot(timeout=900)
-
- # wait till it settle down a bit
- await asyncio.sleep(30)
+ await asyncio.wait_for(
+ get_booted_notification_time(emulator), timeout=1080
+ )
logging.info("Shutting down the emulator ...")
if emulator.is_alive():