| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- import pytest
- from openhands.runtime.utils.bash import split_bash_commands
- def test_split_commands_util():
- cmds = [
- 'ls -l',
- 'echo -e "hello\nworld"',
- """
- echo -e "hello it\\'s me"
- """.strip(),
- """
- echo \\
- -e 'hello' \\
- -v
- """.strip(),
- """
- echo -e 'hello\\nworld\\nare\\nyou\\nthere?'
- """.strip(),
- """
- echo -e 'hello
- world
- are
- you\\n
- there?'
- """.strip(),
- """
- echo -e 'hello
- world "
- '
- """.strip(),
- """
- kubectl apply -f - <<EOF
- apiVersion: v1
- kind: Pod
- metadata:
- name: busybox-sleep
- spec:
- containers:
- - name: busybox
- image: busybox:1.28
- args:
- - sleep
- - "1000000"
- EOF
- """.strip(),
- """
- mkdir -p _modules && \
- for month in {01..04}; do
- for day in {01..05}; do
- touch "_modules/2024-${month}-${day}-sample.md"
- done
- done
- """.strip(),
- ]
- joined_cmds = '\n'.join(cmds)
- split_cmds = split_bash_commands(joined_cmds)
- for s in split_cmds:
- print('\nCMD')
- print(s)
- for i in range(len(cmds)):
- assert (
- split_cmds[i].strip() == cmds[i].strip()
- ), f'At index {i}: {split_cmds[i]} != {cmds[i]}.'
- @pytest.mark.parametrize(
- 'input_command, expected_output',
- [
- ('ls -l', ['ls -l']),
- ("echo 'Hello, world!'", ["echo 'Hello, world!'"]),
- ('cd /tmp && touch test.txt', ['cd /tmp && touch test.txt']),
- ("echo -e 'line1\\nline2\\nline3'", ["echo -e 'line1\\nline2\\nline3'"]),
- (
- "grep 'pattern' file.txt | sort | uniq",
- ["grep 'pattern' file.txt | sort | uniq"],
- ),
- ('for i in {1..5}; do echo $i; done', ['for i in {1..5}; do echo $i; done']),
- (
- "echo 'Single quotes don\\'t escape'",
- ["echo 'Single quotes don\\'t escape'"],
- ),
- (
- 'echo "Double quotes \\"do\\" escape"',
- ['echo "Double quotes \\"do\\" escape"'],
- ),
- ],
- )
- def test_single_commands(input_command, expected_output):
- assert split_bash_commands(input_command) == expected_output
- def test_heredoc():
- input_commands = """
- cat <<EOF
- multiline
- text
- EOF
- echo "Done"
- """
- expected_output = ['cat <<EOF\nmultiline\ntext\nEOF', 'echo "Done"']
- assert split_bash_commands(input_commands) == expected_output
- def test_backslash_continuation():
- input_commands = """
- echo "This is a long \
- command that spans \
- multiple lines"
- echo "Next command"
- """
- expected_output = [
- 'echo "This is a long command that spans multiple lines"',
- 'echo "Next command"',
- ]
- assert split_bash_commands(input_commands) == expected_output
- def test_comments():
- input_commands = """
- echo "Hello" # This is a comment
- # This is another comment
- ls -l
- """
- expected_output = [
- 'echo "Hello" # This is a comment\n# This is another comment',
- 'ls -l',
- ]
- assert split_bash_commands(input_commands) == expected_output
- def test_complex_quoting():
- input_commands = """
- echo "This is a \\"quoted\\" string"
- echo 'This is a '\''single-quoted'\'' string'
- echo "Mixed 'quotes' in \\"double quotes\\""
- """
- expected_output = [
- 'echo "This is a \\"quoted\\" string"',
- "echo 'This is a '''single-quoted''' string'",
- 'echo "Mixed \'quotes\' in \\"double quotes\\""',
- ]
- assert split_bash_commands(input_commands) == expected_output
- def test_invalid_syntax():
- invalid_inputs = [
- 'echo "Unclosed quote',
- "echo 'Unclosed quote",
- 'cat <<EOF\nUnclosed heredoc',
- ]
- for input_command in invalid_inputs:
- # it will fall back to return the original input
- assert split_bash_commands(input_command) == [input_command]
- @pytest.fixture
- def sample_commands():
- return [
- 'ls -l',
- 'echo "Hello, world!"',
- 'cd /tmp && touch test.txt',
- 'echo -e "line1\\nline2\\nline3"',
- 'grep "pattern" file.txt | sort | uniq',
- 'for i in {1..5}; do echo $i; done',
- 'cat <<EOF\nmultiline\ntext\nEOF',
- 'echo "Escaped \\"quotes\\""',
- "echo 'Single quotes don\\'t escape'",
- 'echo "Command with a trailing backslash \\\n and continuation"',
- ]
- def test_split_single_commands(sample_commands):
- for cmd in sample_commands:
- result = split_bash_commands(cmd)
- assert len(result) == 1, f'Expected single command, got: {result}'
- def test_split_commands_with_heredoc():
- input_commands = """
- cat <<EOF
- multiline
- text
- EOF
- echo "Done"
- """
- expected_output = ['cat <<EOF\nmultiline\ntext\nEOF', 'echo "Done"']
- result = split_bash_commands(input_commands)
- assert result == expected_output, f'Expected {expected_output}, got {result}'
- def test_split_commands_with_backslash_continuation():
- input_commands = """
- echo "This is a long \
- command that spans \
- multiple lines"
- echo "Next command"
- """
- expected_output = [
- 'echo "This is a long command that spans multiple lines"',
- 'echo "Next command"',
- ]
- result = split_bash_commands(input_commands)
- assert result == expected_output, f'Expected {expected_output}, got {result}'
- def test_split_commands_with_empty_lines():
- input_commands = """
- ls -l
- echo "Hello"
- cd /tmp
- """
- expected_output = ['ls -l', 'echo "Hello"', 'cd /tmp']
- result = split_bash_commands(input_commands)
- assert result == expected_output, f'Expected {expected_output}, got {result}'
- def test_split_commands_with_comments():
- input_commands = """
- echo "Hello" # This is a comment
- # This is another comment
- ls -l
- """
- expected_output = [
- 'echo "Hello" # This is a comment\n# This is another comment',
- 'ls -l',
- ]
- result = split_bash_commands(input_commands)
- assert result == expected_output, f'Expected {expected_output}, got {result}'
- def test_split_commands_with_complex_quoting():
- input_commands = """
- echo "This is a \\"quoted\\" string"
- echo "Mixed 'quotes' in \\"double quotes\\""
- """
- # echo 'This is a '\''single-quoted'\'' string'
- expected_output = [
- 'echo "This is a \\"quoted\\" string"',
- 'echo "Mixed \'quotes\' in \\"double quotes\\""',
- ]
- # "echo 'This is a '\\''single-quoted'\\'' string'",
- result = split_bash_commands(input_commands)
- assert result == expected_output, f'Expected {expected_output}, got {result}'
- def test_split_commands_with_invalid_input():
- invalid_inputs = [
- 'echo "Unclosed quote',
- "echo 'Unclosed quote",
- 'cat <<EOF\nUnclosed heredoc',
- ]
- for input_command in invalid_inputs:
- # it will fall back to return the original input
- assert split_bash_commands(input_command) == [input_command]
|