~hopem/charms/trusty/nova-cloud-controller/lp1499435

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