Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / command_tree / test.py @ 38db356b

History | View | Annotate | Download (16.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
35
from unittest import TestCase
36
from itertools import product
37

    
38
from kamaki.cli import command_tree
39

    
40

    
41
class Command(TestCase):
42

    
43
    def test___init__(self):
44
        for args in product(
45
                (None, '', 'cmd'),
46
                (None, '', 'Some help'),
47
                (None, '', {}, dict(cmd0a=None, cmd0b=None)),
48
                (None, command_tree.Command('cmd_cmd0')),
49
                (None, 'long description')):
50
            path, help, subcommands, cmd_class, long_help = args
51
            try:
52
                cmd = command_tree.Command(*args)
53
            except Exception as e:
54
                if path:
55
                    raise
56
                self.assertTrue(isinstance(e, AssertionError))
57
                continue
58
            self.assertEqual(cmd.help, help or '')
59
            self.assertEqual(cmd.subcommands, subcommands or {})
60
            self.assertEqual(cmd.cmd_class, cmd_class or None)
61
            self.assertEqual(cmd.long_help, long_help or '')
62

    
63
    def test_name(self):
64
        for path in ('cmd', 'cmd_cmd0', 'cmd_cmd0_cmd1', '', None):
65
            if path:
66
                cmd = command_tree.Command(path)
67
                self.assertEqual(cmd.name, path.split('_')[-1])
68
            else:
69
                try:
70
                    command_tree.Command(path)
71
                except Exception as e:
72
                    self.assertTrue(isinstance(e, AssertionError))
73

    
74
    def test_add_subcmd(self):
75
        cmd = command_tree.Command('cmd')
76
        for subname in (None, 'cmd0', 'cmd_cmd0'):
77
            if subname:
78
                subcmd = command_tree.Command(subname)
79
                if subname.startswith(cmd.name + '_'):
80
                    self.assertTrue(cmd.add_subcmd(subcmd))
81
                    self.assertTrue(subcmd.name in cmd.subcommands)
82
                else:
83
                    self.assertFalse(cmd.add_subcmd(subcmd))
84
                    self.assertTrue(len(cmd.subcommands) == 0)
85
            else:
86
                self.assertRaises(cmd.add_subcmd, subname, AttributeError)
87

    
88
    def test_get_subcmd(self):
89
        cmd = command_tree.Command('cmd')
90
        cmd.subcommands = dict(
91
            cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict(
92
                cmd1=command_tree.Command('cmd_cmd0a_cmd1'))),
93
            cmd0b=command_tree.Command('cmd_cmd0b'))
94
        for subname in ('', None, 'cmd0a', 'cmd1', 'cmd0b'):
95
            try:
96
                expected = cmd.subcommands[subname] if subname else None
97
            except KeyError:
98
                expected = None
99
            self.assertEqual(cmd.get_subcmd(subname), expected)
100

    
101
    def test_contains(self):
102
        cmd = command_tree.Command('cmd')
103
        for subname in ('', 'cmd0'):
104
            self.assertFalse(cmd.contains(subname))
105
        cmd.subcommands = dict(
106
            cmd0a=command_tree.Command('cmd_cmd0a'),
107
            cmd0b=command_tree.Command('cmd_cmd0b'))
108
        for subname in ('cmd0a', 'cmd0b'):
109
            self.assertTrue(cmd.contains(subname))
110
        for subname in ('', 'cmd0c'):
111
            self.assertFalse(cmd.contains(subname))
112
        cmd.subcommands['cmd0a'].subcommands = dict(
113
            cmd1=command_tree.Command('cmd_cmd0a_cmd1'))
114
        for subname in ('cmd0a', 'cmd0b'):
115
            self.assertTrue(cmd.contains(subname))
116
        for subname in ('', 'cmd0c', 'cmd1', 'cmd0a_cmd1'):
117
            self.assertFalse(cmd.contains(subname))
118

    
119
    def test_is_command(self):
120
        cmd = command_tree.Command('cmd')
121
        cmd.subcommands = dict(
122
            itis=command_tree.Command('cmd_itis', cmd_class=Command),
123
            itsnot=command_tree.Command('cmd_itsnot'))
124
        self.assertFalse(cmd.is_command)
125
        self.assertTrue(cmd.subcommands['itis'].is_command)
126
        self.assertFalse(cmd.subcommands['itsnot'].is_command)
127

    
128
    def test_parent_path(self):
129
        cmd = command_tree.Command('cmd')
130
        cmd.subcommands = dict(
131
            cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict(
132
                cmd1=command_tree.Command('cmd_cmd0a_cmd1'))),
