51.1.2
by Adam Gandelman
Check in start of py redux. |
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 |
||
9 |
||
10 |
def load_config(): |
|
11 |
'''
|
|
12 |
Walk backwords from __file__ looking for config.yaml, load and return the
|
|
13 |
'options' section'
|
|
14 |
'''
|
|
15 |
config = None |
|
16 |
f = __file__ |
|
17 |
while config is None: |
|
18 |
d = os.path.dirname(f) |
|
19 |
if os.path.isfile(os.path.join(d, 'config.yaml')): |
|
20 |
config = os.path.join(d, 'config.yaml') |
|
21 |
break
|
|
22 |
f = d |
|
23 |
||
24 |
if not config: |
|
25 |
logging.error('Could not find config.yaml in any parent directory ' |
|
140.3.16
by Felipe Reyes
fix lint warning |
26 |
'of %s. ' % f) |
51.1.2
by Adam Gandelman
Check in start of py redux. |
27 |
raise Exception |
28 |
||
29 |
return yaml.safe_load(open(config).read())['options'] |
|
30 |
||
31 |
||
32 |
def get_default_config(): |
|
33 |
'''
|
|
34 |
Load default charm config from config.yaml return as a dict.
|
|
35 |
If no default is set in config.yaml, its value is None.
|
|
36 |
'''
|
|
37 |
default_config = {} |
|
38 |
config = load_config() |
|
39 |
for k, v in config.iteritems(): |
|
40 |
if 'default' in v: |
|
41 |
default_config[k] = v['default'] |
|
42 |
else: |
|
43 |
default_config[k] = None |
|
44 |
return default_config |
|
45 |
||
46 |
||
47 |
class CharmTestCase(unittest.TestCase): |
|
52.3.9
by James Page
Rebase on trunk |
48 |
|
51.1.2
by Adam Gandelman
Check in start of py redux. |
49 |
def setUp(self, obj, patches): |
50 |
super(CharmTestCase, self).setUp() |
|
51 |
self.patches = patches |
|
52 |
self.obj = obj |
|
53 |
self.test_config = TestConfig() |
|
54 |
self.test_relation = TestRelation() |
|
55 |
self.patch_all() |
|
56 |
||
57 |
def patch(self, method): |
|
58 |
_m = patch.object(self.obj, method) |
|
59 |
mock = _m.start() |
|
60 |
self.addCleanup(_m.stop) |
|
61 |
return mock |
|
62 |
||
63 |
def patch_all(self): |
|
64 |
for method in self.patches: |
|
65 |
setattr(self, method, self.patch(method)) |
|
66 |
||
67 |
||
68 |
class TestConfig(object): |
|
52.3.9
by James Page
Rebase on trunk |
69 |
|
51.1.2
by Adam Gandelman
Check in start of py redux. |
70 |
def __init__(self): |
71 |
self.config = get_default_config() |
|
72 |
||
73 |
def get(self, attr=None): |
|
74 |
if not attr: |
|
75 |
return self.get_all() |
|
76 |
try: |
|
77 |
return self.config[attr] |
|
78 |
except KeyError: |
|
79 |
return None |
|
80 |
||
81 |
def get_all(self): |
|
82 |
return self.config |
|
83 |
||
84 |
def set(self, attr, value): |
|
83.1.10
by james.page at ubuntu
Refine service guard function, disable by default |
85 |
if attr not in self.config: |
86 |
raise KeyError |
|
87 |
self.config[attr] = value |
|
51.1.2
by Adam Gandelman
Check in start of py redux. |
88 |
|
89 |
||
90 |
class TestRelation(object): |
|
52.3.9
by James Page
Rebase on trunk |
91 |
|
51.1.2
by Adam Gandelman
Check in start of py redux. |
92 |
def __init__(self, relation_data={}): |
93 |
self.relation_data = relation_data |
|
94 |
||
95 |
def set(self, relation_data): |
|
96 |
self.relation_data = relation_data |
|
97 |
||
98 |
def get(self, attr=None, unit=None, rid=None): |
|
99 |
if attr is None: |
|
100 |
return self.relation_data |
|
101 |
elif attr in self.relation_data: |
|
102 |
return self.relation_data[attr] |
|
103 |
return None |
|
104 |
||
105 |
||
106 |
@contextmanager
|
|
107 |
def patch_open(): |
|
108 |
'''Patch open() to allow mocking both open() itself and the file that is
|
|
109 |
yielded.
|
|
110 |
||
111 |
Yields the mock for "open" and "file", respectively.'''
|
|
112 |
mock_open = MagicMock(spec=open) |
|
113 |
mock_file = MagicMock(spec=file) |
|
114 |
||
115 |
@contextmanager
|
|
116 |
def stub_open(*args, **kwargs): |
|
117 |
mock_open(*args, **kwargs) |
|
118 |
yield mock_file |
|
119 |
||
120 |
with patch('__builtin__.open', stub_open): |
|
121 |
yield mock_open, mock_file |