23
by Liam Young
Added hooks unit tests |
1 |
import logging |
2 |
import unittest |
|
3 |
import os |
|
4 |
import yaml |
|
5 |
||
6 |
from contextlib import contextmanager |
|
7 |
from mock import patch, MagicMock |
|
8 |
||
111.3.24
by David Ames
Fix unit tests |
9 |
patch('charmhelpers.contrib.openstack.utils.set_os_workload_status').start() |
10 |
patch('charmhelpers.core.hookenv.status_set').start() |
|
11 |
||
23
by Liam Young
Added hooks unit tests |
12 |
|
13 |
def load_config(): |
|
14 |
'''
|
|
15 |
Walk backwords from __file__ looking for config.yaml, load and return the
|
|
16 |
'options' section'
|
|
17 |
'''
|
|
18 |
config = None |
|
19 |
f = __file__ |
|
20 |
while config is None: |
|
21 |
d = os.path.dirname(f) |
|
22 |
if os.path.isfile(os.path.join(d, 'config.yaml')): |
|
23 |
config = os.path.join(d, 'config.yaml') |
|
24 |
break
|
|
25 |
f = d |
|
26 |
||
27 |
if not config: |
|
28 |
logging.error('Could not find config.yaml in any parent directory ' |
|
29 |
'of %s. ' % file) |
|
30 |
raise Exception |
|
31 |
||
32 |
return yaml.safe_load(open(config).read())['options'] |
|
33 |
||
34 |
||
35 |
def get_default_config(): |
|
36 |
'''
|
|
37 |
Load default charm config from config.yaml return as a dict.
|
|
38 |
If no default is set in config.yaml, its value is None.
|
|
39 |
'''
|
|
40 |
default_config = {} |
|
41 |
config = load_config() |
|
42 |
for k, v in config.iteritems(): |
|
43 |
if 'default' in v: |
|
44 |
default_config[k] = v['default'] |
|
45 |
else: |
|
46 |
default_config[k] = None |
|
47 |
return default_config |
|
48 |
||
49 |
||
50 |
class CharmTestCase(unittest.TestCase): |
|
51 |
||
52 |
def setUp(self, obj, patches): |
|
53 |
super(CharmTestCase, self).setUp() |
|
54 |
self.patches = patches |
|
55 |
self.obj = obj |
|
56 |
self.test_config = TestConfig() |
|
57 |
self.test_relation = TestRelation() |
|
58 |
self.patch_all() |
|
59 |
||
60 |
def patch(self, method): |
|
61 |
_m = patch.object(self.obj, method) |
|
62 |
mock = _m.start() |
|
63 |
self.addCleanup(_m.stop) |
|
64 |
return mock |
|
65 |
||
66 |
def patch_all(self): |
|
67 |
for method in self.patches: |
|
68 |
setattr(self, method, self.patch(method)) |
|
69 |
||
70 |
||
71 |
class TestConfig(object): |
|
72 |
||
73 |
def __init__(self): |
|
74 |
self.config = get_default_config() |
|
75 |
||
76 |
def get(self, attr=None): |
|
77 |
if not attr: |
|
78 |
return self.get_all() |
|
79 |
try: |
|
80 |
return self.config[attr] |
|
81 |
except KeyError: |
|
82 |
return None |
|
83 |
||
84 |
def get_all(self): |
|
85 |
return self.config |
|
86 |
||
87 |
def set(self, attr, value): |
|
88 |
if attr not in self.config: |
|
89 |
raise KeyError |
|
90 |
self.config[attr] = value |
|
91 |
||
92 |
||
93 |
class TestRelation(object): |
|
94 |
||
95 |
def __init__(self, relation_data={}): |
|
96 |
self.relation_data = relation_data |
|
97 |
||
98 |
def set(self, relation_data): |
|
99 |
self.relation_data = relation_data |
|
100 |
||
26
by Liam Young
more tests, more coverage |
101 |
def get(self, attribute=None, unit=None, rid=None): |
102 |
if attribute is None: |
|
23
by Liam Young
Added hooks unit tests |
103 |
return self.relation_data |
26
by Liam Young
more tests, more coverage |
104 |
elif attribute in self.relation_data: |
105 |
return self.relation_data[attribute] |
|
23
by Liam Young
Added hooks unit tests |
106 |
return None |
107 |
||
108 |
||
109 |
@contextmanager
|
|
110 |
def patch_open(): |
|
111 |
'''Patch open() to allow mocking both open() itself and the file that is
|
|
112 |
yielded.
|
|
113 |
||
114 |
Yields the mock for "open" and "file", respectively.'''
|
|
115 |
mock_open = MagicMock(spec=open) |
|
116 |
mock_file = MagicMock(spec=file) |
|
117 |
||
118 |
@contextmanager
|
|
119 |
def stub_open(*args, **kwargs): |
|
120 |
mock_open(*args, **kwargs) |
|
121 |
yield mock_file |
|
122 |
||
123 |
with patch('__builtin__.open', stub_open): |
|
124 |
yield mock_open, mock_file |