aboutsummaryrefslogtreecommitdiff
path: root/tests/cli/testllvmpush.py
blob: 1d9b8ab0ca942bc487c814f06bfb3804fd0ed5bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
"""Command line interface tests for llvm.py push.

Note that although this uses the unittest framework, it does *not* contain unit
tests.

"""

import shutil
import os
import subprocess
import unittest

from tempfile import mkdtemp
from uuid import uuid4

from linaropy.cd import cd
from linaropy.git.clone import Clone
from llvmtestcase import LLVMTestCase, debug


class Testllvmpush(LLVMTestCase):

    @classmethod
    def llvm_push(cls, *args, **kwargs):
        return cls.command_with_defaults("push", *args, **kwargs)

    @classmethod
    def get_origin_path(cls, subproj):
        return os.path.join(cls.origins, subproj)

    @classmethod
    def get_clone_path(cls, subproj):
        return os.path.join(cls.repos, subproj)

    @classmethod
    def setUpClass(cls):
        """Create the file structure and environment for testing llvm push."""
        cls.all_repos = ("llvm", "clang", "compiler-rt", "lld", "lldb",
                         "libcxx", "libcxxabi", "libunwind", "test-suite")

        cls.origins = mkdtemp()
        cls.repos = mkdtemp()
        cls.llvm_root = mkdtemp()

        cls.user = "llvm-developer"

        # Create dummy repos - one origin that we will push to, and one clone
        # that we will create worktrees from
        for reponame in cls.all_repos:
            origin = cls.get_origin_path(reponame)
            cls.create_dummy_repo(origin)

            clone = cls.get_clone_path(reponame)
            cls.create_dummy_repo(
                clone, "file://{}@{}".format(cls.user, origin))

    @classmethod
    def tearDownClass(cls):
        shutil.rmtree(cls.origins)
        shutil.rmtree(cls.repos)

    @classmethod
    def setUp(cls):
        cls.env = os.path.join(cls.llvm_root, "env" + str(uuid4()))
        cls.llvm_src = os.path.join(cls.env, "llvm")

        # Create LLVM worktree
        cls.branch = "br" + str(uuid4())
        cls.add_worktree(cls.get_clone_path("llvm"), cls.llvm_src,
                         cls.branch)

    @classmethod
    def tearDown(cls):
        # Clean up the directories where we might have added subprojects.
        # This isn't 100% clean, because we don't clean up the repos between
        # tests (so any branches will remain), but it's good enough for the
        # current tests.
        for subprojdir in (os.path.join(cls.llvm_src, "projects"),
                           os.path.join(cls.llvm_src, "tools")):
            if os.path.isdir(subprojdir):
                shutil.rmtree(subprojdir)
                os.makedirs(subprojdir)

        # Run prune on the original repos, to remove any dangling worktrees.
        for reponame in cls.all_repos:
            repopath = cls.get_clone_path(reponame)
            with cd(repopath):
                cls.run_quietly(["git", "worktree", "prune"])

    def test_push(self):
        with cd(self.llvm_src):
            self.create_dummy_commit("Test llvm push")

        enabled = ["clang", "lld"]

        for subproj in enabled:
            worktreePath = os.path.join(self.llvm_src, "tools", subproj)
            self.add_worktree(self.get_clone_path(subproj),
                              worktreePath,
                              self.branch)
            with cd(worktreePath):
                self.create_dummy_commit("Test {} push".format(subproj))

        pushed = self.run_with_output(self.llvm_push())
        remote_branch = "linaro-local/{}/{}".format(self.user, self.branch)

        self.assertRegex(
            pushed, "(.*\n)*Pushed to {}(.*\n)*".format(remote_branch))

        for subproj in self.all_repos:
            origin = self.get_origin_path(subproj)

            with cd(origin):
                if subproj == "llvm" or subproj in enabled:
                    output = self.run_with_output(["git", "log", "--oneline",
                                                   "-1", remote_branch])

                    self.assertRegex(
                        output, ".*Test {} push.*".format(subproj))
                else:
                    with self.assertRaises(subprocess.CalledProcessError) as context:
                        output = self.run_with_output(
                            ["git", "log", "--oneline", "-1", remote_branch])

                    self.assertRegex(
                        str(context.exception.output),
                        "(.*\n)*.*unknown revision or path not in the working tree(.*\n)*")

    def test_push_mismatched_branches(self):
        with cd(self.llvm_src):
            self.create_dummy_commit("Test llvm push")

        enabled = ["clang", "lld"]

        for subproj in enabled:
            branch = self.branch

            # Move only lld to a different branch
            if subproj == "lld":
                branch = branch + "-different"

            worktreePath = os.path.join(self.llvm_src, "tools", subproj)
            self.add_worktree(self.get_clone_path(subproj),
                              worktreePath,
                              branch)
            with cd(worktreePath):
                self.create_dummy_commit("Test {} push".format(subproj))

        with self.assertRaises(subprocess.CalledProcessError) as context:
            output = self.run_with_output(self.llvm_push())

        # Check that we error out because lld is on a different branch
        self.assertRegex(str(context.exception.output),
                         "(.*\n)*.*lld is on branch {}, but should be on {}".format(
            self.branch + "-different", self.branch))

        # Check that we haven't pushed llvm or clang either, even if they're on
        # the same branch
        remote_branch = "linaro-local/{}/{}".format(self.user, self.branch)

        for subproj in ["llvm", "clang"]:
            with cd(self.get_origin_path(subproj)):
                with self.assertRaises(subprocess.CalledProcessError) as context:
                    self.run_with_output(["git", "log", "--oneline", "-1",
                                          remote_branch])

                self.assertRegex(
                    str(context.exception.output),
                    "(.*\n)*.*unknown revision or path not in the working tree(.*\n)*")