Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / argument / test.py @ b7ff6e0c

History | View | Annotate | Download (11.3 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, MagicMock
35
from unittest import TestCase
36
from StringIO import StringIO
37
from datetime import datetime
38
#from itertools import product
39

    
40
from kamaki.cli import argument, errors
41
from kamaki.cli.config import Config
42

    
43

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

    
46

    
47
class Argument(TestCase):
48

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

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

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

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

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

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

    
92

    
93
class ConfigArgument(TestCase):
94

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

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

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

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

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

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

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

    
164

    
165
class RuntimeConfigArgument(TestCase):
166

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

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

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

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

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

    
195

    
196
class FlagArgument(TestCase):
197

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

    
205

    
206
class ValueArgument(TestCase):
207

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

    
215

    
216
class IntArgument(TestCase):
217

    
218
    def test_value(self):
219
        ia = argument.IntArgument(parsed_name='--ia')
220
        self.assertEqual(ia.value, None)
221
        for v in (1, 0, -1, 923455555555555555555555555555555):
222
            ia.value = v
223
            self.assertEqual(ia.value, v)
224
        for v in ('1', '-1', 2.8):
225
            ia.value = v
226
            self.assertEqual(ia.value, int(v))
227
        for v, err in (
228
                ('invalid', errors.CLIError),
229
                (None, TypeError), (False, TypeError), ([1, 2, 3], TypeError)):
230
            try:
231
                ia.value = v
232
            except Exception as e:
233
                self.assertTrue(isinstance(e, err))
234

    
235

    
236
class DateArgument(TestCase):
237

    
238
    def test_timestamp(self):
239
        da = argument.DateArgument(parsed_name='--date')
240
        self.assertEqual(da.timestamp, None)
241
        date, format, exp = '24-10-1917', '%d-%m-%Y', -1646964000.0
242
        da._value = argument.dtm.strptime(date, format)
243
        self.assertEqual(da.timestamp, exp)
244

    
245
    def test_formated(self):
246
        da = argument.DateArgument(parsed_name='--date')
247
        self.assertEqual(da.formated, None)
248
        date, format, exp = (
249
            '24-10-1917', '%d-%m-%Y', 'Wed Oct 24 00:00:00 1917')
250
        da._value = argument.dtm.strptime(date, format)
251
        self.assertEqual(da.formated, exp)
252

    
253
    @patch('kamaki.cli.argument.DateArgument.timestamp')
254
    @patch('kamaki.cli.argument.DateArgument.format_date')
255
    def test_value(self, format_date, timestamp):
256
        da = argument.DateArgument(parsed_name='--date')
257
        self.assertTrue(isinstance(da.value, MagicMock))
258
        da.value = 'Something'
259
        format_date.assert_called_once(call('Something'))
260

    
261
    def test_format_date(self):
262
        da = argument.DateArgument(parsed_name='--date')
263
        for datestr, exp in (
264
                ('Wed Oct 24 01:02:03 1917', datetime(1917, 10, 24, 1, 2, 3)),
265
                ('24-10-1917', datetime(1917, 10, 24)),
266
                ('01:02:03 24-10-1917', datetime(1917, 10, 24, 1, 2, 3))):
267
            self.assertEqual(da.format_date(datestr), exp)
268
        for datestr, err in (
269
                ('32-40-20134', errors.CLIError),
270
                ('Wednesday, 24 Oct 2017', errors.CLIError),
271
                (None, TypeError), (0.8, TypeError)):
272
            self.assertRaises(err, da.format_date, datestr)
273

    
274

    
275
if __name__ == '__main__':
276
    from sys import argv
277
    from kamaki.cli.test import runTestCase
278
    runTestCase(Argument, 'Argument', argv[1:])
279
    runTestCase(ConfigArgument, 'ConfigArgument', argv[1:])
280
    runTestCase(RuntimeConfigArgument, 'RuntimeConfigArgument', argv[1:])
281
    runTestCase(FlagArgument, 'FlagArgument', argv[1:])
282
    runTestCase(FlagArgument, 'ValueArgument', argv[1:])
283
    runTestCase(IntArgument, 'IntArgument', argv[1:])
284
    runTestCase(DateArgument, 'DateArgument', argv[1:])