1 #!/usr/bin/env python 2 # 3 # Copyright 2017 - The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 """Unit test for gsi_util.utils.cmd_utils.""" 18 19 import logging 20 from logging import handlers 21 import shutil 22 import subprocess 23 import tempfile 24 import unittest 25 26 from gsi_util.utils import cmd_utils 27 28 29 class RunCommandTest(unittest.TestCase): 30 31 def setUp(self): 32 """Sets up logging output for assert checks.""" 33 log_entries = self._log_entries = [] 34 35 class Target(object): 36 """The target handler to store log output.""" 37 38 def handle(self, record): 39 log_entries.append((record.levelname, record.msg % record.args)) 40 41 self._handler = handlers.MemoryHandler(capacity=0, target=Target()) 42 logging.getLogger().addHandler(self._handler) 43 44 def tearDown(self): 45 """Removes logging handler.""" 46 logging.getLogger().removeHandler(self._handler) 47 48 def test_command_sequence(self): 49 result = cmd_utils.run_command(['echo', '123']) 50 self.assertEqual((0, None, None), result) 51 self.assertEqual(('INFO', "Executed command: 'echo 123' (ret: 0)"), 52 self._log_entries[0]) 53 54 def test_shell_command(self): 55 result = cmd_utils.run_command('echo uses shell', shell=True) 56 self.assertEqual((0, None, None), result) 57 self.assertEqual(('INFO', "Executed command: 'echo uses shell' (ret: 0)"), 58 self._log_entries[0]) 59 60 def test_log_stdout(self): 61 result = cmd_utils.run_command(['echo', '456'], raise_on_error=False, 62 log_stdout=True) 63 self.assertEqual((0, None, None), result) 64 self.assertEqual(('INFO', "Executed command: 'echo 456' (ret: 0)"), 65 self._log_entries[0]) 66 self.assertEqual(('INFO', " stdout: '456\\n'"), 67 self._log_entries[1]) 68 69 def test_log_stderr(self): 70 error_cmd = 'echo foo; echo bar; (echo 123; echo 456;)>&2; exit 3' 71 result = cmd_utils.run_command(error_cmd, shell=True, raise_on_error=False, 72 log_stderr=True) 73 self.assertEqual((3, None, None), result) 74 self.assertEqual( 75 ('ERROR', 'Executed command: %r (ret: %d)' % (error_cmd, 3)), 76 self._log_entries[0]) 77 self.assertEqual(('ERROR', " stderr: '123\\n456\\n'"), 78 self._log_entries[1]) 79 80 def test_log_stdout_and_log_stderr(self): 81 error_cmd = 'echo foo; echo bar; (echo 123; echo 456;)>&2; exit 5' 82 result = cmd_utils.run_command(error_cmd, shell=True, raise_on_error=False, 83 log_stdout=True, log_stderr=True) 84 self.assertEqual((5, None, None), result) 85 self.assertEqual( 86 ('ERROR', 'Executed command: %r (ret: %d)' % (error_cmd, 5)), 87 self._log_entries[0]) 88 self.assertEqual(('ERROR', " stdout: 'foo\\nbar\\n'"), 89 self._log_entries[1]) 90 self.assertEqual(('ERROR', " stderr: '123\\n456\\n'"), 91 self._log_entries[2]) 92 93 def test_read_stdout(self): 94 result = cmd_utils.run_command('echo 123; echo 456; exit 7', shell=True, 95 read_stdout=True, raise_on_error=False) 96 self.assertEqual(7, result.returncode) 97 self.assertEqual('123\n456\n', result.stdoutdata) 98 self.assertEqual(None, result.stderrdata) 99 100 def test_read_stderr(self): 101 result = cmd_utils.run_command('(echo error1; echo error2)>&2; exit 9', 102 shell=True, read_stderr=True, 103 raise_on_error=False) 104 self.assertEqual(9, result.returncode) 105 self.assertEqual(None, result.stdoutdata) 106 self.assertEqual('error1\nerror2\n', result.stderrdata) 107 108 def test_read_stdout_and_stderr(self): 109 result = cmd_utils.run_command('echo foo; echo bar>&2; exit 11', 110 shell=True, read_stdout=True, 111 read_stderr=True, raise_on_error=False) 112 self.assertEqual(11, result.returncode) 113 self.assertEqual('foo\n', result.stdoutdata) 114 self.assertEqual('bar\n', result.stderrdata) 115 116 def test_raise_on_error(self): 117 error_cmd = 'echo foo; exit 13' 118 with self.assertRaises(subprocess.CalledProcessError) as context_manager: 119 cmd_utils.run_command(error_cmd, shell=True, raise_on_error=True) 120 proc_err = context_manager.exception 121 self.assertEqual(13, proc_err.returncode) 122 self.assertEqual(error_cmd, proc_err.cmd) 123 124 def test_change_working_directory(self): 125 """Tests that cwd argument can be passed to subprocess.Popen().""" 126 tmp_dir = tempfile.mkdtemp(prefix='cmd_utils_test') 127 result = cmd_utils.run_command('pwd', shell=True, 128 read_stdout=True, raise_on_error=False, 129 cwd=tmp_dir) 130 self.assertEqual('%s\n' % tmp_dir, result.stdoutdata) 131 shutil.rmtree(tmp_dir) 132 133 if __name__ == '__main__': 134 logging.basicConfig(format='%(message)s', level=logging.INFO) 135 unittest.main() 136