133
            cmd0b=command_tree.Command('cmd_cmd0b'))
134
        self.assertEqual(cmd.parent_path, '')
135
        self.assertEqual(cmd.subcommands['cmd0a'].parent_path, cmd.path)
136
        self.assertEqual(cmd.subcommands['cmd0b'].parent_path, cmd.path)
137
        cmd0a = cmd.subcommands['cmd0a']
138
        self.assertEqual(cmd0a.subcommands['cmd1'].parent_path, cmd0a.path)
139

    
140
    def test_parse_out(self):
141
        cmd = command_tree.Command('cmd')
142
        cmd.subcommands = dict(
143
            cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict(
144
                cmd1=command_tree.Command('cmd_cmd0a_cmd1'))),
145
            cmd0b=command_tree.Command('cmd_cmd0b'))
146
        for invalids in (None, 42, 0.88):
147
            self.assertRaises(TypeError, cmd.parse_out, invalids)
148
        for c, l, expc, expl in (
149
                (cmd, ['cmd'], cmd, ['cmd']),
150
                (cmd, ['XXX'], cmd, ['XXX']),
151
                (cmd, ['cmd0a'], cmd.subcommands['cmd0a'], []),
152
                (cmd, ['XXX', 'cmd0a'], cmd, ['XXX', 'cmd0a']),
153
                (cmd, ['cmd0a', 'XXX'], cmd.subcommands['cmd0a'], ['XXX']),
154
                (cmd, ['cmd0a', 'cmd0b'], cmd.subcommands['cmd0a'], ['cmd0b']),
155
                (cmd, ['cmd0b', 'XXX'], cmd.subcommands['cmd0b'], ['XXX']),
156
                (
157
                    cmd, ['cmd0a', 'cmd1'],
158
                    cmd.subcommands['cmd0a'].subcommands['cmd1'], []),
159
                (
160
                    cmd, ['cmd0a', 'cmd1', 'XXX'],
161
                    cmd.subcommands['cmd0a'].subcommands['cmd1'], ['XXX']),
162
                (
163
                    cmd, ['cmd0a', 'XXX', 'cmd1'],
164
                    cmd.subcommands['cmd0a'], ['XXX', 'cmd1'])):
165
            self.assertEqual((expc, expl), c.parse_out(l))
166

    
167

    
168
class CommandTree(TestCase):
169

    
170
    def _add_commands(self, ctree):
171
        for cmd in self.commands:
172
            ctree.add_command(cmd.path, cmd.help, cmd.cmd_class)
173

    
174
    def _commands_are_equal(self, c1, c2):
175
        self.assertEqual(c1.path, c2.path)
176
        self.assertEqual(c1.name, c2.name)
177
        self.assertEqual(c1.cmd_class, c2.cmd_class)
178
        self.assertEqual(c1.help, c2.help)
179

    
180
    def setUp(self):
181
        cmd = command_tree.Command('cmd', subcommands=dict(
182
            cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict(
183
                cmd1a=command_tree.Command(
184
                    'cmd_cmd0a_cmd1a', subcommands=dict(
185
                        cmd2=command_tree.Command(
186
                            'cmd_cmd0a_cmd1a_cmd2', cmd_class=Command)
187
                        ),
188
                ),
189
                cmd1b=command_tree.Command(
190
                    'cmd_cmd0a_cmd1b', subcommands=dict(
191
                        cmd2=command_tree.Command(
192
                            'cmd_cmd0a_cmd1b_cmd2', cmd_class=Command)
193
                        ),
194
                )
195
            )),
196
            cmd0b=command_tree.Command('cmd_cmd0b'),
197
            cmd0c=command_tree.Command('cmd_cmd0c', subcommands=dict(
198
                cmd1a=command_tree.Command('cmd_cmd0c_cmd1a'),
199
                cmd1b=command_tree.Command(
200
                    'cmd_cmd0c_cmd1b', subcommands=dict(
201
                        cmd2=command_tree.Command(
202
                            'cmd_cmd0c_cmd1b_cmd2', cmd_class=Command)
203
                        ),
204
                )
205
            ))
206
        ))
207
        self.commands = [
208
            cmd,
209
            cmd.subcommands['cmd0a'],
210
            cmd.subcommands['cmd0a'].subcommands['cmd1a'],
211
            cmd.subcommands['cmd0a'].subcommands['cmd1a'].subcommands['cmd2'],
212
            cmd.subcommands['cmd0a'].subcommands['cmd1b'],
213
            cmd.subcommands['cmd0a'].subcommands['cmd1b'].subcommands['cmd2'],
214
            cmd.subcommands['cmd0b'],
215
            cmd.subcommands['cmd0c'],
216
            cmd.subcommands['cmd0c'].subcommands['cmd1a'],
217
            cmd.subcommands['cmd0c'].subcommands['cmd1b'],
218
            cmd.subcommands['cmd0c'].subcommands['cmd1b'].subcommands['cmd2'],
219
            command_tree.Command('othercmd')
220
        ]
