def testRunCommandCaptureOutput(self): """Test that RunCommand can capture stdout if a command succeeds.""" result = cros_build_lib.RunCommand( ['echo', '-n', 'Hi'], # Keep the test quiet options print_cmd=False, redirect_stdout=True, redirect_stderr=True) self.assertEqual(result, 'Hi')
def testRunCommandErrorException(self): """Test that RunCommand can throw an exception when a command fails.""" function = lambda: cros_build_lib.RunCommand( ['ls', '/nosuchdir'], # Keep the test quiet options print_cmd=False, redirect_stdout=True, redirect_stderr=True) self.assertRaises(cros_build_lib.RunCommandException, function)
def testRunCommandSimple(self): """Test that RunCommand can run a simple successful command.""" result = cros_build_lib.RunCommand( ['ls'], # Keep the test quiet options print_cmd=False, redirect_stdout=True, redirect_stderr=True, # Test specific options exit_code=True) self.assertEqual(result, 0)
def testRunCommandError(self): """Test that RunCommand can return an error code for a failed command.""" result = cros_build_lib.RunCommand( ['ls', '/nosuchdir'], # Keep the test quiet options print_cmd=False, redirect_stdout=True, redirect_stderr=True, # Test specific options exit_code=True) self.assertNotEqual(result, 0) self.assertEquals(type(result), int)
def testRunCommandLogToFile(self): """Test that RunCommand can log output to a file correctly.""" log_file = tempfile.mktemp() cros_build_lib.RunCommand( ['echo', '-n', 'Hi'], # Keep the test quiet options print_cmd=False, # Test specific options log_to_file=log_file) log_fh = open(log_file) log_data = log_fh.read() self.assertEquals('Hi', log_data) log_fh.close() os.remove(log_file)
def testRunCommandErrorCodeNoException(self): """Test that RunCommand doesn't throw an exception with exit_code.""" result = cros_build_lib.RunCommand( ['ls', '/nosuchdir'], # Keep the test quiet options print_cmd=False, redirect_stdout=True, redirect_stderr=True, # Test specific options exit_code=True) # We are really testing that it doesn't throw an exception if exit_code # if true. self.assertNotEqual(result, 0) self.assertEquals(type(result), int)
def testRunCommandErrorRetries(self): """Test that RunCommand can retry a failed command that always fails.""" # We don't actually check that it's retrying, just exercise the code path. result = cros_build_lib.RunCommand( ['ls', '/nosuchdir'], # Keep the test quiet options print_cmd=False, redirect_stdout=True, redirect_stderr=True, # Test specific options num_retries=2, error_ok=True, exit_code=True) self.assertNotEqual(result, 0) self.assertEquals(type(result), int)
def _enter(self): if os.getuid() == 0: cros_build_lib.Die('This script cannot be run as root.') start_for_tty = self._DaemonNeeded() if not start_for_tty: # Daemon is already started. return # Note despite the impulse to use 'sudo -v' instead of 'sudo true', the # builder's sudoers configuration is slightly whacked resulting in it # asking for password everytime. As such use 'sudo true' instead. cmds = [ 'sudo -n true 2>/dev/null', 'sudo -n true < /dev/null > /dev/null 2>&1' ] # First check to see if we're already authed. If so, then we don't # need to prompt the user for their password. for idx, cmd in enumerate(cmds): ret = cros_build_lib.RunCommand(cmd, print_cmd=False, shell=True, error_code_ok=True) if ret.returncode != 0: tty_msg = 'Please disable tty_tickets using these instructions: %s' if os.path.exists("/etc/goobuntu"): url = 'https://goto.google.com/chromeos-sudoers' else: url = 'https://goo.gl/fz9YW' # If ttyless sudo is not strictly required for this script, don't # prompt for a password a second time. Instead, just complain. if idx > 0: cros_build_lib.Error(tty_msg, url) if not self._ttyless_sudo: break # We need to go interactive and allow sudo to ask for credentials. interactive_cmd = cmd.replace(' -n', '') cros_build_lib.RunCommand(interactive_cmd, shell=True, print_cmd=False) # Verify that sudo access is set up properly. try: cros_build_lib.RunCommand(cmd, shell=True, print_cmd=False) except cros_build_lib.RunCommandError: if idx == 0: raise cros_build_lib.Die( 'tty_tickets must be disabled. ' + tty_msg, url) # Anything other than a timeout results in us shutting down. repeat_interval = self._repeat_interval * 60 cmd = ('while :; do read -t %i; [ $? -le 128 ] && exit; %s; done' % (repeat_interval, '; '.join(cmds))) def ignore_sigint(): # We don't want our sudo process shutdown till we shut it down; # since it's part of the session group it however gets SIGINT. # Thus suppress it (which bash then inherits). signal.signal(signal.SIGINT, signal.SIG_IGN) self._proc = subprocess.Popen(['bash', '-c', cmd], shell=False, close_fds=True, preexec_fn=ignore_sigint, stdin=subprocess.PIPE) self._existing_keepalive_value = os.environ.get('CROS_SUDO_KEEP_ALIVE') os.environ['CROS_SUDO_KEEP_ALIVE'] = start_for_tty