Beispiel #1
0
class OmsShellTerminalProtocol(object):
    """Connect a OmsShellProtocol to a web terminal session."""
    def logged_in(self, principal):
        self.principal = principal

    def connection_made(self, terminal, size):
        self.shell = OmsShellProtocol()
        self.shell.set_terminal(terminal)
        self.shell.connectionMade()
        self.shell.terminalSize(size[0], size[1])
        self.shell.logged_in(self.principal)

    def handle_key(self, key):
        self.shell.terminal.dataReceived(key)

    def terminalSize(self, width, height):
        # Insults terminal doesn't work well after resizes
        # also disabled in the oms shell over ssh.
        #
        # self.shell.terminalSize(width, height)
        pass
Beispiel #2
0
class OmsShellTerminalProtocol(object):
    """Connect a OmsShellProtocol to a web terminal session."""

    def logged_in(self, principal):
        self.principal = principal

    def connection_made(self, terminal, size):
        self.shell = OmsShellProtocol()
        self.shell.set_terminal(terminal)
        self.shell.connectionMade()
        self.shell.terminalSize(size[0], size[1])
        self.shell.logged_in(self.principal)

    def handle_key(self, key):
        self.shell.terminal.dataReceived(key)

    def terminalSize(self, width, height):
        # Insults terminal doesn't work well after resizes
        # also disabled in the oms shell over ssh.
        #
        # self.shell.terminalSize(width, height)
        pass
