diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /tools/lint/test/test_condprof_addons.py | |
parent | Initial commit. (diff) | |
download | firefox-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.py | 285 |
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() |