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