Beispiel #3
0
class CmdCompletionTestCase(unittest.TestCase):
    def setUp(self):
        self.oms_ssh = OmsShellProtocol()
        auth = getUtility(IAuthentication, context=None)
        user = auth.getPrincipal('user')
        user.groups.append('admins')
        self.oms_ssh.batch = True
        self.oms_ssh.logged_in(user)
        self.oms_ssh.batch = False

        self.terminal = mock.Mock()
        self.oms_ssh.terminal = self.terminal

        self.oms_ssh.connectionMade()

        # the standard model doesn't have any command or path which
        # is a prefix of another (len > 1), I don't want to force changes
        # to the model just for testing completion, so we have monkey patch
        # the commands() function and add a command 'hello'.
        self.orig_commands = registry.commands

        class HelloCmd(Cmd):
            name = 'hello'

        registry.commands = lambda: dict(hello=HelloCmd,
                                         **self.orig_commands())

    def tearDown(self):
        registry.commands = self.orig_commands

    def make_compute(self,
                     hostname=u'tux-for-test',
                     state=u'active',
                     arch=u'linux',
                     memory=2000):
        return Compute(hostname, state, arch, memory)

    def _input(self, string):
        for s in string:
            self.oms_ssh.characterReceived(s, False)

    def _tab_after(self, string):
        self._input(string)
        self.terminal.reset_mock()

        self.oms_ssh.handle_TAB()

    def test_command_completion(self):
        self._tab_after('q')
        with assert_mock(self.terminal) as t:
            t.write('uit ')
            no_more_calls(t)

    def test_command_completion_spaces(self):
        self._tab_after('    q')
        with assert_mock(self.terminal) as t:
            t.write('uit ')
            no_more_calls(t)

    def test_complete_not_found(self):
        self._tab_after('asdasd')
        with assert_mock(self.terminal) as t:
            no_more_calls(t)

    def test_complete_quotes(self):
        self._tab_after('ls "comp')
        with assert_mock(self.terminal) as t:
            t.write('utes/')
            no_more_calls(t)

    def test_complete_prefix(self):
        self._tab_after('he')
        with assert_mock(self.terminal) as t:
            t.write('l')
            no_more_calls(t)

        # hit tab twice
        self.terminal.reset_mock()
        self.oms_ssh.handle_TAB()

        with assert_mock(self.terminal) as t:
            t.write('')
            t.nextLine()
            t.write('help  hello\n')
            t.write(self.oms_ssh.ps[0] + 'hel')
            no_more_calls(t)

    def test_spaces_between_arg(self):
        self._tab_after('ls comp')

        with assert_mock(self.terminal) as t:
            t.write('utes/')
            no_more_calls(t)

    def test_command_arg_spaces_before_command(self):
        self._tab_after(' ls comp')
        with assert_mock(self.terminal) as t:
            t.write('utes/')
            no_more_calls(t)

    def test_mandatory_positional(self):
        self._tab_after('cat ')
        with assert_mock(self.terminal) as t:
            skip(t, 4)
            no_more_calls(t)

    def test_complete_switches(self):
        self._tab_after('quit ')
        with assert_mock(self.terminal) as t:
            no_more_calls(t)

        # hit tab twice
        self.oms_ssh.handle_TAB()
        with assert_mock(self.terminal) as t:
            no_more_calls(t)

        # now try with a dash
        self._tab_after('-')
        with assert_mock(self.terminal) as t:
            t.write('')
            t.nextLine()
            t.write('-h  --help\n')
            t.write(self.oms_ssh.ps[0] + 'quit -')
            no_more_calls(t)
        # disambiguate
        self._tab_after('-')
        with assert_mock(self.terminal) as t:
            t.write('help ')
            no_more_calls(t)

    def test_complete_consumed_switches(self):
        self._tab_after('ls --help')
        with assert_mock(self.terminal) as t:
            t.write(' ')
            no_more_calls(t)

        self._tab_after('-')
        with assert_mock(self.terminal) as t:
            skip(t, 2)
            with current_call(t) as c:
                assert 'help' not in c.arg
                assert '-h' not in c.arg

    @run_in_reactor
    def test_complete_context_dependent_no_context(self):
        """Test whether context dependent arguments are correctly built when the
        context argument (i.e. the `set` cmd `path` argument) is not yet present.

        """
        self._tab_after('set /comp')
        with assert_mock(self.terminal) as t:
            t.write('utes/')
            no_more_calls(t)

    @run_in_reactor
    def test_complete_keyword_switches(self):
        computes = db.get_root()['oms_root']['computes']
        cid = computes.add(self.make_compute())
        transaction.commit()

        self._tab_after('set /computes/%s st' % cid)
        with assert_mock(self.terminal) as t:
            t.write('ate=')
            no_more_calls(t)

        self._tab_after('ina')
        with assert_mock(self.terminal) as t:
            t.write('ctive ')
            no_more_calls(t)

    @run_in_reactor
    def test_complete_keyword_switches_mk(self):
        self.oms_ssh.lineReceived('cd computes')

        self._tab_after('mk compute st')
        with assert_mock(self.terminal) as t:
            t.write('ate=')
            no_more_calls(t)

        self._tab_after('ina')
        with assert_mock(self.terminal) as t:
            t.write('ctive ')
            no_more_calls(t)

    @run_in_reactor
    def test_complete_consumed_keyword_switches_mk(self):
        """Test consuming of already completed switches when there are mandatory arguments."""
        self.oms_ssh.lineReceived('cd computes')

        self._tab_after('mk compute st')
        with assert_mock(self.terminal) as t:
            t.write('ate=')
            no_more_calls(t)

        self._tab_after('ina')
        with assert_mock(self.terminal) as t:
            t.write('ctive ')
            no_more_calls(t)

        self._tab_after('st')
        assert not self.terminal.method_calls

    @run_in_reactor
    def test_complete_mk_legal_types(self):
        """Test that only legal types are shown."""
        self.oms_ssh.lineReceived('cd computes')

        self._tab_after('mk net')
        assert not self.terminal.method_calls

        self.oms_ssh.handle_RETURN()
        self.terminal.reset_mock()

        self._tab_after('mk comp')
        #~ eq_(self.terminal.method_calls, [('write', ('ute ',), {})])
        with assert_mock(self.terminal) as t:
            t.write('ute ')
            no_more_calls(t)

        self._tab_after('arch')
        with assert_mock(self.terminal) as t:
            t.write('itecture=')
            no_more_calls(t)

    @run_in_reactor
    def test_complete_mk_legal_types_interface(self):
        class ITest(Interface):
            pass

        class Test(Model):
            implements(ITest)

            def __init__(self):
                pass

        class TestInterfaceContainer(Container):
            __contains__ = ITest

        class TestClassContainer(Container):
            __contains__ = Test

        creatable_models['some-test'] = Test

        orig_current_object = commands.CreateObjCmd.current_obj

        try:
            commands.CreateObjCmd.current_obj = TestInterfaceContainer()
            self._tab_after('mk ')
            with assert_mock(self.terminal) as t:
                t.write('some-test ')
                no_more_calls(t)

            self.oms_ssh.handle_RETURN()
            self.terminal.reset_mock()

            commands.CreateObjCmd.current_obj = TestClassContainer()

            self._tab_after('mk ')
            with assert_mock(self.terminal) as t:
                t.write('some-test ')
                no_more_calls(t)
        finally:
            commands.CreateObjCmd.current_obj = orig_current_object
            del creatable_models['some-test']

    @run_in_reactor
    def test_complete_positional_choice(self):
        self.oms_ssh.lineReceived('cd computes')

        self._tab_after('mk comp')
        with assert_mock(self.terminal) as t:
            t.write('ute ')
            no_more_calls(t)

        self._tab_after('comp')
        assert not self.terminal.method_calls

    @run_in_reactor
    def test_complete_container_symlink(self):
        computes = db.get_root()['oms_root']['computes']
        cid = computes.add(self.make_compute())
        transaction.commit()

        self._tab_after('cd /computes/%s' % cid)
        with assert_mock(self.terminal) as t:
            t.write('/')
