summaryrefslogtreecommitdiff
path: root/tests/test_parsing.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_parsing.py')
-rw-r--r--tests/test_parsing.py183
1 files changed, 154 insertions, 29 deletions
diff --git a/tests/test_parsing.py b/tests/test_parsing.py
index 19237f6e..7b361b7e 100644
--- a/tests/test_parsing.py
+++ b/tests/test_parsing.py
@@ -16,7 +16,7 @@ from cmd2 import utils
def parser():
parser = StatementParser(
allow_redirection=True,
- terminators=[';'],
+ terminators=[';', '&'],
multiline_commands=['multiline'],
aliases={'helpalias': 'help',
'42': 'theanswer',
@@ -38,7 +38,13 @@ def test_parse_empty_string(parser):
('command /* with some comment */ arg', ['command', 'arg']),
('command arg1 arg2 # comment at the end', ['command', 'arg1', 'arg2']),
('42 arg1 arg2', ['theanswer', 'arg1', 'arg2']),
- ('l', ['shell', 'ls', '-al'])
+ ('l', ['shell', 'ls', '-al']),
+ ('termbare ; > /tmp/output', ['termbare', ';', '>', '/tmp/output']),
+ ('termbare; > /tmp/output', ['termbare', ';', '>', '/tmp/output']),
+ ('termbare & > /tmp/output', ['termbare', '&', '>', '/tmp/output']),
+ ('termbare& > /tmp/output', ['termbare', '&', '>', '/tmp/output']),
+ ('help|less', ['help', '|', 'less']),
+ ('l|less', ['shell', 'ls', '-al', '|', 'less']),
])
def test_tokenize(parser, line, tokens):
tokens_to_test = parser.tokenize(line)
@@ -46,7 +52,7 @@ def test_tokenize(parser, line, tokens):
def test_tokenize_unclosed_quotes(parser):
with pytest.raises(ValueError):
- tokens = parser.tokenize('command with "unclosed quotes')
+ _ = parser.tokenize('command with "unclosed quotes')
@pytest.mark.parametrize('tokens,command,args', [
([], None, None),
@@ -69,18 +75,28 @@ def test_parse_single_word(parser, line):
assert not statement.args
assert statement.argv == [utils.strip_quotes(line)]
-def test_parse_word_plus_terminator(parser):
- line = 'termbare;'
+@pytest.mark.parametrize('line,terminator', [
+ ('termbare;', ';'),
+ ('termbare ;', ';'),
+ ('termbare&', '&'),
+ ('termbare &', '&'),
+])
+def test_parse_word_plus_terminator(parser, line, terminator):
statement = parser.parse(line)
assert statement.command == 'termbare'
- assert statement.terminator == ';'
+ assert statement.terminator == terminator
assert statement.argv == ['termbare']
-def test_parse_suffix_after_terminator(parser):
- line = 'termbare; suffx'
+@pytest.mark.parametrize('line,terminator', [
+ ('termbare; suffx', ';'),
+ ('termbare ;suffx', ';'),
+ ('termbare& suffx', '&'),
+ ('termbare &suffx', '&'),
+])
+def test_parse_suffix_after_terminator(parser, line, terminator):
statement = parser.parse(line)
assert statement.command == 'termbare'
- assert statement.terminator == ';'
+ assert statement.terminator == terminator
assert statement.suffix == 'suffx'
assert statement.argv == ['termbare']
@@ -134,12 +150,16 @@ def test_parse_what_if_quoted_strings_seem_to_start_comments(parser):
assert not statement.pipe_to
assert statement.argv == ['what', 'if', 'quoted strings /* seem to ', 'start', 'comments?']
-def test_parse_simple_piped(parser):
- statement = parser.parse('simple | piped')
+@pytest.mark.parametrize('line',[
+ 'simple | piped',
+ 'simple|piped',
+])
+def test_parse_simple_pipe(parser, line):
+ statement = parser.parse(line)
assert statement.command == 'simple'
assert not statement.args
assert statement.argv == ['simple']
- assert statement.pipe_to == 'piped'
+ assert statement.pipe_to == ['piped']
def test_parse_double_pipe_is_not_a_pipe(parser):
line = 'double-pipe || is not a pipe'
@@ -150,16 +170,29 @@ def test_parse_double_pipe_is_not_a_pipe(parser):
assert not statement.pipe_to
def test_parse_complex_pipe(parser):
- line = 'command with args, terminator;sufx | piped'
+ line = 'command with args, terminator&sufx | piped'
statement = parser.parse(line)
assert statement.command == 'command'
assert statement.args == "with args, terminator"
assert statement.argv == ['command', 'with', 'args,', 'terminator']
- assert statement.terminator == ';'
+ assert statement.terminator == '&'
assert statement.suffix == 'sufx'
- assert statement.pipe_to == 'piped'
+ assert statement.pipe_to == ['piped']
+
+@pytest.mark.parametrize('line,output', [
+ ('help > out.txt', '>'),
+ ('help>out.txt', '>'),
+ ('help >> out.txt', '>>'),
+ ('help>>out.txt', '>>'),
+])
+def test_parse_redirect(parser,line, output):
+ statement = parser.parse(line)
+ assert statement.command == 'help'
+ assert not statement.args
+ assert statement.output == output
+ assert statement.output_to == 'out.txt'
-def test_parse_output_redirect(parser):
+def test_parse_redirect_with_args(parser):
line = 'output into > afile.txt'
statement = parser.parse(line)
assert statement.command == 'output'
@@ -168,7 +201,7 @@ def test_parse_output_redirect(parser):
assert statement.output == '>'
assert statement.output_to == 'afile.txt'
-def test_parse_output_redirect_with_dash_in_path(parser):
+def test_parse_redirect_with_dash_in_path(parser):
line = 'output into > python-cmd2/afile.txt'
statement = parser.parse(line)
assert statement.command == 'output'
@@ -177,7 +210,7 @@ def test_parse_output_redirect_with_dash_in_path(parser):
assert statement.output == '>'
assert statement.output_to == 'python-cmd2/afile.txt'
-def test_parse_output_redirect_append(parser):
+def test_parse_redirect_append(parser):
line = 'output appended to >> /tmp/afile.txt'
statement = parser.parse(line)
assert statement.command == 'output'
@@ -194,9 +227,9 @@ def test_parse_pipe_and_redirect(parser):
assert statement.argv == ['output', 'into']
assert statement.terminator == ';'
assert statement.suffix == 'sufx'
- assert statement.pipe_to == 'pipethrume plz'
- assert statement.output == '>'
- assert statement.output_to == 'afile.txt'
+ assert statement.pipe_to == ['pipethrume', 'plz', '>', 'afile.txt']
+ assert not statement.output
+ assert not statement.output_to
def test_parse_output_to_paste_buffer(parser):
line = 'output to paste buffer >> '
@@ -207,8 +240,9 @@ def test_parse_output_to_paste_buffer(parser):
assert statement.output == '>>'
def test_parse_redirect_inside_terminator(parser):
- """The terminator designates the end of the commmand/arguments portion. If a redirector
- occurs before a terminator, then it will be treated as part of the arguments and not as a redirector."""
+ """The terminator designates the end of the commmand/arguments portion.
+ If a redirector occurs before a terminator, then it will be treated as
+ part of the arguments and not as a redirector."""
line = 'has > inside;'
statement = parser.parse(line)
assert statement.command == 'has'
@@ -216,6 +250,23 @@ def test_parse_redirect_inside_terminator(parser):
assert statement.argv == ['has', '>', 'inside']
assert statement.terminator == ';'
+@pytest.mark.parametrize('line,terminator',[
+ ('multiline with | inside;', ';'),
+ ('multiline with | inside ;', ';'),
+ ('multiline with | inside;;;', ';'),
+ ('multiline with | inside;; ;;', ';'),
+ ('multiline with | inside&', '&'),
+ ('multiline with | inside &;', '&'),
+ ('multiline with | inside&&;', '&'),
+ ('multiline with | inside &; &;', '&'),
+])
+def test_parse_multiple_terminators(parser, line, terminator):
+ statement = parser.parse(line)
+ assert statement.multiline_command == 'multiline'
+ assert statement.args == 'with | inside'
+ assert statement.argv == ['multiline', 'with', '|', 'inside']
+ assert statement.terminator == terminator
+
def test_parse_unfinished_multiliine_command(parser):
line = 'multiline has > inside an unfinished command'
statement = parser.parse(line)
@@ -225,13 +276,19 @@ def test_parse_unfinished_multiliine_command(parser):
assert statement.argv == ['multiline', 'has', '>', 'inside', 'an', 'unfinished', 'command']
assert not statement.terminator
-def test_parse_multiline_command_ignores_redirectors_within_it(parser):
- line = 'multiline has > inside;'
+@pytest.mark.parametrize('line,terminator',[
+ ('multiline has > inside;', ';'),
+ ('multiline has > inside;;;', ';'),
+ ('multiline has > inside;; ;;', ';'),
+ ('multiline has > inside &', '&'),
+ ('multiline has > inside & &', '&'),
+])
+def test_parse_multiline_command_ignores_redirectors_within_it(parser, line, terminator):
statement = parser.parse(line)
assert statement.multiline_command == 'multiline'
assert statement.args == 'has > inside'
assert statement.argv == ['multiline', 'has', '>', 'inside']
- assert statement.terminator == ';'
+ assert statement.terminator == terminator
def test_parse_multiline_with_incomplete_comment(parser):
"""A terminator within a comment will be ignored and won't terminate a multiline command.
@@ -296,7 +353,7 @@ def test_parse_redirect_to_unicode_filename(parser):
def test_parse_unclosed_quotes(parser):
with pytest.raises(ValueError):
- tokens = parser.tokenize("command with 'unclosed quotes")
+ _ = parser.tokenize("command with 'unclosed quotes")
def test_empty_statement_raises_exception():
app = cmd2.Cmd()
@@ -315,12 +372,12 @@ def test_empty_statement_raises_exception():
('!ls -al /tmp', 'shell', 'ls -al /tmp'),
('l', 'shell', 'ls -al')
])
-def test_alias_and_shortcut_expansion(parser, line, command, args):
+def test_parse_alias_and_shortcut_expansion(parser, line, command, args):
statement = parser.parse(line)
assert statement.command == command
assert statement.args == args
-def test_alias_on_multiline_command(parser):
+def test_parse_alias_on_multiline_command(parser):
line = 'anothermultiline has > inside an unfinished command'
statement = parser.parse(line)
assert statement.multiline_command == 'multiline'
@@ -328,6 +385,43 @@ def test_alias_on_multiline_command(parser):
assert statement.args == 'has > inside an unfinished command'
assert not statement.terminator
+@pytest.mark.parametrize('line,output', [
+ ('helpalias > out.txt', '>'),
+ ('helpalias>out.txt', '>'),
+ ('helpalias >> out.txt', '>>'),
+ ('helpalias>>out.txt', '>>'),
+])
+def test_parse_alias_redirection(parser, line, output):
+ statement = parser.parse(line)
+ assert statement.command == 'help'
+ assert not statement.args
+ assert statement.output == output
+ assert statement.output_to == 'out.txt'
+
+@pytest.mark.parametrize('line', [
+ 'helpalias | less',
+ 'helpalias|less',
+])
+def test_parse_alias_pipe(parser, line):
+ statement = parser.parse(line)
+ assert statement.command == 'help'
+ assert not statement.args
+ assert statement.pipe_to == ['less']
+
+@pytest.mark.parametrize('line', [
+ 'helpalias;',
+ 'helpalias;;',
+ 'helpalias;; ;',
+ 'helpalias ;',
+ 'helpalias ; ;',
+ 'helpalias ;; ;',
+])
+def test_parse_alias_terminator_no_whitespace(parser, line):
+ statement = parser.parse(line)
+ assert statement.command == 'help'
+ assert not statement.args
+ assert statement.terminator == ';'
+
def test_parse_command_only_command_and_args(parser):
line = 'help history'
statement = parser.parse_command_only(line)
@@ -373,3 +467,34 @@ def test_parse_command_only_quoted_args(parser):
assert statement.command == 'shell'
assert statement.args == 'ls -al "/tmp/directory with spaces/doit.sh"'
assert statement.command_and_args == line.replace('l', 'shell ls -al')
+
+@pytest.mark.parametrize('line', [
+ 'helpalias > out.txt',
+ 'helpalias>out.txt',
+ 'helpalias >> out.txt',
+ 'helpalias>>out.txt',
+ 'help|less',
+ 'helpalias;',
+ 'help ;;',
+ 'help; ;;',
+])
+def test_parse_command_only_specialchars(parser, line):
+ statement = parser.parse_command_only(line)
+ assert statement.command == 'help'
+
+@pytest.mark.parametrize('line', [
+ ';',
+ ';;',
+ ';; ;',
+ '&',
+ '& &',
+ ' && &',
+ '>',
+ "'",
+ '"',
+ '|',
+])
+def test_parse_command_only_none(parser, line):
+ statement = parser.parse_command_only(line)
+ assert statement.command == None
+ assert statement.args == None