1*760c253cSXin Li#!/usr/bin/env python3 2*760c253cSXin Li# Copyright 2020 The ChromiumOS Authors 3*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be 4*760c253cSXin Li# found in the LICENSE file. 5*760c253cSXin Li 6*760c253cSXin Li"""Tests for rust_uprev.py""" 7*760c253cSXin Li 8*760c253cSXin Liimport os 9*760c253cSXin Lifrom pathlib import Path 10*760c253cSXin Liimport shutil 11*760c253cSXin Liimport subprocess 12*760c253cSXin Liimport tempfile 13*760c253cSXin Liimport unittest 14*760c253cSXin Lifrom unittest import mock 15*760c253cSXin Li 16*760c253cSXin Lifrom llvm_tools import git 17*760c253cSXin Li 18*760c253cSXin Li 19*760c253cSXin Li# rust_uprev sets SOURCE_ROOT to the output of `repo --show-toplevel`. 20*760c253cSXin Li# The mock below makes us not actually run repo but use a fake value 21*760c253cSXin Li# instead. 22*760c253cSXin Liwith mock.patch("subprocess.check_output", return_value="/fake/chromiumos"): 23*760c253cSXin Li import rust_uprev 24*760c253cSXin Li 25*760c253cSXin Li 26*760c253cSXin Lidef _fail_command(cmd, *_args, **_kwargs): 27*760c253cSXin Li err = subprocess.CalledProcessError(returncode=1, cmd=cmd) 28*760c253cSXin Li err.stderr = b"mock failure" 29*760c253cSXin Li raise err 30*760c253cSXin Li 31*760c253cSXin Li 32*760c253cSXin Lidef start_mock(obj, *args, **kwargs): 33*760c253cSXin Li """Creates a patcher, starts it, and registers a cleanup to stop it. 34*760c253cSXin Li 35*760c253cSXin Li Args: 36*760c253cSXin Li obj: 37*760c253cSXin Li the object to attach the cleanup to 38*760c253cSXin Li *args: 39*760c253cSXin Li passed to mock.patch() 40*760c253cSXin Li **kwargs: 41*760c253cSXin Li passsed to mock.patch() 42*760c253cSXin Li """ 43*760c253cSXin Li patcher = mock.patch(*args, **kwargs) 44*760c253cSXin Li val = patcher.start() 45*760c253cSXin Li obj.addCleanup(patcher.stop) 46*760c253cSXin Li return val 47*760c253cSXin Li 48*760c253cSXin Li 49*760c253cSXin Liclass FetchDistfileTest(unittest.TestCase): 50*760c253cSXin Li """Tests rust_uprev.fetch_distfile_from_mirror()""" 51*760c253cSXin Li 52*760c253cSXin Li @mock.patch.object( 53*760c253cSXin Li rust_uprev, "get_distdir", return_value=Path("/fake/distfiles") 54*760c253cSXin Li ) 55*760c253cSXin Li @mock.patch.object(subprocess, "call", side_effect=_fail_command) 56*760c253cSXin Li def test_fetch_difstfile_fail(self, *_args) -> None: 57*760c253cSXin Li with self.assertRaises(subprocess.CalledProcessError): 58*760c253cSXin Li rust_uprev.fetch_distfile_from_mirror("test_distfile.tar.gz") 59*760c253cSXin Li 60*760c253cSXin Li @mock.patch.object( 61*760c253cSXin Li rust_uprev, 62*760c253cSXin Li "get_command_output_unchecked", 63*760c253cSXin Li return_value="AccessDeniedException: Access denied.", 64*760c253cSXin Li ) 65*760c253cSXin Li @mock.patch.object( 66*760c253cSXin Li rust_uprev, "get_distdir", return_value=Path("/fake/distfiles") 67*760c253cSXin Li ) 68*760c253cSXin Li @mock.patch.object(subprocess, "call", return_value=0) 69*760c253cSXin Li def test_fetch_distfile_acl_access_denied(self, *_args) -> None: 70*760c253cSXin Li rust_uprev.fetch_distfile_from_mirror("test_distfile.tar.gz") 71*760c253cSXin Li 72*760c253cSXin Li @mock.patch.object( 73*760c253cSXin Li rust_uprev, 74*760c253cSXin Li "get_command_output_unchecked", 75*760c253cSXin Li return_value='[ { "entity": "allUsers", "role": "READER" } ]', 76*760c253cSXin Li ) 77*760c253cSXin Li @mock.patch.object( 78*760c253cSXin Li rust_uprev, "get_distdir", return_value=Path("/fake/distfiles") 79*760c253cSXin Li ) 80*760c253cSXin Li @mock.patch.object(subprocess, "call", return_value=0) 81*760c253cSXin Li def test_fetch_distfile_acl_ok(self, *_args) -> None: 82*760c253cSXin Li rust_uprev.fetch_distfile_from_mirror("test_distfile.tar.gz") 83*760c253cSXin Li 84*760c253cSXin Li @mock.patch.object( 85*760c253cSXin Li rust_uprev, 86*760c253cSXin Li "get_command_output_unchecked", 87*760c253cSXin Li return_value='[ { "entity": "[email protected]", "role": "OWNER" } ]', 88*760c253cSXin Li ) 89*760c253cSXin Li @mock.patch.object( 90*760c253cSXin Li rust_uprev, "get_distdir", return_value=Path("/fake/distfiles") 91*760c253cSXin Li ) 92*760c253cSXin Li @mock.patch.object(subprocess, "call", return_value=0) 93*760c253cSXin Li def test_fetch_distfile_acl_wrong(self, *_args) -> None: 94*760c253cSXin Li with self.assertRaisesRegex(Exception, "allUsers.*READER"): 95*760c253cSXin Li with self.assertLogs(level="ERROR") as log: 96*760c253cSXin Li rust_uprev.fetch_distfile_from_mirror("test_distfile.tar.gz") 97*760c253cSXin Li self.assertIn( 98*760c253cSXin Li '[ { "entity": "[email protected]", "role": "OWNER" } ]', 99*760c253cSXin Li "\n".join(log.output), 100*760c253cSXin Li ) 101*760c253cSXin Li 102*760c253cSXin Li 103*760c253cSXin Liclass FetchRustSrcFromUpstreamTest(unittest.TestCase): 104*760c253cSXin Li """Tests for rust_uprev.fetch_rust_src_from_upstream.""" 105*760c253cSXin Li 106*760c253cSXin Li def setUp(self) -> None: 107*760c253cSXin Li self._mock_get_distdir = start_mock( 108*760c253cSXin Li self, 109*760c253cSXin Li "rust_uprev.get_distdir", 110*760c253cSXin Li return_value=Path("/fake/distfiles"), 111*760c253cSXin Li ) 112*760c253cSXin Li 113*760c253cSXin Li self._mock_gpg = start_mock( 114*760c253cSXin Li self, 115*760c253cSXin Li "subprocess.run", 116*760c253cSXin Li side_effect=self.fake_gpg, 117*760c253cSXin Li ) 118*760c253cSXin Li 119*760c253cSXin Li self._mock_urlretrieve = start_mock( 120*760c253cSXin Li self, 121*760c253cSXin Li "urllib.request.urlretrieve", 122*760c253cSXin Li side_effect=self.fake_urlretrieve, 123*760c253cSXin Li ) 124*760c253cSXin Li 125*760c253cSXin Li self._mock_rust_signing_key = start_mock( 126*760c253cSXin Li self, 127*760c253cSXin Li "rust_uprev.RUST_SIGNING_KEY", 128*760c253cSXin Li "1234567", 129*760c253cSXin Li ) 130*760c253cSXin Li 131*760c253cSXin Li @staticmethod 132*760c253cSXin Li def fake_urlretrieve(src: str, dest: Path) -> None: 133*760c253cSXin Li pass 134*760c253cSXin Li 135*760c253cSXin Li @staticmethod 136*760c253cSXin Li def fake_gpg(cmd, **_kwargs): 137*760c253cSXin Li val = mock.Mock() 138*760c253cSXin Li val.returncode = 0 139*760c253cSXin Li val.stdout = "" 140*760c253cSXin Li if "--verify" in cmd: 141*760c253cSXin Li val.stdout = "GOODSIG 1234567" 142*760c253cSXin Li return val 143*760c253cSXin Li 144*760c253cSXin Li def test_success(self): 145*760c253cSXin Li with mock.patch("rust_uprev.GPG", "gnupg"): 146*760c253cSXin Li rust_uprev.fetch_rust_src_from_upstream( 147*760c253cSXin Li "fakehttps://rustc-1.60.3-src.tar.gz", 148*760c253cSXin Li Path("/fake/distfiles/rustc-1.60.3-src.tar.gz"), 149*760c253cSXin Li ) 150*760c253cSXin Li self._mock_urlretrieve.has_calls( 151*760c253cSXin Li [ 152*760c253cSXin Li ( 153*760c253cSXin Li "fakehttps://rustc-1.60.3-src.tar.gz", 154*760c253cSXin Li Path("/fake/distfiles/rustc-1.60.3-src.tar.gz"), 155*760c253cSXin Li ), 156*760c253cSXin Li ( 157*760c253cSXin Li "fakehttps://rustc-1.60.3-src.tar.gz.asc", 158*760c253cSXin Li Path("/fake/distfiles/rustc-1.60.3-src.tar.gz.asc"), 159*760c253cSXin Li ), 160*760c253cSXin Li ] 161*760c253cSXin Li ) 162*760c253cSXin Li self._mock_gpg.has_calls( 163*760c253cSXin Li [ 164*760c253cSXin Li (["gnupg", "--refresh-keys", "1234567"], {"check": True}), 165*760c253cSXin Li ] 166*760c253cSXin Li ) 167*760c253cSXin Li 168*760c253cSXin Li def test_no_signature_file(self): 169*760c253cSXin Li def _urlretrieve(src, dest): 170*760c253cSXin Li if src.endswith(".asc"): 171*760c253cSXin Li raise Exception("404 not found") 172*760c253cSXin Li return self.fake_urlretrieve(src, dest) 173*760c253cSXin Li 174*760c253cSXin Li self._mock_urlretrieve.side_effect = _urlretrieve 175*760c253cSXin Li 176*760c253cSXin Li with self.assertRaises(rust_uprev.SignatureVerificationError) as ctx: 177*760c253cSXin Li rust_uprev.fetch_rust_src_from_upstream( 178*760c253cSXin Li "fakehttps://rustc-1.60.3-src.tar.gz", 179*760c253cSXin Li Path("/fake/distfiles/rustc-1.60.3-src.tar.gz"), 180*760c253cSXin Li ) 181*760c253cSXin Li self.assertIn("error fetching signature file", ctx.exception.message) 182*760c253cSXin Li 183*760c253cSXin Li def test_key_expired(self): 184*760c253cSXin Li def _gpg_verify(cmd, *args, **kwargs): 185*760c253cSXin Li val = self.fake_gpg(cmd, *args, **kwargs) 186*760c253cSXin Li if "--verify" in cmd: 187*760c253cSXin Li val.stdout = "EXPKEYSIG 1234567" 188*760c253cSXin Li return val 189*760c253cSXin Li 190*760c253cSXin Li self._mock_gpg.side_effect = _gpg_verify 191*760c253cSXin Li 192*760c253cSXin Li with self.assertRaises(rust_uprev.SignatureVerificationError) as ctx: 193*760c253cSXin Li rust_uprev.fetch_rust_src_from_upstream( 194*760c253cSXin Li "fakehttps://rustc-1.60.3-src.tar.gz", 195*760c253cSXin Li Path("/fake/distfiles/rustc-1.60.3-src.tar.gz"), 196*760c253cSXin Li ) 197*760c253cSXin Li self.assertIn("key has expired", ctx.exception.message) 198*760c253cSXin Li 199*760c253cSXin Li def test_key_revoked(self): 200*760c253cSXin Li def _gpg_verify(cmd, *args, **kwargs): 201*760c253cSXin Li val = self.fake_gpg(cmd, *args, **kwargs) 202*760c253cSXin Li if "--verify" in cmd: 203*760c253cSXin Li val.stdout = "REVKEYSIG 1234567" 204*760c253cSXin Li return val 205*760c253cSXin Li 206*760c253cSXin Li self._mock_gpg.side_effect = _gpg_verify 207*760c253cSXin Li 208*760c253cSXin Li with self.assertRaises(rust_uprev.SignatureVerificationError) as ctx: 209*760c253cSXin Li rust_uprev.fetch_rust_src_from_upstream( 210*760c253cSXin Li "fakehttps://rustc-1.60.3-src.tar.gz", 211*760c253cSXin Li Path("/fake/distfiles/rustc-1.60.3-src.tar.gz"), 212*760c253cSXin Li ) 213*760c253cSXin Li self.assertIn("key has been revoked", ctx.exception.message) 214*760c253cSXin Li 215*760c253cSXin Li def test_signature_expired(self): 216*760c253cSXin Li def _gpg_verify(cmd, *args, **kwargs): 217*760c253cSXin Li val = self.fake_gpg(cmd, *args, **kwargs) 218*760c253cSXin Li if "--verify" in cmd: 219*760c253cSXin Li val.stdout = "EXPSIG 1234567" 220*760c253cSXin Li return val 221*760c253cSXin Li 222*760c253cSXin Li self._mock_gpg.side_effect = _gpg_verify 223*760c253cSXin Li 224*760c253cSXin Li with self.assertRaises(rust_uprev.SignatureVerificationError) as ctx: 225*760c253cSXin Li rust_uprev.fetch_rust_src_from_upstream( 226*760c253cSXin Li "fakehttps://rustc-1.60.3-src.tar.gz", 227*760c253cSXin Li Path("/fake/distfiles/rustc-1.60.3-src.tar.gz"), 228*760c253cSXin Li ) 229*760c253cSXin Li self.assertIn("signature has expired", ctx.exception.message) 230*760c253cSXin Li 231*760c253cSXin Li def test_wrong_key(self): 232*760c253cSXin Li def _gpg_verify(cmd, *args, **kwargs): 233*760c253cSXin Li val = self.fake_gpg(cmd, *args, **kwargs) 234*760c253cSXin Li if "--verify" in cmd: 235*760c253cSXin Li val.stdout = "GOODSIG 0000000" 236*760c253cSXin Li return val 237*760c253cSXin Li 238*760c253cSXin Li self._mock_gpg.side_effect = _gpg_verify 239*760c253cSXin Li 240*760c253cSXin Li with self.assertRaises(rust_uprev.SignatureVerificationError) as ctx: 241*760c253cSXin Li rust_uprev.fetch_rust_src_from_upstream( 242*760c253cSXin Li "fakehttps://rustc-1.60.3-src.tar.gz", 243*760c253cSXin Li Path("/fake/distfiles/rustc-1.60.3-src.tar.gz"), 244*760c253cSXin Li ) 245*760c253cSXin Li self.assertIn("1234567 not found", ctx.exception.message) 246*760c253cSXin Li 247*760c253cSXin Li 248*760c253cSXin Liclass FindEbuildPathTest(unittest.TestCase): 249*760c253cSXin Li """Tests for rust_uprev.find_ebuild_path()""" 250*760c253cSXin Li 251*760c253cSXin Li def test_exact_version(self): 252*760c253cSXin Li with tempfile.TemporaryDirectory() as t: 253*760c253cSXin Li tmpdir = Path(t) 254*760c253cSXin Li ebuild = tmpdir / "test-1.3.4.ebuild" 255*760c253cSXin Li ebuild.touch() 256*760c253cSXin Li (tmpdir / "test-1.2.3.ebuild").touch() 257*760c253cSXin Li result = rust_uprev.find_ebuild_path( 258*760c253cSXin Li tmpdir, "test", rust_uprev.RustVersion(1, 3, 4) 259*760c253cSXin Li ) 260*760c253cSXin Li self.assertEqual(result, ebuild) 261*760c253cSXin Li 262*760c253cSXin Li def test_no_version(self): 263*760c253cSXin Li with tempfile.TemporaryDirectory() as t: 264*760c253cSXin Li tmpdir = Path(t) 265*760c253cSXin Li ebuild = tmpdir / "test-1.2.3.ebuild" 266*760c253cSXin Li ebuild.touch() 267*760c253cSXin Li result = rust_uprev.find_ebuild_path(tmpdir, "test") 268*760c253cSXin Li self.assertEqual(result, ebuild) 269*760c253cSXin Li 270*760c253cSXin Li def test_patch_version(self): 271*760c253cSXin Li with tempfile.TemporaryDirectory() as t: 272*760c253cSXin Li tmpdir = Path(t) 273*760c253cSXin Li ebuild = tmpdir / "test-1.3.4-r3.ebuild" 274*760c253cSXin Li ebuild.touch() 275*760c253cSXin Li (tmpdir / "test-1.2.3.ebuild").touch() 276*760c253cSXin Li result = rust_uprev.find_ebuild_path( 277*760c253cSXin Li tmpdir, "test", rust_uprev.RustVersion(1, 3, 4) 278*760c253cSXin Li ) 279*760c253cSXin Li self.assertEqual(result, ebuild) 280*760c253cSXin Li 281*760c253cSXin Li def test_multiple_versions(self): 282*760c253cSXin Li with tempfile.TemporaryDirectory() as t: 283*760c253cSXin Li tmpdir = Path(t) 284*760c253cSXin Li (tmpdir / "test-1.3.4-r3.ebuild").touch() 285*760c253cSXin Li (tmpdir / "test-1.3.5.ebuild").touch() 286*760c253cSXin Li with self.assertRaises(AssertionError): 287*760c253cSXin Li rust_uprev.find_ebuild_path(tmpdir, "test") 288*760c253cSXin Li 289*760c253cSXin Li def test_selected_version(self): 290*760c253cSXin Li with tempfile.TemporaryDirectory() as t: 291*760c253cSXin Li tmpdir = Path(t) 292*760c253cSXin Li ebuild = tmpdir / "test-1.3.4-r3.ebuild" 293*760c253cSXin Li ebuild.touch() 294*760c253cSXin Li (tmpdir / "test-1.3.5.ebuild").touch() 295*760c253cSXin Li result = rust_uprev.find_ebuild_path( 296*760c253cSXin Li tmpdir, "test", rust_uprev.RustVersion(1, 3, 4) 297*760c253cSXin Li ) 298*760c253cSXin Li self.assertEqual(result, ebuild) 299*760c253cSXin Li 300*760c253cSXin Li def test_symlink(self): 301*760c253cSXin Li # Symlinks to ebuilds in the same directory are allowed, and the return 302*760c253cSXin Li # value is the regular file. 303*760c253cSXin Li with tempfile.TemporaryDirectory() as t: 304*760c253cSXin Li tmpdir = Path(t) 305*760c253cSXin Li ebuild = tmpdir / "test-1.3.4.ebuild" 306*760c253cSXin Li ebuild.touch() 307*760c253cSXin Li (tmpdir / "test-1.3.4-r1.ebuild").symlink_to("test-1.3.4.ebuild") 308*760c253cSXin Li result = rust_uprev.find_ebuild_path(tmpdir, "test") 309*760c253cSXin Li self.assertEqual(result, ebuild) 310*760c253cSXin Li 311*760c253cSXin Li 312*760c253cSXin Liclass FindRustVersionsTest(unittest.TestCase): 313*760c253cSXin Li """Tests for rust_uprev.find_rust_versions.""" 314*760c253cSXin Li 315*760c253cSXin Li def test_with_symlinks(self): 316*760c253cSXin Li with tempfile.TemporaryDirectory() as t: 317*760c253cSXin Li tmpdir = Path(t) 318*760c253cSXin Li rust_1_49_1_ebuild = tmpdir / "rust-1.49.1.ebuild" 319*760c253cSXin Li rust_1_50_0_ebuild = tmpdir / "rust-1.50.0.ebuild" 320*760c253cSXin Li rust_1_50_0_r1_ebuild = tmpdir / "rust-1.50.0-r1.ebuild" 321*760c253cSXin Li rust_1_49_1_ebuild.touch() 322*760c253cSXin Li rust_1_50_0_ebuild.touch() 323*760c253cSXin Li rust_1_50_0_r1_ebuild.symlink_to(rust_1_50_0_ebuild) 324*760c253cSXin Li with mock.patch("rust_uprev.RUST_PATH", tmpdir): 325*760c253cSXin Li actual = rust_uprev.find_rust_versions() 326*760c253cSXin Li expected = [ 327*760c253cSXin Li (rust_uprev.RustVersion(1, 49, 1), rust_1_49_1_ebuild), 328*760c253cSXin Li (rust_uprev.RustVersion(1, 50, 0), rust_1_50_0_ebuild), 329*760c253cSXin Li ] 330*760c253cSXin Li self.assertEqual(actual, expected) 331*760c253cSXin Li 332*760c253cSXin Li 333*760c253cSXin Liclass MirrorHasFileTest(unittest.TestCase): 334*760c253cSXin Li """Tests for rust_uprev.mirror_has_file.""" 335*760c253cSXin Li 336*760c253cSXin Li @mock.patch.object(subprocess, "run") 337*760c253cSXin Li def test_no(self, mock_run): 338*760c253cSXin Li mock_run.return_value = mock.Mock( 339*760c253cSXin Li returncode=1, 340*760c253cSXin Li stdout="CommandException: One or more URLs matched no objects.", 341*760c253cSXin Li ) 342*760c253cSXin Li self.assertFalse(rust_uprev.mirror_has_file("rustc-1.69.0-src.tar.gz")) 343*760c253cSXin Li 344*760c253cSXin Li @mock.patch.object(subprocess, "run") 345*760c253cSXin Li def test_yes(self, mock_run): 346*760c253cSXin Li mock_run.return_value = mock.Mock( 347*760c253cSXin Li returncode=0, 348*760c253cSXin Li # pylint: disable=line-too-long 349*760c253cSXin Li stdout="gs://chromeos-localmirror/distfiles/rustc-1.69.0-src.tar.gz", 350*760c253cSXin Li ) 351*760c253cSXin Li self.assertTrue(rust_uprev.mirror_has_file("rustc-1.69.0-src.tar.gz")) 352*760c253cSXin Li 353*760c253cSXin Li 354*760c253cSXin Liclass MirrorRustSourceTest(unittest.TestCase): 355*760c253cSXin Li """Tests for rust_uprev.mirror_rust_source.""" 356*760c253cSXin Li 357*760c253cSXin Li def setUp(self) -> None: 358*760c253cSXin Li start_mock(self, "rust_uprev.GSUTIL", "gsutil") 359*760c253cSXin Li start_mock(self, "rust_uprev.MIRROR_PATH", "fakegs://fakemirror/") 360*760c253cSXin Li start_mock( 361*760c253cSXin Li self, "rust_uprev.get_distdir", return_value=Path("/fake/distfiles") 362*760c253cSXin Li ) 363*760c253cSXin Li self.mock_mirror_has_file = start_mock( 364*760c253cSXin Li self, 365*760c253cSXin Li "rust_uprev.mirror_has_file", 366*760c253cSXin Li ) 367*760c253cSXin Li self.mock_fetch_rust_src_from_upstream = start_mock( 368*760c253cSXin Li self, 369*760c253cSXin Li "rust_uprev.fetch_rust_src_from_upstream", 370*760c253cSXin Li ) 371*760c253cSXin Li self.mock_subprocess_run = start_mock( 372*760c253cSXin Li self, 373*760c253cSXin Li "subprocess.run", 374*760c253cSXin Li ) 375*760c253cSXin Li 376*760c253cSXin Li def test_already_present(self): 377*760c253cSXin Li self.mock_mirror_has_file.return_value = True 378*760c253cSXin Li rust_uprev.mirror_rust_source( 379*760c253cSXin Li rust_uprev.RustVersion.parse("1.67.3"), 380*760c253cSXin Li ) 381*760c253cSXin Li self.mock_fetch_rust_src_from_upstream.assert_not_called() 382*760c253cSXin Li self.mock_subprocess_run.assert_not_called() 383*760c253cSXin Li 384*760c253cSXin Li def test_fetch_and_upload(self): 385*760c253cSXin Li self.mock_mirror_has_file.return_value = False 386*760c253cSXin Li rust_uprev.mirror_rust_source( 387*760c253cSXin Li rust_uprev.RustVersion.parse("1.67.3"), 388*760c253cSXin Li ) 389*760c253cSXin Li self.mock_fetch_rust_src_from_upstream.called_once() 390*760c253cSXin Li self.mock_subprocess_run.has_calls( 391*760c253cSXin Li [ 392*760c253cSXin Li ( 393*760c253cSXin Li [ 394*760c253cSXin Li "gsutil", 395*760c253cSXin Li "cp", 396*760c253cSXin Li "-a", 397*760c253cSXin Li "public-read", 398*760c253cSXin Li "/fake/distdir/rustc-1.67.3-src.tar.gz", 399*760c253cSXin Li "fakegs://fakemirror/rustc-1.67.3-src.tar.gz", 400*760c253cSXin Li ] 401*760c253cSXin Li ), 402*760c253cSXin Li ] 403*760c253cSXin Li ) 404*760c253cSXin Li 405*760c253cSXin Li 406*760c253cSXin Liclass RemoveEbuildVersionTest(unittest.TestCase): 407*760c253cSXin Li """Tests for rust_uprev.remove_ebuild_version()""" 408*760c253cSXin Li 409*760c253cSXin Li @mock.patch.object(subprocess, "check_call") 410*760c253cSXin Li def test_single(self, check_call): 411*760c253cSXin Li with tempfile.TemporaryDirectory() as tmpdir: 412*760c253cSXin Li ebuild_dir = Path(tmpdir, "test-ebuilds") 413*760c253cSXin Li ebuild_dir.mkdir() 414*760c253cSXin Li ebuild = Path(ebuild_dir, "test-3.1.4.ebuild") 415*760c253cSXin Li ebuild.touch() 416*760c253cSXin Li Path(ebuild_dir, "unrelated-1.0.0.ebuild").touch() 417*760c253cSXin Li rust_uprev.remove_ebuild_version( 418*760c253cSXin Li ebuild_dir, "test", rust_uprev.RustVersion(3, 1, 4) 419*760c253cSXin Li ) 420*760c253cSXin Li check_call.assert_called_once_with( 421*760c253cSXin Li ["git", "rm", "test-3.1.4.ebuild"], cwd=ebuild_dir 422*760c253cSXin Li ) 423*760c253cSXin Li 424*760c253cSXin Li @mock.patch.object(subprocess, "check_call") 425*760c253cSXin Li def test_symlink(self, check_call): 426*760c253cSXin Li with tempfile.TemporaryDirectory() as tmpdir: 427*760c253cSXin Li ebuild_dir = Path(tmpdir, "test-ebuilds") 428*760c253cSXin Li ebuild_dir.mkdir() 429*760c253cSXin Li ebuild = Path(ebuild_dir, "test-3.1.4.ebuild") 430*760c253cSXin Li ebuild.touch() 431*760c253cSXin Li symlink = Path(ebuild_dir, "test-3.1.4-r5.ebuild") 432*760c253cSXin Li symlink.symlink_to(ebuild.name) 433*760c253cSXin Li Path(ebuild_dir, "unrelated-1.0.0.ebuild").touch() 434*760c253cSXin Li rust_uprev.remove_ebuild_version( 435*760c253cSXin Li ebuild_dir, "test", rust_uprev.RustVersion(3, 1, 4) 436*760c253cSXin Li ) 437*760c253cSXin Li check_call.assert_has_calls( 438*760c253cSXin Li [ 439*760c253cSXin Li mock.call( 440*760c253cSXin Li ["git", "rm", "test-3.1.4.ebuild"], cwd=ebuild_dir 441*760c253cSXin Li ), 442*760c253cSXin Li mock.call( 443*760c253cSXin Li ["git", "rm", "test-3.1.4-r5.ebuild"], cwd=ebuild_dir 444*760c253cSXin Li ), 445*760c253cSXin Li ], 446*760c253cSXin Li any_order=True, 447*760c253cSXin Li ) 448*760c253cSXin Li 449*760c253cSXin Li 450*760c253cSXin Liclass RustVersionTest(unittest.TestCase): 451*760c253cSXin Li """Tests for RustVersion class""" 452*760c253cSXin Li 453*760c253cSXin Li def test_str(self): 454*760c253cSXin Li obj = rust_uprev.RustVersion(major=1, minor=2, patch=3) 455*760c253cSXin Li self.assertEqual(str(obj), "1.2.3") 456*760c253cSXin Li 457*760c253cSXin Li def test_parse_version_only(self): 458*760c253cSXin Li expected = rust_uprev.RustVersion(major=1, minor=2, patch=3) 459*760c253cSXin Li actual = rust_uprev.RustVersion.parse("1.2.3") 460*760c253cSXin Li self.assertEqual(expected, actual) 461*760c253cSXin Li 462*760c253cSXin Li def test_parse_ebuild_name(self): 463*760c253cSXin Li expected = rust_uprev.RustVersion(major=1, minor=2, patch=3) 464*760c253cSXin Li actual = rust_uprev.RustVersion.parse_from_ebuild("rust-1.2.3.ebuild") 465*760c253cSXin Li self.assertEqual(expected, actual) 466*760c253cSXin Li 467*760c253cSXin Li actual = rust_uprev.RustVersion.parse_from_ebuild( 468*760c253cSXin Li "rust-1.2.3-r1.ebuild" 469*760c253cSXin Li ) 470*760c253cSXin Li self.assertEqual(expected, actual) 471*760c253cSXin Li 472*760c253cSXin Li def test_parse_fail(self): 473*760c253cSXin Li with self.assertRaises(AssertionError) as context: 474*760c253cSXin Li rust_uprev.RustVersion.parse("invalid-rust-1.2.3") 475*760c253cSXin Li self.assertEqual( 476*760c253cSXin Li "failed to parse 'invalid-rust-1.2.3'", str(context.exception) 477*760c253cSXin Li ) 478*760c253cSXin Li 479*760c253cSXin Li 480*760c253cSXin Liclass PrepareUprevTest(unittest.TestCase): 481*760c253cSXin Li """Tests for prepare_uprev step in rust_uprev""" 482*760c253cSXin Li 483*760c253cSXin Li def setUp(self): 484*760c253cSXin Li self.version_old = rust_uprev.RustVersion(1, 2, 3) 485*760c253cSXin Li self.version_new = rust_uprev.RustVersion(1, 3, 5) 486*760c253cSXin Li 487*760c253cSXin Li @mock.patch.object( 488*760c253cSXin Li rust_uprev, 489*760c253cSXin Li "find_ebuild_for_rust_version", 490*760c253cSXin Li return_value=Path("/path/to/ebuild"), 491*760c253cSXin Li ) 492*760c253cSXin Li @mock.patch.object(rust_uprev, "get_command_output") 493*760c253cSXin Li def test_success_with_template(self, mock_command, _ebuild_for_version): 494*760c253cSXin Li expected = rust_uprev.PreparedUprev(self.version_old) 495*760c253cSXin Li actual = rust_uprev.prepare_uprev( 496*760c253cSXin Li rust_version=self.version_new, template=self.version_old 497*760c253cSXin Li ) 498*760c253cSXin Li self.assertEqual(expected, actual) 499*760c253cSXin Li mock_command.assert_not_called() 500*760c253cSXin Li 501*760c253cSXin Li @mock.patch.object( 502*760c253cSXin Li rust_uprev, 503*760c253cSXin Li "find_ebuild_for_rust_version", 504*760c253cSXin Li return_value="/path/to/ebuild", 505*760c253cSXin Li ) 506*760c253cSXin Li @mock.patch.object(rust_uprev, "get_command_output") 507*760c253cSXin Li def test_return_none_with_template_larger_than_input( 508*760c253cSXin Li self, mock_command, *_args 509*760c253cSXin Li ): 510*760c253cSXin Li ret = rust_uprev.prepare_uprev( 511*760c253cSXin Li rust_version=self.version_old, template=self.version_new 512*760c253cSXin Li ) 513*760c253cSXin Li self.assertIsNone(ret) 514*760c253cSXin Li mock_command.assert_not_called() 515*760c253cSXin Li 516*760c253cSXin Li def test_prepare_uprev_from_json(self): 517*760c253cSXin Li json_result = (list(self.version_new),) 518*760c253cSXin Li expected = rust_uprev.PreparedUprev( 519*760c253cSXin Li self.version_new, 520*760c253cSXin Li ) 521*760c253cSXin Li actual = rust_uprev.prepare_uprev_from_json(json_result) 522*760c253cSXin Li self.assertEqual(expected, actual) 523*760c253cSXin Li 524*760c253cSXin Li 525*760c253cSXin Liclass ToggleProfileData(unittest.TestCase): 526*760c253cSXin Li """Tests functionality to include or exclude profile data from SRC_URI.""" 527*760c253cSXin Li 528*760c253cSXin Li ebuild_with_profdata = """ 529*760c253cSXin Li# Some text here. 530*760c253cSXin LiINCLUDE_PROFDATA_IN_SRC_URI=yes 531*760c253cSXin Lisome code here 532*760c253cSXin Li""" 533*760c253cSXin Li 534*760c253cSXin Li ebuild_without_profdata = """ 535*760c253cSXin Li# Some text here. 536*760c253cSXin LiINCLUDE_PROFDATA_IN_SRC_URI= 537*760c253cSXin Lisome code here 538*760c253cSXin Li""" 539*760c253cSXin Li 540*760c253cSXin Li ebuild_unexpected_content = """ 541*760c253cSXin Li# Does not contain OMIT_PROFDATA_FROM_SRC_URI assignment 542*760c253cSXin Li""" 543*760c253cSXin Li 544*760c253cSXin Li def setUp(self): 545*760c253cSXin Li self.mock_read_text = start_mock(self, "pathlib.Path.read_text") 546*760c253cSXin Li 547*760c253cSXin Li def test_turn_off_profdata(self): 548*760c253cSXin Li # Test that a file with profdata on is rewritten to a file with 549*760c253cSXin Li # profdata off. 550*760c253cSXin Li self.mock_read_text.return_value = self.ebuild_with_profdata 551*760c253cSXin Li ebuild_file = "/path/to/eclass/cros-rustc.eclass" 552*760c253cSXin Li with mock.patch("pathlib.Path.write_text") as mock_write_text: 553*760c253cSXin Li rust_uprev.set_include_profdata_src(ebuild_file, include=False) 554*760c253cSXin Li mock_write_text.assert_called_once_with( 555*760c253cSXin Li self.ebuild_without_profdata, encoding="utf-8" 556*760c253cSXin Li ) 557*760c253cSXin Li 558*760c253cSXin Li def test_turn_on_profdata(self): 559*760c253cSXin Li # Test that a file with profdata off is rewritten to a file with 560*760c253cSXin Li # profdata on. 561*760c253cSXin Li self.mock_read_text.return_value = self.ebuild_without_profdata 562*760c253cSXin Li ebuild_file = "/path/to/eclass/cros-rustc.eclass" 563*760c253cSXin Li with mock.patch("pathlib.Path.write_text") as mock_write_text: 564*760c253cSXin Li rust_uprev.set_include_profdata_src(ebuild_file, include=True) 565*760c253cSXin Li mock_write_text.assert_called_once_with( 566*760c253cSXin Li self.ebuild_with_profdata, encoding="utf-8" 567*760c253cSXin Li ) 568*760c253cSXin Li 569*760c253cSXin Li def test_turn_on_profdata_fails_if_no_assignment(self): 570*760c253cSXin Li # Test that if the string the code expects to find is not found, 571*760c253cSXin Li # this causes an exception and the file is not overwritten. 572*760c253cSXin Li self.mock_read_text.return_value = self.ebuild_unexpected_content 573*760c253cSXin Li ebuild_file = "/path/to/eclass/cros-rustc.eclass" 574*760c253cSXin Li with mock.patch("pathlib.Path.write_text") as mock_write_text: 575*760c253cSXin Li with self.assertRaises(Exception): 576*760c253cSXin Li rust_uprev.set_include_profdata_src(ebuild_file, include=False) 577*760c253cSXin Li mock_write_text.assert_not_called() 578*760c253cSXin Li 579*760c253cSXin Li 580*760c253cSXin Liclass UpdateBootstrapVersionTest(unittest.TestCase): 581*760c253cSXin Li """Tests for update_bootstrap_version step in rust_uprev""" 582*760c253cSXin Li 583*760c253cSXin Li ebuild_file_before = """ 584*760c253cSXin LiBOOTSTRAP_VERSION="1.2.0" 585*760c253cSXin Li """ 586*760c253cSXin Li ebuild_file_after = """ 587*760c253cSXin LiBOOTSTRAP_VERSION="1.3.6" 588*760c253cSXin Li """ 589*760c253cSXin Li 590*760c253cSXin Li def setUp(self): 591*760c253cSXin Li self.mock_read_text = start_mock(self, "pathlib.Path.read_text") 592*760c253cSXin Li 593*760c253cSXin Li def test_success(self): 594*760c253cSXin Li self.mock_read_text.return_value = self.ebuild_file_before 595*760c253cSXin Li # ebuild_file and new bootstrap version are deliberately different 596*760c253cSXin Li ebuild_file = "/path/to/rust/cros-rustc.eclass" 597*760c253cSXin Li with mock.patch("pathlib.Path.write_text") as mock_write_text: 598*760c253cSXin Li rust_uprev.update_bootstrap_version( 599*760c253cSXin Li ebuild_file, rust_uprev.RustVersion.parse("1.3.6") 600*760c253cSXin Li ) 601*760c253cSXin Li mock_write_text.assert_called_once_with( 602*760c253cSXin Li self.ebuild_file_after, encoding="utf-8" 603*760c253cSXin Li ) 604*760c253cSXin Li 605*760c253cSXin Li def test_fail_when_ebuild_misses_a_variable(self): 606*760c253cSXin Li self.mock_read_text.return_value = "" 607*760c253cSXin Li ebuild_file = "/path/to/rust/rust-1.3.5.ebuild" 608*760c253cSXin Li with self.assertRaises(RuntimeError) as context: 609*760c253cSXin Li rust_uprev.update_bootstrap_version( 610*760c253cSXin Li ebuild_file, rust_uprev.RustVersion.parse("1.2.0") 611*760c253cSXin Li ) 612*760c253cSXin Li self.assertEqual( 613*760c253cSXin Li "BOOTSTRAP_VERSION not found in /path/to/rust/rust-1.3.5.ebuild", 614*760c253cSXin Li str(context.exception), 615*760c253cSXin Li ) 616*760c253cSXin Li 617*760c253cSXin Li 618*760c253cSXin Liclass UpdateRustPackagesTests(unittest.TestCase): 619*760c253cSXin Li """Tests for update_rust_packages step.""" 620*760c253cSXin Li 621*760c253cSXin Li def setUp(self): 622*760c253cSXin Li self.old_version = rust_uprev.RustVersion(1, 1, 0) 623*760c253cSXin Li self.current_version = rust_uprev.RustVersion(1, 2, 3) 624*760c253cSXin Li self.new_version = rust_uprev.RustVersion(1, 3, 5) 625*760c253cSXin Li self.ebuild_file = os.path.join( 626*760c253cSXin Li rust_uprev.RUST_PATH, "rust-{self.new_version}.ebuild" 627*760c253cSXin Li ) 628*760c253cSXin Li 629*760c253cSXin Li def test_add_new_rust_packages(self): 630*760c253cSXin Li package_before = ( 631*760c253cSXin Li f"dev-lang/rust-{self.old_version}\n" 632*760c253cSXin Li f"dev-lang/rust-{self.current_version}" 633*760c253cSXin Li ) 634*760c253cSXin Li package_after = ( 635*760c253cSXin Li f"dev-lang/rust-{self.old_version}\n" 636*760c253cSXin Li f"dev-lang/rust-{self.current_version}\n" 637*760c253cSXin Li f"dev-lang/rust-{self.new_version}" 638*760c253cSXin Li ) 639*760c253cSXin Li mock_open = mock.mock_open(read_data=package_before) 640*760c253cSXin Li with mock.patch("builtins.open", mock_open): 641*760c253cSXin Li rust_uprev.update_rust_packages( 642*760c253cSXin Li "dev-lang/rust", self.new_version, add=True 643*760c253cSXin Li ) 644*760c253cSXin Li mock_open.return_value.__enter__().write.assert_called_once_with( 645*760c253cSXin Li package_after 646*760c253cSXin Li ) 647*760c253cSXin Li 648*760c253cSXin Li def test_remove_old_rust_packages(self): 649*760c253cSXin Li package_before = ( 650*760c253cSXin Li f"dev-lang/rust-{self.old_version}\n" 651*760c253cSXin Li f"dev-lang/rust-{self.current_version}\n" 652*760c253cSXin Li f"dev-lang/rust-{self.new_version}" 653*760c253cSXin Li ) 654*760c253cSXin Li package_after = ( 655*760c253cSXin Li f"dev-lang/rust-{self.current_version}\n" 656*760c253cSXin Li f"dev-lang/rust-{self.new_version}" 657*760c253cSXin Li ) 658*760c253cSXin Li mock_open = mock.mock_open(read_data=package_before) 659*760c253cSXin Li with mock.patch("builtins.open", mock_open): 660*760c253cSXin Li rust_uprev.update_rust_packages( 661*760c253cSXin Li "dev-lang/rust", self.old_version, add=False 662*760c253cSXin Li ) 663*760c253cSXin Li mock_open.return_value.__enter__().write.assert_called_once_with( 664*760c253cSXin Li package_after 665*760c253cSXin Li ) 666*760c253cSXin Li 667*760c253cSXin Li 668*760c253cSXin Liclass RustUprevOtherStagesTests(unittest.TestCase): 669*760c253cSXin Li """Tests for other steps in rust_uprev""" 670*760c253cSXin Li 671*760c253cSXin Li def setUp(self): 672*760c253cSXin Li self.old_version = rust_uprev.RustVersion(1, 1, 0) 673*760c253cSXin Li self.current_version = rust_uprev.RustVersion(1, 2, 3) 674*760c253cSXin Li self.new_version = rust_uprev.RustVersion(1, 3, 5) 675*760c253cSXin Li self.ebuild_file = os.path.join( 676*760c253cSXin Li rust_uprev.RUST_PATH, "rust-{self.new_version}.ebuild" 677*760c253cSXin Li ) 678*760c253cSXin Li 679*760c253cSXin Li @mock.patch.object(shutil, "copyfile") 680*760c253cSXin Li @mock.patch.object(subprocess, "check_call") 681*760c253cSXin Li def test_create_rust_ebuild(self, mock_call, mock_copy): 682*760c253cSXin Li template_ebuild = ( 683*760c253cSXin Li rust_uprev.EBUILD_PREFIX 684*760c253cSXin Li / f"dev-lang/rust/rust-{self.current_version}.ebuild" 685*760c253cSXin Li ) 686*760c253cSXin Li new_ebuild = ( 687*760c253cSXin Li rust_uprev.EBUILD_PREFIX 688*760c253cSXin Li / f"dev-lang/rust/rust-{self.new_version}.ebuild" 689*760c253cSXin Li ) 690*760c253cSXin Li rust_uprev.create_ebuild( 691*760c253cSXin Li "dev-lang", "rust", self.current_version, self.new_version 692*760c253cSXin Li ) 693*760c253cSXin Li mock_copy.assert_called_once_with( 694*760c253cSXin Li template_ebuild, 695*760c253cSXin Li new_ebuild, 696*760c253cSXin Li ) 697*760c253cSXin Li mock_call.assert_called_once_with( 698*760c253cSXin Li ["git", "add", f"rust-{self.new_version}.ebuild"], 699*760c253cSXin Li cwd=new_ebuild.parent, 700*760c253cSXin Li ) 701*760c253cSXin Li 702*760c253cSXin Li @mock.patch.object(shutil, "copyfile") 703*760c253cSXin Li @mock.patch.object(subprocess, "check_call") 704*760c253cSXin Li def test_create_rust_host_ebuild(self, mock_call, mock_copy): 705*760c253cSXin Li template_ebuild = ( 706*760c253cSXin Li rust_uprev.EBUILD_PREFIX 707*760c253cSXin Li / f"dev-lang/rust-host/rust-host-{self.current_version}.ebuild" 708*760c253cSXin Li ) 709*760c253cSXin Li new_ebuild = ( 710*760c253cSXin Li rust_uprev.EBUILD_PREFIX 711*760c253cSXin Li / f"dev-lang/rust-host/rust-host-{self.new_version}.ebuild" 712*760c253cSXin Li ) 713*760c253cSXin Li rust_uprev.create_ebuild( 714*760c253cSXin Li "dev-lang", "rust-host", self.current_version, self.new_version 715*760c253cSXin Li ) 716*760c253cSXin Li mock_copy.assert_called_once_with( 717*760c253cSXin Li template_ebuild, 718*760c253cSXin Li new_ebuild, 719*760c253cSXin Li ) 720*760c253cSXin Li mock_call.assert_called_once_with( 721*760c253cSXin Li ["git", "add", f"rust-host-{self.new_version}.ebuild"], 722*760c253cSXin Li cwd=new_ebuild.parent, 723*760c253cSXin Li ) 724*760c253cSXin Li 725*760c253cSXin Li @mock.patch.object(subprocess, "check_call") 726*760c253cSXin Li def test_remove_virtual_rust(self, mock_call): 727*760c253cSXin Li with tempfile.TemporaryDirectory() as tmpdir: 728*760c253cSXin Li ebuild_path = Path( 729*760c253cSXin Li tmpdir, f"virtual/rust/rust-{self.old_version}.ebuild" 730*760c253cSXin Li ) 731*760c253cSXin Li os.makedirs(ebuild_path.parent) 732*760c253cSXin Li ebuild_path.touch() 733*760c253cSXin Li with mock.patch("rust_uprev.EBUILD_PREFIX", Path(tmpdir)): 734*760c253cSXin Li rust_uprev.remove_virtual_rust(self.old_version) 735*760c253cSXin Li mock_call.assert_called_once_with( 736*760c253cSXin Li ["git", "rm", str(ebuild_path.name)], cwd=ebuild_path.parent 737*760c253cSXin Li ) 738*760c253cSXin Li 739*760c253cSXin Li @mock.patch.object(subprocess, "check_call") 740*760c253cSXin Li def test_remove_virtual_rust_with_symlink(self, mock_call): 741*760c253cSXin Li with tempfile.TemporaryDirectory() as tmpdir: 742*760c253cSXin Li ebuild_path = Path( 743*760c253cSXin Li tmpdir, f"virtual/rust/rust-{self.old_version}.ebuild" 744*760c253cSXin Li ) 745*760c253cSXin Li symlink_path = Path( 746*760c253cSXin Li tmpdir, f"virtual/rust/rust-{self.old_version}-r14.ebuild" 747*760c253cSXin Li ) 748*760c253cSXin Li os.makedirs(ebuild_path.parent) 749*760c253cSXin Li ebuild_path.touch() 750*760c253cSXin Li symlink_path.symlink_to(ebuild_path.name) 751*760c253cSXin Li with mock.patch("rust_uprev.EBUILD_PREFIX", Path(tmpdir)): 752*760c253cSXin Li rust_uprev.remove_virtual_rust(self.old_version) 753*760c253cSXin Li mock_call.assert_has_calls( 754*760c253cSXin Li [ 755*760c253cSXin Li mock.call( 756*760c253cSXin Li ["git", "rm", ebuild_path.name], 757*760c253cSXin Li cwd=ebuild_path.parent, 758*760c253cSXin Li ), 759*760c253cSXin Li mock.call( 760*760c253cSXin Li ["git", "rm", symlink_path.name], 761*760c253cSXin Li cwd=ebuild_path.parent, 762*760c253cSXin Li ), 763*760c253cSXin Li ], 764*760c253cSXin Li any_order=True, 765*760c253cSXin Li ) 766*760c253cSXin Li 767*760c253cSXin Li @mock.patch.object(rust_uprev, "find_ebuild_path") 768*760c253cSXin Li @mock.patch.object(shutil, "copyfile") 769*760c253cSXin Li @mock.patch.object(subprocess, "check_call") 770*760c253cSXin Li def test_update_virtual_rust(self, mock_call, mock_copy, mock_find_ebuild): 771*760c253cSXin Li ebuild_path = Path( 772*760c253cSXin Li f"/some/dir/virtual/rust/rust-{self.current_version}.ebuild" 773*760c253cSXin Li ) 774*760c253cSXin Li mock_find_ebuild.return_value = Path(ebuild_path) 775*760c253cSXin Li rust_uprev.update_virtual_rust(self.current_version, self.new_version) 776*760c253cSXin Li mock_call.assert_called_once_with( 777*760c253cSXin Li ["git", "add", f"rust-{self.new_version}.ebuild"], 778*760c253cSXin Li cwd=ebuild_path.parent, 779*760c253cSXin Li ) 780*760c253cSXin Li mock_copy.assert_called_once_with( 781*760c253cSXin Li ebuild_path.parent.joinpath(f"rust-{self.current_version}.ebuild"), 782*760c253cSXin Li ebuild_path.parent.joinpath(f"rust-{self.new_version}.ebuild"), 783*760c253cSXin Li ) 784*760c253cSXin Li 785*760c253cSXin Li @mock.patch("rust_uprev.find_rust_versions") 786*760c253cSXin Li def test_find_oldest_rust_version_pass(self, rust_versions): 787*760c253cSXin Li oldest_version_name = f"rust-{self.old_version}.ebuild" 788*760c253cSXin Li rust_versions.return_value = [ 789*760c253cSXin Li (self.old_version, oldest_version_name), 790*760c253cSXin Li (self.current_version, f"rust-{self.current_version}.ebuild"), 791*760c253cSXin Li (self.new_version, f"rust-{self.new_version}.ebuild"), 792*760c253cSXin Li ] 793*760c253cSXin Li actual = rust_uprev.find_oldest_rust_version() 794*760c253cSXin Li expected = self.old_version 795*760c253cSXin Li self.assertEqual(expected, actual) 796*760c253cSXin Li 797*760c253cSXin Li @mock.patch("rust_uprev.find_rust_versions") 798*760c253cSXin Li def test_find_oldest_rust_version_fail_with_only_one_ebuild( 799*760c253cSXin Li self, rust_versions 800*760c253cSXin Li ): 801*760c253cSXin Li rust_versions.return_value = [ 802*760c253cSXin Li (self.new_version, f"rust-{self.new_version}.ebuild"), 803*760c253cSXin Li ] 804*760c253cSXin Li with self.assertRaises(RuntimeError) as context: 805*760c253cSXin Li rust_uprev.find_oldest_rust_version() 806*760c253cSXin Li self.assertEqual( 807*760c253cSXin Li "Expect to find more than one Rust versions", str(context.exception) 808*760c253cSXin Li ) 809*760c253cSXin Li 810*760c253cSXin Li @mock.patch.object(rust_uprev, "get_command_output") 811*760c253cSXin Li @mock.patch.object(git, "CreateBranch") 812*760c253cSXin Li def test_create_new_repo(self, mock_branch, mock_output): 813*760c253cSXin Li mock_output.return_value = "" 814*760c253cSXin Li rust_uprev.create_new_repo(self.new_version) 815*760c253cSXin Li mock_branch.assert_called_once_with( 816*760c253cSXin Li rust_uprev.EBUILD_PREFIX, f"rust-to-{self.new_version}" 817*760c253cSXin Li ) 818*760c253cSXin Li 819*760c253cSXin Li @mock.patch.object(rust_uprev, "run_in_chroot") 820*760c253cSXin Li def test_build_cross_compiler(self, mock_run_in_chroot): 821*760c253cSXin Li cros_targets = [ 822*760c253cSXin Li "x86_64-cros-linux-gnu", 823*760c253cSXin Li "armv7a-cros-linux-gnueabihf", 824*760c253cSXin Li "aarch64-cros-linux-gnu", 825*760c253cSXin Li ] 826*760c253cSXin Li all_triples = ["x86_64-pc-linux-gnu"] + cros_targets 827*760c253cSXin Li rust_ebuild = "RUSTC_TARGET_TRIPLES=(" + "\n\t".join(all_triples) + ")" 828*760c253cSXin Li with mock.patch("rust_uprev.find_ebuild_path") as mock_find_ebuild_path: 829*760c253cSXin Li mock_path = mock.Mock() 830*760c253cSXin Li mock_path.read_text.return_value = rust_ebuild 831*760c253cSXin Li mock_find_ebuild_path.return_value = mock_path 832*760c253cSXin Li rust_uprev.build_cross_compiler(rust_uprev.RustVersion(7, 3, 31)) 833*760c253cSXin Li 834*760c253cSXin Li mock_run_in_chroot.assert_called_once_with( 835*760c253cSXin Li ["sudo", "emerge", "-j", "-G"] 836*760c253cSXin Li + [f"cross-{x}/gcc" for x in cros_targets + ["arm-none-eabi"]] 837*760c253cSXin Li ) 838*760c253cSXin Li 839*760c253cSXin Li 840*760c253cSXin Liif __name__ == "__main__": 841*760c253cSXin Li unittest.main() 842