xref: /aosp_15_r20/external/crosvm/tools/tests/cl_tests.py (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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