diff --git a/gui/mozregui/wizard.py b/gui/mozregui/wizard.py index a97ac56d0..6cc5ae9cb 100644 --- a/gui/mozregui/wizard.py +++ b/gui/mozregui/wizard.py @@ -121,7 +121,8 @@ def _set_fetch_config(self, index): self.fetch_config = create_config(app_name, mozinfo.os, bits, mozinfo.processor) - self.arch_model = QStringListModel(self.fetch_config.available_archs()) + available_archs = self.fetch_config.available_archs() + self.arch_model = QStringListModel(available_archs) self.ui.arch_combo.setModel(self.arch_model) if not self.arch_model.stringList(): self.ui.arch_label.setDisabled(True) @@ -129,6 +130,8 @@ def _set_fetch_config(self, index): else: self.ui.arch_label.setEnabled(True) self.ui.arch_combo.setEnabled(True) + if mozinfo.processor in available_archs: + self.ui.arch_combo.setCurrentIndex(available_archs.index(mozinfo.processor)) self.build_type_model = QStringListModel(self.fetch_config.available_build_types()) self.ui.build_type.setModel(self.build_type_model) diff --git a/mozregression/cli.py b/mozregression/cli.py index efc1b4bfb..835ec623d 100644 --- a/mozregression/cli.py +++ b/mozregression/cli.py @@ -285,7 +285,7 @@ def create_parser(defaults): "x86_64", ), default=None, - help=("Force alternate build (applies to GVE, Fenix, and Focus)."), + help=("Force alternate build (applies to Firefox, Firefox-l10n, GVE, Fenix, and Focus)."), ) parser.add_argument( @@ -562,6 +562,16 @@ def validate(self): options = self.options arch_options = { + "firefox": [ + "aarch64", + "x86", + "x86_64", + ], + "firefox-l10n": [ + "aarch64", + "x86", + "x86_64", + ], "gve": [ "aarch64", "arm", @@ -585,8 +595,18 @@ def validate(self): options.bits = parse_bits(options.bits or mozinfo.bits) if options.arch is not None: - if options.app not in ("gve", "fenix", "focus"): - self.logger.warning("--arch ignored for non Android apps.") + if user_defined_bits: + self.logger.warning( + "--arch and --bits are passed together. --arch will be preferred." + ) + + if options.app not in arch_options: + self.logger.warning(f"--arch ignored for {options.app}.") + options.arch = None + elif options.app in ("firefox", "firefox-l10n") and mozinfo.os == "mac": + self.logger.warning( + "--arch ignored for Firefox for macOS as it uses unified binary." + ) options.arch = None elif options.arch not in arch_options[options.app]: raise MozRegressionError( @@ -630,7 +650,7 @@ def validate(self): self.logger.info("bits option not specified, using 64-bit builds.") if options.bits == 32 and mozinfo.os == "mac": - self.logger.info("only 64-bit builds available for mac, using " "64-bit builds") + self.logger.info("only 64-bit builds available for mac, using 64-bit builds.") if fetch_config.is_integration() and fetch_config.tk_needs_auth(): creds = tc_authenticate(self.logger) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index df145f93f..a24549075 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -47,7 +47,25 @@ TIMESTAMP_GECKOVIEW_ARM = to_utc_timestamp(datetime.datetime(2021, 6, 5, 3, 56, 19)) -def get_build_regex(name, os, bits, processor, platprefix=r".*", platsuffix="", with_ext=True): +def infer_arch_from_bits(bits, processor): + """ + Infers the processor architecture from the bits argument. + + :param bits: the bits information of the build. Either 32 or 64. + :param processor: the architecture of the build. + """ + if bits == 64: + if processor == "aarch64": + return processor + else: + return "x86_64" + else: + return "x86" + + +def get_build_regex( + name, os, bits, processor, platprefix=r".*", platsuffix="", with_ext=True, arch=None +): """ Returns a string regexp that can match a build filename. @@ -60,21 +78,27 @@ def get_build_regex(name, os, bits, processor, platprefix=r".*", platsuffix="", :param platsuffix: optional suffix after the platform :param with_ext: if True, the build extension will be appended (either .zip, .tar.bz2 or .dmg depending on the os). + :param arch: optional arch, either x86, x86_64, aarch64. Inferred from bits if not given. """ + if arch is None: + arch = infer_arch_from_bits(bits, processor) + if os == "win": - if bits == 64: - if processor == "aarch64": - platform = r"win64-aarch64" - else: - platform = r"win64(-x86_64)?" - ext = r"\.zip" + ext = r"\.zip" + if arch == "aarch64": + platform = r"win64-aarch64" + elif arch == "x86_64": + platform = r"win64(-x86_64)?" else: - platform, ext = r"win32", r"\.zip" + platform = r"win32" elif os == "linux": - if bits == 64: - platform, ext = r"linux-x86_64", r"\.tar.bz2" + ext = r"\.tar.bz2" + if arch == "aarch64": + platform = r"linux-aarch64" + elif arch == "x86_64": + platform = r"linux-x86_64" else: - platform, ext = r"linux-i686", r"\.tar.bz2" + platform = r"linux-i686" elif os == "mac": platform, ext = r"mac.*", r"\.dmg" else: @@ -132,7 +156,9 @@ def build_regex(self): """ Returns a string regex that can match a build file on the servers. """ - return get_build_regex(self.app_name, self.os, self.bits, self.processor) + "$" + return ( + get_build_regex(self.app_name, self.os, self.bits, self.processor, arch=self.arch) + "$" + ) def build_info_regex(self): """ @@ -140,7 +166,9 @@ def build_info_regex(self): on the servers. """ return ( - get_build_regex(self.app_name, self.os, self.bits, self.processor, with_ext=False) + get_build_regex( + self.app_name, self.os, self.bits, self.processor, with_ext=False, arch=self.arch + ) + r"\.txt$" ) @@ -577,6 +605,7 @@ def build_regex(self): self.bits, self.processor, platprefix=r".*\." + self.lang + r"\.", + arch=self.arch, ) + "$" ) @@ -609,14 +638,37 @@ def build_regex(self): self.bits, self.processor, platsuffix="-asan-reporter" if "asan" in self.build_type else "", + arch=self.arch, ) + "$" ) + def available_bits(self): + """ + Returns the available bits for this application. + """ + return () + + def available_archs(self): + """ + Returns the available architectures for this application. + """ + return ["x86", "x86_64", "aarch64"] + @REGISTRY.register("firefox-l10n", attr_value="firefox") class FirefoxL10nConfig(L10nMixin, FirefoxL10nNightlyConfigMixin, CommonConfig): - pass + def available_bits(self): + """ + Returns the available bits for this application. + """ + return () + + def available_archs(self): + """ + Returns the available architectures for this application. + """ + return ["x86", "x86_64", "aarch64"] @REGISTRY.register("thunderbird") @@ -731,22 +783,29 @@ class JsShellConfig(FirefoxConfig): def build_info_regex(self): # the info file is the one for firefox return ( - get_build_regex("firefox", self.os, self.bits, self.processor, with_ext=False) + get_build_regex( + "firefox", self.os, self.bits, self.processor, with_ext=False, arch=self.arch + ) + r"\.txt$" ) def build_regex(self): + arch = self.arch + if arch is None: + arch = infer_arch_from_bits(self.bits, self.processor) + if self.os == "linux": - if self.bits == 64: + if arch == "aarch64": + part = "linux-aarch64" + elif arch == "x86_64": part = "linux-x86_64" else: part = "linux-i686" elif self.os == "win": - if self.bits == 64: - if self.processor == "aarch64": - part = "win64-aarch64" - else: - part = "win64(-x86_64)?" + if arch == "aarch64": + part = "win64-aarch64" + elif arch == "x86_64": + part = "win64(-x86_64)?" else: part = "win32" else: diff --git a/tests/unit/test_fetch_configs.py b/tests/unit/test_fetch_configs.py index 3a93b0628..133ef4b5c 100644 --- a/tests/unit/test_fetch_configs.py +++ b/tests/unit/test_fetch_configs.py @@ -154,6 +154,34 @@ def test_nightly_repo_regex_before_2005_10_19(self): self.conf.get_nightly_repo_regex(datetime.date(2005, 9, 7)) +class TestFirefoxl10nConfigWithArch(unittest.TestCase): + app_name = "firefox-l10n" + os = "linux" + bits = 64 + processor = "aarch64" + lang = "ar" + arch = "x86" + + instance_type = FirefoxL10nConfig + + build_examples = ["firefox-38.0a1.ar.linux-i686.tar.bz2"] + build_info_examples = ["firefox-38.0a1.en-US.linux-i686.txt"] + + def setUp(self): + self.conf = create_config(self.app_name, self.os, self.bits, self.processor, arch=self.arch) + self.conf.set_lang(self.lang) + + def test_build_regex(self): + for example in self.build_examples: + res = re.match(self.conf.build_regex(), example) + self.assertIsNotNone(res) + + def test_build_info_regex(self): + for example in self.build_info_examples: + res = re.match(self.conf.build_info_regex(), example) + self.assertIsNotNone(res) + + class TestThunderbirdConfig(unittest.TestCase): os = "linux" bits = 64 @@ -295,6 +323,14 @@ def test_for_linux(self): get_build_regex("test", "linux", 64, "x86_64", with_ext=False), r"(target|test.*linux-x86_64)", ) + self.assertEqual( + get_build_regex("test", "linux", 64, "x86_64", arch="x86"), + r"(target|test.*linux-i686)\.tar.bz2", + ) + self.assertEqual( + get_build_regex("test", "linux", 64, "aarch64"), + r"(target|test.*linux-aarch64)\.tar.bz2", + ) def test_for_win(self): self.assertEqual(get_build_regex("test", "win", 32, "x86"), r"(target|test.*win32)\.zip") @@ -313,6 +349,14 @@ def test_for_win(self): get_build_regex("test", "win", 64, "aarch64"), r"(target|test.*win64-aarch64)\.zip", ) + self.assertEqual( + get_build_regex("test", "win", 64, "aarch64", arch="x86_64"), + r"(target|test.*win64(-x86_64)?)\.zip", + ) + self.assertEqual( + get_build_regex("test", "win", 64, "aarch64", arch="x86"), + r"(target|test.*win32)\.zip", + ) def test_for_mac(self): self.assertEqual(get_build_regex("test", "mac", 32, "x86"), r"(target|test.*mac.*)\.dmg") @@ -550,7 +594,10 @@ def test_jsshell_build_info_regex(): [ ("linux", 32, "x86", "jsshell-linux-i686.zip"), ("linux", 64, "x86_64", "jsshell-linux-x86_64.zip"), + ("linux", 32, "aarch64", "jsshell-linux-i686.zip"), + ("linux", 64, "aarch64", "jsshell-linux-aarch64.zip"), ("mac", 64, "x86_64", "jsshell-mac.zip"), + ("mac", 64, "aarch64", "jsshell-mac.zip"), ("win", 32, "x86", "jsshell-win32.zip"), ("win", 64, "x86_64", "jsshell-win64.zip"), ("win", 64, "x86_64", "jsshell-win64-x86_64.zip"), @@ -568,6 +615,14 @@ def test_jsshell_x86_64_build_regex(): assert not re.match(conf.build_regex(), "jsshell-win64-aarch64.zip") +def test_jsshell_aarch64_build_regex(): + conf = create_config("jsshell", "win", 64, "aarch64") + assert re.match(conf.build_regex(), "jsshell-win64-aarch64.zip") + + conf = create_config("jsshell", "win", 64, "aarch64", arch="x86_64") + assert re.match(conf.build_regex(), "jsshell-win64-x86_64.zip") + + @pytest.mark.parametrize( "os,bits,processor,tc_suffix", [