Bug 1874684 - Part 17: Fix uninitialised variable warnings from clang-tidy. r=allstarschh
[gecko.git] / tools / lint / test / test_condprof_addons.py
blobe1401a7119ff40117482f31ea7b2047f60301a74
1 import importlib
2 import tempfile
3 from pathlib import Path
4 from unittest import mock
6 import mozunit
7 import requests
9 LINTER = "condprof-addons"
12 def linter_module_mocks(
13 customizations_path=".", browsertime_fetches_path="browsertime.yml", **othermocks
15 return mock.patch.multiple(
16 LINTER,
17 CUSTOMIZATIONS_PATH=Path(customizations_path),
18 BROWSERTIME_FETCHES_PATH=Path(browsertime_fetches_path),
19 **othermocks,
23 def linter_class_mocks(**mocks):
24 return mock.patch.multiple(
25 f"{LINTER}.CondprofAddonsLinter",
26 **mocks,
30 # Sanity check (make sure linter message includes the xpi filename).
31 def test_get_missing_xpi_msg(lint, paths):
32 condprof_addons = importlib.import_module("condprof-addons")
33 with linter_class_mocks(
34 get_firefox_addons_tar_names=mock.Mock(return_value=list()),
36 instance = condprof_addons.CondprofAddonsLinter(
37 topsrcdir=paths()[0], logger=mock.Mock()
39 assert instance.get_missing_xpi_msg("test.xpi").startswith(
40 "test.xpi is missing"
44 def test_xpi_missing_from_firefox_addons_tar(lint, paths):
45 fixture_customizations = paths("with-missing-xpi.json")
46 with linter_module_mocks(), linter_class_mocks(
47 get_firefox_addons_tar_names=mock.Mock(return_value=list()),
49 logger_mock = mock.Mock()
50 lint(fixture_customizations, logger=logger_mock)
51 assert logger_mock.lint_error.call_count == 1
52 assert Path(fixture_customizations[0]).samefile(
53 logger_mock.lint_error.call_args.kwargs["path"]
55 importlib.import_module("condprof-addons")
56 assert "non-existing.xpi" in logger_mock.lint_error.call_args.args[0]
59 def test_xpi_all_found_in_firefox_addons_tar(lint, paths):
60 get_tarnames_mock = mock.Mock(
61 return_value=["an-extension.xpi", "another-extension.xpi"]
63 read_json_mock = mock.Mock(
64 return_value={
65 "addons": {
66 "an-extension": "http://localhost/ext/an-extension.xpi",
67 "another-extension": "http://localhost/ext/another-extension.xpi",
72 with linter_module_mocks(), linter_class_mocks(
73 get_firefox_addons_tar_names=get_tarnames_mock, read_json=read_json_mock
75 logger_mock = mock.Mock()
76 # Compute a fake condprof customization path, the content is
77 # going to be the read_json_mock.return_value and so the
78 # fixture file does not actually exists.
79 fixture_customizations = paths("fake-condprof-config.json")
80 lint(
81 fixture_customizations,
82 logger=logger_mock,
83 config={"include": paths(), "extensions": ["json", "yml"]},
85 assert read_json_mock.call_count == 1
86 assert get_tarnames_mock.call_count == 1
87 assert logger_mock.lint_error.call_count == 0
90 def test_lint_error_on_missing_or_invalid_firefoxaddons_fetch_task(
91 lint,
92 paths,
94 read_json_mock = mock.Mock(return_value=dict())
95 read_yaml_mock = mock.Mock(return_value=dict())
96 # Verify that an explicit linter error is reported if the fetch task is not found.
97 with linter_module_mocks(), linter_class_mocks(
98 read_json=read_json_mock, read_yaml=read_yaml_mock
100 logger_mock = mock.Mock()
101 fixture_customizations = paths("fake-condprof-config.json")
102 condprof_addons = importlib.import_module("condprof-addons")
104 def assert_linter_error(yaml_mock_value, expected_msg):
105 logger_mock.reset_mock()
106 read_yaml_mock.return_value = yaml_mock_value
107 lint(fixture_customizations, logger=logger_mock)
108 assert logger_mock.lint_error.call_count == 1
109 expected_path = condprof_addons.BROWSERTIME_FETCHES_PATH
110 assert logger_mock.lint_error.call_args.kwargs["path"] == expected_path
111 assert logger_mock.lint_error.call_args.args[0] == expected_msg
113 # Mock a yaml file that is not including the expected firefox-addons fetch task.
114 assert_linter_error(
115 yaml_mock_value=dict(), expected_msg=condprof_addons.ERR_FETCH_TASK_MISSING
117 # Mock a yaml file where firefox-addons is missing the fetch attribute.
118 assert_linter_error(
119 yaml_mock_value={"firefox-addons": {}},
120 expected_msg=condprof_addons.ERR_FETCH_TASK_MISSING,
122 # Mock a yaml file where firefox-addons add-prefix is missing.
123 assert_linter_error(
124 yaml_mock_value={"firefox-addons": {"fetch": {}}},
125 expected_msg=condprof_addons.ERR_FETCH_TASK_ADDPREFIX,
127 # Mock a yaml file where firefox-addons add-prefix is invalid.
128 assert_linter_error(
129 yaml_mock_value={
130 "firefox-addons": {"fetch": {"add-prefix": "invalid-subdir-name/"}}
132 expected_msg=condprof_addons.ERR_FETCH_TASK_ADDPREFIX,
136 def test_get_xpi_list_from_fetch_dir(lint, paths):
137 # Verify that when executed on the CI, the helper method looks for the xpi files
138 # in the MOZ_FETCHES_DIR subdir where they are expected to be unpacked by the
139 # fetch task.
140 with linter_module_mocks(
141 MOZ_AUTOMATION=1, MOZ_FETCHES_DIR=paths("fake-fetches-dir")[0]
143 condprof_addons = importlib.import_module("condprof-addons")
144 logger_mock = mock.Mock()
145 Path(paths("browsertime.yml")[0])
147 linter = condprof_addons.CondprofAddonsLinter(
148 topsrcdir=paths()[0], logger=logger_mock
150 results = linter.tar_xpi_filenames
152 results.sort()
153 assert results == ["fake-ext-01.xpi", "fake-ext-02.xpi"]
156 def test_get_xpi_list_from_downloaded_tar(lint, paths):
157 def mocked_download_tar(firefox_addons_tar_url, tar_tmp_path):
158 tar_tmp_path.write_bytes(Path(paths("firefox-addons-fake.tar")[0]).read_bytes())
160 download_firefox_addons_tar_mock = mock.Mock()
161 download_firefox_addons_tar_mock.side_effect = mocked_download_tar
163 # Verify that when executed locally on a developer machine, the tar archive is downloaded
164 # and the list of xpi files included in it returned by the helper method.
165 with tempfile.TemporaryDirectory() as tempdir, linter_module_mocks(
166 MOZ_AUTOMATION=0,
167 tempdir=tempdir,
168 ), linter_class_mocks(
169 download_firefox_addons_tar=download_firefox_addons_tar_mock,
171 condprof_addons = importlib.import_module("condprof-addons")
172 logger_mock = mock.Mock()
173 Path(paths("browsertime.yml")[0])
175 linter = condprof_addons.CondprofAddonsLinter(
176 topsrcdir=paths()[0], logger=logger_mock
178 results = linter.tar_xpi_filenames
179 assert len(results) > 0
180 print("List of addons found in the downloaded file archive:", results)
181 assert all(filename.endswith(".xpi") for filename in results)
182 assert download_firefox_addons_tar_mock.call_count == 1
185 @mock.patch("requests.get")
186 def test_error_on_downloading_tar(requests_get_mock, lint, paths):
187 # Verify that when executed locally and the tar archive fails to download
188 # the linter does report an explicit linting error with the http error included.
189 with tempfile.TemporaryDirectory() as tempdir, linter_module_mocks(
190 MOZ_AUTOMATION=0, tempdir=tempdir
192 condprof_addons = importlib.import_module("condprof-addons")
193 logger_mock = mock.Mock()
194 response_mock = mock.Mock()
195 response_mock.raise_for_status.side_effect = requests.exceptions.HTTPError(
196 "MOCK_ERROR"
198 requests_get_mock.return_value = response_mock
199 Path(paths("browsertime.yml")[0])
201 linter = condprof_addons.CondprofAddonsLinter(
202 topsrcdir=paths()[0], logger=logger_mock
205 assert (
206 logger_mock.lint_error.call_args.kwargs["path"]
207 == condprof_addons.BROWSERTIME_FETCHES_PATH
209 assert (
210 logger_mock.lint_error.call_args.args[0]
211 == f"{condprof_addons.ERR_FETCH_TASK_ARCHIVE}, MOCK_ERROR"
213 assert requests_get_mock.call_count == 1
214 assert len(linter.tar_xpi_filenames) == 0
217 @mock.patch("requests.get")
218 def test_error_on_opening_tar(requests_get_mock, lint, paths):
219 # Verify that when executed locally and the tar archive fails to open
220 # the linter does report an explicit linting error with the tarfile error included.
221 with tempfile.TemporaryDirectory() as tempdir, linter_module_mocks(
222 MOZ_AUTOMATION=0, tempdir=tempdir
224 condprof_addons = importlib.import_module("condprof-addons")
225 logger_mock = mock.Mock()
226 response_mock = mock.Mock()
227 response_mock.raise_for_status.return_value = None
229 def mock_iter_content(chunk_size):
230 yield b"fake tar content"
231 yield b"expected to trigger tarfile.ReadError"
233 response_mock.iter_content.side_effect = mock_iter_content
234 requests_get_mock.return_value = response_mock
235 Path(paths("browsertime.yml")[0])
237 linter = condprof_addons.CondprofAddonsLinter(
238 topsrcdir=paths()[0], logger=logger_mock
241 assert (
242 logger_mock.lint_error.call_args.kwargs["path"]
243 == condprof_addons.BROWSERTIME_FETCHES_PATH
245 actual_msg = logger_mock.lint_error.call_args.args[0]
246 print("Got linter error message:", actual_msg)
247 assert actual_msg.startswith(
248 f"{condprof_addons.ERR_FETCH_TASK_ARCHIVE}, file could not be opened successfully"
250 assert requests_get_mock.call_count == 1
251 assert len(linter.tar_xpi_filenames) == 0
254 def test_lint_all_customization_files_when_linting_browsertime_yml(
255 lint,
256 paths,
258 get_tarnames_mock = mock.Mock(return_value=["an-extension.xpi"])
259 read_json_mock = mock.Mock(
260 return_value={
261 "addons": {"an-extension": "http://localhost/ext/an-extension.xpi"}
264 with linter_module_mocks(
265 customizations_path="fake-customizations-dir",
266 ), linter_class_mocks(
267 get_firefox_addons_tar_names=get_tarnames_mock,
268 read_json=read_json_mock,
270 logger_mock = mock.Mock()
271 importlib.import_module("condprof-addons")
272 # When mozlint detects a change to the ci fetch browser.yml support file,
273 # condprof-addons linter is called for the entire customizations dir path
274 # and we expect that to be expanded to the list of the json customizations
275 # files from that directory path.
276 lint(paths("fake-customizations-dir"), logger=logger_mock)
277 # Expect read_json_mock to be called once per each of the json files
278 # found in the fixture dir.
279 assert read_json_mock.call_count == 3
280 assert get_tarnames_mock.call_count == 1
281 assert logger_mock.lint_error.call_count == 0
284 if __name__ == "__main__":
285 mozunit.main()