diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_parsing.py | 95 | ||||
-rw-r--r-- | tests/test_plugin.py | 471 |
2 files changed, 550 insertions, 16 deletions
diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 59f9a610..0865b6f6 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -30,6 +30,7 @@ def test_parse_empty_string(parser): statement = parser.parse('') assert not statement.command assert not statement.args + assert statement == '' assert statement.raw == '' @pytest.mark.parametrize('line,tokens', [ @@ -71,7 +72,8 @@ def test_command_and_args(parser, tokens, command, args): def test_parse_single_word(parser, line): statement = parser.parse(line) assert statement.command == line - assert not statement.args + assert statement.args is None + assert statement == '' assert statement.argv == [utils.strip_quotes(line)] @pytest.mark.parametrize('line,terminator', [ @@ -83,8 +85,10 @@ def test_parse_single_word(parser, line): def test_parse_word_plus_terminator(parser, line, terminator): statement = parser.parse(line) assert statement.command == 'termbare' - assert statement.terminator == terminator + assert statement.args is None + assert statement == '' assert statement.argv == ['termbare'] + assert statement.terminator == terminator @pytest.mark.parametrize('line,terminator', [ ('termbare; suffx', ';'), @@ -95,15 +99,18 @@ def test_parse_word_plus_terminator(parser, line, terminator): def test_parse_suffix_after_terminator(parser, line, terminator): statement = parser.parse(line) assert statement.command == 'termbare' + assert statement.args is None + assert statement == '' + assert statement.argv == ['termbare'] assert statement.terminator == terminator assert statement.suffix == 'suffx' - assert statement.argv == ['termbare'] def test_parse_command_with_args(parser): line = 'command with args' statement = parser.parse(line) assert statement.command == 'command' assert statement.args == 'with args' + assert statement == statement.args assert statement.argv == ['command', 'with', 'args'] def test_parse_command_with_quoted_args(parser): @@ -111,6 +118,7 @@ def test_parse_command_with_quoted_args(parser): statement = parser.parse(line) assert statement.command == 'command' assert statement.args == 'with "quoted args" and "some not"' + assert statement == statement.args assert statement.argv == ['command', 'with', 'quoted args', 'and', 'some not'] def test_parse_command_with_args_terminator_and_suffix(parser): @@ -118,22 +126,25 @@ def test_parse_command_with_args_terminator_and_suffix(parser): statement = parser.parse(line) assert statement.command == 'command' assert statement.args == "with args and terminator" + assert statement.argv == ['command', 'with', 'args', 'and', 'terminator'] + assert statement == statement.args assert statement.terminator == ';' assert statement.suffix == 'and suffix' - assert statement.argv == ['command', 'with', 'args', 'and', 'terminator'] def test_parse_hashcomment(parser): statement = parser.parse('hi # this is all a comment') assert statement.command == 'hi' - assert not statement.args + assert statement.args is None + assert statement == '' assert statement.argv == ['hi'] def test_parse_c_comment(parser): statement = parser.parse('hi /* this is | all a comment */') assert statement.command == 'hi' - assert not statement.args - assert not statement.pipe_to + assert statement.args is None assert statement.argv == ['hi'] + assert statement == '' + assert not statement.pipe_to def test_parse_c_comment_empty(parser): statement = parser.parse('/* this is | all a comment */') @@ -141,13 +152,15 @@ def test_parse_c_comment_empty(parser): assert not statement.args assert not statement.pipe_to assert not statement.argv + assert statement == '' def test_parse_what_if_quoted_strings_seem_to_start_comments(parser): statement = parser.parse('what if "quoted strings /* seem to " start comments?') assert statement.command == 'what' assert statement.args == 'if "quoted strings /* seem to " start comments?' - assert not statement.pipe_to assert statement.argv == ['what', 'if', 'quoted strings /* seem to ', 'start', 'comments?'] + assert statement == statement.args + assert not statement.pipe_to @pytest.mark.parametrize('line',[ 'simple | piped', @@ -156,7 +169,8 @@ def test_parse_what_if_quoted_strings_seem_to_start_comments(parser): def test_parse_simple_pipe(parser, line): statement = parser.parse(line) assert statement.command == 'simple' - assert not statement.args + assert statement.args is None + assert statement == '' assert statement.argv == ['simple'] assert statement.pipe_to == ['piped'] @@ -165,6 +179,7 @@ def test_parse_double_pipe_is_not_a_pipe(parser): statement = parser.parse(line) assert statement.command == 'double-pipe' assert statement.args == '|| is not a pipe' + assert statement == statement.args assert statement.argv == ['double-pipe', '||', 'is', 'not', 'a', 'pipe'] assert not statement.pipe_to @@ -174,6 +189,7 @@ def test_parse_complex_pipe(parser): assert statement.command == 'command' assert statement.args == "with args, terminator" assert statement.argv == ['command', 'with', 'args,', 'terminator'] + assert statement == statement.args assert statement.terminator == '&' assert statement.suffix == 'sufx' assert statement.pipe_to == ['piped'] @@ -187,7 +203,8 @@ def test_parse_complex_pipe(parser): def test_parse_redirect(parser,line, output): statement = parser.parse(line) assert statement.command == 'help' - assert not statement.args + assert statement.args is None + assert statement == '' assert statement.output == output assert statement.output_to == 'out.txt' @@ -196,6 +213,7 @@ def test_parse_redirect_with_args(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'into' + assert statement == statement.args assert statement.argv == ['output', 'into'] assert statement.output == '>' assert statement.output_to == 'afile.txt' @@ -205,6 +223,7 @@ def test_parse_redirect_with_dash_in_path(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'into' + assert statement == statement.args assert statement.argv == ['output', 'into'] assert statement.output == '>' assert statement.output_to == 'python-cmd2/afile.txt' @@ -214,6 +233,7 @@ def test_parse_redirect_append(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'appended to' + assert statement == statement.args assert statement.argv == ['output', 'appended', 'to'] assert statement.output == '>>' assert statement.output_to == '/tmp/afile.txt' @@ -223,6 +243,7 @@ def test_parse_pipe_and_redirect(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'into' + assert statement == statement.args assert statement.argv == ['output', 'into'] assert statement.terminator == ';' assert statement.suffix == 'sufx' @@ -235,6 +256,7 @@ def test_parse_output_to_paste_buffer(parser): statement = parser.parse(line) assert statement.command == 'output' assert statement.args == 'to paste buffer' + assert statement == statement.args assert statement.argv == ['output', 'to', 'paste', 'buffer'] assert statement.output == '>>' @@ -246,6 +268,7 @@ def test_parse_redirect_inside_terminator(parser): statement = parser.parse(line) assert statement.command == 'has' assert statement.args == '> inside' + assert statement == statement.args assert statement.argv == ['has', '>', 'inside'] assert statement.terminator == ';' @@ -263,6 +286,7 @@ def test_parse_multiple_terminators(parser, line, terminator): statement = parser.parse(line) assert statement.multiline_command == 'multiline' assert statement.args == 'with | inside' + assert statement == statement.args assert statement.argv == ['multiline', 'with', '|', 'inside'] assert statement.terminator == terminator @@ -272,6 +296,7 @@ def test_parse_unfinished_multiliine_command(parser): assert statement.multiline_command == 'multiline' assert statement.command == 'multiline' assert statement.args == 'has > inside an unfinished command' + assert statement == statement.args assert statement.argv == ['multiline', 'has', '>', 'inside', 'an', 'unfinished', 'command'] assert not statement.terminator @@ -286,6 +311,7 @@ def test_parse_multiline_command_ignores_redirectors_within_it(parser, line, ter statement = parser.parse(line) assert statement.multiline_command == 'multiline' assert statement.args == 'has > inside' + assert statement == statement.args assert statement.argv == ['multiline', 'has', '>', 'inside'] assert statement.terminator == terminator @@ -297,6 +323,7 @@ def test_parse_multiline_with_incomplete_comment(parser): assert statement.multiline_command == 'multiline' assert statement.command == 'multiline' assert statement.args == 'command' + assert statement == statement.args assert statement.argv == ['multiline', 'command'] assert not statement.terminator @@ -306,6 +333,7 @@ def test_parse_multiline_with_complete_comment(parser): assert statement.multiline_command == 'multiline' assert statement.command == 'multiline' assert statement.args == 'command is done' + assert statement == statement.args assert statement.argv == ['multiline', 'command', 'is', 'done'] assert statement.terminator == ';' @@ -315,6 +343,7 @@ def test_parse_multiline_termninated_by_empty_line(parser): assert statement.multiline_command == 'multiline' assert statement.command == 'multiline' assert statement.args == 'command ends' + assert statement == statement.args assert statement.argv == ['multiline', 'command', 'ends'] assert statement.terminator == '\n' @@ -324,6 +353,7 @@ def test_parse_multiline_ignores_terminators_in_comments(parser): assert statement.multiline_command == 'multiline' assert statement.command == 'multiline' assert statement.args == 'command "with term; ends" now' + assert statement == statement.args assert statement.argv == ['multiline', 'command', 'with term; ends', 'now'] assert statement.terminator == '\n' @@ -332,6 +362,7 @@ def test_parse_command_with_unicode_args(parser): statement = parser.parse(line) assert statement.command == 'drink' assert statement.args == 'café' + assert statement == statement.args assert statement.argv == ['drink', 'café'] def test_parse_unicode_command(parser): @@ -339,6 +370,7 @@ def test_parse_unicode_command(parser): statement = parser.parse(line) assert statement.command == 'café' assert statement.args == 'au lait' + assert statement == statement.args assert statement.argv == ['café', 'au', 'lait'] def test_parse_redirect_to_unicode_filename(parser): @@ -346,6 +378,7 @@ def test_parse_redirect_to_unicode_filename(parser): statement = parser.parse(line) assert statement.command == 'dir' assert statement.args == 'home' + assert statement == statement.args assert statement.argv == ['dir', 'home'] assert statement.output == '>' assert statement.output_to == 'café' @@ -375,6 +408,10 @@ def test_parse_alias_and_shortcut_expansion(parser, line, command, args): statement = parser.parse(line) assert statement.command == command assert statement.args == args + if statement.args is None: + assert statement == '' + else: + assert statement == statement.args def test_parse_alias_on_multiline_command(parser): line = 'anothermultiline has > inside an unfinished command' @@ -382,6 +419,7 @@ def test_parse_alias_on_multiline_command(parser): assert statement.multiline_command == 'multiline' assert statement.command == 'multiline' assert statement.args == 'has > inside an unfinished command' + assert statement == statement.args assert not statement.terminator @pytest.mark.parametrize('line,output', [ @@ -393,7 +431,8 @@ def test_parse_alias_on_multiline_command(parser): def test_parse_alias_redirection(parser, line, output): statement = parser.parse(line) assert statement.command == 'help' - assert not statement.args + assert statement.args is None + assert statement == '' assert statement.output == output assert statement.output_to == 'out.txt' @@ -404,7 +443,8 @@ def test_parse_alias_redirection(parser, line, output): def test_parse_alias_pipe(parser, line): statement = parser.parse(line) assert statement.command == 'help' - assert not statement.args + assert statement.args is None + assert statement == '' assert statement.pipe_to == ['less'] @pytest.mark.parametrize('line', [ @@ -418,7 +458,8 @@ def test_parse_alias_pipe(parser, line): def test_parse_alias_terminator_no_whitespace(parser, line): statement = parser.parse(line) assert statement.command == 'help' - assert not statement.args + assert statement.args is None + assert statement == '' assert statement.terminator == ';' def test_parse_command_only_command_and_args(parser): @@ -426,6 +467,7 @@ def test_parse_command_only_command_and_args(parser): statement = parser.parse_command_only(line) assert statement.command == 'help' assert statement.args == 'history' + assert statement == statement.args assert statement.command_and_args == line def test_parse_command_only_emptyline(parser): @@ -434,9 +476,9 @@ def test_parse_command_only_emptyline(parser): # statement is a subclass of str(), the value of the str # should be '', to retain backwards compatibility with # the cmd in the standard library - assert statement == '' assert statement.command is None assert statement.args is None + assert statement == '' assert not statement.argv assert statement.command_and_args == None @@ -445,6 +487,7 @@ def test_parse_command_only_strips_line(parser): statement = parser.parse_command_only(line) assert statement.command == 'help' assert statement.args == 'history' + assert statement == statement.args assert statement.command_and_args == line.strip() def test_parse_command_only_expands_alias(parser): @@ -452,12 +495,14 @@ def test_parse_command_only_expands_alias(parser): statement = parser.parse_command_only(line) assert statement.command == 'pyscript' assert statement.args == 'foobar.py' + assert statement == statement.args def test_parse_command_only_expands_shortcuts(parser): line = '!cat foobar.txt' statement = parser.parse_command_only(line) assert statement.command == 'shell' assert statement.args == 'cat foobar.txt' + assert statement == statement.args assert statement.command_and_args == 'shell cat foobar.txt' def test_parse_command_only_quoted_args(parser): @@ -465,6 +510,7 @@ def test_parse_command_only_quoted_args(parser): statement = parser.parse_command_only(line) assert statement.command == 'shell' assert statement.args == 'ls -al "/tmp/directory with spaces/doit.sh"' + assert statement == statement.args assert statement.command_and_args == line.replace('l', 'shell ls -al') @pytest.mark.parametrize('line', [ @@ -495,5 +541,22 @@ def test_parse_command_only_specialchars(parser, line): ]) def test_parse_command_only_none(parser, line): statement = parser.parse_command_only(line) - assert statement.command == None - assert statement.args == None + assert statement.command is None + assert statement.args is None + assert statement == '' + +def test_statement_initialization(parser): + string = 'alias' + statement = cmd2.Statement(string) + assert string == statement + assert statement.raw is None + assert statement.command is None + assert statement.args is None + assert isinstance(statement.argv, list) + assert not statement.argv + assert statement.multiline_command is None + assert statement.terminator is None + assert statement.suffix is None + assert statement.pipe_to is None + assert statement.output is None + assert statement.output_to is None diff --git a/tests/test_plugin.py b/tests/test_plugin.py new file mode 100644 index 00000000..d4d6166e --- /dev/null +++ b/tests/test_plugin.py @@ -0,0 +1,471 @@ +# coding=utf-8 +""" +Test plugin infrastructure and hooks. + +Copyright 2018 Jared Crapo <jared@kotfu.net> +Released under MIT license, see LICENSE file +""" + +from typing import Tuple + +import pytest + +import cmd2 +from cmd2 import plugin + +from .conftest import StdOut + +class Plugin: + "A mixin class for testing hook registration and calling" + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.reset_counters() + + def reset_counters(self): + self.called_postparsing = 0 + self.called_precmd = 0 + + ### + # + # preloop and postloop hooks + # which share the same signature and are thus interchangable + # + ### + def prepost_hook_one(self) -> None: + "Method used for preloop or postloop hooks" + self.poutput("one") + + def prepost_hook_two(self) -> None: + "Another method used for preloop or postloop hooks" + self.poutput("two") + + def prepost_hook_too_many_parameters(self, param) -> None: + "A preloop or postloop hook with too many parameters" + pass + + def prepost_hook_with_wrong_return_type(self) -> bool: + "A preloop or postloop hook with incorrect return type" + pass + + ### + # + # Postparsing hooks + # + ### + def postparse_hook(self, statement: cmd2.Statement) -> Tuple[bool, cmd2.Statement]: + "A postparsing hook" + self.called_postparsing += 1 + return False, statement + + def postparse_hook_stop(self, statement: cmd2.Statement) -> Tuple[bool, cmd2.Statement]: + "A postparsing hook with requests application exit" + self.called_postparsing += 1 + return True, statement + + def postparse_hook_emptystatement(self, statement: cmd2.Statement) -> Tuple[bool, cmd2.Statement]: + "A postparsing hook with raises an EmptyStatement exception" + self.called_postparsing += 1 + raise cmd2.EmptyStatement + + def postparse_hook_exception(self, statement: cmd2.Statement) -> Tuple[bool, cmd2.Statement]: + "A postparsing hook which raises an exception" + self.called_postparsing += 1 + raise ValueError + + ### + # + # precommand hooks, some valid, some invalid + # + ### + def precmd(self, statement: cmd2.Statement) -> cmd2.Statement: + "Override cmd.Cmd method" + self.called_precmd += 1 + return statement + + def precmd_hook(self, data: plugin.PrecommandData) -> plugin.PrecommandData: + "A precommand hook" + self.called_precmd += 1 + return data + + def precmd_hook_emptystatement(self, data: plugin.PrecommandData) -> plugin.PrecommandData: + "A precommand hook which raises an EmptyStatement exception" + self.called_precmd += 1 + raise cmd2.EmptyStatement + + def precmd_hook_exception(self, data: plugin.PrecommandData) -> plugin.PrecommandData: + "A precommand hook which raises an exception" + self.called_precmd += 1 + raise ValueError + + def precmd_hook_not_enough_parameters(self) -> plugin.PrecommandData: + "A precommand hook with no parameters" + pass + + def precmd_hook_too_many_parameters(self, one: plugin.PrecommandData, two: str) -> plugin.PrecommandData: + "A precommand hook with too many parameters" + return one + + def precmd_hook_no_parameter_type(self, mydat) -> plugin.PrecommandData: + "A precommand hook with no type annotation on the parameter" + return mydat + + def precmd_hook_wrong_parameter_type(self, mydat: str) -> plugin.PrecommandData: + "A precommand hook with the incorrect type annotation on the parameter" + return mydat + + def precmd_hook_no_return_type(self, mydat: plugin.PrecommandData): + "A precommand hook with no type annotation on the return value" + return mydat + + def precmd_hook_wrong_return_type(self, mydat: plugin.PrecommandData) -> cmd2.Statement: + return self.statement_parser.parse('hi there') + + +class PluggedApp(Plugin, cmd2.Cmd): + "A sample app with a plugin mixed in" + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def do_say(self, statement): + """Repeat back the arguments""" + self.poutput(statement) + +### +# +# test pre and postloop hooks +# +### +def test_register_preloop_hook_too_many_parameters(): + app = PluggedApp() + with pytest.raises(TypeError): + app.register_preloop_hook(app.prepost_hook_too_many_parameters) + +def test_register_preloop_hook_with_return_type(): + app = PluggedApp() + with pytest.raises(TypeError): + app.register_preloop_hook(app.prepost_hook_with_wrong_return_type) + +def test_preloop_hook(capsys): + app = PluggedApp() + app.register_preloop_hook(app.prepost_hook_one) + app.cmdqueue.append('say hello') + app.cmdqueue.append('quit') + app.cmdloop() + out, err = capsys.readouterr() + assert out == 'one\nhello\n' + assert not err + +def test_preloop_hooks(capsys): + app = PluggedApp() + app.register_preloop_hook(app.prepost_hook_one) + app.register_preloop_hook(app.prepost_hook_two) + app.cmdqueue.append('say hello') + app.cmdqueue.append('quit') + app.cmdloop() + out, err = capsys.readouterr() + assert out == 'one\ntwo\nhello\n' + assert not err + +def test_register_postloop_hook_too_many_parameters(): + app = PluggedApp() + with pytest.raises(TypeError): + app.register_postloop_hook(app.prepost_hook_too_many_parameters) + +def test_register_postloop_hook_with_wrong_return_type(): + app = PluggedApp() + with pytest.raises(TypeError): + app.register_postloop_hook(app.prepost_hook_with_wrong_return_type) + +def test_postloop_hook(capsys): + app = PluggedApp() + app.register_postloop_hook(app.prepost_hook_one) + app.cmdqueue.append('say hello') + app.cmdqueue.append('quit') + app.cmdloop() + out, err = capsys.readouterr() + assert out == 'hello\none\n' + assert not err + +def test_postloop_hooks(capsys): + app = PluggedApp() + app.register_postloop_hook(app.prepost_hook_one) + app.register_postloop_hook(app.prepost_hook_two) + app.cmdqueue.append('say hello') + app.cmdqueue.append('quit') + app.cmdloop() + out, err = capsys.readouterr() + assert out == 'hello\none\ntwo\n' + assert not err + +### +# +# test postparsing hooks +# +### +def test_postparsing_hook(capsys): + app = PluggedApp() + app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert out == 'hello\n' + assert not err + assert not app.called_postparsing + + app.reset_counters() + app.register_postparsing_hook(app.postparse_hook) + app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert out == 'hello\n' + assert not err + assert app.called_postparsing == 1 + + # register the function again, so it should be called twice + app.reset_counters() + app.register_postparsing_hook(app.postparse_hook) + app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert out == 'hello\n' + assert not err + assert app.called_postparsing == 2 + +def test_postparsing_hook_stop_first(capsys): + app = PluggedApp() + app.register_postparsing_hook(app.postparse_hook_stop) + stop = app.onecmd_plus_hooks('say hello') + assert app.called_postparsing == 1 + assert stop + + # register another function but it shouldn't be called + app.reset_counters() + app.register_postparsing_hook(app.postparse_hook) + stop = app.onecmd_plus_hooks('say hello') + assert app.called_postparsing == 1 + assert stop + +def test_postparsing_hook_stop_second(capsys): + app = PluggedApp() + app.register_postparsing_hook(app.postparse_hook) + stop = app.onecmd_plus_hooks('say hello') + assert app.called_postparsing == 1 + assert not stop + + # register another function and make sure it gets called + app.reset_counters() + app.register_postparsing_hook(app.postparse_hook_stop) + stop = app.onecmd_plus_hooks('say hello') + assert app.called_postparsing == 2 + assert stop + + # register a third function which shouldn't be called + app.reset_counters() + app.register_postparsing_hook(app.postparse_hook) + stop = app.onecmd_plus_hooks('say hello') + assert app.called_postparsing == 2 + assert stop + +def test_postparsing_hook_emptystatement_first(capsys): + app = PluggedApp() + app.register_postparsing_hook(app.postparse_hook_emptystatement) + stop = app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert not err + assert app.called_postparsing == 1 + + # register another function but it shouldn't be called + app.reset_counters() + stop = app.register_postparsing_hook(app.postparse_hook) + app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert not err + assert app.called_postparsing == 1 + +def test_postparsing_hook_emptystatement_second(capsys): + app = PluggedApp() + app.register_postparsing_hook(app.postparse_hook) + stop = app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert out == 'hello\n' + assert not err + assert app.called_postparsing == 1 + + # register another function and make sure it gets called + app.reset_counters() + app.register_postparsing_hook(app.postparse_hook_emptystatement) + stop = app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert not err + assert app.called_postparsing == 2 + + # register a third function which shouldn't be called + app.reset_counters() + app.register_postparsing_hook(app.postparse_hook) + stop = app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert not err + assert app.called_postparsing == 2 + +def test_postparsing_hook_exception(capsys): + app = PluggedApp() + app.register_postparsing_hook(app.postparse_hook_exception) + stop = app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert err + assert app.called_postparsing == 1 + + # register another function, but it shouldn't be called + app.reset_counters() + stop = app.register_postparsing_hook(app.postparse_hook) + app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert err + assert app.called_postparsing == 1 + +### +# +# test precmd hooks +# +##### +def test_register_precmd_hook_parameter_count(): + app = PluggedApp() + with pytest.raises(TypeError): + app.register_precmd_hook(app.precmd_hook_not_enough_parameters) + with pytest.raises(TypeError): + app.register_precmd_hook(app.precmd_hook_too_many_parameters) + +def test_register_precmd_hook_no_parameter_annotation(): + app = PluggedApp() + with pytest.raises(TypeError): + app.register_precmd_hook(app.precmd_hook_no_parameter_type) + +def test_register_precmd_hook_wrong_parameter_annotation(): + app = PluggedApp() + with pytest.raises(TypeError): + app.register_precmd_hook(app.precmd_hook_wrong_parameter_type) + +def test_register_precmd_hook_no_return_annotation(): + app = PluggedApp() + with pytest.raises(TypeError): + app.register_precmd_hook(app.precmd_hook_no_return_type) + +def test_register_precmd_hook_wrong_return_annotation(): + app = PluggedApp() + with pytest.raises(TypeError): + app.register_precmd_hook(app.precmd_hook_wrong_return_type) + +def test_precmd_hook(capsys): + app = PluggedApp() + app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert out == 'hello\n' + assert not err + # without registering any hooks, precmd() should be called + assert app.called_precmd == 1 + + app.reset_counters() + app.register_precmd_hook(app.precmd_hook) + app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert out == 'hello\n' + assert not err + # with one hook registered, we should get precmd() and the hook + assert app.called_precmd == 2 + + # register the function again, so it should be called twice + app.reset_counters() + app.register_precmd_hook(app.precmd_hook) + app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert out == 'hello\n' + assert not err + # with two hooks registered, we should get precmd() and both hooks + assert app.called_precmd == 3 + +def test_precmd_hook_emptystatement_first(capsys): + app = PluggedApp() + app.register_precmd_hook(app.precmd_hook_emptystatement) + stop = app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert not err + # since the registered hooks are called before precmd(), if a registered + # hook throws an exception, precmd() is never called + assert app.called_precmd == 1 + + # register another function but it shouldn't be called + app.reset_counters() + stop = app.register_precmd_hook(app.precmd_hook) + app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert not err + # the exception raised by the first hook should prevent the second + # hook from being called, and it also prevents precmd() from being + # called + assert app.called_precmd == 1 + +def test_precmd_hook_emptystatement_second(capsys): + app = PluggedApp() + app.register_precmd_hook(app.precmd_hook) + stop = app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert out == 'hello\n' + assert not err + # with one hook registered, we should get precmd() and the hook + assert app.called_precmd == 2 + + # register another function and make sure it gets called + app.reset_counters() + app.register_precmd_hook(app.precmd_hook_emptystatement) + stop = app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert not err + # since the registered hooks are called before precmd(), if a registered + # hook throws an exception, precmd() is never called + assert app.called_precmd == 2 + + # register a third function which shouldn't be called + app.reset_counters() + app.register_precmd_hook(app.precmd_hook) + stop = app.onecmd_plus_hooks('say hello') + out, err = capsys.readouterr() + assert not stop + assert not out + assert not err + # the exception raised by the second hook should prevent the third + # hook from being called. since the registered hooks are called before precmd(), + # if a registered hook throws an exception, precmd() is never called + assert app.called_precmd == 2 + +### +# +# test postcmd hooks +# +#### +def test_postcmd(capsys): + pass + +## +# +# command finalization +# +### +def test_cmdfinalization(capsys): + pass + |