Diana Picus | efc7bda | 2017-06-09 19:14:08 +0200 | [diff] [blame] | 1 | """Command line interface tests for llvm.py push. |
| 2 | |
| 3 | Note that although this uses the unittest framework, it does *not* contain unit |
| 4 | tests. |
| 5 | |
| 6 | """ |
| 7 | |
| 8 | import shutil |
| 9 | import os |
| 10 | import subprocess |
| 11 | import unittest |
| 12 | |
| 13 | from tempfile import mkdtemp |
| 14 | from uuid import uuid4 |
| 15 | |
| 16 | from linaropy.cd import cd |
| 17 | from linaropy.git.clone import Clone |
| 18 | from llvmtestcase import LLVMTestCase, debug |
| 19 | |
| 20 | |
| 21 | class Testllvmpush(LLVMTestCase): |
| 22 | |
| 23 | @classmethod |
| 24 | def llvm_push(cls, *args, **kwargs): |
| 25 | return cls.command_with_defaults("push", *args, **kwargs) |
| 26 | |
| 27 | @classmethod |
| 28 | def get_origin_path(cls, subproj): |
| 29 | return os.path.join(cls.origins, subproj) |
| 30 | |
| 31 | @classmethod |
| 32 | def get_clone_path(cls, subproj): |
| 33 | return os.path.join(cls.repos, subproj) |
| 34 | |
| 35 | @classmethod |
| 36 | def setUpClass(cls): |
| 37 | """Create the file structure and environment for testing llvm push.""" |
| 38 | cls.all_repos = ("llvm", "clang", "compiler-rt", "lld", "lldb", |
| 39 | "libcxx", "libcxxabi", "libunwind", "test-suite") |
| 40 | |
| 41 | cls.origins = mkdtemp() |
| 42 | cls.repos = mkdtemp() |
| 43 | cls.llvm_root = mkdtemp() |
| 44 | |
| 45 | cls.user = "llvm-developer" |
| 46 | |
| 47 | # Create dummy repos - one origin that we will push to, and one clone |
| 48 | # that we will create worktrees from |
| 49 | for reponame in cls.all_repos: |
| 50 | origin = cls.get_origin_path(reponame) |
| 51 | cls.create_dummy_repo(origin) |
| 52 | |
| 53 | clone = cls.get_clone_path(reponame) |
| 54 | cls.create_dummy_repo( |
| 55 | clone, "file://{}@{}".format(cls.user, origin)) |
| 56 | |
| 57 | @classmethod |
| 58 | def tearDownClass(cls): |
| 59 | shutil.rmtree(cls.origins) |
| 60 | shutil.rmtree(cls.repos) |
| 61 | |
| 62 | @classmethod |
| 63 | def setUp(cls): |
| 64 | cls.env = os.path.join(cls.llvm_root, "env" + str(uuid4())) |
| 65 | cls.llvm_src = os.path.join(cls.env, "llvm") |
| 66 | |
| 67 | # Create LLVM worktree |
| 68 | cls.branch = "br" + str(uuid4()) |
| 69 | cls.add_worktree(cls.get_clone_path("llvm"), cls.llvm_src, |
| 70 | cls.branch) |
| 71 | |
| 72 | @classmethod |
| 73 | def tearDown(cls): |
| 74 | # Clean up the directories where we might have added subprojects. |
| 75 | # This isn't 100% clean, because we don't clean up the repos between |
| 76 | # tests (so any branches will remain), but it's good enough for the |
| 77 | # current tests. |
| 78 | for subprojdir in (os.path.join(cls.llvm_src, "projects"), |
| 79 | os.path.join(cls.llvm_src, "tools")): |
| 80 | if os.path.isdir(subprojdir): |
| 81 | shutil.rmtree(subprojdir) |
| 82 | os.makedirs(subprojdir) |
| 83 | |
| 84 | # Run prune on the original repos, to remove any dangling worktrees. |
| 85 | for reponame in cls.all_repos: |
| 86 | repopath = cls.get_clone_path(reponame) |
| 87 | with cd(repopath): |
| 88 | cls.run_quietly(["git", "worktree", "prune"]) |
| 89 | |
| 90 | def test_push(self): |
| 91 | with cd(self.llvm_src): |
| 92 | self.create_dummy_commit("Test llvm push") |
| 93 | |
| 94 | enabled = ["clang", "lld"] |
| 95 | |
| 96 | for subproj in enabled: |
| 97 | worktreePath = os.path.join(self.llvm_src, "tools", subproj) |
| 98 | self.add_worktree(self.get_clone_path(subproj), |
| 99 | worktreePath, |
| 100 | self.branch) |
| 101 | with cd(worktreePath): |
| 102 | self.create_dummy_commit("Test {} push".format(subproj)) |
| 103 | |
Diana Picus | 95226d4 | 2017-11-01 13:16:54 +0100 | [diff] [blame] | 104 | pushed = self.run_with_output(self.llvm_push()) |
Diana Picus | efc7bda | 2017-06-09 19:14:08 +0200 | [diff] [blame] | 105 | remote_branch = "linaro-local/{}/{}".format(self.user, self.branch) |
| 106 | |
Diana Picus | 95226d4 | 2017-11-01 13:16:54 +0100 | [diff] [blame] | 107 | self.assertRegex( |
| 108 | pushed, "(.*\n)*Pushed to {}(.*\n)*".format(remote_branch)) |
| 109 | |
Diana Picus | efc7bda | 2017-06-09 19:14:08 +0200 | [diff] [blame] | 110 | for subproj in self.all_repos: |
| 111 | origin = self.get_origin_path(subproj) |
| 112 | |
| 113 | with cd(origin): |
| 114 | if subproj == "llvm" or subproj in enabled: |
| 115 | output = self.run_with_output(["git", "log", "--oneline", |
| 116 | "-1", remote_branch]) |
| 117 | |
| 118 | self.assertRegex( |
| 119 | output, ".*Test {} push.*".format(subproj)) |
| 120 | else: |
| 121 | with self.assertRaises(subprocess.CalledProcessError) as context: |
| 122 | output = self.run_with_output( |
| 123 | ["git", "log", "--oneline", "-1", remote_branch]) |
| 124 | |
| 125 | self.assertRegex( |
| 126 | str(context.exception.output), |
| 127 | "(.*\n)*.*unknown revision or path not in the working tree(.*\n)*") |
| 128 | |
| 129 | def test_push_mismatched_branches(self): |
| 130 | with cd(self.llvm_src): |
| 131 | self.create_dummy_commit("Test llvm push") |
| 132 | |
| 133 | enabled = ["clang", "lld"] |
| 134 | |
| 135 | for subproj in enabled: |
| 136 | branch = self.branch |
| 137 | |
| 138 | # Move only lld to a different branch |
| 139 | if subproj == "lld": |
| 140 | branch = branch + "-different" |
| 141 | |
| 142 | worktreePath = os.path.join(self.llvm_src, "tools", subproj) |
| 143 | self.add_worktree(self.get_clone_path(subproj), |
| 144 | worktreePath, |
| 145 | branch) |
| 146 | with cd(worktreePath): |
| 147 | self.create_dummy_commit("Test {} push".format(subproj)) |
| 148 | |
| 149 | with self.assertRaises(subprocess.CalledProcessError) as context: |
| 150 | output = self.run_with_output(self.llvm_push()) |
| 151 | |
| 152 | # Check that we error out because lld is on a different branch |
| 153 | self.assertRegex(str(context.exception.output), |
| 154 | "(.*\n)*.*lld is on branch {}, but should be on {}".format( |
| 155 | self.branch + "-different", self.branch)) |
| 156 | |
| 157 | # Check that we haven't pushed llvm or clang either, even if they're on |
| 158 | # the same branch |
| 159 | remote_branch = "linaro-local/{}/{}".format(self.user, self.branch) |
| 160 | |
| 161 | for subproj in ["llvm", "clang"]: |
| 162 | with cd(self.get_origin_path(subproj)): |
| 163 | with self.assertRaises(subprocess.CalledProcessError) as context: |
| 164 | self.run_with_output(["git", "log", "--oneline", "-1", |
| 165 | remote_branch]) |
| 166 | |
| 167 | self.assertRegex( |
| 168 | str(context.exception.output), |
| 169 | "(.*\n)*.*unknown revision or path not in the working tree(.*\n)*") |