"""Common TestCase used for testing llvm.py subcommands.""" import shutil import os import subprocess import unittest from tempfile import mkdtemp from uuid import uuid4 from linaropy.cd import cd # TODO: move this somewhere more public (maybe linaropy?) def debug(test): """ Decorator that dumps the output of any subprocess.CalledProcessError exception. Use this to decorate a test function when you can't tell what the problem is. """ def wrapper(*args, **kwargs): # Catch any exceptions so we can dump all the output try: test(*args, **kwargs) except subprocess.CalledProcessError as exc: print("Error in {}:".format(test.__name__)) print("Command {} exited with error code {}:\n{}".format( exc.cmd, exc.returncode, exc.output)) return wrapper class LLVMTestCase(unittest.TestCase): python = "python3" script = os.path.join("scripts", "llvm.py") @classmethod def create_dummy_commit(cls, commitMessage="Dummy commit"): filename = "filethatshouldntexist" + str(uuid4()) cls.run_quietly(["touch", filename]) try: cls.run_quietly(["git", "add", filename]) cls.run_quietly(["git", "commit", "-m", commitMessage]) except subprocess.CalledProcessError as exc: print("Command {} exited with error code {}:\n{}".format( exc.cmd, exc.returncode, exc.output)) @classmethod def create_dummy_repo(cls, repopath, originpath=None): if originpath is not None: cls.run_quietly(["git", "clone", originpath, repopath]) else: if not os.path.isdir(repopath): os.makedirs(repopath) with cd(repopath): cls.run_quietly(["git", "init"]) with cd(repopath): cls.create_dummy_commit() @classmethod def add_worktree(cls, repopath, worktreepath, branch): with cd(repopath): cls.run_quietly(["git", "worktree", "add", worktreepath, "-b", branch]) @staticmethod def run_with_output(*args, **kwargs): """Helper for running a command and capturing stdout and stderr""" kwargs["stderr"] = subprocess.STDOUT return str(subprocess.check_output(*args, **kwargs), 'utf-8') @staticmethod def run_quietly(*args, **kwargs): """ Helper for running a command and ignoring stdout and stderr. Exceptions are still thrown if something goes wrong """ kwargs["stdout"] = subprocess.DEVNULL kwargs["stderr"] = subprocess.DEVNULL return subprocess.check_call(*args, **kwargs) @classmethod def command_with_defaults(cls, subcommand, *args, **kwargs): """ Build a list representing a llvm subcommand with the given args. Unless otherwise specified in kwargs, this uses the values for repos and env that it finds in cls. """ command = [cls.python, cls.script] repos = cls.repos if "repos" in kwargs: repos = kwargs["repos"] if repos: command.append("--repos") command.append(repos) env = cls.env if "env" in kwargs: env = kwargs["env"] if env: command.append("--env") command.append(env) command.append(subcommand) if len(args): command.extend(args) return command