Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / argument / test.py @ 3a5b1ceb

History | View | Annotate | Download (8.9 kB)

1
# Copyright 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from mock import patch, call
35
from unittest import TestCase
36
from StringIO import StringIO
37
from itertools import product
38

    
39
from kamaki.cli import argument
40
from kamaki.cli.config import Config
41

    
42

    
43
cnf_path = 'kamaki.cli.config.Config'
44

    
45

    
46
class Argument(TestCase):
47

    
48
    def test___init__(self):
49
        self.assertRaises(ValueError, argument.Argument, 'non-integer')
50
        self.assertRaises(AssertionError, argument.Argument, 1)
51
        self.assertRaises(AssertionError, argument.Argument, 0, 'noname')
52
        self.assertRaises(AssertionError, argument.Argument, 0, '--no name')
53
        self.assertRaises(AssertionError, argument.Argument, 0, ['-n', 'n m'])
54
        for arity, help, parsed_name, default in (
55
                (0, 'help 0', '--zero', None),
56
                (1, 'help 1', ['--one', '-o'], 'lala'),
57
                (-1, 'help -1', ['--help', '--or', '--more'], 0),
58
                (0, 'help 0 again', ['--again', ], True)):
59
            a = argument.Argument(arity, help, parsed_name, default)
60
            if arity:
61
                self.assertEqual(arity, a.arity)
62
            self.assertEqual(help, a.help)
63

    
64
            exp_name = parsed_name if (
65
                isinstance(parsed_name, list)) else [parsed_name, ]
66
            self.assertEqual(exp_name, a.parsed_name)
67

    
68
            exp_default = default or (None if arity else False)
69
            self.assertEqual(exp_default, a.default)
70

    
71
    def test_value(self):
72
        a = argument.Argument(1, parsed_name='--value')
73
        for value in (None, '', 0, 0.1, -12, [1, 'a', 2.8], (3, 'lala'), 'pi'):
74
            a.value = value
75
            self.assertEqual(value, a.value)
76

    
77
    def test_update_parser(self):
78
        for i, arity in enumerate((-1, 0, 1)):
79
            arp = argument.ArgumentParser()
80
            pname, aname = '--pname%s' % i, 'a_name_%s' % i
81
            a = argument.Argument(arity, 'args', pname, 42)
82
            a.update_parser(arp, aname)
83

    
84
            f = StringIO()
85
            arp.print_usage(file=f), f.seek(0)
86
            usage, exp = f.readline(), '[%s%s]\n' % (
87
                pname, (' %s' % aname.upper()) if arity else '')
88
            self.assertEqual(usage[-len(exp):], exp)
89
            del arp
90

    
91

    
92
class ConfigArgument(TestCase):
93

    
94
    def setUp(self):
95
        argument._config_arg = argument.ConfigArgument('Recovered Path')
96

    
97
    def test_value(self):
98
        c = argument._config_arg
99
        self.assertEqual(c.value, None)
100
        exp = '/some/random/path'
101
        c.value = exp
102
        self.assertTrue(isinstance(c.value, Config))
103
        self.assertEqual(c.file_path, exp)
104
        self.assertEqual(c.value.path, exp)
105

    
106
    def test_get(self):
107
        c = argument._config_arg
108
        c.value = None
109
        with patch('%s.get' % cnf_path, return_value='config') as get:
110
            self.assertEqual(c.value.get('global', 'config_cli'), 'config')
111
            self.assertEqual(get.mock_calls[-1], call('global', 'config_cli'))
112

    
113
    @patch('%s.keys' % cnf_path, return_value=(
114
        'image_cli', 'config_cli', 'history_cli', 'file'))
115
    def test_groups(self, keys):
116
        c = argument._config_arg
117
        c.value = None
118
        cset = set(c.groups)
119
        self.assertTrue(cset.issuperset(['image', 'config', 'history']))
120
        self.assertEqual(keys.mock_calls[-1], call('global'))
121
        self.assertFalse('file' in cset)
122
        self.assertEqual(keys.mock_calls[-1], call('global'))
123

    
124
    @patch('%s.items' % cnf_path, return_value=(
125
        ('image_cli', 'image'), ('file', 'pithos'),
126
        ('config_cli', 'config'), ('history_cli', 'history')))
127
    def test_cli_specs(self, items):
128
        c = argument._config_arg
129
        c.value = None
130
        cset = set(c.cli_specs)
131
        self.assertTrue(cset.issuperset([
132
            ('image', 'image'), ('config', 'config'), ('history', 'history')]))
