# Copyright 2013 GRNET S.A. All rights reserved. # # Redistribution and use in source and binary forms, with or # without modification, are permitted provided that the following # conditions are met: # # 1. Redistributions of source code must retain the above # copyright notice, this list of conditions and the following # disclaimer. # # 2. Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials # provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # The views and conclusions contained in the software and # documentation are those of the authors and should not be # interpreted as representing official policies, either expressed # or implied, of GRNET S.A. #from mock import patch, call from unittest import TestCase from itertools import product from kamaki.cli import command_tree class Command(TestCase): def test___init__(self): for args in product( (None, '', 'cmd'), (None, '', 'Some help'), (None, '', {}, dict(cmd0a=None, cmd0b=None)), (None, command_tree.Command('cmd_cmd0'))): path, help, subcommands, cmd_class = args try: cmd = command_tree.Command(*args) except Exception as e: if path: raise self.assertTrue(isinstance(e, AssertionError)) continue self.assertEqual(cmd.help, help or '') self.assertEqual(cmd.subcommands, subcommands or {}) self.assertEqual(cmd.cmd_class, cmd_class or None) def test_name(self): for path in ('cmd', 'cmd_cmd0', 'cmd_cmd0_cmd1', '', None): if path: cmd = command_tree.Command(path) self.assertEqual(cmd.name, path.split('_')[-1]) else: try: command_tree.Command(path) except Exception as e: self.assertTrue(isinstance(e, AssertionError)) def test_add_subcmd(self): cmd = command_tree.Command('cmd') for subname in (None, 'cmd0', 'cmd_cmd0'): if subname: subcmd = command_tree.Command(subname) if subname.startswith(cmd.name + '_'): self.assertTrue(cmd.add_subcmd(subcmd)) self.assertTrue(subcmd.name in cmd.subcommands) else: self.assertFalse(cmd.add_subcmd(subcmd)) self.assertTrue(len(cmd.subcommands) == 0) else: self.assertRaises(cmd.add_subcmd, subname, AttributeError) def test_get_subcmd(self): cmd = command_tree.Command('cmd') cmd.subcommands = dict( cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict( cmd1=command_tree.Command('cmd_cmd0a_cmd1'))), cmd0b=command_tree.Command('cmd_cmd0b')) for subname in ('', None, 'cmd0a', 'cmd1', 'cmd0b'): try: expected = cmd.subcommands[subname] if subname else None except KeyError: expected = None self.assertEqual(cmd.get_subcmd(subname), expected) def test_contains(self): cmd = command_tree.Command('cmd') for subname in ('', 'cmd0'): self.assertFalse(cmd.contains(subname)) cmd.subcommands = dict( cmd0a=command_tree.Command('cmd_cmd0a'), cmd0b=command_tree.Command('cmd_cmd0b')) for subname in ('cmd0a', 'cmd0b'): self.assertTrue(cmd.contains(subname)) for subname in ('', 'cmd0c'): self.assertFalse(cmd.contains(subname)) cmd.subcommands['cmd0a'].subcommands = dict( cmd1=command_tree.Command('cmd_cmd0a_cmd1')) for subname in ('cmd0a', 'cmd0b'): self.assertTrue(cmd.contains(subname)) for subname in ('', 'cmd0c', 'cmd1', 'cmd0a_cmd1'): self.assertFalse(cmd.contains(subname)) def test_is_command(self): cmd = command_tree.Command('cmd') cmd.subcommands = dict( itis=command_tree.Command('cmd_itis', cmd_class=Command), itsnot=command_tree.Command('cmd_itsnot')) self.assertFalse(cmd.is_command) self.assertTrue(cmd.subcommands['itis'].is_command) self.assertFalse(cmd.subcommands['itsnot'].is_command) def test_parent_path(self): cmd = command_tree.Command('cmd') cmd.subcommands = dict( cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict( cmd1=command_tree.Command('cmd_cmd0a_cmd1'))), cmd0b=command_tree.Command('cmd_cmd0b')) self.assertEqual(cmd.parent_path, '') self.assertEqual(cmd.subcommands['cmd0a'].parent_path, cmd.path) self.assertEqual(cmd.subcommands['cmd0b'].parent_path, cmd.path) cmd0a = cmd.subcommands['cmd0a'] self.assertEqual(cmd0a.subcommands['cmd1'].parent_path, cmd0a.path) def test_parse_out(self): cmd = command_tree.Command('cmd') cmd.subcommands = dict( cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict( cmd1=command_tree.Command('cmd_cmd0a_cmd1'))), cmd0b=command_tree.Command('cmd_cmd0b')) for invalids in (None, 42, 0.88): self.assertRaises(TypeError, cmd.parse_out, invalids) for c, l, expc, expl in ( (cmd, ['cmd'], cmd, ['cmd']), (cmd, ['XXX'], cmd, ['XXX']), (cmd, ['cmd0a'], cmd.subcommands['cmd0a'], []), (cmd, ['XXX', 'cmd0a'], cmd, ['XXX', 'cmd0a']), (cmd, ['cmd0a', 'XXX'], cmd.subcommands['cmd0a'], ['XXX']), (cmd, ['cmd0a', 'cmd0b'], cmd.subcommands['cmd0a'], ['cmd0b']), (cmd, ['cmd0b', 'XXX'], cmd.subcommands['cmd0b'], ['XXX']), ( cmd, ['cmd0a', 'cmd1'], cmd.subcommands['cmd0a'].subcommands['cmd1'], []), ( cmd, ['cmd0a', 'cmd1', 'XXX'], cmd.subcommands['cmd0a'].subcommands['cmd1'], ['XXX']), ( cmd, ['cmd0a', 'XXX', 'cmd1'], cmd.subcommands['cmd0a'], ['XXX', 'cmd1'])): self.assertEqual((expc, expl), c.parse_out(l)) class CommandTree(TestCase): def _add_commands(self, ctree): for cmd in self.commands: ctree.add_command(cmd.path, cmd.help, cmd.cmd_class) def _commands_are_equal(self, c1, c2): self.assertEqual(c1.path, c2.path) self.assertEqual(c1.name, c2.name) self.assertEqual(c1.cmd_class, c2.cmd_class) self.assertEqual(c1.help, c2.help) def setUp(self): cmd = command_tree.Command('cmd', subcommands=dict( cmd0a=command_tree.Command('cmd_cmd0a', subcommands=dict( cmd1a=command_tree.Command( 'cmd_cmd0a_cmd1a', subcommands=dict( cmd2=command_tree.Command( 'cmd_cmd0a_cmd1a_cmd2', cmd_class=Command) ), ), cmd1b=command_tree.Command( 'cmd_cmd0a_cmd1b', subcommands=dict( cmd2=command_tree.Command( 'cmd_cmd0a_cmd1b_cmd2', cmd_class=Command) ), ) )), cmd0b=command_tree.Command('cmd_cmd0b'), cmd0c=command_tree.Command('cmd_cmd0c', subcommands=dict( cmd1a=command_tree.Command('cmd_cmd0c_cmd1a'), cmd1b=command_tree.Command( 'cmd_cmd0c_cmd1b', subcommands=dict( cmd2=command_tree.Command( 'cmd_cmd0c_cmd1b_cmd2', cmd_class=Command) ), ) )) )) self.commands = [ cmd, cmd.subcommands['cmd0a'], cmd.subcommands['cmd0a'].subcommands['cmd1a'], cmd.subcommands['cmd0a'].subcommands['cmd1a'].subcommands['cmd2'], cmd.subcommands['cmd0a'].subcommands['cmd1b'], cmd.subcommands['cmd0a'].subcommands['cmd1b'].subcommands['cmd2'], cmd.subcommands['cmd0b'], cmd.subcommands['cmd0c'], cmd.subcommands['cmd0c'].subcommands['cmd1a'], cmd.subcommands['cmd0c'].subcommands['cmd1b'], cmd.subcommands['cmd0c'].subcommands['cmd1b'].subcommands['cmd2'], command_tree.Command('othercmd') ] def tearDown(self): for cmd in self.commands: del cmd del self.commands def test___init__(self): name, description = 'sampleTree', 'a sample Tree' ctree = command_tree.CommandTree(name) for attr, exp in ( ('groups', {}), ('_all_commands', {}), ('name', name), ('description', '')): self.assertEqual(getattr(ctree, attr), exp) ctree = command_tree.CommandTree(name, description) for attr, exp in ( ('groups', {}), ('_all_commands', {}), ('name', name), ('description', description)): self.assertEqual(getattr(ctree, attr), exp) def test_exclude(self): ctree = command_tree.CommandTree('excludeTree', 'test exclude group') exp = dict() for cmd in self.commands[0:6]: ctree.groups[cmd.name] = cmd exp[cmd.name] = cmd self.assertEqual(exp, ctree.groups) ctree.exclude(exp.keys()[1::2]) for key in exp.keys()[1::2]: exp.pop(key) self.assertEqual(exp, ctree.groups) def test_add_command(self): ctree = command_tree.CommandTree('addCommand', 'test add_command') self._add_commands(ctree) for cmd in self.commands: self.assertTrue(cmd, ctree._all_commands) if cmd.path.count('_'): self.assertFalse(cmd.name in ctree.groups) else: self.assertTrue(cmd.name in ctree.groups) self._commands_are_equal(cmd, ctree.groups[cmd.name]) def test_find_best_match(self): ctree = command_tree.CommandTree('bestMatch', 'test find_best_match') for cmd in self.commands: terms = cmd.path.split('_') best_match, rest = ctree.find_best_match(terms) if len(terms) > 1: self.assertEqual(best_match.path, '_'.join(terms[:-1])) else: self.assertEqual(best_match, None) self.assertEqual(rest, terms[-1:]) ctree.add_command(cmd.path, cmd.help, cmd.cmd_class) best_match, rest = ctree.find_best_match(terms) self._commands_are_equal(best_match, cmd) self.assertEqual(rest, []) def test_add_tree(self): ctree = command_tree.CommandTree('tree', 'the main tree') ctree1 = command_tree.CommandTree('tree1', 'the first tree') ctree2 = command_tree.CommandTree('tree2', 'the second tree') cmds = list(self.commands) del self.commands cmds1, cmds2 = cmds[:6], cmds[6:] self.commands = cmds1 self._add_commands(ctree1) self.commands = cmds2 self._add_commands(ctree2) self.commands = cmds def check_all( p1=False, p2=False, p3=False, p4=False, p5=False, p6=False): for cmd in cmds[:6]: self.assertEquals(cmd.path in ctree._all_commands, p1) self.assertEquals(cmd.path in ctree1._all_commands, p2) if cmd.path != 'cmd': self.assertEquals(cmd.path in ctree2._all_commands, p3) for cmd in cmds[6:]: self.assertEquals(cmd.path in ctree._all_commands, p4) if cmd.path != 'cmd': self.assertEquals(cmd.path in ctree1._all_commands, p5) self.assertEquals(cmd.path in ctree2._all_commands, p6) check_all(False, True, False, False, False, True) ctree.add_tree(ctree1) check_all(True, True, False, False, False, True) ctree.add_tree(ctree2) check_all(True, True, False, True, False, True) ctree2.add_tree(ctree1) check_all(True, True, True, True, False, True) def test_has_command(self): ctree = command_tree.CommandTree('treeHasCommand', 'test has_command') for cmd in self.commands: self.assertFalse(ctree.has_command(cmd.path)) self._add_commands(ctree) for cmd in self.commands: self.assertTrue(ctree.has_command(cmd.path)) self.assertFalse(ctree.has_command('NON_EXISTING_COMMAND')) def test_get_command(self): ctree = command_tree.CommandTree('treeGetCommand', 'test get_command') for cmd in self.commands: self.assertRaises(KeyError, ctree.get_command, cmd.path) self._add_commands(ctree) for cmd in self.commands: self._commands_are_equal(ctree.get_command(cmd.path), cmd) self.assertRaises(KeyError, ctree.get_command, 'NON_EXISTNG_COMMAND') def test_subnames(self): ctree = command_tree.CommandTree('treeSubnames', 'test subnames') self.assertEqual(ctree.subnames(), []) self.assertRaises(KeyError, ctree.subnames, 'cmd') self._add_commands(ctree) for l1, l2 in ( (ctree.subnames(), ['cmd', 'othercmd']), (ctree.subnames('cmd'), ['cmd0a', 'cmd0b', 'cmd0c']), (ctree.subnames('cmd_cmd0a'), ['cmd1a', 'cmd1b']), (ctree.subnames('cmd_cmd0a_cmd1a'), ['cmd2', ]), (ctree.subnames('cmd_cmd0a_cmd1b'), ['cmd2', ]), (ctree.subnames('cmd_cmd0a_cmd1a_cmd2'), []), (ctree.subnames('cmd_cmd0a_cmd1b_cmd2'), []), (ctree.subnames('cmd_cmd0b'), []), (ctree.subnames('cmd_cmd0c'), ['cmd1a', 'cmd1b']), (ctree.subnames('cmd_cmd0c_cmd1a'), []), (ctree.subnames('cmd_cmd0c_cmd1b'), ['cmd2', ]), (ctree.subnames('cmd_cmd0c_cmd1b_cmd2'), []), (ctree.subnames('othercmd'), [])): l1.sort(), l2.sort(), self.assertEqual(l1, l2) self.assertRaises(KeyError, ctree.subnames, 'NON_EXISTNG_CMD') def test_get_subcommands(self): ctree = command_tree.CommandTree('treeSub', 'test get_subcommands') self.assertEqual(ctree.get_subcommands(), []) self.assertRaises(KeyError, ctree.get_subcommands, 'cmd') self._add_commands(ctree) for s1, l2 in ( ('', ['cmd', 'othercmd']), ('cmd', ['cmd0a', 'cmd0b', 'cmd0c']), ('cmd_cmd0a', ['cmd1a', 'cmd1b']), ('cmd_cmd0a_cmd1a', ['cmd2', ]), ('cmd_cmd0a_cmd1b', ['cmd2', ]), ('cmd_cmd0a_cmd1a_cmd2', []), ('cmd_cmd0a_cmd1b_cmd2', []), ('cmd_cmd0b', []), ('cmd_cmd0c', ['cmd1a', 'cmd1b']), ('cmd_cmd0c_cmd1a', []), ('cmd_cmd0c_cmd1b', ['cmd2', ]), ('cmd_cmd0c_cmd1b_cmd2', []), ('othercmd', []) ): l1 = [cmd.path for cmd in ctree.get_subcommands(s1)] l2 = ['_'.join([s1, i]) for i in l2] if s1 else l2 l1.sort(), l2.sort(), self.assertEqual(l1, l2) self.assertRaises(KeyError, ctree.get_subcommands, 'NON_EXISTNG_CMD') if __name__ == '__main__': from sys import argv from kamaki.cli.test import runTestCase runTestCase(Command, 'Command', argv[1:]) runTestCase(CommandTree, 'CommandTree', argv[1:])