diff options
Diffstat (limited to 'rust_tools/rust_uprev_test.py')
-rwxr-xr-x | rust_tools/rust_uprev_test.py | 1064 |
1 files changed, 631 insertions, 433 deletions
diff --git a/rust_tools/rust_uprev_test.py b/rust_tools/rust_uprev_test.py index 00761391..0c4c91ed 100755 --- a/rust_tools/rust_uprev_test.py +++ b/rust_tools/rust_uprev_test.py @@ -1,313 +1,403 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Copyright 2020 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Tests for rust_uprev.py""" import os +from pathlib import Path import shutil import subprocess import tempfile import unittest -from pathlib import Path from unittest import mock from llvm_tools import git - import rust_uprev from rust_uprev import RustVersion def _fail_command(cmd, *_args, **_kwargs): - err = subprocess.CalledProcessError(returncode=1, cmd=cmd) - err.stderr = b'mock failure' - raise err + err = subprocess.CalledProcessError(returncode=1, cmd=cmd) + err.stderr = b"mock failure" + raise err class FetchDistfileTest(unittest.TestCase): - """Tests rust_uprev.fetch_distfile_from_mirror()""" - - @mock.patch.object(rust_uprev, 'get_distdir', return_value='/fake/distfiles') - @mock.patch.object(subprocess, 'call', side_effect=_fail_command) - def test_fetch_difstfile_fail(self, *_args) -> None: - with self.assertRaises(subprocess.CalledProcessError): - rust_uprev.fetch_distfile_from_mirror('test_distfile.tar.gz') - - @mock.patch.object(rust_uprev, - 'get_command_output_unchecked', - return_value='AccessDeniedException: Access denied.') - @mock.patch.object(rust_uprev, 'get_distdir', return_value='/fake/distfiles') - @mock.patch.object(subprocess, 'call', return_value=0) - def test_fetch_distfile_acl_access_denied(self, *_args) -> None: - rust_uprev.fetch_distfile_from_mirror('test_distfile.tar.gz') - - @mock.patch.object( - rust_uprev, - 'get_command_output_unchecked', - return_value='[ { "entity": "allUsers", "role": "READER" } ]') - @mock.patch.object(rust_uprev, 'get_distdir', return_value='/fake/distfiles') - @mock.patch.object(subprocess, 'call', return_value=0) - def test_fetch_distfile_acl_ok(self, *_args) -> None: - rust_uprev.fetch_distfile_from_mirror('test_distfile.tar.gz') - - @mock.patch.object( - rust_uprev, - 'get_command_output_unchecked', - return_value='[ { "entity": "___fake@google.com", "role": "OWNER" } ]') - @mock.patch.object(rust_uprev, 'get_distdir', return_value='/fake/distfiles') - @mock.patch.object(subprocess, 'call', return_value=0) - def test_fetch_distfile_acl_wrong(self, *_args) -> None: - with self.assertRaisesRegex(Exception, 'allUsers.*READER'): - with self.assertLogs(level='ERROR') as log: - rust_uprev.fetch_distfile_from_mirror('test_distfile.tar.gz') - self.assertIn( - '[ { "entity": "___fake@google.com", "role": "OWNER" } ]', - '\n'.join(log.output)) + """Tests rust_uprev.fetch_distfile_from_mirror()""" + + @mock.patch.object( + rust_uprev, "get_distdir", return_value="/fake/distfiles" + ) + @mock.patch.object(subprocess, "call", side_effect=_fail_command) + def test_fetch_difstfile_fail(self, *_args) -> None: + with self.assertRaises(subprocess.CalledProcessError): + rust_uprev.fetch_distfile_from_mirror("test_distfile.tar.gz") + + @mock.patch.object( + rust_uprev, + "get_command_output_unchecked", + return_value="AccessDeniedException: Access denied.", + ) + @mock.patch.object( + rust_uprev, "get_distdir", return_value="/fake/distfiles" + ) + @mock.patch.object(subprocess, "call", return_value=0) + def test_fetch_distfile_acl_access_denied(self, *_args) -> None: + rust_uprev.fetch_distfile_from_mirror("test_distfile.tar.gz") + + @mock.patch.object( + rust_uprev, + "get_command_output_unchecked", + return_value='[ { "entity": "allUsers", "role": "READER" } ]', + ) + @mock.patch.object( + rust_uprev, "get_distdir", return_value="/fake/distfiles" + ) + @mock.patch.object(subprocess, "call", return_value=0) + def test_fetch_distfile_acl_ok(self, *_args) -> None: + rust_uprev.fetch_distfile_from_mirror("test_distfile.tar.gz") + + @mock.patch.object( + rust_uprev, + "get_command_output_unchecked", + return_value='[ { "entity": "___fake@google.com", "role": "OWNER" } ]', + ) + @mock.patch.object( + rust_uprev, "get_distdir", return_value="/fake/distfiles" + ) + @mock.patch.object(subprocess, "call", return_value=0) + def test_fetch_distfile_acl_wrong(self, *_args) -> None: + with self.assertRaisesRegex(Exception, "allUsers.*READER"): + with self.assertLogs(level="ERROR") as log: + rust_uprev.fetch_distfile_from_mirror("test_distfile.tar.gz") + self.assertIn( + '[ { "entity": "___fake@google.com", "role": "OWNER" } ]', + "\n".join(log.output), + ) class FindEbuildPathTest(unittest.TestCase): - """Tests for rust_uprev.find_ebuild_path()""" - - def test_exact_version(self): - with tempfile.TemporaryDirectory() as tmpdir: - ebuild = Path(tmpdir, 'test-1.3.4.ebuild') - ebuild.touch() - Path(tmpdir, 'test-1.2.3.ebuild').touch() - result = rust_uprev.find_ebuild_path(tmpdir, 'test', - rust_uprev.RustVersion(1, 3, 4)) - self.assertEqual(result, ebuild) - - def test_no_version(self): - with tempfile.TemporaryDirectory() as tmpdir: - ebuild = Path(tmpdir, 'test-1.2.3.ebuild') - ebuild.touch() - result = rust_uprev.find_ebuild_path(tmpdir, 'test') - self.assertEqual(result, ebuild) - - def test_patch_version(self): - with tempfile.TemporaryDirectory() as tmpdir: - ebuild = Path(tmpdir, 'test-1.3.4-r3.ebuild') - ebuild.touch() - Path(tmpdir, 'test-1.2.3.ebuild').touch() - result = rust_uprev.find_ebuild_path(tmpdir, 'test', - rust_uprev.RustVersion(1, 3, 4)) - self.assertEqual(result, ebuild) + """Tests for rust_uprev.find_ebuild_path()""" + + def test_exact_version(self): + with tempfile.TemporaryDirectory() as t: + tmpdir = Path(t) + ebuild = tmpdir / "test-1.3.4.ebuild" + ebuild.touch() + (tmpdir / "test-1.2.3.ebuild").touch() + result = rust_uprev.find_ebuild_path( + tmpdir, "test", rust_uprev.RustVersion(1, 3, 4) + ) + self.assertEqual(result, ebuild) + + def test_no_version(self): + with tempfile.TemporaryDirectory() as t: + tmpdir = Path(t) + ebuild = tmpdir / "test-1.2.3.ebuild" + ebuild.touch() + result = rust_uprev.find_ebuild_path(tmpdir, "test") + self.assertEqual(result, ebuild) + + def test_patch_version(self): + with tempfile.TemporaryDirectory() as t: + tmpdir = Path(t) + ebuild = tmpdir / "test-1.3.4-r3.ebuild" + ebuild.touch() + (tmpdir / "test-1.2.3.ebuild").touch() + result = rust_uprev.find_ebuild_path( + tmpdir, "test", rust_uprev.RustVersion(1, 3, 4) + ) + self.assertEqual(result, ebuild) + + def test_multiple_versions(self): + with tempfile.TemporaryDirectory() as t: + tmpdir = Path(t) + (tmpdir / "test-1.3.4-r3.ebuild").touch() + (tmpdir / "test-1.3.5.ebuild").touch() + with self.assertRaises(AssertionError): + rust_uprev.find_ebuild_path(tmpdir, "test") + + def test_selected_version(self): + with tempfile.TemporaryDirectory() as t: + tmpdir = Path(t) + ebuild = tmpdir / "test-1.3.4-r3.ebuild" + ebuild.touch() + (tmpdir / "test-1.3.5.ebuild").touch() + result = rust_uprev.find_ebuild_path( + tmpdir, "test", rust_uprev.RustVersion(1, 3, 4) + ) + self.assertEqual(result, ebuild) + + def test_symlink(self): + # Symlinks to ebuilds in the same directory are allowed, and the return + # value is the regular file. + with tempfile.TemporaryDirectory() as t: + tmpdir = Path(t) + ebuild = tmpdir / "test-1.3.4.ebuild" + ebuild.touch() + (tmpdir / "test-1.3.4-r1.ebuild").symlink_to("test-1.3.4.ebuild") + result = rust_uprev.find_ebuild_path(tmpdir, "test") + self.assertEqual(result, ebuild) + + +class RemoveEbuildVersionTest(unittest.TestCase): + """Tests for rust_uprev.remove_ebuild_version()""" + + @mock.patch.object(subprocess, "check_call") + def test_single(self, check_call): + with tempfile.TemporaryDirectory() as tmpdir: + ebuild_dir = Path(tmpdir, "test-ebuilds") + ebuild_dir.mkdir() + ebuild = Path(ebuild_dir, "test-3.1.4.ebuild") + ebuild.touch() + Path(ebuild_dir, "unrelated-1.0.0.ebuild").touch() + rust_uprev.remove_ebuild_version( + ebuild_dir, "test", rust_uprev.RustVersion(3, 1, 4) + ) + check_call.assert_called_once_with( + ["git", "rm", "test-3.1.4.ebuild"], cwd=ebuild_dir + ) + + @mock.patch.object(subprocess, "check_call") + def test_symlink(self, check_call): + with tempfile.TemporaryDirectory() as tmpdir: + ebuild_dir = Path(tmpdir, "test-ebuilds") + ebuild_dir.mkdir() + ebuild = Path(ebuild_dir, "test-3.1.4.ebuild") + ebuild.touch() + symlink = Path(ebuild_dir, "test-3.1.4-r5.ebuild") + symlink.symlink_to(ebuild.name) + Path(ebuild_dir, "unrelated-1.0.0.ebuild").touch() + rust_uprev.remove_ebuild_version( + ebuild_dir, "test", rust_uprev.RustVersion(3, 1, 4) + ) + check_call.assert_has_calls( + [ + mock.call( + ["git", "rm", "test-3.1.4.ebuild"], cwd=ebuild_dir + ), + mock.call( + ["git", "rm", "test-3.1.4-r5.ebuild"], cwd=ebuild_dir + ), + ], + any_order=True, + ) class RustVersionTest(unittest.TestCase): - """Tests for RustVersion class""" + """Tests for RustVersion class""" - def test_str(self): - obj = rust_uprev.RustVersion(major=1, minor=2, patch=3) - self.assertEqual(str(obj), '1.2.3') + def test_str(self): + obj = rust_uprev.RustVersion(major=1, minor=2, patch=3) + self.assertEqual(str(obj), "1.2.3") - def test_parse_version_only(self): - expected = rust_uprev.RustVersion(major=1, minor=2, patch=3) - actual = rust_uprev.RustVersion.parse('1.2.3') - self.assertEqual(expected, actual) + def test_parse_version_only(self): + expected = rust_uprev.RustVersion(major=1, minor=2, patch=3) + actual = rust_uprev.RustVersion.parse("1.2.3") + self.assertEqual(expected, actual) - def test_parse_ebuild_name(self): - expected = rust_uprev.RustVersion(major=1, minor=2, patch=3) - actual = rust_uprev.RustVersion.parse_from_ebuild('rust-1.2.3.ebuild') - self.assertEqual(expected, actual) + def test_parse_ebuild_name(self): + expected = rust_uprev.RustVersion(major=1, minor=2, patch=3) + actual = rust_uprev.RustVersion.parse_from_ebuild("rust-1.2.3.ebuild") + self.assertEqual(expected, actual) - actual = rust_uprev.RustVersion.parse_from_ebuild('rust-1.2.3-r1.ebuild') - self.assertEqual(expected, actual) + actual = rust_uprev.RustVersion.parse_from_ebuild( + "rust-1.2.3-r1.ebuild" + ) + self.assertEqual(expected, actual) - def test_parse_fail(self): - with self.assertRaises(AssertionError) as context: - rust_uprev.RustVersion.parse('invalid-rust-1.2.3') - self.assertEqual("failed to parse 'invalid-rust-1.2.3'", - str(context.exception)) + def test_parse_fail(self): + with self.assertRaises(AssertionError) as context: + rust_uprev.RustVersion.parse("invalid-rust-1.2.3") + self.assertEqual( + "failed to parse 'invalid-rust-1.2.3'", str(context.exception) + ) class PrepareUprevTest(unittest.TestCase): - """Tests for prepare_uprev step in rust_uprev""" - - def setUp(self): - self.bootstrap_version = rust_uprev.RustVersion(1, 1, 0) - self.version_old = rust_uprev.RustVersion(1, 2, 3) - self.version_new = rust_uprev.RustVersion(1, 3, 5) - - @mock.patch.object(rust_uprev, - 'find_ebuild_for_rust_version', - return_value='/path/to/ebuild') - @mock.patch.object(rust_uprev, 'find_ebuild_path') - @mock.patch.object(rust_uprev, 'get_command_output') - def test_success_with_template(self, mock_command, mock_find_ebuild, - _ebuild_for_version): - bootstrap_ebuild_path = Path( - '/path/to/rust-bootstrap/', - f'rust-bootstrap-{self.bootstrap_version}.ebuild') - mock_find_ebuild.return_value = bootstrap_ebuild_path - expected = (self.version_old, '/path/to/ebuild', self.bootstrap_version) - actual = rust_uprev.prepare_uprev(rust_version=self.version_new, - template=self.version_old) - self.assertEqual(expected, actual) - mock_command.assert_not_called() - - @mock.patch.object(rust_uprev, - 'find_ebuild_for_rust_version', - return_value='/path/to/ebuild') - @mock.patch.object(rust_uprev, - 'get_rust_bootstrap_version', - return_value=RustVersion(0, 41, 12)) - @mock.patch.object(rust_uprev, 'get_command_output') - def test_return_none_with_template_larger_than_input(self, mock_command, - *_args): - ret = rust_uprev.prepare_uprev(rust_version=self.version_old, - template=self.version_new) - self.assertIsNone(ret) - mock_command.assert_not_called() - - @mock.patch.object(rust_uprev, 'find_ebuild_path') - @mock.patch.object(os.path, 'exists') - @mock.patch.object(rust_uprev, 'get_command_output') - def test_success_without_template(self, mock_command, mock_exists, - mock_find_ebuild): - rust_ebuild_path = f'/path/to/rust/rust-{self.version_old}-r3.ebuild' - mock_command.return_value = rust_ebuild_path - bootstrap_ebuild_path = Path( - '/path/to/rust-bootstrap', - f'rust-bootstrap-{self.bootstrap_version}.ebuild') - mock_find_ebuild.return_value = bootstrap_ebuild_path - expected = (self.version_old, rust_ebuild_path, self.bootstrap_version) - actual = rust_uprev.prepare_uprev(rust_version=self.version_new, - template=None) - self.assertEqual(expected, actual) - mock_command.assert_called_once_with(['equery', 'w', 'rust']) - mock_exists.assert_not_called() - - @mock.patch.object(rust_uprev, - 'get_rust_bootstrap_version', - return_value=RustVersion(0, 41, 12)) - @mock.patch.object(os.path, 'exists') - @mock.patch.object(rust_uprev, 'get_command_output') - def test_return_none_with_ebuild_larger_than_input(self, mock_command, - mock_exists, *_args): - mock_command.return_value = f'/path/to/rust/rust-{self.version_new}.ebuild' - ret = rust_uprev.prepare_uprev(rust_version=self.version_old, - template=None) - self.assertIsNone(ret) - mock_exists.assert_not_called() - - def test_prepare_uprev_from_json(self): - ebuild_path = '/path/to/the/ebuild' - json_result = (list(self.version_new), ebuild_path, - list(self.bootstrap_version)) - expected = (self.version_new, ebuild_path, self.bootstrap_version) - actual = rust_uprev.prepare_uprev_from_json(json_result) - self.assertEqual(expected, actual) - - -class UpdateEbuildTest(unittest.TestCase): - """Tests for update_ebuild step in rust_uprev""" - ebuild_file_before = """ + """Tests for prepare_uprev step in rust_uprev""" + + def setUp(self): + self.bootstrap_version = rust_uprev.RustVersion(1, 1, 0) + self.version_old = rust_uprev.RustVersion(1, 2, 3) + self.version_new = rust_uprev.RustVersion(1, 3, 5) + + @mock.patch.object( + rust_uprev, + "find_ebuild_for_rust_version", + return_value="/path/to/ebuild", + ) + @mock.patch.object(rust_uprev, "find_ebuild_path") + @mock.patch.object(rust_uprev, "get_command_output") + def test_success_with_template( + self, mock_command, mock_find_ebuild, _ebuild_for_version + ): + bootstrap_ebuild_path = Path( + "/path/to/rust-bootstrap/", + f"rust-bootstrap-{self.bootstrap_version}.ebuild", + ) + mock_find_ebuild.return_value = bootstrap_ebuild_path + expected = (self.version_old, "/path/to/ebuild", self.bootstrap_version) + actual = rust_uprev.prepare_uprev( + rust_version=self.version_new, template=self.version_old + ) + self.assertEqual(expected, actual) + mock_command.assert_not_called() + + @mock.patch.object( + rust_uprev, + "find_ebuild_for_rust_version", + return_value="/path/to/ebuild", + ) + @mock.patch.object( + rust_uprev, + "get_rust_bootstrap_version", + return_value=RustVersion(0, 41, 12), + ) + @mock.patch.object(rust_uprev, "get_command_output") + def test_return_none_with_template_larger_than_input( + self, mock_command, *_args + ): + ret = rust_uprev.prepare_uprev( + rust_version=self.version_old, template=self.version_new + ) + self.assertIsNone(ret) + mock_command.assert_not_called() + + @mock.patch.object(rust_uprev, "find_ebuild_path") + @mock.patch.object(os.path, "exists") + @mock.patch.object(rust_uprev, "get_command_output") + def test_success_without_template( + self, mock_command, mock_exists, mock_find_ebuild + ): + rust_ebuild_path = f"/path/to/rust/rust-{self.version_old}-r3.ebuild" + mock_command.return_value = rust_ebuild_path + bootstrap_ebuild_path = Path( + "/path/to/rust-bootstrap", + f"rust-bootstrap-{self.bootstrap_version}.ebuild", + ) + mock_find_ebuild.return_value = bootstrap_ebuild_path + expected = (self.version_old, rust_ebuild_path, self.bootstrap_version) + actual = rust_uprev.prepare_uprev( + rust_version=self.version_new, template=None + ) + self.assertEqual(expected, actual) + mock_command.assert_called_once_with(["equery", "w", "rust"]) + mock_exists.assert_not_called() + + @mock.patch.object( + rust_uprev, + "get_rust_bootstrap_version", + return_value=RustVersion(0, 41, 12), + ) + @mock.patch.object(os.path, "exists") + @mock.patch.object(rust_uprev, "get_command_output") + def test_return_none_with_ebuild_larger_than_input( + self, mock_command, mock_exists, *_args + ): + mock_command.return_value = ( + f"/path/to/rust/rust-{self.version_new}.ebuild" + ) + ret = rust_uprev.prepare_uprev( + rust_version=self.version_old, template=None + ) + self.assertIsNone(ret) + mock_exists.assert_not_called() + + def test_prepare_uprev_from_json(self): + ebuild_path = "/path/to/the/ebuild" + json_result = ( + list(self.version_new), + ebuild_path, + list(self.bootstrap_version), + ) + expected = (self.version_new, ebuild_path, self.bootstrap_version) + actual = rust_uprev.prepare_uprev_from_json(json_result) + self.assertEqual(expected, actual) + + +class UpdateBootstrapVersionTest(unittest.TestCase): + """Tests for update_bootstrap_version step in rust_uprev""" + + ebuild_file_before = """ BOOTSTRAP_VERSION="1.2.0" """ - ebuild_file_after = """ + ebuild_file_after = """ BOOTSTRAP_VERSION="1.3.6" """ - def test_success(self): - mock_open = mock.mock_open(read_data=self.ebuild_file_before) - # ebuild_file and new bootstrap version are deliberately different - ebuild_file = '/path/to/rust/rust-1.3.5.ebuild' - with mock.patch('builtins.open', mock_open): - rust_uprev.update_ebuild(ebuild_file, - rust_uprev.RustVersion.parse('1.3.6')) - mock_open.return_value.__enter__().write.assert_called_once_with( - self.ebuild_file_after) - - def test_fail_when_ebuild_misses_a_variable(self): - mock_open = mock.mock_open(read_data='') - ebuild_file = '/path/to/rust/rust-1.3.5.ebuild' - with mock.patch('builtins.open', mock_open): - with self.assertRaises(RuntimeError) as context: - rust_uprev.update_ebuild(ebuild_file, - rust_uprev.RustVersion.parse('1.2.0')) - self.assertEqual('BOOTSTRAP_VERSION not found in rust ebuild', - str(context.exception)) + def test_success(self): + mock_open = mock.mock_open(read_data=self.ebuild_file_before) + # ebuild_file and new bootstrap version are deliberately different + ebuild_file = "/path/to/rust/cros-rustc.eclass" + with mock.patch("builtins.open", mock_open): + rust_uprev.update_bootstrap_version( + ebuild_file, rust_uprev.RustVersion.parse("1.3.6") + ) + mock_open.return_value.__enter__().write.assert_called_once_with( + self.ebuild_file_after + ) + + def test_fail_when_ebuild_misses_a_variable(self): + mock_open = mock.mock_open(read_data="") + ebuild_file = "/path/to/rust/rust-1.3.5.ebuild" + with mock.patch("builtins.open", mock_open): + with self.assertRaises(RuntimeError) as context: + rust_uprev.update_bootstrap_version( + ebuild_file, rust_uprev.RustVersion.parse("1.2.0") + ) + self.assertEqual( + "BOOTSTRAP_VERSION not found in /path/to/rust/rust-1.3.5.ebuild", + str(context.exception), + ) class UpdateManifestTest(unittest.TestCase): - """Tests for update_manifest step in rust_uprev""" - - # pylint: disable=protected-access - def _run_test_flip_mirror(self, before, after, add, expect_write): - mock_open = mock.mock_open(read_data=f'RESTRICT="{before}"') - with mock.patch('builtins.open', mock_open): - rust_uprev.flip_mirror_in_ebuild('', add=add) - if expect_write: - mock_open.return_value.__enter__().write.assert_called_once_with( - f'RESTRICT="{after}"') - - def test_add_mirror_in_ebuild(self): - self._run_test_flip_mirror(before='variable1 variable2', - after='variable1 variable2 mirror', - add=True, - expect_write=True) - - def test_remove_mirror_in_ebuild(self): - self._run_test_flip_mirror(before='variable1 variable2 mirror', - after='variable1 variable2', - add=False, - expect_write=True) - - def test_add_mirror_when_exists(self): - self._run_test_flip_mirror(before='variable1 variable2 mirror', - after='variable1 variable2 mirror', - add=True, - expect_write=False) - - def test_remove_mirror_when_not_exists(self): - self._run_test_flip_mirror(before='variable1 variable2', - after='variable1 variable2', - add=False, - expect_write=False) - - @mock.patch.object(rust_uprev, 'flip_mirror_in_ebuild') - @mock.patch.object(rust_uprev, 'ebuild_actions') - def test_update_manifest(self, mock_run, mock_flip): - ebuild_file = Path('/path/to/rust/rust-1.1.1.ebuild') - rust_uprev.update_manifest(ebuild_file) - mock_run.assert_called_once_with('rust', ['manifest']) - mock_flip.assert_has_calls( - [mock.call(ebuild_file, add=True), - mock.call(ebuild_file, add=False)]) + """Tests for update_manifest step in rust_uprev""" + + @mock.patch.object(rust_uprev, "ebuild_actions") + def test_update_manifest(self, mock_run): + ebuild_file = Path("/path/to/rust/rust-1.1.1.ebuild") + rust_uprev.update_manifest(ebuild_file) + mock_run.assert_called_once_with("rust", ["manifest"]) class UpdateBootstrapEbuildTest(unittest.TestCase): - """Tests for rust_uprev.update_bootstrap_ebuild()""" - - def test_update_bootstrap_ebuild(self): - # The update should do two things: - # 1. Create a copy of rust-bootstrap's ebuild with the new version number. - # 2. Add the old PV to RUSTC_RAW_FULL_BOOTSTRAP_SEQUENCE. - with tempfile.TemporaryDirectory() as tmpdir_str, \ - mock.patch.object(rust_uprev, 'find_ebuild_path') as mock_find_ebuild: - tmpdir = Path(tmpdir_str) - bootstrapdir = Path.joinpath(tmpdir, 'rust-bootstrap') - bootstrapdir.mkdir() - old_ebuild = bootstrapdir.joinpath('rust-bootstrap-1.45.2.ebuild') - old_ebuild.write_text(encoding='utf-8', - data=""" + """Tests for rust_uprev.update_bootstrap_ebuild()""" + + def test_update_bootstrap_ebuild(self): + # The update should do two things: + # 1. Create a copy of rust-bootstrap's ebuild with the new version number. + # 2. Add the old PV to RUSTC_RAW_FULL_BOOTSTRAP_SEQUENCE. + with tempfile.TemporaryDirectory() as tmpdir_str, mock.patch.object( + rust_uprev, "find_ebuild_path" + ) as mock_find_ebuild: + tmpdir = Path(tmpdir_str) + bootstrapdir = Path.joinpath(tmpdir, "rust-bootstrap") + bootstrapdir.mkdir() + old_ebuild = bootstrapdir.joinpath("rust-bootstrap-1.45.2.ebuild") + old_ebuild.write_text( + encoding="utf-8", + data=""" some text RUSTC_RAW_FULL_BOOTSTRAP_SEQUENCE=( \t1.43.1 \t1.44.1 ) some more text -""") - mock_find_ebuild.return_value = old_ebuild - rust_uprev.update_bootstrap_ebuild(rust_uprev.RustVersion(1, 46, 0)) - new_ebuild = bootstrapdir.joinpath('rust-bootstrap-1.46.0.ebuild') - self.assertTrue(new_ebuild.exists()) - text = new_ebuild.read_text() - self.assertEqual( - text, """ +""", + ) + mock_find_ebuild.return_value = old_ebuild + rust_uprev.update_bootstrap_ebuild(rust_uprev.RustVersion(1, 46, 0)) + new_ebuild = bootstrapdir.joinpath("rust-bootstrap-1.46.0.ebuild") + self.assertTrue(new_ebuild.exists()) + text = new_ebuild.read_text() + self.assertEqual( + text, + """ some text RUSTC_RAW_FULL_BOOTSTRAP_SEQUENCE=( \t1.43.1 @@ -315,186 +405,294 @@ RUSTC_RAW_FULL_BOOTSTRAP_SEQUENCE=( \t1.45.2 ) some more text -""") +""", + ) class UpdateRustPackagesTests(unittest.TestCase): - """Tests for update_rust_packages step.""" - - def setUp(self): - self.old_version = rust_uprev.RustVersion(1, 1, 0) - self.current_version = rust_uprev.RustVersion(1, 2, 3) - self.new_version = rust_uprev.RustVersion(1, 3, 5) - self.ebuild_file = os.path.join(rust_uprev.RUST_PATH, - 'rust-{self.new_version}.ebuild') - - def test_add_new_rust_packages(self): - package_before = (f'dev-lang/rust-{self.old_version}\n' - f'dev-lang/rust-{self.current_version}') - package_after = (f'dev-lang/rust-{self.old_version}\n' - f'dev-lang/rust-{self.current_version}\n' - f'dev-lang/rust-{self.new_version}') - mock_open = mock.mock_open(read_data=package_before) - with mock.patch('builtins.open', mock_open): - rust_uprev.update_rust_packages(self.new_version, add=True) - mock_open.return_value.__enter__().write.assert_called_once_with( - package_after) - - def test_remove_old_rust_packages(self): - package_before = (f'dev-lang/rust-{self.old_version}\n' - f'dev-lang/rust-{self.current_version}\n' - f'dev-lang/rust-{self.new_version}') - package_after = (f'dev-lang/rust-{self.current_version}\n' - f'dev-lang/rust-{self.new_version}') - mock_open = mock.mock_open(read_data=package_before) - with mock.patch('builtins.open', mock_open): - rust_uprev.update_rust_packages(self.old_version, add=False) - mock_open.return_value.__enter__().write.assert_called_once_with( - package_after) + """Tests for update_rust_packages step.""" + + def setUp(self): + self.old_version = rust_uprev.RustVersion(1, 1, 0) + self.current_version = rust_uprev.RustVersion(1, 2, 3) + self.new_version = rust_uprev.RustVersion(1, 3, 5) + self.ebuild_file = os.path.join( + rust_uprev.RUST_PATH, "rust-{self.new_version}.ebuild" + ) + + def test_add_new_rust_packages(self): + package_before = ( + f"dev-lang/rust-{self.old_version}\n" + f"dev-lang/rust-{self.current_version}" + ) + package_after = ( + f"dev-lang/rust-{self.old_version}\n" + f"dev-lang/rust-{self.current_version}\n" + f"dev-lang/rust-{self.new_version}" + ) + mock_open = mock.mock_open(read_data=package_before) + with mock.patch("builtins.open", mock_open): + rust_uprev.update_rust_packages( + "dev-lang/rust", self.new_version, add=True + ) + mock_open.return_value.__enter__().write.assert_called_once_with( + package_after + ) + + def test_remove_old_rust_packages(self): + package_before = ( + f"dev-lang/rust-{self.old_version}\n" + f"dev-lang/rust-{self.current_version}\n" + f"dev-lang/rust-{self.new_version}" + ) + package_after = ( + f"dev-lang/rust-{self.current_version}\n" + f"dev-lang/rust-{self.new_version}" + ) + mock_open = mock.mock_open(read_data=package_before) + with mock.patch("builtins.open", mock_open): + rust_uprev.update_rust_packages( + "dev-lang/rust", self.old_version, add=False + ) + mock_open.return_value.__enter__().write.assert_called_once_with( + package_after + ) class RustUprevOtherStagesTests(unittest.TestCase): - """Tests for other steps in rust_uprev""" - - def setUp(self): - self.old_version = rust_uprev.RustVersion(1, 1, 0) - self.current_version = rust_uprev.RustVersion(1, 2, 3) - self.new_version = rust_uprev.RustVersion(1, 3, 5) - self.ebuild_file = os.path.join(rust_uprev.RUST_PATH, - 'rust-{self.new_version}.ebuild') - - @mock.patch.object(shutil, 'copyfile') - @mock.patch.object(os, 'listdir') - @mock.patch.object(subprocess, 'check_call') - def test_copy_patches(self, mock_call, mock_ls, mock_copy): - mock_ls.return_value = [ - f'rust-{self.old_version}-patch-1.patch', - f'rust-{self.old_version}-patch-2-old.patch', - f'rust-{self.current_version}-patch-1.patch', - f'rust-{self.current_version}-patch-2-new.patch' - ] - rust_uprev.copy_patches(rust_uprev.RUST_PATH, self.current_version, - self.new_version) - mock_copy.assert_has_calls([ - mock.call( - os.path.join(rust_uprev.RUST_PATH, 'files', - f'rust-{self.current_version}-patch-1.patch'), - os.path.join(rust_uprev.RUST_PATH, 'files', - f'rust-{self.new_version}-patch-1.patch'), - ), - mock.call( - os.path.join(rust_uprev.RUST_PATH, 'files', - f'rust-{self.current_version}-patch-2-new.patch'), - os.path.join(rust_uprev.RUST_PATH, 'files', - f'rust-{self.new_version}-patch-2-new.patch')) - ]) - mock_call.assert_called_once_with( - ['git', 'add', f'rust-{self.new_version}-*.patch'], - cwd=rust_uprev.RUST_PATH.joinpath('files')) - - @mock.patch.object(shutil, 'copyfile') - @mock.patch.object(subprocess, 'check_call') - def test_create_ebuild(self, mock_call, mock_copy): - template_ebuild = f'/path/to/rust-{self.current_version}-r2.ebuild' - rust_uprev.create_ebuild(template_ebuild, self.new_version) - mock_copy.assert_called_once_with( - template_ebuild, - rust_uprev.RUST_PATH.joinpath(f'rust-{self.new_version}.ebuild')) - mock_call.assert_called_once_with( - ['git', 'add', f'rust-{self.new_version}.ebuild'], - cwd=rust_uprev.RUST_PATH) - - @mock.patch.object(rust_uprev, 'find_ebuild_for_package') - @mock.patch.object(subprocess, 'check_call') - def test_remove_rust_bootstrap_version(self, mock_call, *_args): - bootstrap_path = os.path.join(rust_uprev.RUST_PATH, '..', 'rust-bootstrap') - rust_uprev.remove_rust_bootstrap_version(self.old_version, lambda *x: ()) - mock_call.has_calls([ - [ - 'git', 'rm', - os.path.join(bootstrap_path, 'files', - f'rust-bootstrap-{self.old_version}-*.patch') - ], - [ - 'git', 'rm', - os.path.join(bootstrap_path, - f'rust-bootstrap-{self.old_version}.ebuild') - ], - ]) - - @mock.patch.object(rust_uprev, 'find_ebuild_path') - @mock.patch.object(subprocess, 'check_call') - def test_remove_virtual_rust(self, mock_call, mock_find_ebuild): - ebuild_path = Path( - f'/some/dir/virtual/rust/rust-{self.old_version}.ebuild') - mock_find_ebuild.return_value = Path(ebuild_path) - rust_uprev.remove_virtual_rust(self.old_version) - mock_call.assert_called_once_with( - ['git', 'rm', str(ebuild_path.name)], cwd=ebuild_path.parent) - - @mock.patch.object(rust_uprev, 'find_ebuild_path') - @mock.patch.object(shutil, 'copyfile') - @mock.patch.object(subprocess, 'check_call') - def test_update_virtual_rust(self, mock_call, mock_copy, mock_find_ebuild): - ebuild_path = Path( - f'/some/dir/virtual/rust/rust-{self.current_version}.ebuild') - mock_find_ebuild.return_value = Path(ebuild_path) - rust_uprev.update_virtual_rust(self.current_version, self.new_version) - mock_call.assert_called_once_with( - ['git', 'add', f'rust-{self.new_version}.ebuild'], - cwd=ebuild_path.parent) - mock_copy.assert_called_once_with( - ebuild_path.parent.joinpath(f'rust-{self.current_version}.ebuild'), - ebuild_path.parent.joinpath(f'rust-{self.new_version}.ebuild')) - - @mock.patch.object(os, 'listdir') - def test_find_oldest_rust_version_in_chroot_pass(self, mock_ls): - oldest_version_name = f'rust-{self.old_version}.ebuild' - mock_ls.return_value = [ - oldest_version_name, f'rust-{self.current_version}.ebuild', - f'rust-{self.new_version}.ebuild' - ] - actual = rust_uprev.find_oldest_rust_version_in_chroot() - expected = (self.old_version, - os.path.join(rust_uprev.RUST_PATH, oldest_version_name)) - self.assertEqual(expected, actual) - - @mock.patch.object(os, 'listdir') - def test_find_oldest_rust_version_in_chroot_fail_with_only_one_ebuild( - self, mock_ls): - mock_ls.return_value = [f'rust-{self.new_version}.ebuild'] - with self.assertRaises(RuntimeError) as context: - rust_uprev.find_oldest_rust_version_in_chroot() - self.assertEqual('Expect to find more than one Rust versions', - str(context.exception)) - - @mock.patch.object(rust_uprev, 'get_command_output') - @mock.patch.object(git, 'CreateBranch') - def test_create_new_repo(self, mock_branch, mock_output): - mock_output.return_value = '' - rust_uprev.create_new_repo(self.new_version) - mock_branch.assert_called_once_with(rust_uprev.RUST_PATH, - f'rust-to-{self.new_version}') - - @mock.patch.object(rust_uprev, 'get_command_output') - @mock.patch.object(subprocess, 'check_call') - def test_build_cross_compiler(self, mock_call, mock_output): - mock_output.return_value = f'rust-{self.new_version}.ebuild' - cros_targets = [ - 'x86_64-cros-linux-gnu', - 'armv7a-cros-linux-gnueabihf', - 'aarch64-cros-linux-gnu', - ] - all_triples = ['x86_64-pc-linux-gnu'] + cros_targets - rust_ebuild = 'RUSTC_TARGET_TRIPLES=(' + '\n\t'.join(all_triples) + ')' - mock_open = mock.mock_open(read_data=rust_ebuild) - with mock.patch('builtins.open', mock_open): - rust_uprev.build_cross_compiler() - - mock_call.assert_called_once_with( - ['sudo', 'emerge', '-j', '-G'] + - [f'cross-{x}/gcc' for x in cros_targets + ['arm-none-eabi']]) - - -if __name__ == '__main__': - unittest.main() + """Tests for other steps in rust_uprev""" + + def setUp(self): + self.old_version = rust_uprev.RustVersion(1, 1, 0) + self.current_version = rust_uprev.RustVersion(1, 2, 3) + self.new_version = rust_uprev.RustVersion(1, 3, 5) + self.ebuild_file = os.path.join( + rust_uprev.RUST_PATH, "rust-{self.new_version}.ebuild" + ) + + @mock.patch.object(shutil, "copyfile") + @mock.patch.object(os, "listdir") + @mock.patch.object(subprocess, "check_call") + def test_copy_patches(self, mock_call, mock_ls, mock_copy): + mock_ls.return_value = [ + f"rust-{self.old_version}-patch-1.patch", + f"rust-{self.old_version}-patch-2-old.patch", + f"rust-{self.current_version}-patch-1.patch", + f"rust-{self.current_version}-patch-2-new.patch", + ] + rust_uprev.copy_patches( + rust_uprev.RUST_PATH, self.current_version, self.new_version + ) + mock_copy.assert_has_calls( + [ + mock.call( + os.path.join( + rust_uprev.RUST_PATH, + "files", + f"rust-{self.current_version}-patch-1.patch", + ), + os.path.join( + rust_uprev.RUST_PATH, + "files", + f"rust-{self.new_version}-patch-1.patch", + ), + ), + mock.call( + os.path.join( + rust_uprev.RUST_PATH, + "files", + f"rust-{self.current_version}-patch-2-new.patch", + ), + os.path.join( + rust_uprev.RUST_PATH, + "files", + f"rust-{self.new_version}-patch-2-new.patch", + ), + ), + ] + ) + mock_call.assert_called_once_with( + ["git", "add", f"rust-{self.new_version}-*.patch"], + cwd=rust_uprev.RUST_PATH.joinpath("files"), + ) + + @mock.patch.object(shutil, "copyfile") + @mock.patch.object(subprocess, "check_call") + def test_create_rust_ebuild(self, mock_call, mock_copy): + template_ebuild = f"/path/to/rust-{self.current_version}-r2.ebuild" + rust_uprev.create_ebuild( + template_ebuild, "dev-lang/rust", self.new_version + ) + mock_copy.assert_called_once_with( + template_ebuild, + rust_uprev.RUST_PATH.joinpath(f"rust-{self.new_version}.ebuild"), + ) + mock_call.assert_called_once_with( + ["git", "add", f"rust-{self.new_version}.ebuild"], + cwd=rust_uprev.RUST_PATH, + ) + + @mock.patch.object(shutil, "copyfile") + @mock.patch.object(subprocess, "check_call") + def test_create_rust_host_ebuild(self, mock_call, mock_copy): + template_ebuild = f"/path/to/rust-host-{self.current_version}-r2.ebuild" + rust_uprev.create_ebuild( + template_ebuild, "dev-lang/rust-host", self.new_version + ) + mock_copy.assert_called_once_with( + template_ebuild, + rust_uprev.EBUILD_PREFIX.joinpath( + f"dev-lang/rust-host/rust-host-{self.new_version}.ebuild" + ), + ) + mock_call.assert_called_once_with( + ["git", "add", f"rust-host-{self.new_version}.ebuild"], + cwd=rust_uprev.EBUILD_PREFIX.joinpath("dev-lang/rust-host"), + ) + + @mock.patch.object(rust_uprev, "find_ebuild_for_package") + @mock.patch.object(subprocess, "check_call") + def test_remove_rust_bootstrap_version(self, mock_call, *_args): + bootstrap_path = os.path.join( + rust_uprev.RUST_PATH, "..", "rust-bootstrap" + ) + rust_uprev.remove_rust_bootstrap_version( + self.old_version, lambda *x: () + ) + mock_call.has_calls( + [ + [ + "git", + "rm", + os.path.join( + bootstrap_path, + "files", + f"rust-bootstrap-{self.old_version}-*.patch", + ), + ], + [ + "git", + "rm", + os.path.join( + bootstrap_path, + f"rust-bootstrap-{self.old_version}.ebuild", + ), + ], + ] + ) + + @mock.patch.object(subprocess, "check_call") + def test_remove_virtual_rust(self, mock_call): + with tempfile.TemporaryDirectory() as tmpdir: + ebuild_path = Path( + tmpdir, f"virtual/rust/rust-{self.old_version}.ebuild" + ) + os.makedirs(ebuild_path.parent) + ebuild_path.touch() + with mock.patch("rust_uprev.EBUILD_PREFIX", Path(tmpdir)): + rust_uprev.remove_virtual_rust(self.old_version) + mock_call.assert_called_once_with( + ["git", "rm", str(ebuild_path.name)], cwd=ebuild_path.parent + ) + + @mock.patch.object(subprocess, "check_call") + def test_remove_virtual_rust_with_symlink(self, mock_call): + with tempfile.TemporaryDirectory() as tmpdir: + ebuild_path = Path( + tmpdir, f"virtual/rust/rust-{self.old_version}.ebuild" + ) + symlink_path = Path( + tmpdir, f"virtual/rust/rust-{self.old_version}-r14.ebuild" + ) + os.makedirs(ebuild_path.parent) + ebuild_path.touch() + symlink_path.symlink_to(ebuild_path.name) + with mock.patch("rust_uprev.EBUILD_PREFIX", Path(tmpdir)): + rust_uprev.remove_virtual_rust(self.old_version) + mock_call.assert_has_calls( + [ + mock.call( + ["git", "rm", ebuild_path.name], + cwd=ebuild_path.parent, + ), + mock.call( + ["git", "rm", symlink_path.name], + cwd=ebuild_path.parent, + ), + ], + any_order=True, + ) + + @mock.patch.object(rust_uprev, "find_ebuild_path") + @mock.patch.object(shutil, "copyfile") + @mock.patch.object(subprocess, "check_call") + def test_update_virtual_rust(self, mock_call, mock_copy, mock_find_ebuild): + ebuild_path = Path( + f"/some/dir/virtual/rust/rust-{self.current_version}.ebuild" + ) + mock_find_ebuild.return_value = Path(ebuild_path) + rust_uprev.update_virtual_rust(self.current_version, self.new_version) + mock_call.assert_called_once_with( + ["git", "add", f"rust-{self.new_version}.ebuild"], + cwd=ebuild_path.parent, + ) + mock_copy.assert_called_once_with( + ebuild_path.parent.joinpath(f"rust-{self.current_version}.ebuild"), + ebuild_path.parent.joinpath(f"rust-{self.new_version}.ebuild"), + ) + + @mock.patch.object(os, "listdir") + def test_find_oldest_rust_version_in_chroot_pass(self, mock_ls): + oldest_version_name = f"rust-{self.old_version}.ebuild" + mock_ls.return_value = [ + oldest_version_name, + f"rust-{self.current_version}.ebuild", + f"rust-{self.new_version}.ebuild", + ] + actual = rust_uprev.find_oldest_rust_version_in_chroot() + expected = self.old_version + self.assertEqual(expected, actual) + + @mock.patch.object(os, "listdir") + def test_find_oldest_rust_version_in_chroot_fail_with_only_one_ebuild( + self, mock_ls + ): + mock_ls.return_value = [f"rust-{self.new_version}.ebuild"] + with self.assertRaises(RuntimeError) as context: + rust_uprev.find_oldest_rust_version_in_chroot() + self.assertEqual( + "Expect to find more than one Rust versions", str(context.exception) + ) + + @mock.patch.object(rust_uprev, "get_command_output") + @mock.patch.object(git, "CreateBranch") + def test_create_new_repo(self, mock_branch, mock_output): + mock_output.return_value = "" + rust_uprev.create_new_repo(self.new_version) + mock_branch.assert_called_once_with( + rust_uprev.EBUILD_PREFIX, f"rust-to-{self.new_version}" + ) + + @mock.patch.object(rust_uprev, "get_command_output") + @mock.patch.object(subprocess, "check_call") + def test_build_cross_compiler(self, mock_call, mock_output): + mock_output.return_value = f"rust-{self.new_version}.ebuild" + cros_targets = [ + "x86_64-cros-linux-gnu", + "armv7a-cros-linux-gnueabihf", + "aarch64-cros-linux-gnu", + ] + all_triples = ["x86_64-pc-linux-gnu"] + cros_targets + rust_ebuild = "RUSTC_TARGET_TRIPLES=(" + "\n\t".join(all_triples) + ")" + mock_open = mock.mock_open(read_data=rust_ebuild) + with mock.patch("builtins.open", mock_open): + rust_uprev.build_cross_compiler() + + mock_call.assert_called_once_with( + ["sudo", "emerge", "-j", "-G"] + + [f"cross-{x}/gcc" for x in cros_targets + ["arm-none-eabi"]] + ) + + +if __name__ == "__main__": + unittest.main() |