mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #30522 from terminalmage/fix-worktree-tests
Update git.list_worktree tests to reflect new return data
This commit is contained in:
commit
79528c59c3
2 changed files with 176 additions and 66 deletions
|
@ -588,7 +588,7 @@ class GitModuleTest(integration.ModuleCase):
|
|||
)
|
||||
shutil.rmtree(new_repo)
|
||||
|
||||
# Test for git.is_worktree is in test_worktree
|
||||
# Test for git.is_worktree is in test_worktree_add_rm
|
||||
|
||||
def test_list_branches(self):
|
||||
'''
|
||||
|
@ -893,10 +893,11 @@ class GitModuleTest(integration.ModuleCase):
|
|||
|
||||
@skipIf(not _worktrees_supported(),
|
||||
'Git 2.5 or newer required for worktree support')
|
||||
def test_worktrees(self):
|
||||
def test_worktree_add_rm(self):
|
||||
'''
|
||||
This tests git.worktree_add, git.is_worktree, git.list_worktrees,
|
||||
git.worktree_rm, and git.worktree_prune
|
||||
This tests git.worktree_add, git.is_worktree, git.worktree_rm, and
|
||||
git.worktree_prune. Tests for 'git worktree list' are covered in
|
||||
tests.unit.modules.git_test.
|
||||
'''
|
||||
# We don't need to enclose this comparison in a try/except, since the
|
||||
# decorator would skip this test if git is not installed and we'd never
|
||||
|
@ -926,49 +927,8 @@ class GitModuleTest(integration.ModuleCase):
|
|||
empty_dir = tempfile.mkdtemp(dir=integration.TMP)
|
||||
self.assertFalse(self.run_function('git.is_worktree', [empty_dir]))
|
||||
shutil.rmtree(empty_dir)
|
||||
# Both worktrees should show up here
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo]),
|
||||
{os.path.basename(worktree_path): worktree_path,
|
||||
os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# There should be no stale worktrees right now
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo], stale=True),
|
||||
{}
|
||||
)
|
||||
# Both worktrees should show in the all=True output
|
||||
self.assertEqual(
|
||||
self.run_function(
|
||||
'git.list_worktrees',
|
||||
[self.repo],
|
||||
**{'all': True}
|
||||
),
|
||||
{os.path.basename(worktree_path): worktree_path,
|
||||
os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# Remove the first worktree
|
||||
self.assertTrue(self.run_function('git.worktree_rm', [worktree_path]))
|
||||
# The first worktree should no longer show up here
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo]),
|
||||
{os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# The first worktree should be identified as stale now
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo], stale=True),
|
||||
{os.path.basename(worktree_path): worktree_path}
|
||||
)
|
||||
# Both worktrees should show in the all=True output
|
||||
self.assertEqual(
|
||||
self.run_function(
|
||||
'git.list_worktrees',
|
||||
[self.repo],
|
||||
**{'all': True}
|
||||
),
|
||||
{os.path.basename(worktree_path): worktree_path,
|
||||
os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# Prune the worktrees
|
||||
prune_message = (
|
||||
'Removing worktrees/{0}: gitdir file points to non-existent '
|
||||
|
@ -984,31 +944,11 @@ class GitModuleTest(integration.ModuleCase):
|
|||
),
|
||||
prune_message
|
||||
)
|
||||
# Test pruning for real, and make sure the output is the same
|
||||
self.assertEqual(
|
||||
self.run_function('git.worktree_prune', [self.repo]),
|
||||
prune_message
|
||||
)
|
||||
# The first worktree should still no longer show up here
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo]),
|
||||
{os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
# The first worktree should no loner be identified as stale, since it
|
||||
# was just pruned.
|
||||
self.assertEqual(
|
||||
self.run_function('git.list_worktrees', [self.repo], stale=True),
|
||||
{}
|
||||
)
|
||||
# Only the second worktree should still show in the all=True output,
|
||||
# since the first was pruned.
|
||||
self.assertEqual(
|
||||
self.run_function(
|
||||
'git.list_worktrees',
|
||||
[self.repo],
|
||||
**{'all': True}
|
||||
),
|
||||
{os.path.basename(worktree_path2): worktree_path2}
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
170
tests/unit/modules/git_test.py
Normal file
170
tests/unit/modules/git_test.py
Normal file
|
@ -0,0 +1,170 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:codeauthor: :email:`Erik Johnson <erik@saltstack.com>`
|
||||
'''
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
import copy
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import TestCase, skipIf
|
||||
from salttesting.mock import (
|
||||
MagicMock,
|
||||
patch,
|
||||
NO_MOCK,
|
||||
NO_MOCK_REASON
|
||||
)
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.modules import git as git_mod # Don't potentially shadow GitPython
|
||||
|
||||
# Globals
|
||||
git_mod.__salt__ = {}
|
||||
git_mod.__context__ = {}
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
WORKTREE_ROOT = '/tmp/salt-tests-tmpdir/main'
|
||||
WORKTREE_INFO = {
|
||||
WORKTREE_ROOT: {
|
||||
'HEAD': '119f025073875a938f2456f5ffd7d04e79e5a427',
|
||||
'branch': 'refs/heads/master',
|
||||
'stale': False,
|
||||
},
|
||||
'/tmp/salt-tests-tmpdir/worktree1': {
|
||||
'HEAD': 'd8d19cf75d7cc3bdc598dc2d472881d26b51a6bf',
|
||||
'branch': 'refs/heads/worktree1',
|
||||
'stale': False,
|
||||
},
|
||||
'/tmp/salt-tests-tmpdir/worktree2': {
|
||||
'HEAD': '56332ca504aa8b37bb62b54272d52b1d6d832629',
|
||||
'branch': 'refs/heads/worktree2',
|
||||
'stale': True,
|
||||
},
|
||||
'/tmp/salt-tests-tmpdir/worktree3': {
|
||||
'HEAD': 'e148ea2d521313579f661373fbb93a48a5a6d40d',
|
||||
'branch': 'detached',
|
||||
'tags': ['v1.1'],
|
||||
'stale': False,
|
||||
},
|
||||
'/tmp/salt-tests-tmpdir/worktree4': {
|
||||
'HEAD': '6bbac64d3ad5582b3147088a708952df185db020',
|
||||
'branch': 'detached',
|
||||
'stale': True,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _git_version():
|
||||
git_version = subprocess.Popen(
|
||||
['git', '--version'],
|
||||
shell=False,
|
||||
close_fds=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE).communicate()[0]
|
||||
if not git_version:
|
||||
log.error('Git not installed')
|
||||
return False
|
||||
log.debug('Detected git version ' + git_version)
|
||||
return LooseVersion(git_version.split()[-1])
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class GitTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.modules.git
|
||||
'''
|
||||
def test_list_worktrees(self):
|
||||
'''
|
||||
This tests git.list_worktrees
|
||||
'''
|
||||
def _build_worktree_output(path):
|
||||
'''
|
||||
Build 'git worktree list' output for a given path
|
||||
'''
|
||||
return 'worktree {0}\nHEAD {1}\n{2}\n'.format(
|
||||
path,
|
||||
WORKTREE_INFO[path]['HEAD'],
|
||||
'branch {0}'.format(WORKTREE_INFO[path]['branch'])
|
||||
if WORKTREE_INFO[path]['branch'] != 'detached'
|
||||
else 'detached'
|
||||
)
|
||||
|
||||
# Build dict for _cmd_run_side_effect below. Start with the output from
|
||||
# 'git worktree list'.
|
||||
_cmd_run_values = {
|
||||
'git worktree list --porcelain': '\n'.join(
|
||||
[_build_worktree_output(x) for x in WORKTREE_INFO]
|
||||
),
|
||||
'git --version': 'git version 2.7.0',
|
||||
}
|
||||
# Add 'git tag --points-at' output for detached HEAD worktrees with
|
||||
# tags pointing at HEAD.
|
||||
for path in WORKTREE_INFO:
|
||||
if WORKTREE_INFO[path]['branch'] != 'detached':
|
||||
continue
|
||||
key = 'git tag --points-at ' + WORKTREE_INFO[path]['HEAD']
|
||||
_cmd_run_values[key] = '\n'.join(
|
||||
WORKTREE_INFO[path].get('tags', [])
|
||||
)
|
||||
|
||||
def _cmd_run_side_effect(key, **kwargs):
|
||||
# Not using dict.get() here because we want to know if
|
||||
# _cmd_run_values doesn't account for all uses of cmd.run_all.
|
||||
return {'stdout': _cmd_run_values[' '.join(key)],
|
||||
'stderr': '',
|
||||
'retcode': 0,
|
||||
'pid': 12345}
|
||||
|
||||
def _isdir_side_effect(key):
|
||||
# os.path.isdir() would return True on a non-stale worktree
|
||||
return not WORKTREE_INFO[key].get('stale', False)
|
||||
|
||||
# Build return dict for comparison
|
||||
worktree_ret = copy.deepcopy(WORKTREE_INFO)
|
||||
for key in worktree_ret:
|
||||
ptr = worktree_ret.get(key)
|
||||
ptr['detached'] = ptr['branch'] == 'detached'
|
||||
ptr['branch'] = None \
|
||||
if ptr['detached'] \
|
||||
else ptr['branch'].replace('refs/heads/', '', 1)
|
||||
|
||||
cmd_run_mock = MagicMock(side_effect=_cmd_run_side_effect)
|
||||
isdir_mock = MagicMock(side_effect=_isdir_side_effect)
|
||||
with patch.dict(git_mod.__salt__, {'cmd.run_all': cmd_run_mock}):
|
||||
with patch.object(os.path, 'isdir', isdir_mock):
|
||||
# Test all=True. Include all return data.
|
||||
self.maxDiff = None
|
||||
self.assertEqual(
|
||||
git_mod.list_worktrees(
|
||||
WORKTREE_ROOT, all=True, stale=False
|
||||
),
|
||||
worktree_ret
|
||||
)
|
||||
# Test all=False and stale=False. Exclude stale worktrees from
|
||||
# return data.
|
||||
self.assertEqual(
|
||||
git_mod.list_worktrees(
|
||||
WORKTREE_ROOT, all=False, stale=False
|
||||
),
|
||||
dict([(x, worktree_ret[x]) for x in WORKTREE_INFO
|
||||
if not WORKTREE_INFO[x].get('stale', False)])
|
||||
)
|
||||
# Test stale=True. Exclude non-stale worktrees from return
|
||||
# data.
|
||||
self.assertEqual(
|
||||
git_mod.list_worktrees(
|
||||
WORKTREE_ROOT, all=False, stale=True
|
||||
),
|
||||
dict([(x, worktree_ret[x]) for x in WORKTREE_INFO
|
||||
if WORKTREE_INFO[x].get('stale', False)])
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(GitTestCase, needs_daemon=False)
|
Loading…
Add table
Reference in a new issue