221

    
222
    def tearDown(self):
223
        for cmd in self.commands:
224
            del cmd
225
        del self.commands
226

    
227
    def test___init__(self):
228
        name, description = 'sampleTree', 'a sample Tree'
229
        ctree = command_tree.CommandTree(name)
230
        for attr, exp in (
231
                ('groups', {}), ('_all_commands', {}),
232
                ('name', name), ('description', '')):
233
            self.assertEqual(getattr(ctree, attr), exp)
234
        ctree = command_tree.CommandTree(name, description)
235
        for attr, exp in (
236
                ('groups', {}), ('_all_commands', {}),
237
                ('name', name), ('description', description)):
238
            self.assertEqual(getattr(ctree, attr), exp)
239

    
240
    def test_exclude(self):
241
        ctree = command_tree.CommandTree('excludeTree', 'test exclude group')
242
        exp = dict()
243
        for cmd in self.commands[0:6]:
244
            ctree.groups[cmd.name] = cmd
245
            exp[cmd.name] = cmd
246
        self.assertEqual(exp, ctree.groups)
247
        ctree.exclude(exp.keys()[1::2])
248
        for key in exp.keys()[1::2]:
249
            exp.pop(key)
250
        self.assertEqual(exp, ctree.groups)
251

    
252
    def test_add_command(self):
253
        ctree = command_tree.CommandTree('addCommand', 'test add_command')
254
        self._add_commands(ctree)
255
        for cmd in self.commands:
256
            self.assertTrue(cmd, ctree._all_commands)
257
            if cmd.path.count('_'):
258
                self.assertFalse(cmd.name in ctree.groups)
259
            else:
260
                self.assertTrue(cmd.name in ctree.groups)
261
                self._commands_are_equal(cmd, ctree.groups[cmd.name])
262

    
263
    def test_find_best_match(self):
264
        ctree = command_tree.CommandTree('bestMatch', 'test find_best_match')
265
        for cmd in self.commands:
266
            terms = cmd.path.split('_')
267
            best_match, rest = ctree.find_best_match(terms)
268
            if len(terms) > 1:
269
                self.assertEqual(best_match.path, '_'.join(terms[:-1]))
270
            else:
271
                self.assertEqual(best_match, None)
272
            self.assertEqual(rest, terms[-1:])
273
            ctree.add_command(cmd.path, cmd.help, cmd.cmd_class)
274
            best_match, rest = ctree.find_best_match(terms)
275
            self._commands_are_equal(best_match, cmd)
276
            self.assertEqual(rest, [])
277

    
278
    def test_add_tree(self):
279
        ctree = command_tree.CommandTree('tree', 'the main tree')
280
        ctree1 = command_tree.CommandTree('tree1', 'the first tree')
281
        ctree2 = command_tree.CommandTree('tree2', 'the second tree')
282

    
283
        cmds = list(self.commands)
284
        del self.commands
285
        cmds1, cmds2 = cmds[:6], cmds[6:]
286
        self.commands = cmds1
287
        self._add_commands(ctree1)
288
        self.commands = cmds2
289
        self._add_commands(ctree2)
290
        self.commands = cmds
291

    
292
        def check_all(
293
                p1=False, p2=False, p3=False, p4=False, p5=False, p6=False):
294
            for cmd in cmds[:6]:
295
                self.assertEquals(cmd.path in ctree._all_commands, p1)
296
                self.assertEquals(cmd.path in ctree1._all_commands, p2)
297
                if cmd.path != 'cmd':
298
                    self.assertEquals(cmd.path in ctree2._all_commands, p3)
299
            for cmd in cmds[6:]:
300
                self.assertEquals(cmd.path in ctree._all_commands, p4)
301
                if cmd.path != 'cmd':
302
                    self.assertEquals(cmd.path in ctree1._all_commands, p5)
303
                self.assertEquals(cmd.path in ctree2._all_commands, p6)
304

    
305
        check_all(False, True, False, False, False, True)
306
        ctree.add_tree(ctree1)
307
        check_all(True, True, False, False, False, True)
308
        ctree.add_tree(ctree2)
309
        check_all(True, True, False, True, False, True)
310
        ctree2.add_tree(ctree1)
