aboutsummaryrefslogtreecommitdiff
path: root/deprecated/automation/common/command_executer_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'deprecated/automation/common/command_executer_test.py')
-rwxr-xr-xdeprecated/automation/common/command_executer_test.py210
1 files changed, 210 insertions, 0 deletions
diff --git a/deprecated/automation/common/command_executer_test.py b/deprecated/automation/common/command_executer_test.py
new file mode 100755
index 00000000..2caaa146
--- /dev/null
+++ b/deprecated/automation/common/command_executer_test.py
@@ -0,0 +1,210 @@
+#!/usr/bin/python2
+#
+# Copyright 2011 Google Inc. All Rights Reserved.
+#
+
+__author__ = 'kbaclawski@google.com (Krystian Baclawski)'
+
+import cStringIO
+import logging
+import os
+import signal
+import socket
+import sys
+import time
+import unittest
+
+
+def AddScriptDirToPath():
+ """Required for remote python script execution."""
+ path = os.path.abspath(__file__)
+
+ for _ in range(3):
+ path, _ = os.path.split(path)
+
+ if not path in sys.path:
+ sys.path.append(path)
+
+
+AddScriptDirToPath()
+
+from automation.common.command_executer import CommandExecuter
+
+
+class LoggerMock(object):
+
+ def LogCmd(self, cmd, machine='', user=''):
+ if machine:
+ logging.info('[%s] Executing: %s', machine, cmd)
+ else:
+ logging.info('Executing: %s', cmd)
+
+ def LogError(self, msg):
+ logging.error(msg)
+
+ def LogWarning(self, msg):
+ logging.warning(msg)
+
+ def LogOutput(self, msg):
+ logging.info(msg)
+
+
+class CommandExecuterUnderTest(CommandExecuter):
+
+ def __init__(self):
+ CommandExecuter.__init__(self, logger_to_set=LoggerMock())
+
+ # We will record stdout and stderr.
+ self._stderr = cStringIO.StringIO()
+ self._stdout = cStringIO.StringIO()
+
+ @property
+ def stdout(self):
+ return self._stdout.getvalue()
+
+ @property
+ def stderr(self):
+ return self._stderr.getvalue()
+
+ def DataReceivedOnOutput(self, data):
+ self._stdout.write(data)
+
+ def DataReceivedOnError(self, data):
+ self._stderr.write(data)
+
+
+class CommandExecuterLocalTests(unittest.TestCase):
+ HOSTNAME = None
+
+ def setUp(self):
+ self._executer = CommandExecuterUnderTest()
+
+ def tearDown(self):
+ pass
+
+ def RunCommand(self, method, **kwargs):
+ program = os.path.abspath(sys.argv[0])
+
+ return self._executer.RunCommand('%s runHelper %s' % (program, method),
+ machine=self.HOSTNAME,
+ **kwargs)
+
+ def testCommandTimeout(self):
+ exit_code = self.RunCommand('SleepForMinute', command_timeout=3)
+
+ self.assertTrue(-exit_code in [signal.SIGTERM, signal.SIGKILL],
+ 'Invalid exit code: %d' % exit_code)
+
+ def testCommandTimeoutIfSigTermIgnored(self):
+ exit_code = self.RunCommand('IgnoreSigTerm', command_timeout=3)
+
+ self.assertTrue(-exit_code in [signal.SIGTERM, signal.SIGKILL])
+
+ def testCommandSucceeded(self):
+ self.assertFalse(self.RunCommand('ReturnTrue'))
+
+ def testCommandFailed(self):
+ self.assertTrue(self.RunCommand('ReturnFalse'))
+
+ def testStringOnOutputStream(self):
+ self.assertFalse(self.RunCommand('EchoToOutputStream'))
+ self.assertEquals(self._executer.stderr, '')
+ self.assertEquals(self._executer.stdout, 'test')
+
+ def testStringOnErrorStream(self):
+ self.assertFalse(self.RunCommand('EchoToErrorStream'))
+ self.assertEquals(self._executer.stderr, 'test')
+ self.assertEquals(self._executer.stdout, '')
+
+ def testOutputStreamNonInteractive(self):
+ self.assertFalse(
+ self.RunCommand('IsOutputStreamInteractive'),
+ 'stdout stream is a terminal!')
+
+ def testErrorStreamNonInteractive(self):
+ self.assertFalse(
+ self.RunCommand('IsErrorStreamInteractive'),
+ 'stderr stream is a terminal!')
+
+ def testAttemptToRead(self):
+ self.assertFalse(self.RunCommand('WaitForInput', command_timeout=3))
+
+ def testInterruptedProcess(self):
+ self.assertEquals(self.RunCommand('TerminateBySigAbrt'), -signal.SIGABRT)
+
+
+class CommandExecuterRemoteTests(CommandExecuterLocalTests):
+ HOSTNAME = socket.gethostname()
+
+ def testCommandTimeoutIfSigTermIgnored(self):
+ exit_code = self.RunCommand('IgnoreSigTerm', command_timeout=6)
+
+ self.assertEquals(exit_code, 255)
+
+ lines = self._executer.stdout.splitlines()
+ pid = int(lines[0])
+
+ try:
+ with open('/proc/%d/cmdline' % pid) as f:
+ cmdline = f.read()
+ except IOError:
+ cmdline = ''
+
+ self.assertFalse('IgnoreSigTerm' in cmdline, 'Process is still alive.')
+
+
+class CommandExecuterTestHelpers(object):
+
+ def SleepForMinute(self):
+ time.sleep(60)
+ return 1
+
+ def ReturnTrue(self):
+ return 0
+
+ def ReturnFalse(self):
+ return 1
+
+ def EchoToOutputStream(self):
+ sys.stdout.write('test')
+ return 0
+
+ def EchoToErrorStream(self):
+ sys.stderr.write('test')
+ return 0
+
+ def IsOutputStreamInteractive(self):
+ return sys.stdout.isatty()
+
+ def IsErrorStreamInteractive(self):
+ return sys.stderr.isatty()
+
+ def IgnoreSigTerm(self):
+ os.write(1, '%d' % os.getpid())
+ signal.signal(signal.SIGTERM, signal.SIG_IGN)
+ time.sleep(30)
+ return 0
+
+ def WaitForInput(self):
+ try:
+ # can only read end-of-file marker
+ return os.read(0, 1) != ''
+ except OSError:
+ # that means that stdin descriptor is closed
+ return 0
+
+ def TerminateBySigAbrt(self):
+ os.kill(os.getpid(), signal.SIGABRT)
+ return 0
+
+
+if __name__ == '__main__':
+ FORMAT = '%(asctime)-15s %(levelname)s %(message)s'
+ logging.basicConfig(format=FORMAT, level=logging.DEBUG)
+
+ if len(sys.argv) > 1:
+ if sys.argv[1] == 'runHelper':
+ helpers = CommandExecuterTestHelpers()
+ sys.exit(getattr(helpers, sys.argv[2])())
+
+ unittest.main()