def _info(self, branch=None, revision=None, cwd=''): commit = self.find(branch=branch, revision=revision) if not commit: return mocks.ProcessCompletion(returncode=1, stderr='svn: E160006: No such revision {}\n'.format(revision)) return mocks.ProcessCompletion( returncode=0, stdout= 'Path: .\n' 'Working Copy Root Path: {path}\n' 'URL: {remote}/{branch}{directory}\n' 'Relative URL: ^/{branch}{directory}\n' 'Repository Root: {remote}\n' 'Revision: {revision}\n' 'NodeKind: directory\n' 'Schedule: normal\n' 'Last Changed Author: {author}\n' 'Last Changed Rev: {revision}\n' 'Last Changed Date: {date}'.format( directory=cwd[len(self.path):], path=self.path, remote=self.remote, branch=self.branch, revision=commit.revision, author=commit.author.email, date=datetime.utcfromtimestamp(commit.timestamp).strftime('%Y-%m-%d %H:%M:%S {} (%a, %d %b %Y)'.format(self.utc_offset)), ), )
def test_documentation(self): with OutputCapture(): with mocks.Subprocess( 'ls', completion=mocks.ProcessCompletion( returncode=0, stdout='file1.txt\nfile2.txt\n'), ): result = run(['ls'], capture_output=True, encoding='utf-8') assert result.returncode == 0 assert result.stdout == 'file1.txt\nfile2.txt\n' with mocks.Subprocess( 'ls', completion=mocks.ProcessCompletion( returncode=0, stdout='file1.txt\nfile2.txt\n'), ): assert subprocess.check_output(['ls' ]) == b'file1.txt\nfile2.txt\n' assert subprocess.check_call(['ls']) == 0 with mocks.Subprocess( mocks.Subprocess.CommandRoute( 'command-a', 'argument', completion=mocks.ProcessCompletion(returncode=0)), mocks.Subprocess.CommandRoute( 'command-b', completion=mocks.ProcessCompletion(returncode=-1)), ): result = run(['command-a', 'argument']) assert result.returncode == 0 result = run(['command-b']) assert result.returncode == -1
def test_cwd_priority(self): with OutputCapture(), mocks.Subprocess( mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=0), cwd='/example'), mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=1)), ): self.assertEqual(run(['command']).returncode, 1) self.assertEqual(run(['command'], cwd='/example').returncode, 0)
def test_argument_priority(self): with OutputCapture(), mocks.Subprocess( mocks.Subprocess.Route( 'command', '--help', completion=mocks.ProcessCompletion(returncode=0)), mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=1)), ): self.assertEqual(run(['command']).returncode, 1) self.assertEqual(run(['command', '--help']).returncode, 0)
def _log_for(self, branch=None, revision=None): commit = self.find(branch=branch, revision=revision) if not commit: return mocks.ProcessCompletion(returncode=1) return mocks.ProcessCompletion( returncode=0, stdout= '------------------------------------------------------------------------\n' '{line} | {lines} lines\n\n' '{log}\n'.format(line=self.log_line(commit), lines=len(commit.message.splitlines()), log=commit.message), )
def test_input_priority(self): with OutputCapture(), mocks.Subprocess( mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=0), input='stdin'), mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=1)), ): self.assertEqual(run(['command']).returncode, 1) self.assertEqual(run(['command'], input='stdin').returncode, 0) self.assertEqual( run(['command'], stdin=BytesIO(b'stdin')).returncode, 0)
def test_ordered(self): with OutputCapture(), mocks.Subprocess( mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=0)), mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=1)), ordered=True, ): self.assertEqual(run(['command']).returncode, 0) self.assertEqual(run(['command']).returncode, 1) with self.assertRaises(OSError): run(['command'])
def test_implied_route(self): with mocks.Subprocess( 'command', completion=mocks.ProcessCompletion(returncode=0)): self.assertEqual(run(['command']).returncode, 0) with self.assertRaises(OSError): run(['invalid-file'])
def _log_range(self, branch=None, end=None, begin=None): if end < begin: return mocks.ProcessCompletion(returncode=1) output = '' previous = None for b in [branch, 'trunk']: for candidate in reversed(self.commits.get(b, [])): if candidate.revision > end or candidate.revision < begin: continue if previous and previous.revision <= candidate.revision: continue previous = candidate output += ('------------------------------------------------------------------------\n' '{line} | {lines} lines\n\n' '{log}\n').format( line=self.log_line(candidate), lines=len(candidate.message.splitlines()), log=candidate.message ) return mocks.ProcessCompletion(returncode=0, stdout=output)
def filter_branch(self, range, identifier_template=None, environment_shell=None): # We can't effectively mock the bash script in the command, but we can mock the python code that # script calls, which is where the program logic is. head, start = range.split('...') head = self.find(head) start = self.find(start) commits_to_edit = [] for commit in reversed(self.commits[head.branch]): if commit.branch == start.branch and commit.identifier <= start.identifier: break commits_to_edit.insert(0, commit) if head.branch != self.default_branch: for commit in reversed( self.commits[self.default_branch][:head.branch_point]): if commit.identifier <= start.identifier: break commits_to_edit.insert(0, commit) stdout = StringIO() original_env = { key: os.environ.get('OLDPWD') for key in [ 'OLDPWD', 'GIT_COMMIT', 'GIT_AUTHOR_NAME', 'GIT_AUTHOR_EMAIL', 'GIT_COMMITTER_NAME', 'GIT_COMMITTER_EMAIL', ] } try: count = 0 os.environ['OLDPWD'] = self.path for commit in commits_to_edit: count += 1 os.environ['GIT_COMMIT'] = commit.hash os.environ['GIT_AUTHOR_NAME'] = commit.author.name os.environ['GIT_AUTHOR_EMAIL'] = commit.author.email os.environ['GIT_COMMITTER_NAME'] = commit.author.name os.environ['GIT_COMMITTER_EMAIL'] = commit.author.email stdout.write( 'Rewrite {hash} ({count}/{total}) (--- seconds passed, remaining --- predicted)\n' .format( hash=commit.hash, count=count, total=len(commits_to_edit), )) if identifier_template: messagefile = StringIO() messagefile.write(commit.message) messagefile.seek(0) with OutputCapture() as captured: message_main(messagefile, identifier_template) lines = captured.stdout.getvalue().splitlines() if lines[-1].startswith('git-svn-id: https://svn'): lines.pop(-1) commit.message = '\n'.join(lines) if not environment_shell: continue if re.search(r'echo "Overwriting', environment_shell): stdout.write('Overwriting {}\n'.format(commit.hash)) match = re.search(r'(?P<json>\S+\.json)', environment_shell) if match: with OutputCapture() as captured: committer_main(match.group('json')) captured.stdout.seek(0) for line in captured.stdout.readlines(): line = line.rstrip() os.environ[line.split(' ')[0]] = ' '.join( line.split(' ')[1:]) commit.author = Contributor( name=os.environ['GIT_AUTHOR_NAME'], emails=[os.environ['GIT_AUTHOR_EMAIL']]) if re.search(r'echo "\s+', environment_shell): for key in [ 'GIT_AUTHOR_NAME', 'GIT_AUTHOR_EMAIL', 'GIT_COMMITTER_NAME', 'GIT_COMMITTER_EMAIL' ]: stdout.write(' {}={}\n'.format( key, os.environ[key])) finally: for key, value in original_env.items(): if value is not None: os.environ[key] = value else: del os.environ[key] return mocks.ProcessCompletion( returncode=0, stdout=stdout.getvalue(), )
def __init__( self, path='/.invalid-git', datafile=None, remote=None, tags=None, detached=None, default_branch='main', git_svn=False, ): self.path = path self.default_branch = default_branch self.remote = remote or '[email protected]:/mock/{}'.format( os.path.basename(path)) self.detached = detached or False self.tags = tags or {} try: self.executable = local.Git.executable() except (OSError, AssertionError): self.executable = '/usr/bin/git' with open(datafile or os.path.join(os.path.dirname(os.path.dirname(__file__)), 'git-repo.json')) as file: self.commits = json.load(file) for key, commits in self.commits.items(): self.commits[key] = [Commit(**kwargs) for kwargs in commits] if not git_svn: for commit in self.commits[key]: commit.revision = None self.head = self.commits[self.default_branch][-1] self.remotes = { 'origin/{}'.format(branch): commits[-1] for branch, commits in self.commits.items() } self.tags = {} # If the directory provided actually exists, populate it if os.path.isdir(self.path): if not os.path.isdir(os.path.join(self.path, '.git')): os.mkdir(os.path.join(self.path, '.git')) with open(os.path.join(self.path, '.git', 'config'), 'w') as config: config.write('[core]\n' '\trepositoryformatversion = 0\n' '\tfilemode = true\n' '\tbare = false\n' '\tlogallrefupdates = true\n' '\tignorecase = true\n' '\tprecomposeunicode = true\n' '[remote "origin"]\n' '\turl = {remote}\n' '\tfetch = +refs/heads/*:refs/remotes/origin/*\n' '[branch "{branch}"]\n' '\tremote = origin\n' '\tmerge = refs/heads/{branch}\n'.format( remote=self.remote, branch=self.default_branch, )) if git_svn: domain = 'webkit.org' if self.remote.startswith('https://'): domain = self.remote.split('/')[2] elif '@' in self.remote: domain = self.remote.split('@')[1].split(':')[0] config.write( '[svn-remote "svn"]\n' ' url = https://svn.{domain}/repository/webkit\n' ' fetch = trunk:refs/remotes/origin/{branch}'. format( domain=domain, branch=self.default_branch, )) if git_svn: git_svn_routes = [ mocks.Subprocess.Route( self.executable, 'svn', 'find-rev', re.compile(r'r\d+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout=getattr(self.find(args[3][1:]), 'hash', '\n'), )), mocks.Subprocess.Route( self.executable, 'svn', 'info', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='Path: .\n' 'URL: {remote}/{branch}\n' 'Repository Root: {remote}\n' 'Revision: {revision}\n' 'Node Kind: directory\n' 'Schedule: normal\n' 'Last Changed Author: {author}\n' 'Last Changed Rev: {revision}\n' 'Last Changed Date: {date}'.format( path=self.path, remote=self.remote, branch=self.head.branch, revision=self.head.revision, author=self.head.author.email, date=datetime.fromtimestamp(self.head.timestamp). strftime('%Y-%m-%d %H:%M:%S'), ), ), ), ] else: git_svn_routes = [ mocks.Subprocess.Route( self.executable, 'svn', cwd=self.path, completion=mocks.ProcessCompletion(returncode=1, elapsed=2), ) ] super(Git, self).__init__( mocks.Subprocess.Route( '/usr/bin/which', 'git', completion=mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.executable), ), ), mocks.Subprocess.Route( self.executable, 'status', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='''HEAD detached at b8a315ed93c nothing to commit, working tree clean ''' if self.detached else ''''On branch {branch} Your branch is up to date with 'origin/{branch}'. nothing to commit, working tree clean '''.format(branch=self.branch), ), ), mocks.Subprocess.Route( self.executable, 'rev-parse', '--show-toplevel', cwd=self.path, completion=mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.path), ), ), mocks.Subprocess.Route( self.executable, 'rev-parse', '--abbrev-ref', 'HEAD', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format('HEAD' if self.detached else self.branch), ), ), mocks.Subprocess.Route( self.executable, 'remote', 'get-url', '.*', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.remote), ) if args[3] == 'origin' else mocks.ProcessCompletion( returncode=128, stderr="fatal: No such remote '{}'\n".format(args[3]), ), ), mocks.Subprocess.Route( self.executable, 'branch', '-a', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='\n'.join( sorted(['* ' + self.branch] + list( ({default_branch} | set(self.commits.keys())) - { self.branch }))) + '\nremotes/origin/HEAD -> origin/{}\n'. format(default_branch), ), ), mocks.Subprocess.Route( self.executable, 'tag', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='\n'.join(sorted(self.tags.keys())) + '\n', ), ), mocks.Subprocess.Route( self.executable, 'rev-parse', '--abbrev-ref', 'origin/HEAD', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='origin/{}\n'.format(default_branch), ), ), mocks.Subprocess.Route( self.executable, 'rev-parse', '.*', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.find(args[2]).hash), ) if self.find(args[2]) else mocks.ProcessCompletion(returncode =128)), mocks.Subprocess.Route( self.executable, 'log', re.compile(r'.+'), '-1', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout= 'commit {hash} (HEAD -> {branch}, origin/{branch}, origin/HEAD)\n' 'Author: {author} <{email}>\n' 'Date: {date}\n' '\n{log}'.format( hash=self.find(args[2]).hash, branch=self.branch, author=self.find(args[2] ).author.name, email=self.find(args[ 2]).author.email, date =datetime.fromtimestamp(self.find( args[2]).timestamp).strftime('%a %b %d %H:%M:%S %Y' ), log ='\n'.join( [(' ' + line) if line else '' for line in self. find(args[2]) .message.splitlines()] + ([ 'git-svn-id: https://svn.{}/repository/{}/trunk@{} 268f45cc-cd09-0410-ab3c-d52691b4dbfc' .format( self.remote.split('@')[-1].split(':')[0], os.path.basename(path), self.find(args[2]).revision, ) ] if git_svn else []), )), ) if self.find(args[2]) else mocks.ProcessCompletion(returncode =128), ), mocks.Subprocess.Route( self.executable, 'rev-list', '--count', '--no-merges', re.compile(r'.+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.count(args[4]))) if self.find(args[4]) else mocks.ProcessCompletion(returncode= 128), ), mocks.Subprocess.Route( self.executable, 'show', '-s', '--format=%ct', re.compile(r'.+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.find(args[4]).timestamp, )) if self.find(args[4]) else mocks.ProcessCompletion(returncode= 128), ), mocks.Subprocess.Route( self.executable, 'branch', '-a', '--contains', re.compile(r'.+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='\n'.join(sorted(self.branches_on(args[4]))) + '\n', ) if self.find(args[4]) else mocks.ProcessCompletion(returncode =128), ), mocks.Subprocess.Route(self.executable, 'checkout', re.compile(r'.+'), cwd=self.path, generator=lambda *args, **kwargs: mocks. ProcessCompletion(returncode=0) if self.checkout(args[2]) else mocks. ProcessCompletion(returncode=1)), mocks.Subprocess.Route( self.executable, 'filter-branch', '-f', cwd=self.path, generator=lambda *args, **kwargs: self.filter_branch( args[-1], identifier_template=args[-2].split("'")[-2] if args[-3] == '--msg-filter' else None, environment_shell=args[4] if args[3] == '--env-filter' and args[4] else None, )), mocks.Subprocess.Route( self.executable, 'svn', 'fetch', '--log-window-size=5000', '-r', re.compile(r'\d+:HEAD'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0) if git_svn or local.Git(self.path).is_svn else mocks.ProcessCompletion(returncode=-1), ), mocks.Subprocess.Route( self.executable, 'pull', cwd=self.path, completion=mocks.ProcessCompletion(returncode=0), ), mocks.Subprocess.Route( self.executable, cwd=self.path, completion=mocks.ProcessCompletion( returncode=1, stderr='usage: git [--version] [--help]...\n', ), ), mocks.Subprocess.Route( self.executable, completion=mocks.ProcessCompletion( returncode=128, stderr= 'fatal: not a git repository (or any parent up to mount point)\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\n', ), ), *git_svn_routes)
def __init__( self, path='/.invalid-git', datafile=None, remote=None, branches=None, tags=None, detached=None, default_branch='main', git_svn=False, ): self.path = path self.default_branch = default_branch self.remote = remote or '[email protected]:/mock/{}'.format(os.path.basename(path)) self.detached = detached or False self.branches = branches or [] self.tags = tags or {} try: self.executable = local.Git.executable() except (OSError, AssertionError): self.executable = '/usr/bin/git' with open(datafile or os.path.join(os.path.dirname(os.path.dirname(__file__)), 'git-repo.json')) as file: self.commits = json.load(file) for key, commits in self.commits.items(): self.commits[key] = [Commit(**kwargs) for kwargs in commits] if not git_svn: for commit in self.commits[key]: commit.revision = None self.head = self.commits[self.default_branch][-1] self.tags = {} if git_svn: git_svn_routes = [ mocks.Subprocess.Route( self.executable, 'svn', 'find-rev', re.compile(r'r\d+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout=getattr(self.find(args[3][1:]), 'hash', '\n'), ) ), mocks.Subprocess.Route( self.executable, 'svn', 'info', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout= 'Path: .\n' 'URL: {remote}/{branch}\n' 'Repository Root: {remote}\n' 'Revision: {revision}\n' 'Node Kind: directory\n' 'Schedule: normal\n' 'Last Changed Author: {author}\n' 'Last Changed Rev: {revision}\n' 'Last Changed Date: {date}'.format( path=self.path, remote=self.remote, branch=self.head.branch, revision=self.head.revision, author=self.head.author.email, date=datetime.fromtimestamp(self.head.timestamp).strftime('%Y-%m-%d %H:%M:%S'), ), ), ), ] else: git_svn_routes = [mocks.Subprocess.Route( self.executable, 'svn', cwd=self.path, completion=mocks.ProcessCompletion(returncode=1, elapsed=2), )] super(Git, self).__init__( mocks.Subprocess.Route( '/usr/bin/which', 'git', completion=mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.executable), ), ), mocks.Subprocess.Route( self.executable, 'status', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='''HEAD detached at b8a315ed93c nothing to commit, working tree clean ''' if self.detached else ''''On branch {branch} Your branch is up to date with 'origin/{branch}'. nothing to commit, working tree clean '''.format(branch=self.branch), ), ), mocks.Subprocess.Route( self.executable, 'rev-parse', '--show-toplevel', cwd=self.path, completion=mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.path), ), ), mocks.Subprocess.Route( self.executable, 'rev-parse', '--abbrev-ref', 'HEAD', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format('HEAD' if self.detached else self.branch), ), ), mocks.Subprocess.Route( self.executable, 'remote', 'get-url', '.*', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.remote), ) if args[3] == 'origin' else mocks.ProcessCompletion( returncode=128, stderr="fatal: No such remote '{}'\n".format(args[3]), ), ), mocks.Subprocess.Route( self.executable, 'branch', '-a', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='\n'.join(sorted(['* ' + self.branch] + list(({default_branch} | set(self.commits.keys()) | set(self.branches)) - {self.branch}))) + '\nremotes/origin/HEAD -> origin/{}\n'.format(default_branch), ), ), mocks.Subprocess.Route( self.executable, 'tag', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='\n'.join(sorted(self.tags.keys())) + '\n', ), ), mocks.Subprocess.Route( self.executable, 'rev-parse', '--abbrev-ref', 'origin/HEAD', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='origin/{}\n'.format(default_branch), ), ), mocks.Subprocess.Route( self.executable, 'rev-parse', '.*', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.find(args[2]).hash), ) if self.find(args[2]) else mocks.ProcessCompletion(returncode=128) ), mocks.Subprocess.Route( self.executable, 'log', re.compile(r'.+'), '-1', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout= 'commit {hash} (HEAD -> {branch}, origin/{branch}, origin/HEAD)\n' 'Author: {author} <{email}>\n' 'Date: {date}\n' '\n{log}'.format( hash=self.find(args[2]).hash, branch=self.branch, author=self.find(args[2]).author.name, email=self.find(args[2]).author.email, date=datetime.fromtimestamp(self.find(args[2]).timestamp).strftime('%a %b %d %H:%M:%S %Y'), log='\n'.join([ (' ' + line) if line else '' for line in self.find(args[2]).message.splitlines() ] + ['git-svn-id: https://svn.{}/repository/{}/trunk@{} 268f45cc-cd09-0410-ab3c-d52691b4dbfc'.format( self.remote.split('@')[-1].split(':')[0], os.path.basename(path), self.find(args[2]).revision, )] if git_svn else [], ) ), ) if self.find(args[2]) else mocks.ProcessCompletion(returncode=128), ), mocks.Subprocess.Route( self.executable, 'rev-list', '--count', '--no-merges', re.compile(r'.+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.count(args[4])) ) if self.find(args[4]) else mocks.ProcessCompletion(returncode=128), ), mocks.Subprocess.Route( self.executable, 'show', '-s', '--format=%ct', re.compile(r'.+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format( self.find(args[4]).timestamp, ) ) if self.find(args[4]) else mocks.ProcessCompletion(returncode=128), ), mocks.Subprocess.Route( self.executable, 'branch', '-a', '--contains', re.compile(r'.+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='\n'.join(sorted(self.branches_on(args[4]))) + '\n', ) if self.find(args[4]) else mocks.ProcessCompletion(returncode=128), ), mocks.Subprocess.Route( self.executable, 'checkout', re.compile(r'.+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion(returncode=0) if self.checkout(args[2]) else mocks.ProcessCompletion(returncode=1) ), mocks.Subprocess.Route( self.executable, cwd=self.path, completion=mocks.ProcessCompletion( returncode=1, stderr='usage: git [--version] [--help]...\n', ), ), mocks.Subprocess.Route( self.executable, completion=mocks.ProcessCompletion( returncode=128, stderr='fatal: not a git repository (or any parent up to mount point)\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\n', ), ), *git_svn_routes )
def __init__(self, path='/.invalid-svn', datafile=None, remote=None, utc_offset=None): self.path = path self.remote = remote or 'https://svn.mock.org/repository/{}'.format(os.path.basename(path)) self.utc_offset = utc_offset or '0000' self.connected = True try: self.executable = local.Svn.executable() except (OSError, AssertionError): self.executable = '/usr/bin/svn' with open(datafile or os.path.join(os.path.dirname(os.path.dirname(__file__)), 'svn-repo.json')) as file: self.commits = json.load(file) for key, commits in self.commits.items(): self.commits[key] = [Commit(**kwargs) for kwargs in commits] self.head = self.commits['trunk'][-1] super(Svn, self).__init__( mocks.Subprocess.Route( self.executable, 'info', cwd=self.path, generator=lambda *args, **kwargs: self._info(cwd=kwargs.get('cwd', '')) ), mocks.Subprocess.Route( self.executable, 'info', self.BRANCH_RE, cwd=self.path, generator=lambda *args, **kwargs: self._info(branch=self.BRANCH_RE.match(args[2]).group('branch'), cwd=kwargs.get('cwd', '')) ), mocks.Subprocess.Route( self.executable, 'list', '^/branches', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='/\n'.join(sorted(set(self.commits.keys()) - {'trunk'} - self.tags)) + '/\n', ) if self.connected else mocks.ProcessCompletion(returncode=1), ), mocks.Subprocess.Route( self.executable, 'list', '^/tags', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='/\n'.join([tag[len('tags/'):] for tag in sorted(self.tags)]) + '/\n', ) if self.connected else mocks.ProcessCompletion(returncode=1), ), mocks.Subprocess.Route( self.executable, 'log', '-v', '-q', self.remote, '-r', re.compile(r'\d+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout= '{line}\n' 'Changed paths:\n' ' M /{branch}/ChangeLog\n' ' M /{branch}/file.cpp\n' ' D /{branch}/deleted.cpp\n' ' A /{branch}/added.cpp\n'.format( line=self.log_line(self.find(revision=args[6])), branch=self.find(revision=args[6]).branch if self.find(revision=args[6]).branch.split('/')[0] in ['trunk', 'tags'] else 'branches/{}'.format(self.find(revision=args[6]).branch) ), ) if self.connected and self.find(revision=args[6]) else mocks.ProcessCompletion(returncode=1), ), mocks.Subprocess.Route( self.executable, 'log', '-q', self.BRANCH_RE, cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='\n{}\n'.format('-' * 72).join([ self.log_line(commit) for commit in self._commits_for(branch=self.BRANCH_RE.match(args[3]).group('branch')) ]), ) if self.connected and self.BRANCH_RE.match(args[3]).group('branch') in self.commits else mocks.ProcessCompletion(returncode=1) ), mocks.Subprocess.Route( self.executable, 'log', '-l', '1', '-r', re.compile(r'\d+'), self.BRANCH_RE, cwd=self.path, generator=lambda *args, **kwargs: self._log_for( branch=self.BRANCH_RE.match(args[6]).group('branch'), revision=args[5], ) if self.connected else mocks.ProcessCompletion(returncode=1) ), mocks.Subprocess.Route( self.executable, 'up', '-r', re.compile(r'\d+'), cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion(returncode=0) if self.up(args[3]) else mocks.ProcessCompletion(returncode=1) ), mocks.Subprocess.Route( self.executable, 'up', cwd=self.path, completion=mocks.ProcessCompletion(returncode=0), ), mocks.Subprocess.Route( self.executable, cwd=self.path, completion=mocks.ProcessCompletion( returncode=1, stderr="Type 'svn help' for usage.\n", ) ), mocks.Subprocess.Route( self.executable, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=1, stderr="svn: E155007: '{}' is not a working copy\n".format(kwargs.get('cwd')), ) ), )
def __init__(self, path='/.invalid-svn', branch=None, remote=None, branches=None, tags=None): self.path = path self.branch = branch or 'trunk' self.remote = remote or 'https://svn.mock.org/repository/{}'.format( os.path.basename(path)) self.branches = branches or [] self.tags = tags or [] super(Svn, self).__init__( mocks.Subprocess.Route( local.Svn.executable, 'info', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='Path: .\n' 'Working Copy Root Path: {path}\n' 'URL: {remote}/{branch}{directory}\n' 'Relative URL: ^/{branch}{directory}\n' 'Repository Root: {remote}\n'.format( directory=kwargs.get('cwd', '')[len(self.path):], path=self.path, remote=self.remote, branch=self.branch, ), ), ), mocks.Subprocess.Route( local.Svn.executable, 'list', '^/branches', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='/\n'.join(self.branches) + '/\n', ), ), mocks.Subprocess.Route( local.Svn.executable, 'list', '^/tags', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='/\n'.join(self.tags) + '/\n', ), ), mocks.Subprocess.Route(local.Svn.executable, cwd=self.path, completion=mocks.ProcessCompletion( returncode=1, stderr="Type 'svn help' for usage.\n", )), mocks.Subprocess.Route( local.Svn.executable, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=1, stderr="svn: E155007: '{}' is not a working copy\n".format( kwargs.get('cwd')), )), )
class MockSubprocess(unittest.TestCase): LS = mocks.Subprocess.Route( 'ls', completion=mocks.ProcessCompletion(returncode=0, stdout='file1.txt\nfile2.txt\n'), ) SLEEP = mocks.Subprocess.Route( 'sleep', generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, elapsed=int(args[1])), ) def test_documentation(self): with OutputCapture(): with mocks.Subprocess( 'ls', completion=mocks.ProcessCompletion( returncode=0, stdout='file1.txt\nfile2.txt\n'), ): result = run(['ls'], capture_output=True, encoding='utf-8') assert result.returncode == 0 assert result.stdout == 'file1.txt\nfile2.txt\n' with mocks.Subprocess( 'ls', completion=mocks.ProcessCompletion( returncode=0, stdout='file1.txt\nfile2.txt\n'), ): assert subprocess.check_output(['ls' ]) == b'file1.txt\nfile2.txt\n' assert subprocess.check_call(['ls']) == 0 with mocks.Subprocess( mocks.Subprocess.CommandRoute( 'command-a', 'argument', completion=mocks.ProcessCompletion(returncode=0)), mocks.Subprocess.CommandRoute( 'command-b', completion=mocks.ProcessCompletion(returncode=-1)), ): result = run(['command-a', 'argument']) assert result.returncode == 0 result = run(['command-b']) assert result.returncode == -1 def test_no_file(self): with mocks.Subprocess(self.LS, self.SLEEP): with self.assertRaises(OSError): run(['invalid-file']) def test_implied_route(self): with mocks.Subprocess( 'command', completion=mocks.ProcessCompletion(returncode=0)): self.assertEqual(run(['command']).returncode, 0) with self.assertRaises(OSError): run(['invalid-file']) def test_popen(self): with mocks.Time: with mocks.Subprocess(self.LS, self.SLEEP): ls = subprocess.Popen(['ls'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ls.wait() self.assertEqual(0, ls.poll()) self.assertEqual(b'file1.txt\nfile2.txt\n', ls.stdout.read()) sleep = subprocess.Popen(['sleep', '1'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.assertEqual(None, sleep.poll()) sleep.wait() self.assertEqual(0, sleep.poll()) def test_ordered(self): with OutputCapture(), mocks.Subprocess( mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=0)), mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=1)), ordered=True, ): self.assertEqual(run(['command']).returncode, 0) self.assertEqual(run(['command']).returncode, 1) with self.assertRaises(OSError): run(['command']) def test_argument_priority(self): with OutputCapture(), mocks.Subprocess( mocks.Subprocess.Route( 'command', '--help', completion=mocks.ProcessCompletion(returncode=0)), mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=1)), ): self.assertEqual(run(['command']).returncode, 1) self.assertEqual(run(['command', '--help']).returncode, 0) def test_cwd_priority(self): with OutputCapture(), mocks.Subprocess( mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=0), cwd='/example'), mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=1)), ): self.assertEqual(run(['command']).returncode, 1) self.assertEqual(run(['command'], cwd='/example').returncode, 0) def test_input_priority(self): with OutputCapture(), mocks.Subprocess( mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=0), input='stdin'), mocks.Subprocess.Route( 'command', completion=mocks.ProcessCompletion(returncode=1)), ): self.assertEqual(run(['command']).returncode, 1) self.assertEqual(run(['command'], input='stdin').returncode, 0) self.assertEqual( run(['command'], stdin=BytesIO(b'stdin')).returncode, 0)
def __init__( self, path='/.invalid-git', branch=None, remote=None, branches=None, tags=None, detached=None, default_branch='main', ): self.path = path self.branch = branch or default_branch self.remote = remote or '[email protected]:/mock/{}'.format( os.path.basename(path)) self.detached = detached or False self.branches = branches or [] self.tags = tags or [] super(Git, self).__init__( mocks.Subprocess.Route( local.Git.executable, 'status', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='''HEAD detached at b8a315ed93c nothing to commit, working tree clean ''' if self.detached else ''''On branch {branch} Your branch is up to date with 'origin/{branch}'. nothing to commit, working tree clean '''.format(branch=self.branch), ), ), mocks.Subprocess.Route( local.Git.executable, 'rev-parse', '--show-toplevel', cwd=self.path, completion=mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.path), ), ), mocks.Subprocess.Route( local.Git.executable, 'rev-parse', '--abbrev-ref', 'HEAD', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format('HEAD' if self.detached else self.branch), ), ), mocks.Subprocess.Route( local.Git.executable, 'remote', 'get-url', '.*', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='{}\n'.format(self.remote), ) if args[3] == 'origin' else mocks.ProcessCompletion( returncode=128, stderr="fatal: No such remote '{}'\n".format(args[3]), ), ), mocks.Subprocess.Route( local.Git.executable, 'branch', '-a', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='\n'.join( sorted(['* ' + self.branch] + list( ({default_branch} | set(self.branches)) - { self.branch }))) + '\nremotes/origin/HEAD -> origin/{}\n'. format(default_branch), ), ), mocks.Subprocess.Route( local.Git.executable, 'tag', cwd=self.path, generator=lambda *args, **kwargs: mocks.ProcessCompletion( returncode=0, stdout='\n'.join(self.tags) + '\n', ), ), mocks.Subprocess.Route( local.Git.executable, cwd=self.path, completion=mocks.ProcessCompletion( returncode=1, stderr='usage: git [--version] [--help]...\n', ), ), mocks.Subprocess.Route( local.Git.executable, completion=mocks.ProcessCompletion( returncode=128, stderr= 'fatal: not a git repository (or any parent up to mount point)\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\n', ), ), )