Initial unit_tests added - NOT FUNCTIONAL at this stage

This adds in the unit_test framework but there is a name collision
between charm.openstack as a module, and charm.openstack here which the
package loader can't resolve.  Therefore, going to change the
charm.openstack package to charms.openstack to avoid the collision.
This commit is contained in:
Alex Kavanagh 2016-05-19 18:00:23 +00:00
parent c7fc7ba5e0
commit 1ea4507ced
13 changed files with 157 additions and 20 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ build
layers layers
interfaces interfaces
trusty trusty
.testrepository

8
.testr.conf Normal file
View File

@ -0,0 +1,8 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ ./unit_tests $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -2,7 +2,14 @@
LAYER_PATH := layers LAYER_PATH := layers
clean: clean:
rm -Rf build .tox rm -Rf build .tox .testrepository
generate: clean generate: clean
LAYER_PATH=$(LAYER_PATH) tox -e generate LAYER_PATH=$(LAYER_PATH) tox -e generate
lint:
@tox -e lint
test:
@echo Starting unit tests...
@tox -e py27

0
src/lib/__init__.py Normal file
View File

View File

View File

View File

@ -4,9 +4,13 @@
# needed on the class. # needed on the class.
from __future__ import absolute_import from __future__ import absolute_import
import charmhelpers.fetch
import charmhelpers.core.hookenv as hookenv
import charmhelpers.contrib.openstack.utils as ch_utils
import charm.openstack.charm import charm.openstack.charm
import charm.openstack.adapters import charm.openstack.adapters
import charmhelpers.fetch import charm.openstack.ip as os_ip
PACKAGES = ['barbican-common', 'barbican-api', 'barbican-worker', PACKAGES = ['barbican-common', 'barbican-api', 'barbican-worker',
'python-mysqldb'] 'python-mysqldb']
@ -30,16 +34,17 @@ def setup_amqp_req(amqp):
"""Use the amqp interface to request access to the amqp broker using our """Use the amqp interface to request access to the amqp broker using our
local configuration. local configuration.
""" """
amqp.request_access(username=config('rabbit-user'), amqp.request_access(username=hookenv.config('rabbit-user'),
vhost=config('rabbit-vhost')) vhost=hookenv.config('rabbit-vhost'))
def setup_database(database): def setup_database(database):
"""On receiving database credentials, configure the database on the """On receiving database credentials, configure the database on the
interface. interface.
""" """
database.configure(config('database'), config('database-user'), database.configure(hookenv.config('database'),
unit_private_ip()) hookenv.config('database-user'),
hookenv.unit_private_ip())
def setup_endpoint(keystone): def setup_endpoint(keystone):
@ -64,11 +69,11 @@ def render_configs(interfaces_list):
### ###
# Implementation of the Barbican Charm classes # Implementation of the Barbican Charm classes
class BarbicanConfigurationAdapater( class BarbicanConfigurationAdapter(
charm.openstack.adapters.ConfigurationAdapter): charm.openstack.adapters.ConfigurationAdapter):
def __init__(self): def __init__(self):
super(BarbicanConfigurationAdapater, self).__init__() super(BarbicanConfigurationAdapter, self).__init__()
if self.keystone_api_version not in ['2', '3', 'none']: if self.keystone_api_version not in ['2', '3', 'none']:
raise ValueError( raise ValueError(
"Unsupported keystone-api-version ({}). It should be 2 or 3" "Unsupported keystone-api-version ({}). It should be 2 or 3"
@ -107,17 +112,15 @@ class BarbicanCharm(charm.openstack.charm.OpenStackCharm):
functionality to manage a barbican unit. functionality to manage a barbican unit.
""" """
releases = { # don't set releases here (as we need to self refer - see below)
'liberty': BarbicanCharm
}
first_release = 'liberty' first_release = 'liberty'
name = 'barbican' name = 'barbican'
packages = PACKAGES packages = PACKAGES
api_ports = { api_ports = {
'barbican-api': { 'barbican-api': {
PUBLIC: 9311, os_ip.PUBLIC: 9311,
ADMIN: 9312, os_ip.ADMIN: 9312,
INTERNAL: 9313, os_ip.INTERNAL: 9313,
} }
} }
service_type = 'secretstore' service_type = 'secretstore'
@ -136,14 +139,13 @@ class BarbicanCharm(charm.openstack.charm.OpenStackCharm):
"""Custom initialiser for class """Custom initialiser for class
If no release is passed, then the charm determines the release from the If no release is passed, then the charm determines the release from the
os_release() function. ch_utils.os_release() function.
""" """
if release is None: if release is None:
#release = os_release('barbican-common') # release = ch_utils.os_release('barbican-common')
release = os_release('python-keystonemiddleware') release = ch_utils.os_release('python-keystonemiddleware')
super(BarbicanCharm, self).__init__(release=release, **kwargs) super(BarbicanCharm, self).__init__(release=release, **kwargs)
def install(self): def install(self):
"""Customise the installation, configure the source and then call the """Customise the installation, configure the source and then call the
parent install() method to install the packages parent install() method to install the packages
@ -152,3 +154,11 @@ class BarbicanCharm(charm.openstack.charm.OpenStackCharm):
self.configure_source() self.configure_source()
# and do the actual install # and do the actual install
super(BarbicanCharm, self).install() super(BarbicanCharm, self).install()
# Set Barbican releases here because we need it to refer to itself. For derived
# classes of BarbicanCharm for different series we would still set the releases
# here.
BarbicanCharm.releases = {
'liberty': BarbicanCharm,
}

0
src/reactive/__init__.py Normal file
View File

View File

@ -3,14 +3,18 @@ from __future__ import absolute_import
from __future__ import print_function from __future__ import print_function
import sys import sys
sys.path.append('lib') sys.path.append('src/lib')
import charms.reactive as reactive import charms.reactive as reactive
print(sys.path) print(sys.path)
import os
print(os.getcwd())
print(os.path.dirname(os.path.realpath(__file__)))
# This charm's library contains all of the handler code # This charm's library contains all of the handler code
import charm.openstack.barbican as barbican import charm.openstack.barbican as barbican
# use a synthetic state to ensure that it get it to be installed independent of # use a synthetic state to ensure that it get it to be installed independent of
# the install hook. # the install hook.
@reactive.when_not('charm.installed') @reactive.when_not('charm.installed')

7
test-requirements.txt Normal file
View File

@ -0,0 +1,7 @@
flake8>=2.2.4,<=2.4.1
os-testr>=0.4.1
charm-tools>=2.0.0
charms.reactive
mock>=1.2
coverage>=3.6
https://github.com/ajkavanagh/charm.openstack/zipball/master

15
tox.ini
View File

@ -18,7 +18,20 @@ deps =
[testenv:generate] [testenv:generate]
basepython = python2.7 basepython = python2.7
commands = commands =
charm build --log-level DEBUG -o {toxinidir}/build charm charm build --log-level DEBUG -o {toxinidir}/build src
[testenv:py27]
basepython = python2.7
deps = -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs}
[testenv:lint]
basepython = python2.7
deps = -r{toxinidir}/test-requirements.txt
commands = flake8 {posargs} src unit_tests
[testenv:venv] [testenv:venv]
commands = {posargs} commands = {posargs}
[flake8]
ignore = E402,E226

24
unit_tests/__init__.py Normal file
View File

@ -0,0 +1,24 @@
import sys
import mock
charmhelpers = mock.MagicMock()
sys.modules['charmhelpers'] = charmhelpers
sys.modules['charmhelpers.core'] = charmhelpers.core
sys.modules['charmhelpers.core.hookenv'] = charmhelpers.core.hookenv
sys.modules['charmhelpers.core.host'] = charmhelpers.core.host
sys.modules['charmhelpers.core.templating'] = charmhelpers.core.templating
sys.modules['charmhelpers.contrib'] = charmhelpers.contrib
sys.modules['charmhelpers.contrib.openstack'] = charmhelpers.contrib.openstack
sys.modules['charmhelpers.contrib.openstack.utils'] = (
charmhelpers.contrib.openstack.utils)
sys.modules['charmhelpers.contrib.openstack.templating'] = (
charmhelpers.contrib.openstack.templating)
sys.modules['charmhelpers.contrib.network'] = charmhelpers.contrib.network
sys.modules['charmhelpers.contrib.network.ip'] = (
charmhelpers.contrib.network.ip)
sys.modules['charmhelpers.fetch'] = charmhelpers.fetch
sys.modules['charmhelpers.cli'] = charmhelpers.cli
sys.modules['charmhelpers.contrib.hahelpers'] = charmhelpers.contrib.hahelpers
sys.modules['charmhelpers.contrib.hahelpers.cluster'] = (
charmhelpers.contrib.hahelpers.cluster)

View File

@ -0,0 +1,63 @@
from __future__ import absolute_import
from __future__ import print_function
import sys
import unittest
import mock
sys.path.append('src')
sys.path.append('src/lib')
import reactive.barbican_handlers as handlers
_hook_args = {}
def mock_hook(*args, **kwargs):
def inner(f):
# remember what we were passed. Note that we can't actually determine
# the class we're attached to, as the decorator only gets the function.
_hook_args[f.__name__] = dict(args=args, kwargs=kwargs)
return f
return inner
class TestBarbicanHandlers(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._patched_hook = mock.patch('charms.reactive.hook', mock_hook)
cls._patched_hook_started = cls._patched_hook.start()
# force requires to rerun the mock_hook decorator:
reload(requires)
@classmethod
def tearDownClass(cls):
cls._patched_hook.stop()
cls._patched_hook_started = None
cls._patched_hook = None
# and fix any breakage we did to the module
reload(requires)
def patch(self, attr, return_value=None):
mocked = mock.patch.object(self.kr, attr)
self._patches[attr] = mocked
started = mocked.start()
started.return_value = return_value
self._patches_start[attr] = started
setattr(self, attr, started)
def test_registered_hooks(self):
# test that the hooks actually registered the relation expressions that
# are meaningful for this interface: this is to handle regressions.
# The keys are the function names that the hook attaches to.
hook_patterns = {
'joined': ('{requires:keystone}-relation-joined', ),
'changed': ('{requires:keystone}-relation-changed', ),
'departed': ('{requires:keystone}-relation-{broken,departed}', ),
}
print(_hook_args)
# for k, v in _hook_args.items():
# self.assertEqual(hook_patterns[k], v['args'])