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 |
Diana Picus | 9276b78 | 2018-01-24 14:40:46 +0100 | [diff] [blame] | 18 | from llvmtestcase import LLVMTestCase, require_command_arg, debug |
Diana Picus | efc7bda | 2017-06-09 19:14:08 +0200 | [diff] [blame] | 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 | |
Diana Picus | 9276b78 | 2018-01-24 14:40:46 +0100 | [diff] [blame] | 90 | @require_command_arg("--source-dir") |
Diana Picus | 9f75686 | 2017-12-20 10:35:08 +0100 | [diff] [blame] | 91 | def test_source_dir_ir_compulsory(self): |
| 92 | """Test that we get an error if we don't pass the source dir.""" |
Diana Picus | 9276b78 | 2018-01-24 14:40:46 +0100 | [diff] [blame] | 93 | self.run_with_output(self.llvm_push()) |
Diana Picus | 9f75686 | 2017-12-20 10:35:08 +0100 | [diff] [blame] | 94 | |
Diana Picus | efc7bda | 2017-06-09 19:14:08 +0200 | [diff] [blame] | 95 | def test_push(self): |
| 96 | with cd(self.llvm_src): |
| 97 | self.create_dummy_commit("Test llvm push") |
| 98 | |
| 99 | enabled = ["clang", "lld"] |
| 100 | |
| 101 | for subproj in enabled: |
| 102 | worktreePath = os.path.join(self.llvm_src, "tools", subproj) |
| 103 | self.add_worktree(self.get_clone_path(subproj), |
| 104 | worktreePath, |
| 105 | self.branch) |
| 106 | with cd(worktreePath): |
| 107 | self.create_dummy_commit("Test {} push".format(subproj)) |
| 108 | |
Diana Picus | 9f75686 | 2017-12-20 10:35:08 +0100 | [diff] [blame] | 109 | pushed = self.run_with_output( |
| 110 | self.llvm_push("--source-dir", self.llvm_src)) |
Diana Picus | efc7bda | 2017-06-09 19:14:08 +0200 | [diff] [blame] | 111 | remote_branch = "linaro-local/{}/{}".format(self.user, self.branch) |
| 112 | |
Diana Picus | 95226d4 | 2017-11-01 13:16:54 +0100 | [diff] [blame] | 113 | self.assertRegex( |
| 114 | pushed, "(.*\n)*Pushed to {}(.*\n)*".format(remote_branch)) |
| 115 | |
Diana Picus | efc7bda | 2017-06-09 19:14:08 +0200 | [diff] [blame] | 116 | for subproj in self.all_repos: |
| 117 | origin = self.get_origin_path(subproj) |
| 118 | |
| 119 | with cd(origin): |
| 120 | if subproj == "llvm" or subproj in enabled: |
| 121 | output = self.run_with_output(["git", "log", "--oneline", |
| 122 | "-1", remote_branch]) |
| 123 | |
| 124 | self.assertRegex( |
| 125 | output, ".*Test {} push.*".format(subproj)) |
| 126 | else: |
| 127 | with self.assertRaises(subprocess.CalledProcessError) as context: |
| 128 | output = self.run_with_output( |
| 129 | ["git", "log", "--oneline", "-1", remote_branch]) |
| 130 | |
| 131 | self.assertRegex( |
| 132 | str(context.exception.output), |
| 133 | "(.*\n)*.*unknown revision or path not in the working tree(.*\n)*") |
| 134 | |
| 135 | def test_push_mismatched_branches(self): |
| 136 | with cd(self.llvm_src): |
| 137 | self.create_dummy_commit("Test llvm push") |
| 138 | |
| 139 | enabled = ["clang", "lld"] |
| 140 | |
| 141 | for subproj in enabled: |
| 142 | branch = self.branch |
| 143 | |
| 144 | # Move only lld to a different branch |
| 145 | if subproj == "lld": |
| 146 | branch = branch + "-different" |
| 147 | |
| 148 | worktreePath = os.path.join(self.llvm_src, "tools", subproj) |
| 149 | self.add_worktree(self.get_clone_path(subproj), |
| 150 | worktreePath, |
| 151 | branch) |
| 152 | with cd(worktreePath): |
| 153 | self.create_dummy_commit("Test {} push".format(subproj)) |
| 154 | |
| 155 | with self.assertRaises(subprocess.CalledProcessError) as context: |
Diana Picus | 9f75686 | 2017-12-20 10:35:08 +0100 | [diff] [blame] | 156 | output = self.run_with_output( |
| 157 | self.llvm_push("--source-dir", self.llvm_src)) |
Diana Picus | efc7bda | 2017-06-09 19:14:08 +0200 | [diff] [blame] | 158 | |
| 159 | # Check that we error out because lld is on a different branch |
| 160 | self.assertRegex(str(context.exception.output), |
| 161 | "(.*\n)*.*lld is on branch {}, but should be on {}".format( |
| 162 | self.branch + "-different", self.branch)) |
| 163 | |
| 164 | # Check that we haven't pushed llvm or clang either, even if they're on |
| 165 | # the same branch |
| 166 | remote_branch = "linaro-local/{}/{}".format(self.user, self.branch) |
| 167 | |
| 168 | for subproj in ["llvm", "clang"]: |
| 169 | with cd(self.get_origin_path(subproj)): |
| 170 | with self.assertRaises(subprocess.CalledProcessError) as context: |
| 171 | self.run_with_output(["git", "log", "--oneline", "-1", |
| 172 | remote_branch]) |
| 173 | |
| 174 | self.assertRegex( |
| 175 | str(context.exception.output), |
| 176 | "(.*\n)*.*unknown revision or path not in the working tree(.*\n)*") |