diff --git a/mozregression/.launchers.py.swo b/mozregression/.launchers.py.swo new file mode 100644 index 000000000..26fb5b706 Binary files /dev/null and b/mozregression/.launchers.py.swo differ diff --git a/mozregression/cli.py b/mozregression/cli.py index 8392712df..397b47bfc 100644 --- a/mozregression/cli.py +++ b/mozregression/cli.py @@ -276,9 +276,16 @@ def create_parser(defaults): parser.add_argument( "--arch", - choices=("arm", "x86_64", "aarch64"), + choices=( + "aarch64", + "arm", + "arm64-v8a", + "armeabi-v7a", + "x86", + "x86_64", + ), default=None, - help=("Force alternate build (only applies to GVE app). Default: arm"), + help=("Force alternate build (applies to GVE and Fenix)."), ) parser.add_argument( @@ -554,12 +561,32 @@ def validate(self): """ options = self.options + arch_options = { + "gve": [ + "aarch64", + "arm", + "x86_64", + ], + "fenix": [ + "arm64-v8a", + "armeabi-v7a", + "x86", + "x86_64", + ], + } + user_defined_bits = options.bits is not None options.bits = parse_bits(options.bits or mozinfo.bits) if options.arch is not None: - if options.app != "gve": + if options.app not in ("gve", "fenix"): self.logger.warning("--arch ignored for non-GVE app.") options.arch = None + else: + if options.arch not in arch_options[options.app]: + raise MozRegressionError( + f"Invalid arch ({options.arch}) specified for app ({options.app}). " + f"Valid options are: {', '.join(arch_options[options.app])}." + ) fetch_config = create_config( options.app, mozinfo.os, options.bits, mozinfo.processor, options.arch diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index fa91b2042..e0f4cbebe 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -382,6 +382,19 @@ def get_nightly_repo_regex(self, date): return self._get_nightly_repo_regex(date, repo) +class FenixNightlyConfigMixin(NightlyConfigMixin): + nightly_base_repo_name = "fenix" + arch_regex_bits = "" + + def _get_nightly_repo(self, date): + return "fenix" + + def get_nightly_repo_regex(self, date): + repo = self.get_nightly_repo(date) + repo += self.arch_regex_bits # e.g., ".*arm64.*". + return self._get_nightly_repo_regex(date, repo) + + class IntegrationConfigMixin(metaclass=ABCMeta): """ Define the integration-related required configuration. @@ -607,6 +620,38 @@ def available_bits(self): return () +@REGISTRY.register("fenix") +class FenixConfig(CommonConfig, FenixNightlyConfigMixin): + BUILD_TYPES = ("shippable", "opt") + + def build_regex(self): + return r"fenix-.*\.apk" + + def available_bits(self): + return () + + def available_archs(self): + return [ + "arm64-v8a", + "armeabi-v7a", + "x86", + "x86_64", + ] + + def set_arch(self, arch): + CommonConfig.set_arch(self, arch) + mapping = { + "arm64-v8a": "-.+-android-arm64-v8a", + "armeabi-v7a": "-.+-android-armeabi-v7a", + "x86": "-.+-android-x86", + "x86_64": "-.+-android-x86_64", + } + self.arch_regex_bits = mapping[self.arch] + + def should_use_archive(self): + return True + + @REGISTRY.register("gve") class GeckoViewExampleConfig(CommonConfig, FennecNightlyConfigMixin, FennecIntegrationConfigMixin): BUILD_TYPES = ("shippable", "opt", "debug") diff --git a/mozregression/launchers.py b/mozregression/launchers.py index 735ade008..646506706 100644 --- a/mozregression/launchers.py +++ b/mozregression/launchers.py @@ -493,6 +493,31 @@ def _stop(self): if self.adb.exists(self.remote_profile): self.adb.rm(self.remote_profile, recursive=True) + def launch_browser( + self, + app_name, + activity, + intent="android.intent.action.VIEW", + moz_env=None, + url=None, + wait=True, + fail_if_running=True, + timeout=None, + ): + extras = {} + extras["args"] = f"-profile {self.remote_profile}" + + self.adb.launch_application( + app_name, + activity, + intent, + url=url, + extras=extras, + wait=wait, + fail_if_running=fail_if_running, + timeout=timeout, + ) + def get_app_info(self): return self.app_info @@ -504,7 +529,17 @@ def _get_package_name(self): def _launch(self): LOG.debug("Launching fennec") - self.adb.launch_fennec(self.package_name, extra_args=["-profile", self.remote_profile]) + self.launch_browser(self.package_name, "org.mozilla.gecko.BrowserApp") + + +@REGISTRY.register("fenix") +class FenixLauncher(AndroidLauncher): + def _get_package_name(self): + return "org.mozilla.fenix" + + def _launch(self): + LOG.debug("Launching fenix") + self.launch_browser(self.package_name, ".IntentReceiverActivity") @REGISTRY.register("gve") diff --git a/tests/unit/test_launchers.py b/tests/unit/test_launchers.py index 42f9fc2f5..044a4bb0d 100644 --- a/tests/unit/test_launchers.py +++ b/tests/unit/test_launchers.py @@ -371,8 +371,15 @@ def test_start_stop(self, _create_profile): self.adb.exists.assert_called_once_with(self.remote_profile_path) self.adb.rm.assert_called_once_with(self.remote_profile_path, recursive=True) self.adb.push.assert_called_once_with(self.profile.profile, self.remote_profile_path) - self.adb.launch_fennec.assert_called_once_with( - "org.mozilla.fennec", extra_args=["-profile", self.remote_profile_path] + self.adb.launch_application.assert_called_once_with( + "org.mozilla.fennec", + "org.mozilla.gecko.BrowserApp", + "android.intent.action.VIEW", + url=None, + extras={"args": f"-profile {self.remote_profile_path}"}, + wait=True, + fail_if_running=True, + timeout=None, ) # ensure get_app_info returns something self.assertIsNotNone(launcher.get_app_info()) @@ -387,8 +394,15 @@ def test_adb_calls_with_custom_package_name(self, _create_profile): launcher = self.create_launcher(version_value={"package_name": pkg_name}) self.adb.uninstall_app.assert_called_once_with(pkg_name) launcher.start(profile="my_profile") - self.adb.launch_fennec.assert_called_once_with( - pkg_name, extra_args=["-profile", self.remote_profile_path] + self.adb.launch_application.assert_called_once_with( + pkg_name, + "org.mozilla.gecko.BrowserApp", + "android.intent.action.VIEW", + url=None, + extras={"args": f"-profile {self.remote_profile_path}"}, + wait=True, + fail_if_running=True, + timeout=None, ) launcher.stop() self.adb.stop_application.assert_called_once_with(pkg_name)