From 911e02ba10eb3fdd698e28bfcbb880339ced2461 Mon Sep 17 00:00:00 2001 From: Russell Martin Date: Thu, 14 Mar 2024 12:17:16 -0400 Subject: [PATCH] Exclude logging output from emulator list --- changes/1697.bugfix.rst | 1 + src/briefcase/integrations/android_sdk.py | 19 +++---- .../android_sdk/AndroidSDK/test_emulators.py | 53 ++++++++++--------- 3 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 changes/1697.bugfix.rst diff --git a/changes/1697.bugfix.rst b/changes/1697.bugfix.rst new file mode 100644 index 000000000..2db576c14 --- /dev/null +++ b/changes/1697.bugfix.rst @@ -0,0 +1 @@ +A spurious Android emulator named ``@INFO`` will no longer be included in the list of available emulators. diff --git a/src/briefcase/integrations/android_sdk.py b/src/briefcase/integrations/android_sdk.py index 40ff8ca43..40802db93 100644 --- a/src/briefcase/integrations/android_sdk.py +++ b/src/briefcase/integrations/android_sdk.py @@ -814,10 +814,10 @@ def verify_emulator_skin(self, skin: str): extract_dir=skin_path, **({"filter": "data"} if sys.version_info >= (3, 12) else {}), ) - except (shutil.ReadError, EOFError) as err: + except (shutil.ReadError, EOFError) as e: raise BriefcaseCommandError( f"Unable to unpack {skin} device skin." - ) from err + ) from e # Delete the downloaded file. skin_tgz_path.unlink() @@ -825,17 +825,18 @@ def verify_emulator_skin(self, skin: str): def emulators(self) -> list[str]: """Find the list of emulators that are available.""" try: - # Capture `stderr` so that if the process exits with failure, the - # stderr data is in `e.output`. - output = self.tools.subprocess.check_output( + emulators = self.tools.subprocess.check_output( [self.emulator_path, "-list-avds"] ).strip() - # AVD names are returned one per line. - if len(output) == 0: - return [] - return output.split("\n") except subprocess.CalledProcessError as e: raise BriefcaseCommandError("Unable to obtain Android emulator list") from e + else: + return [ + emu + for emu in emulators.split("\n") + # ignore any logging output included in output list + if emu and not emu.startswith(("INFO |", "WARNING |", "ERROR |")) + ] def devices(self) -> dict[str, dict[str, str | bool]]: """Find the devices that are attached and available to ADB.""" diff --git a/tests/integrations/android_sdk/AndroidSDK/test_emulators.py b/tests/integrations/android_sdk/AndroidSDK/test_emulators.py index 1619345c7..7a9fb001a 100644 --- a/tests/integrations/android_sdk/AndroidSDK/test_emulators.py +++ b/tests/integrations/android_sdk/AndroidSDK/test_emulators.py @@ -5,32 +5,35 @@ from briefcase.exceptions import BriefcaseCommandError -def test_no_emulators(mock_tools, android_sdk): - """If there are no emulators, an empty list is returned.""" - mock_tools.subprocess.check_output.return_value = "" - - assert android_sdk.emulators() == [] - - -def test_one_emulator(mock_tools, android_sdk): - """If there is a single emulator, it is returned.""" - mock_tools.subprocess.check_output.return_value = "first\n" - - assert android_sdk.emulators() == ["first"] - - -def test_multiple_emulators(mock_tools, android_sdk): - """If there are multiple emulators, they are all returned.""" - mock_tools.subprocess.check_output.return_value = "first\nsecond\nthird\n" - - assert android_sdk.emulators() == ["first", "second", "third"] - - -def test_adb_error(mock_tools, android_sdk): - """If there is a problem invoking adb, an error is returned.""" +@pytest.mark.parametrize( + "output, expected_list", + [ + ("", []), + ("first\n", ["first"]), + ("first\nsecond\nthird\n", ["first", "second", "third"]), + ("first\n\nsecond", ["first", "second"]), + ( + "first\nINFO | Storing crashdata in\nsecond\nWARNING | nothing to see\n" + "third\nERROR | lot to see here", + ["first", "second", "third"], + ), + ], +) +def test_no_emulators(mock_tools, android_sdk, output, expected_list): + """The returned list of emulators is properly parsed.""" + mock_tools.subprocess.check_output.return_value = output + + assert android_sdk.emulators() == expected_list + + +def test_emulator_error(mock_tools, android_sdk): + """If there is a problem invoking emulator, an error is returned.""" mock_tools.subprocess.check_output.side_effect = subprocess.CalledProcessError( - returncode=69, cmd="adb devices -l" + returncode=69, cmd="emulator -list-avd" ) - with pytest.raises(BriefcaseCommandError): + with pytest.raises( + BriefcaseCommandError, + match=r"Unable to obtain Android emulator list", + ): android_sdk.emulators()