def test_full_command_is_shown_only_in_debug_output_level(self): """Test that sh() will show full bash script only in case, when '-rl debug' is used :return: """ task = InitTask() task._io = IO() io = IO() out = StringIO() with io.capture_descriptors(stream=out, enable_standard_out=False): # CASE 1 with self.subTest('NORMAL output level'): try: task.sh('python3 -m rkd :sh -c "exit 5"') except subprocess.CalledProcessError as e: self.assertIn( "Command 'exit 5' returned non-zero exit status 5.", e.output) # CASE 2 with self.subTest('DEBUG output level'): try: task.sh('python3 -m rkd -rl debug :sh -c "exit 5"') except subprocess.CalledProcessError as e: self.assertIn( "Command '#!/bin/bash -eopipefail \r\nset -euo pipefail;" + " exit 5' returned non-zero exit status 5.", e.output)
def test_sh_captures_output_in_correct_order_with_various_timing(self): """Test if output is containing stdout and stderr lines mixed in proper order (as it is defined in shell script) Notice: Test is interacting with shell, to reduce possibility of weird behavior it is retried multiple times """ for i in range(1, 100): self.maxDiff = None # unittest setting task = InitTask() task._io = IO() io = IO() out = StringIO() with io.capture_descriptors(stream=out, enable_standard_out=False): task.sh(''' set +e; sleep 0.05; echo "FIRST"; sleep 0.05; echo "SECOND" >&2; echo "THIRD"; echo "FOURTH" >&2; echo "FIFTH" >&2; echo "SIXTH"; echo "SEVENTH" >&2; echo "NINETH"; echo "TENTH"; ''') self.assertEqual( "FIRST\r\nSECOND\r\nTHIRD\r\nFOURTH\r\nFIFTH\r\nSIXTH\r\nSEVENTH\r\nNINETH\r\nTENTH\r\n", out.getvalue())
def test_sh_rkd_in_rkd_shows_first_lines_on_error(self): """Bugfix: sh() was loosing first line(s) of output, when exception was raised Notice: Test is interacting with shell, to reduce possibility of weird behavior it is retried multiple times """ for i in range(1, 5): for std_redirect in ['', '>&2']: task = InitTask() task._io = IO() io = IO() out = StringIO() with io.capture_descriptors(stream=out, enable_standard_out=False): try: task.sh(''' python3 -m rkd --silent :sh -c 'echo "Bartolomeo Vanzetti" ''' + std_redirect + '''; exit 127' ''') except subprocess.CalledProcessError: pass self.assertIn( 'Bartolomeo Vanzetti', out.getvalue(), msg='Expected that output will be shown for std_redirect=%s' % std_redirect)
def test_sh_captures_output_in_correct_order_with_fixed_timing(self): """Test if output contains stdout and stderr lines printed out in proper order, while there is a sleep between prints Notice: Test is interacting with shell, to reduce possibility of weird behavior it is retried multiple times """ for i in range(1, 30): self.maxDiff = None # unittest setting task = InitTask() task._io = IO() io = IO() out = StringIO() with io.capture_descriptors(stream=out, enable_standard_out=False): task.sh(''' set +e; sleep 0.05; echo "FIRST"; sleep 0.05; echo "SECOND" >&2; sleep 0.05; echo "THIRD"; ''') self.assertEqual("FIRST\r\nSECOND\r\nTHIRD\r\n", out.getvalue())
def test_quotes_are_escaped_in_shell_commands(self): task = InitTask() task._io = IO() io = IO() out = StringIO() with io.capture_descriptors(stream=out, enable_standard_out=False): task.sh('echo ${NAME}', env={'NAME': 'Ferdinando "Nicola" Sacco'}) self.assertIn('Ferdinando "Nicola" Sacco', out.getvalue())
def test_sh_provides_stdout_and_stderr_in_exception(self): task = InitTask() task._io = IO() try: task.sh(''' echo "Freedom, Equality, Mutual Aid!" echo "The state and capitalism is failing" >&2 exit 161 ''') except subprocess.CalledProcessError as e: self.assertEqual("Freedom, Equality, Mutual Aid!\n", e.output) self.assertEqual("The state and capitalism is failing\n", e.stderr)
def test_dollar_symbols_are_escaped_in_shell_commands(self): """Check that in envrionment variable there can be defined a value that contains dollar symbols""" task = InitTask() task._io = IO() io = IO() out = StringIO() with io.capture_descriptors(stream=out, enable_standard_out=False): task.sh('env | grep TEST_ENV', env={ 'TEST_ENV': "Mikhail\\$1Bakunin\\$PATHtest", 'TEST_ENV_NOT_ESCAPED': 'Hello $TEST_ENV' }) self.assertIn('TEST_ENV=Mikhail$1Bakunin$PATHtest', out.getvalue()) self.assertIn('TEST_ENV_NOT_ESCAPED=Hello Mikhail$1Bakunin$PATHtest', out.getvalue())
def test_non_interactive_session_returns_output(self): """Checks functionally if process.py is implementing a fall-back for non-interactive sessions 'true |' part enforces the console to be non-interactive, which should cause "termios.error: (25, 'Inappropriate ioctl for device')" that should be handled and interactive mode should be turned off for stdin """ task = InitTask() task._io = IO() io = IO() out = StringIO() with io.capture_descriptors(stream=out, enable_standard_out=False): task.sh( ''' true | python3 -m rkd --silent :sh -c 'echo "Strajk Kobiet! Jebac PiS!"' ''' ) self.assertIn('Strajk Kobiet! Jebac PiS!', out.getvalue())
def test_sh_3rd_depth_rkd_calls(self): """Bugfix: sh() of 3-depth calls -> test -> rkd -> rkd returns first line of output """ for std_redirect in ['', '>&2']: task = InitTask() task._io = IO() io = IO() out = StringIO() with io.capture_descriptors(stream=out, enable_standard_out=False): try: task.sh(''' python3 -m rkd --silent :sh -c 'python -m rkd --silent :sh -c \'echo "Nicola Sacco" ''' + std_redirect + '''; exit 1\'' ''') except subprocess.CalledProcessError: pass self.assertIn( 'Nicola Sacco', out.getvalue(), msg='Expected that output will be shown for std_redirect=%s' % std_redirect)
def test_sh_has_valid_order_of_defining_environment_variables(self): """Checks if built-in sh() method is registering variables in proper order """ task = InitTask() task._io = IO() envs = OrderedDict() envs['ENV_NAME'] = 'riotkit' envs['COMPOSE_CMD'] = 'docker-compose -p ${ENV_NAME}' out = task.sh(''' echo "${COMPOSE_CMD} up -d" ''', env=envs, capture=True) self.assertEqual('docker-compose -p riotkit up -d', out.strip())
def test_sh_accepts_script_syntax(self): task = InitTask() task._io = IO() self.assertIn('__init__.py', task.sh("ls -la rkd\npwd", capture=True))