"""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, require_command_arg, 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"]) @require_command_arg("--source-dir") def test_source_dir_ir_compulsory(self): """Test that we get an error if we don't pass the source dir.""" self.run_with_output(self.llvm_push()) 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("--source-dir", self.llvm_src)) 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("--source-dir", self.llvm_src)) # 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)*")