133
        self.assertEqual(items.mock_calls[-1], call('global'))
134
        self.assertFalse(cset.issuperset([('file', 'pithos'), ]))
135
        self.assertEqual(items.mock_calls[-1], call('global'))
136

    
137
    def test_get_global(self):
138
        c = argument._config_arg
139
        c.value = None
140
        for k, v in (
141
                ('config_cli', 'config'),
142
                ('image_cli', 'image'),
143
                ('history_cli', 'history')):
144
            with patch('%s.get_global' % cnf_path, return_value=v) as gg:
145
                self.assertEqual(c.get_global(k), v)
146
                self.assertEqual(gg.mock_calls[-1], call(k))
147

    
148
    def test_get_cloud(self):
149
        c = argument._config_arg
150
        c.value = None
151
        with patch(
152
                '%s.get_cloud' % cnf_path,
153
                return_value='http://cloud') as get_cloud:
154
            self.assertTrue(len(c.get_cloud('mycloud', 'url')) > 0)
155
            self.assertEqual(get_cloud.mock_calls[-1],  call('mycloud', 'url'))
156
        with patch(
157
                '%s.get_cloud' % cnf_path,
158
                side_effect=KeyError('no token')) as get_cloud:
159
            self.assertRaises(KeyError, c.get_cloud, 'mycloud', 'token')
160
        invalidcloud = 'PLEASE_DO_NOT_EVER_NAME_YOUR_CLOUD_LIKE_THIS111'
161
        self.assertRaises(KeyError, c.get_cloud, invalidcloud, 'url')
162

    
163

    
164
class RuntimeConfigArgument(TestCase):
165

    
166
    def setUp(self):
167
        argument._config_arg = argument.ConfigArgument('Recovered Path')
168

    
169
    @patch('kamaki.cli.argument.Argument.__init__')
170
    def test___init__(self, arg):
171
        config, help, pname, default = 'config', 'help', 'pname', 'default'
172
        rca = argument.RuntimeConfigArgument(config, help, pname, default)
173
        self.assertTrue(isinstance(rca, argument.RuntimeConfigArgument))
174
        self.assertEqual(rca._config_arg, config)
175
        self.assertEqual(arg.mock_calls[-1], call(1, help, pname, default))
176

    
177
    @patch('%s.override' % cnf_path)
178
    def test_value(self, override):
179
        config, help, pname, default = argument._config_arg, 'help', '-n', 'df'
180
        config.value = None
181
        rca = argument.RuntimeConfigArgument(config, help, pname, default)
182
        self.assertEqual(rca.value, default)
183

    
184
        for options in ('grp', 'grp.opt', 'k v', '=nokey', 2.8, None, 42, ''):
185
            self.assertRaises(TypeError, rca.value, options)
186

    
187
        for options in ('key=val', 'grp.key=val', 'dotted.opt.key=val'):
188
            rca.value = options
189
            option, sep, val = options.partition('=')
190
            grp, sep, key = option.partition('.')
191
            grp, key = (grp, key) if key else ('global', grp)
192
            self.assertEqual(override.mock_calls[-1], call(grp, key, val))
193

    
194

    
195
class FlagArgument(TestCase):
196

    
197
    @patch('kamaki.cli.argument.Argument.__init__')
198
    def test___init__(self, arg):
199
        help, pname, default = 'help', 'pname', 'default'
200
        fa = argument.FlagArgument(help, pname, default)
201
        self.assertTrue(isinstance(fa, argument.FlagArgument))
202
        arg.assert_called_once(0, help, pname, default)
203

    
204

    
205
class ValueArgument(TestCase):
206

    
207
    @patch('kamaki.cli.argument.Argument.__init__')
208
    def test___init__(self, arg):
209
        help, pname, default = 'help', 'pname', 'default'
210
        fa = argument.ValueArgument(help, pname, default)
211
        self.assertTrue(isinstance(fa, argument.ValueArgument))
212
        arg.assert_called_once(1, help, pname, default)
213

    
214

    
215
if __name__ == '__main__':
216
    from sys import argv
217
    from kamaki.cli.test import runTestCase
218
    runTestCase(Argument, 'Argument', argv[1:])
219
    runTestCase(ConfigArgument, 'ConfigArgument', argv[1:])
220
    runTestCase(RuntimeConfigArgument, 'RuntimeConfigArgument', argv[1:])
221
    runTestCase(FlagArgument, 'FlagArgument', argv[1:])
222
    runTestCase(FlagArgument, 'ValueArgument', argv[1:])