class CmdCompletionTestCase(unittest.TestCase):

    def setUp(self):
        self.oms_ssh = OmsShellProtocol()
        auth = getUtility(IAuthentication, context=None)
        user = auth.getPrincipal('user')
        user.groups.append('admins')
        self.oms_ssh.batch = True
        self.oms_ssh.logged_in(user)
        self.oms_ssh.batch = False

        self.terminal = mock.Mock()
        self.oms_ssh.terminal = self.terminal

        self.oms_ssh.connectionMade()

        # the standard model doesn't have any command or path which
        # is a prefix of another (len > 1), I don't want to force changes
        # to the model just for testing completion, so we have monkey patch
        # the commands() function and add a command 'hello'.
        self.orig_commands = registry.commands

        class HelloCmd(Cmd):
            name = 'hello'
        registry.commands = lambda: dict(hello=HelloCmd, **self.orig_commands())

    def tearDown(self):
        registry.commands = self.orig_commands

    def make_compute(self, hostname=u'tux-for-test', state=u'active', arch=u'linux', memory=2000):
        return Compute(hostname, state, arch, memory)

    def _input(self, string):
        for s in string:
            self.oms_ssh.characterReceived(s, False)

    def _tab_after(self, string):
        self._input(string)
        self.terminal.reset_mock()

        self.oms_ssh.handle_TAB()

    def test_command_completion(self):
        self._tab_after('q')
        with assert_mock(self.terminal) as t:
            t.write('uit ')
            no_more_calls(t)

    def test_command_completion_spaces(self):
        self._tab_after('    q')
        with assert_mock(self.terminal) as t:
            t.write('uit ')
            no_more_calls(t)

    def test_complete_not_found(self):
        self._tab_after('asdasd')
        with assert_mock(self.terminal) as t:
            no_more_calls(t)

    def test_complete_quotes(self):
        self._tab_after('ls "comp')
        with assert_mock(self.terminal) as t:
            t.write('utes/')
            no_more_calls(t)

    def test_complete_prefix(self):
        self._tab_after('he')
        with assert_mock(self.terminal) as t:
            t.write('l')
            no_more_calls(t)

        # hit tab twice
        self.terminal.reset_mock()
        self.oms_ssh.handle_TAB()

        with assert_mock(self.terminal) as t:
            t.write('')
            t.nextLine()
            t.write('help  hello\n')
            t.write(self.oms_ssh.ps[0] + 'hel')
            no_more_calls(t)

    def test_spaces_between_arg(self):
        self._tab_after('ls comp')

        with assert_mock(self.terminal) as t:
            t.write('utes/')
            no_more_calls(t)

    def test_command_arg_spaces_before_command(self):
        self._tab_after(' ls comp')
        with assert_mock(self.terminal) as t:
            t.write('utes/')
            no_more_calls(t)

    def test_mandatory_positional(self):
        self._tab_after('cat ')
        with assert_mock(self.terminal) as t:
            skip(t, 4)
            no_more_calls(t)

    def test_complete_switches(self):
        self._tab_after('quit ')
        with assert_mock(self.terminal) as t:
            no_more_calls(t)

        # hit tab twice
        self.oms_ssh.handle_TAB()
        with assert_mock(self.terminal) as t:
            no_more_calls(t)

        # now try with a dash
        self._tab_after('-')
        with assert_mock(self.terminal) as t:
            t.write('')
            t.nextLine()
            t.write('-h  --help\n')
            t.write(self.oms_ssh.ps[0] + 'quit -')
            no_more_calls(t)
        # disambiguate
        self._tab_after('-')
        with assert_mock(self.terminal) as t:
            t.write('help ')
            no_more_calls(t)

    def test_complete_consumed_switches(self):
        self._tab_after('ls --help')
        with assert_mock(self.terminal) as t:
            t.write(' ')
            no_more_calls(t)

        self._tab_after('-')
        with assert_mock(self.terminal) as t:
            skip(t, 2)
            with current_call(t) as c:
                assert 'help' not in c.arg
                assert '-h' not in c.arg

    @run_in_reactor
    def test_complete_context_dependent_no_context(self):
        """Test whether context dependent arguments are correctly built when the
        context argument (i.e. the `set` cmd `path` argument) is not yet present.

        """
        self._tab_after('set /comp')
        with assert_mock(self.terminal) as t:
            t.write('utes/')
            no_more_calls(t)

    @run_in_reactor
    def test_complete_keyword_switches(self):
        computes = db.get_root()['oms_root']['computes']
        cid = computes.add(self.make_compute())
        transaction.commit()

        self._tab_after('set /computes/%s st' % cid)
        with assert_mock(self.terminal) as t:
            t.write('ate=')
            no_more_calls(t)

        self._tab_after('ina')
        with assert_mock(self.terminal) as t:
            t.write('ctive ')
            no_more_calls(t)

    @run_in_reactor
    def test_complete_keyword_switches_mk(self):
        self.oms_ssh.lineReceived('cd computes')

        self._tab_after('mk compute st')
        with assert_mock(self.terminal) as t:
            t.write('ate=')
            no_more_calls(t)

        self._tab_after('ina')
        with assert_mock(self.terminal) as t:
            t.write('ctive ')
            no_more_calls(t)

    @run_in_reactor
    def test_complete_consumed_keyword_switches_mk(self):
        """Test consuming of already completed switches when there are mandatory arguments."""
        self.oms_ssh.lineReceived('cd computes')

        self._tab_after('mk compute st')
        with assert_mock(self.terminal) as t:
            t.write('ate=')
            no_more_calls(t)

        self._tab_after('ina')
        with assert_mock(self.terminal) as t:
            t.write('ctive ')
            no_more_calls(t)

        self._tab_after('st')
        assert not self.terminal.method_calls

    @run_in_reactor
    def test_complete_mk_legal_types(self):
        """Test that only legal types are shown."""
        self.oms_ssh.lineReceived('cd computes')

        self._tab_after('mk net')
        assert not self.terminal.method_calls

        self.oms_ssh.handle_RETURN()
        self.terminal.reset_mock()

        self._tab_after('mk comp')
        #~ eq_(self.terminal.method_calls, [('write', ('ute ',), {})])
        with assert_mock(self.terminal) as t:
            t.write('ute ')
            no_more_calls(t)

        self._tab_after('arch')
        with assert_mock(self.terminal) as t:
            t.write('itecture=')
            no_more_calls(t)

    @run_in_reactor
    def test_complete_mk_legal_types_interface(self):
        class ITest(Interface):
            pass

        class Test(Model):
            implements(ITest)

            def __init__(self):
                pass

        class TestInterfaceContainer(Container):
            __contains__ = ITest

        class TestClassContainer(Container):
            __contains__ = Test

        creatable_models['some-test'] = Test

        orig_current_object = commands.CreateObjCmd.current_obj

        try:
            commands.CreateObjCmd.current_obj = TestInterfaceContainer()
            self._tab_after('mk ')
            with assert_mock(self.terminal) as t:
                t.write('some-test ')
                no_more_calls(t)

            self.oms_ssh.handle_RETURN()
            self.terminal.reset_mock()

            commands.CreateObjCmd.current_obj = TestClassContainer()

            self._tab_after('mk ')
            with assert_mock(self.terminal) as t:
                t.write('some-test ')
                no_more_calls(t)
        finally:
            commands.CreateObjCmd.current_obj = orig_current_object
            del creatable_models['some-test']

    @run_in_reactor
    def test_complete_positional_choice(self):
        self.oms_ssh.lineReceived('cd computes')

        self._tab_after('mk comp')
        with assert_mock(self.terminal) as t:
            t.write('ute ')
            no_more_calls(t)

        self._tab_after('comp')
        assert not self.terminal.method_calls

    @run_in_reactor
    def test_complete_container_symlink(self):
        computes = db.get_root()['oms_root']['computes']
        cid = computes.add(self.make_compute())
        transaction.commit()

        self._tab_after('cd /computes/%s' % cid)
        with assert_mock(self.terminal) as t:
            t.write('/')