summaryrefslogtreecommitdiffstats
path: root/tools/lint/test/test_condprof_addons.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /tools/lint/test/test_condprof_addons.py
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tools/lint/test/test_condprof_addons.py')
-rw-r--r--tools/lint/test/test_condprof_addons.py285
1 files changed, 285 insertions, 0 deletions
diff --git a/tools/lint/test/test_condprof_addons.py b/tools/lint/test/test_condprof_addons.py
new file mode 100644
index 0000000000..e1401a7119
--- /dev/null
+++ b/tools/lint/test/test_condprof_addons.py
@@ -0,0 +1,285 @@
+import importlib
+import tempfile
+from pathlib import Path
+from unittest import mock
+
+import mozunit
+import requests
+
+LINTER = "condprof-addons"
+
+
+def linter_module_mocks(
+ customizations_path=".", browsertime_fetches_path="browsertime.yml", **othermocks
+):
+ return mock.patch.multiple(
+ LINTER,
+ CUSTOMIZATIONS_PATH=Path(customizations_path),
+ BROWSERTIME_FETCHES_PATH=Path(browsertime_fetches_path),
+ **othermocks,
+ )
+
+
+def linter_class_mocks(**mocks):
+ return mock.patch.multiple(
+ f"{LINTER}.CondprofAddonsLinter",
+ **mocks,
+ )
+
+
+# Sanity check (make sure linter message includes the xpi filename).
+def test_get_missing_xpi_msg(lint, paths):
+ condprof_addons = importlib.import_module("condprof-addons")
+ with linter_class_mocks(
+ get_firefox_addons_tar_names=mock.Mock(return_value=list()),
+ ):
+ instance = condprof_addons.CondprofAddonsLinter(
+ topsrcdir=paths()[0], logger=mock.Mock()
+ )
+ assert instance.get_missing_xpi_msg("test.xpi").startswith(
+ "test.xpi is missing"
+ )
+
+
+def test_xpi_missing_from_firefox_addons_tar(lint, paths):
+ fixture_customizations = paths("with-missing-xpi.json")
+ with linter_module_mocks(), linter_class_mocks(
+ get_firefox_addons_tar_names=mock.Mock(return_value=list()),
+ ):
+ logger_mock = mock.Mock()
+ lint(fixture_customizations, logger=logger_mock)
+ assert logger_mock.lint_error.call_count == 1
+ assert Path(fixture_customizations[0]).samefile(
+ logger_mock.lint_error.call_args.kwargs["path"]
+ )
+ importlib.import_module("condprof-addons")
+ assert "non-existing.xpi" in logger_mock.lint_error.call_args.args[0]
+
+
+def test_xpi_all_found_in_firefox_addons_tar(lint, paths):
+ get_tarnames_mock = mock.Mock(
+ return_value=["an-extension.xpi", "another-extension.xpi"]
+ )
+ read_json_mock = mock.Mock(
+ return_value={
+ "addons": {
+ "an-extension": "http://localhost/ext/an-extension.xpi",
+ "another-extension": "http://localhost/ext/another-extension.xpi",
+ }
+ }
+ )
+
+ with linter_module_mocks(), linter_class_mocks(
+ get_firefox_addons_tar_names=get_tarnames_mock, read_json=read_json_mock
+ ):
+ logger_mock = mock.Mock()
+ # Compute a fake condprof customization path, the content is
+ # going to be the read_json_mock.return_value and so the
+ # fixture file does not actually exists.
+ fixture_customizations = paths("fake-condprof-config.json")
+ lint(
+ fixture_customizations,
+ logger=logger_mock,
+ config={"include": paths(), "extensions": ["json", "yml"]},
+ )
+ assert read_json_mock.call_count == 1
+ assert get_tarnames_mock.call_count == 1
+ assert logger_mock.lint_error.call_count == 0
+
+
+def test_lint_error_on_missing_or_invalid_firefoxaddons_fetch_task(
+ lint,
+ paths,
+):
+ read_json_mock = mock.Mock(return_value=dict())
+ read_yaml_mock = mock.Mock(return_value=dict())
+ # Verify that an explicit linter error is reported if the fetch task is not found.
+ with linter_module_mocks(), linter_class_mocks(
+ read_json=read_json_mock, read_yaml=read_yaml_mock
+ ):
+ logger_mock = mock.Mock()
+ fixture_customizations = paths("fake-condprof-config.json")
+ condprof_addons = importlib.import_module("condprof-addons")
+
+ def assert_linter_error(yaml_mock_value, expected_msg):
+ logger_mock.reset_mock()
+ read_yaml_mock.return_value = yaml_mock_value
+ lint(fixture_customizations, logger=logger_mock)
+ assert logger_mock.lint_error.call_count == 1
+ expected_path = condprof_addons.BROWSERTIME_FETCHES_PATH
+ assert logger_mock.lint_error.call_args.kwargs["path"] == expected_path
+ assert logger_mock.lint_error.call_args.args[0] == expected_msg
+
+ # Mock a yaml file that is not including the expected firefox-addons fetch task.
+ assert_linter_error(
+ yaml_mock_value=dict(), expected_msg=condprof_addons.ERR_FETCH_TASK_MISSING
+ )
+ # Mock a yaml file where firefox-addons is missing the fetch attribute.
+ assert_linter_error(
+ yaml_mock_value={"firefox-addons": {}},
+ expected_msg=condprof_addons.ERR_FETCH_TASK_MISSING,
+ )
+ # Mock a yaml file where firefox-addons add-prefix is missing.
+ assert_linter_error(
+ yaml_mock_value={"firefox-addons": {"fetch": {}}},
+ expected_msg=condprof_addons.ERR_FETCH_TASK_ADDPREFIX,
+ )
+ # Mock a yaml file where firefox-addons add-prefix is invalid.
+ assert_linter_error(
+ yaml_mock_value={
+ "firefox-addons": {"fetch": {"add-prefix": "invalid-subdir-name/"}}
+ },
+ expected_msg=condprof_addons.ERR_FETCH_TASK_ADDPREFIX,
+ )
+
+
+def test_get_xpi_list_from_fetch_dir(lint, paths):
+ # Verify that when executed on the CI, the helper method looks for the xpi files
+ # in the MOZ_FETCHES_DIR subdir where they are expected to be unpacked by the
+ # fetch task.
+ with linter_module_mocks(
+ MOZ_AUTOMATION=1, MOZ_FETCHES_DIR=paths("fake-fetches-dir")[0]
+ ):
+ condprof_addons = importlib.import_module("condprof-addons")
+ logger_mock = mock.Mock()
+ Path(paths("browsertime.yml")[0])
+
+ linter = condprof_addons.CondprofAddonsLinter(
+ topsrcdir=paths()[0], logger=logger_mock
+ )
+ results = linter.tar_xpi_filenames
+
+ results.sort()
+ assert results == ["fake-ext-01.xpi", "fake-ext-02.xpi"]
+
+
+def test_get_xpi_list_from_downloaded_tar(lint, paths):
+ def mocked_download_tar(firefox_addons_tar_url, tar_tmp_path):
+ tar_tmp_path.write_bytes(Path(paths("firefox-addons-fake.tar")[0]).read_bytes())
+
+ download_firefox_addons_tar_mock = mock.Mock()
+ download_firefox_addons_tar_mock.side_effect = mocked_download_tar
+
+ # Verify that when executed locally on a developer machine, the tar archive is downloaded
+ # and the list of xpi files included in it returned by the helper method.
+ with tempfile.TemporaryDirectory() as tempdir, linter_module_mocks(
+ MOZ_AUTOMATION=0,
+ tempdir=tempdir,
+ ), linter_class_mocks(
+ download_firefox_addons_tar=download_firefox_addons_tar_mock,
+ ):
+ condprof_addons = importlib.import_module("condprof-addons")
+ logger_mock = mock.Mock()
+ Path(paths("browsertime.yml")[0])
+
+ linter = condprof_addons.CondprofAddonsLinter(
+ topsrcdir=paths()[0], logger=logger_mock
+ )
+ results = linter.tar_xpi_filenames
+ assert len(results) > 0
+ print("List of addons found in the downloaded file archive:", results)
+ assert all(filename.endswith(".xpi") for filename in results)
+ assert download_firefox_addons_tar_mock.call_count == 1
+
+
+@mock.patch("requests.get")
+def test_error_on_downloading_tar(requests_get_mock, lint, paths):
+ # Verify that when executed locally and the tar archive fails to download
+ # the linter does report an explicit linting error with the http error included.
+ with tempfile.TemporaryDirectory() as tempdir, linter_module_mocks(
+ MOZ_AUTOMATION=0, tempdir=tempdir
+ ):
+ condprof_addons = importlib.import_module("condprof-addons")
+ logger_mock = mock.Mock()
+ response_mock = mock.Mock()
+ response_mock.raise_for_status.side_effect = requests.exceptions.HTTPError(
+ "MOCK_ERROR"
+ )
+ requests_get_mock.return_value = response_mock
+ Path(paths("browsertime.yml")[0])
+
+ linter = condprof_addons.CondprofAddonsLinter(
+ topsrcdir=paths()[0], logger=logger_mock
+ )
+
+ assert (
+ logger_mock.lint_error.call_args.kwargs["path"]
+ == condprof_addons.BROWSERTIME_FETCHES_PATH
+ )
+ assert (
+ logger_mock.lint_error.call_args.args[0]
+ == f"{condprof_addons.ERR_FETCH_TASK_ARCHIVE}, MOCK_ERROR"
+ )
+ assert requests_get_mock.call_count == 1
+ assert len(linter.tar_xpi_filenames) == 0
+
+
+@mock.patch("requests.get")
+def test_error_on_opening_tar(requests_get_mock, lint, paths):
+ # Verify that when executed locally and the tar archive fails to open
+ # the linter does report an explicit linting error with the tarfile error included.
+ with tempfile.TemporaryDirectory() as tempdir, linter_module_mocks(
+ MOZ_AUTOMATION=0, tempdir=tempdir
+ ):
+ condprof_addons = importlib.import_module("condprof-addons")
+ logger_mock = mock.Mock()
+ response_mock = mock.Mock()
+ response_mock.raise_for_status.return_value = None
+
+ def mock_iter_content(chunk_size):
+ yield b"fake tar content"
+ yield b"expected to trigger tarfile.ReadError"
+
+ response_mock.iter_content.side_effect = mock_iter_content
+ requests_get_mock.return_value = response_mock
+ Path(paths("browsertime.yml")[0])
+
+ linter = condprof_addons.CondprofAddonsLinter(
+ topsrcdir=paths()[0], logger=logger_mock
+ )
+
+ assert (
+ logger_mock.lint_error.call_args.kwargs["path"]
+ == condprof_addons.BROWSERTIME_FETCHES_PATH
+ )
+ actual_msg = logger_mock.lint_error.call_args.args[0]
+ print("Got linter error message:", actual_msg)
+ assert actual_msg.startswith(
+ f"{condprof_addons.ERR_FETCH_TASK_ARCHIVE}, file could not be opened successfully"
+ )
+ assert requests_get_mock.call_count == 1
+ assert len(linter.tar_xpi_filenames) == 0
+
+
+def test_lint_all_customization_files_when_linting_browsertime_yml(
+ lint,
+ paths,
+):
+ get_tarnames_mock = mock.Mock(return_value=["an-extension.xpi"])
+ read_json_mock = mock.Mock(
+ return_value={
+ "addons": {"an-extension": "http://localhost/ext/an-extension.xpi"}
+ }
+ )
+ with linter_module_mocks(
+ customizations_path="fake-customizations-dir",
+ ), linter_class_mocks(
+ get_firefox_addons_tar_names=get_tarnames_mock,
+ read_json=read_json_mock,
+ ):
+ logger_mock = mock.Mock()
+ importlib.import_module("condprof-addons")
+ # When mozlint detects a change to the ci fetch browser.yml support file,
+ # condprof-addons linter is called for the entire customizations dir path
+ # and we expect that to be expanded to the list of the json customizations
+ # files from that directory path.
+ lint(paths("fake-customizations-dir"), logger=logger_mock)
+ # Expect read_json_mock to be called once per each of the json files
+ # found in the fixture dir.
+ assert read_json_mock.call_count == 3
+ assert get_tarnames_mock.call_count == 1
+ assert logger_mock.lint_error.call_count == 0
+
+
+if __name__ == "__main__":
+ mozunit.main()