239 lines
8.3 KiB
Python
239 lines
8.3 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""Tests of some of the functionality in repository_git.py that actually
|
|
interacts with git repositories.
|
|
|
|
We're calling these "system" tests because we expect them to be a lot
|
|
slower than most of the unit tests.
|
|
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import unicode_literals
|
|
from __future__ import print_function
|
|
|
|
import os
|
|
import shutil
|
|
import tempfile
|
|
import unittest
|
|
|
|
from manic.repository_git import GitRepository
|
|
from manic.externals_description import ExternalsDescription
|
|
from manic.externals_description import ExternalsDescriptionDict
|
|
from manic.utils import execute_subprocess
|
|
|
|
# NOTE(wjs, 2018-04-09) I find a mix of camel case and underscores to be
|
|
# more readable for unit test names, so I'm disabling pylint's naming
|
|
# convention check
|
|
# pylint: disable=C0103
|
|
|
|
# Allow access to protected members
|
|
# pylint: disable=W0212
|
|
|
|
|
|
class GitTestCase(unittest.TestCase):
|
|
"""Adds some git-specific unit test functionality on top of TestCase"""
|
|
|
|
def assertIsHash(self, maybe_hash):
|
|
"""Assert that the string given by maybe_hash really does look
|
|
like a git hash.
|
|
"""
|
|
|
|
# Ensure it is non-empty
|
|
self.assertTrue(maybe_hash, msg="maybe_hash is empty")
|
|
|
|
# Ensure it has a single string
|
|
self.assertEqual(1, len(maybe_hash.split()),
|
|
msg="maybe_hash has multiple strings: {}".format(maybe_hash))
|
|
|
|
# Ensure that the only characters in the string are ones allowed
|
|
# in hashes
|
|
allowed_chars_set = set('0123456789abcdef')
|
|
self.assertTrue(set(maybe_hash) <= allowed_chars_set,
|
|
msg="maybe_hash has non-hash characters: {}".format(maybe_hash))
|
|
|
|
|
|
class TestGitTestCase(GitTestCase):
|
|
"""Tests GitTestCase"""
|
|
|
|
def test_assertIsHash_true(self):
|
|
"""Ensure that assertIsHash passes for something that looks
|
|
like a hash"""
|
|
self.assertIsHash('abc123')
|
|
|
|
def test_assertIsHash_empty(self):
|
|
"""Ensure that assertIsHash raises an AssertionError for an
|
|
empty string"""
|
|
with self.assertRaises(AssertionError):
|
|
self.assertIsHash('')
|
|
|
|
def test_assertIsHash_multipleStrings(self):
|
|
"""Ensure that assertIsHash raises an AssertionError when
|
|
given multiple strings"""
|
|
with self.assertRaises(AssertionError):
|
|
self.assertIsHash('abc123 def456')
|
|
|
|
def test_assertIsHash_badChar(self):
|
|
"""Ensure that assertIsHash raises an AssertionError when given a
|
|
string that has a character that doesn't belong in a hash
|
|
"""
|
|
with self.assertRaises(AssertionError):
|
|
self.assertIsHash('abc123g')
|
|
|
|
|
|
class TestGitRepositoryGitCommands(GitTestCase):
|
|
"""Test some git commands in RepositoryGit
|
|
|
|
It's silly that we need to create a repository in order to test
|
|
these git commands. Much or all of the git functionality that is
|
|
currently in repository_git.py should eventually be moved to a
|
|
separate module that is solely responsible for wrapping git
|
|
commands; that would allow us to test it independently of this
|
|
repository class.
|
|
"""
|
|
|
|
# ========================================================================
|
|
# Test helper functions
|
|
# ========================================================================
|
|
|
|
def setUp(self):
|
|
# directory we want to return to after the test system and
|
|
# checkout_externals are done cd'ing all over the place.
|
|
self._return_dir = os.getcwd()
|
|
|
|
self._tmpdir = tempfile.mkdtemp()
|
|
os.chdir(self._tmpdir)
|
|
|
|
self._name = 'component'
|
|
rdata = {ExternalsDescription.PROTOCOL: 'git',
|
|
ExternalsDescription.REPO_URL:
|
|
'/path/to/local/repo',
|
|
ExternalsDescription.TAG:
|
|
'tag1',
|
|
}
|
|
|
|
data = {self._name:
|
|
{
|
|
ExternalsDescription.REQUIRED: False,
|
|
ExternalsDescription.PATH: 'junk',
|
|
ExternalsDescription.EXTERNALS: '',
|
|
ExternalsDescription.REPO: rdata,
|
|
},
|
|
}
|
|
model = ExternalsDescriptionDict(data)
|
|
repo = model[self._name][ExternalsDescription.REPO]
|
|
self._repo = GitRepository('test', repo)
|
|
|
|
def tearDown(self):
|
|
# return to our common starting point
|
|
os.chdir(self._return_dir)
|
|
|
|
shutil.rmtree(self._tmpdir, ignore_errors=True)
|
|
|
|
@staticmethod
|
|
def make_git_repo():
|
|
"""Turn the current directory into an empty git repository"""
|
|
execute_subprocess(['git', 'init'])
|
|
|
|
@staticmethod
|
|
def add_git_commit():
|
|
"""Add a git commit in the current directory"""
|
|
with open('README', 'a') as myfile:
|
|
myfile.write('more info')
|
|
execute_subprocess(['git', 'add', 'README'])
|
|
execute_subprocess(['git', 'commit', '-m', 'my commit message'])
|
|
|
|
@staticmethod
|
|
def checkout_git_branch(branchname):
|
|
"""Checkout a new branch in the current directory"""
|
|
execute_subprocess(['git', 'checkout', '-b', branchname])
|
|
|
|
@staticmethod
|
|
def make_git_tag(tagname):
|
|
"""Make a lightweight tag at the current commit"""
|
|
execute_subprocess(['git', 'tag', '-m', 'making a tag', tagname])
|
|
|
|
@staticmethod
|
|
def checkout_ref(refname):
|
|
"""Checkout the given refname in the current directory"""
|
|
execute_subprocess(['git', 'checkout', refname])
|
|
|
|
# ========================================================================
|
|
# Begin actual tests
|
|
# ========================================================================
|
|
|
|
def test_currentHash_returnsHash(self):
|
|
"""Ensure that the _git_current_hash function returns a hash"""
|
|
self.make_git_repo()
|
|
self.add_git_commit()
|
|
hash_found, myhash = self._repo._git_current_hash()
|
|
self.assertTrue(hash_found)
|
|
self.assertIsHash(myhash)
|
|
|
|
def test_currentHash_outsideGitRepo(self):
|
|
"""Ensure that the _git_current_hash function returns False when
|
|
outside a git repository"""
|
|
hash_found, myhash = self._repo._git_current_hash()
|
|
self.assertFalse(hash_found)
|
|
self.assertEqual('', myhash)
|
|
|
|
def test_currentBranch_onBranch(self):
|
|
"""Ensure that the _git_current_branch function returns the name
|
|
of the branch"""
|
|
self.make_git_repo()
|
|
self.add_git_commit()
|
|
self.checkout_git_branch('foo')
|
|
branch_found, mybranch = self._repo._git_current_branch()
|
|
self.assertTrue(branch_found)
|
|
self.assertEqual('foo', mybranch)
|
|
|
|
def test_currentBranch_notOnBranch(self):
|
|
"""Ensure that the _git_current_branch function returns False
|
|
when not on a branch"""
|
|
self.make_git_repo()
|
|
self.add_git_commit()
|
|
self.make_git_tag('mytag')
|
|
self.checkout_ref('mytag')
|
|
branch_found, mybranch = self._repo._git_current_branch()
|
|
self.assertFalse(branch_found)
|
|
self.assertEqual('', mybranch)
|
|
|
|
def test_currentBranch_outsideGitRepo(self):
|
|
"""Ensure that the _git_current_branch function returns False
|
|
when outside a git repository"""
|
|
branch_found, mybranch = self._repo._git_current_branch()
|
|
self.assertFalse(branch_found)
|
|
self.assertEqual('', mybranch)
|
|
|
|
def test_currentTag_onTag(self):
|
|
"""Ensure that the _git_current_tag function returns the name of
|
|
the tag"""
|
|
self.make_git_repo()
|
|
self.add_git_commit()
|
|
self.make_git_tag('some_tag')
|
|
tag_found, mytag = self._repo._git_current_tag()
|
|
self.assertTrue(tag_found)
|
|
self.assertEqual('some_tag', mytag)
|
|
|
|
def test_currentTag_notOnTag(self):
|
|
"""Ensure tha the _git_current_tag function returns False when
|
|
not on a tag"""
|
|
self.make_git_repo()
|
|
self.add_git_commit()
|
|
self.make_git_tag('some_tag')
|
|
self.add_git_commit()
|
|
tag_found, mytag = self._repo._git_current_tag()
|
|
self.assertFalse(tag_found)
|
|
self.assertEqual('', mytag)
|
|
|
|
def test_currentTag_outsideGitRepo(self):
|
|
"""Ensure that the _git_current_tag function returns False when
|
|
outside a git repository"""
|
|
tag_found, mytag = self._repo._git_current_tag()
|
|
self.assertFalse(tag_found)
|
|
self.assertEqual('', mytag)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|