311
        check_all(True, True, True, True, False, True)
312

    
313
    def test_has_command(self):
314
        ctree = command_tree.CommandTree('treeHasCommand', 'test has_command')
315
        for cmd in self.commands:
316
            self.assertFalse(ctree.has_command(cmd.path))
317
        self._add_commands(ctree)
318
        for cmd in self.commands:
319
            self.assertTrue(ctree.has_command(cmd.path))
320
        self.assertFalse(ctree.has_command('NON_EXISTING_COMMAND'))
321

    
322
    def test_get_command(self):
323
        ctree = command_tree.CommandTree('treeGetCommand', 'test get_command')
324
        for cmd in self.commands:
325
            self.assertRaises(KeyError, ctree.get_command, cmd.path)
326
        self._add_commands(ctree)
327
        for cmd in self.commands:
328
            self._commands_are_equal(ctree.get_command(cmd.path), cmd)
329
        self.assertRaises(KeyError, ctree.get_command, 'NON_EXISTNG_COMMAND')
330

    
331
    def test_subnames(self):
332
        ctree = command_tree.CommandTree('treeSubnames', 'test subnames')
333
        self.assertEqual(ctree.subnames(), [])
334
        self.assertRaises(KeyError, ctree.subnames, 'cmd')
335
        self._add_commands(ctree)
336
        for l1, l2 in (
337
                (ctree.subnames(), ['cmd', 'othercmd']),
338
                (ctree.subnames('cmd'), ['cmd0a', 'cmd0b', 'cmd0c']),
339
                (ctree.subnames('cmd_cmd0a'), ['cmd1a', 'cmd1b']),
340
                (ctree.subnames('cmd_cmd0a_cmd1a'), ['cmd2', ]),
341
                (ctree.subnames('cmd_cmd0a_cmd1b'), ['cmd2', ]),
342
                (ctree.subnames('cmd_cmd0a_cmd1a_cmd2'), []),
343
                (ctree.subnames('cmd_cmd0a_cmd1b_cmd2'), []),
344
                (ctree.subnames('cmd_cmd0b'), []),
345
                (ctree.subnames('cmd_cmd0c'), ['cmd1a', 'cmd1b']),
346
                (ctree.subnames('cmd_cmd0c_cmd1a'), []),
347
                (ctree.subnames('cmd_cmd0c_cmd1b'), ['cmd2', ]),
348
                (ctree.subnames('cmd_cmd0c_cmd1b_cmd2'), []),
349
                (ctree.subnames('othercmd'), [])):
350
            l1.sort(), l2.sort(), self.assertEqual(l1, l2)
351
        self.assertRaises(KeyError, ctree.subnames, 'NON_EXISTNG_CMD')
352

    
353
    def test_get_subcommands(self):
354
        ctree = command_tree.CommandTree('treeSub', 'test get_subcommands')
355
        self.assertEqual(ctree.get_subcommands(), [])
356
        self.assertRaises(KeyError, ctree.get_subcommands, 'cmd')
357
        self._add_commands(ctree)
358
        for s1, l2 in (
359
            ('', ['cmd', 'othercmd']),
360
            ('cmd', ['cmd0a', 'cmd0b', 'cmd0c']),
361
            ('cmd_cmd0a', ['cmd1a', 'cmd1b']),
362
            ('cmd_cmd0a_cmd1a', ['cmd2', ]),
363
            ('cmd_cmd0a_cmd1b', ['cmd2', ]),
364
            ('cmd_cmd0a_cmd1a_cmd2', []),
365
            ('cmd_cmd0a_cmd1b_cmd2', []),
366
            ('cmd_cmd0b', []),
367
            ('cmd_cmd0c', ['cmd1a', 'cmd1b']),
368
            ('cmd_cmd0c_cmd1a', []),
369
            ('cmd_cmd0c_cmd1b', ['cmd2', ]),
370
            ('cmd_cmd0c_cmd1b_cmd2', []),
371
            ('othercmd', [])
372
        ):
373
            l1 = [cmd.path for cmd in ctree.get_subcommands(s1)]
374
            l2 = ['_'.join([s1, i]) for i in l2] if s1 else l2
375
            l1.sort(), l2.sort(), self.assertEqual(l1, l2)
376
        self.assertRaises(KeyError, ctree.get_subcommands, 'NON_EXISTNG_CMD')
377

    
378

    
379
if __name__ == '__main__':
380
    from sys import argv
381
    from kamaki.cli.test import runTestCase
382
    runTestCase(Command, 'Command', argv[1:])
383
    runTestCase(CommandTree, 'CommandTree', argv[1:])