1#!/usr/bin/env python3 2# Copyright 2022 The ChromiumOS Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import os 7from pathlib import Path 8import shutil 9import sys 10import tempfile 11import unittest 12 13sys.path.append(os.path.dirname(sys.path[0])) 14 15from impl.common import CROSVM_ROOT, cmd, quoted, TOOLS_ROOT 16 17git = cmd("git") 18cl = cmd(f"{TOOLS_ROOT}/cl") 19 20 21class ClTests(unittest.TestCase): 22 test_root: Path 23 24 def setUp(self): 25 self.test_root = Path(tempfile.mkdtemp()) 26 os.chdir(self.test_root) 27 git("clone", CROSVM_ROOT, ".").fg(quiet=True) 28 29 # Set up user name (it's not set up in Luci) 30 git("config user.name Nobody").fg(quiet=True) 31 git("config user.email [email protected]").fg(quiet=True) 32 33 # Check out a detached head and delete all branches. 34 git("checkout -d HEAD").fg(quiet=True) 35 branch_list = git("branch").lines() 36 for branch in branch_list: 37 if not branch.startswith("*"): 38 git("branch -D", branch).fg(quiet=True) 39 40 # Set up the origin for testing uploads and rebases. 41 git("remote set-url origin https://chromium.googlesource.com/crosvm/crosvm").fg(quiet=True) 42 git("fetch -q origin main").fg(quiet=True) 43 git("fetch -q origin chromeos").fg(quiet=True) 44 45 def tearDown(self) -> None: 46 shutil.rmtree(self.test_root) 47 48 def create_test_commit(self, message: str, branch: str, upstream: str = "origin/main"): 49 git("checkout -b", branch, "--track", upstream).fg(quiet=True) 50 with Path("Cargo.toml").open("a") as file: 51 file.write("# Foo") 52 git("commit -a -m", quoted(message)).fg(quiet=True) 53 return git("rev-parse HEAD").stdout() 54 55 def test_cl_upload(self): 56 sha = self.create_test_commit("Test Commit", "foo") 57 expected = f"""\ 58Uploading to origin/main: 59 {sha} Test Commit 60 61Not running: git push origin HEAD:refs/for/main%""" 62 63 self.assertEqual(cl("upload --dry-run").stdout(), expected) 64 65 def test_cl_status(self): 66 self.create_test_commit("Test Commit", "foo") 67 expected = """\ 68Branch foo tracking origin/main 69 NOT_UPLOADED Test Commit""" 70 71 self.assertEqual(cl("status").stdout(), expected) 72 73 def test_cl_rebase(self): 74 self.create_test_commit("Test Commit", "foo", "origin/chromeos") 75 cl("rebase").fg() 76 77 # Expect foo-upstream to be tracking `main` and have the same commit 78 self.assertEqual(git("rev-parse --abbrev-ref foo-upstream@{u}").stdout(), "origin/main") 79 self.assertEqual( 80 git("log -1 --format=%s foo").stdout(), 81 git("log -1 --format=%s foo-upstream").stdout(), 82 ) 83 84 def test_cl_rebase_with_existing_branch(self): 85 previous_sha = self.create_test_commit("Previous commit", "foo-upstream ") 86 self.create_test_commit("Test Commit", "foo", "origin/chromeos") 87 message = cl("rebase").stdout() 88 89 # `cl rebase` will overwrite the branch, but we should print the previous sha in case 90 # the user needs to recover it. 91 self.assertIn(previous_sha, message) 92 93 # Expect foo-upstream to be tracking `main` and have the same commit. The previous commit 94 # would be dropped. 95 self.assertEqual(git("rev-parse --abbrev-ref foo-upstream@{u}").stdout(), "origin/main") 96 self.assertEqual( 97 git("log -1 --format=%s foo").stdout(), 98 git("log -1 --format=%s foo-upstream").stdout(), 99 ) 100 101 def test_prune(self): 102 self.create_test_commit("Test Commit", "foo") 103 git("branch foo-no-commit origin/main").fg() 104 cl("prune --force").fg() 105 106 # `foo` has unsubmitted commits, it should still be there. 107 self.assertTrue(git("rev-parse foo").success()) 108 109 # `foo-no-commit` has no commits, it should have been pruned. 110 self.assertFalse(git("rev-parse foo-no-commit").success()) 111 112 113if __name__ == "__main__": 114 unittest.main(warnings="ignore") 115