Changeset 25:0281d2f4f77f in pyenvjasmine
- Timestamp:
- Jan 18, 2018, 12:20:34 PM (7 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pyenvjasmine/runner.py
r22 r25 1 1 import os 2 import sys 2 3 import subprocess 4 import threading 5 import signal 3 6 4 7 … … 12 15 environment = '--environment=UNIX' 13 16 return environment 17 18 19 def print_no_newline(string): 20 sys.stdout.write(str(string)) 21 sys.stdout.flush() 22 23 24 def run_popen_with_timeout( 25 command, timeout, input_data, stdin, stdout, stderr, env=None): 26 """ 27 Run a sub-program in subprocess.Popen, pass it the input_data, 28 kill it if the specified timeout has passed. 29 returns a tuple of success, stdout, stderr 30 31 sample usage: 32 33 timeout = 60 # seconds 34 path = '/path/to/event.log' 35 command = ['/usr/bin/tail', '-30', path] 36 input_data = '' 37 success, stdout, stderr = run_popen_with_timeout(command, timeout, 38 input_data) 39 if not success: 40 print('timeout on tail event.log output') 41 tail_output = stdout 42 """ 43 kill_check = threading.Event() 44 45 def _kill_process_after_a_timeout(pid): 46 try: 47 os.kill(pid, signal.SIGTERM) 48 except OSError: 49 # catch a possible race condition, the process terminated normally 50 # between the timer firing and our kill 51 return 52 kill_check.set() # tell the main routine that we had to kill 53 # use SIGKILL if hard to kill... 54 return 55 56 stdout_l = [] 57 58 # don't use shell if command/options come in as list 59 use_shell = not isinstance(command, list) 60 try: 61 p = subprocess.Popen(command, bufsize=1, shell=use_shell, 62 stdin=stdin, stdout=stdout, 63 stderr=stderr, env=env) 64 except OSError as error_message: 65 stderr = 'OSError: ' + str(error_message) 66 return (False, '', stderr) 67 pid = p.pid 68 69 watchdog = threading.Timer(timeout, _kill_process_after_a_timeout, 70 args=(pid, )) 71 watchdog.start() 72 73 while True: 74 output = p.stdout.readline(1) 75 if output == '' and p.poll() is not None: 76 break 77 if output == '\n': 78 print(output) 79 else: 80 print_no_newline(output) 81 stdout_l.append(output) 82 83 try: 84 (stdout, stderr) = p.communicate(input_data) 85 except OSError as error_message: 86 stdout = '' 87 stderr = 'OSError: ' + str(error_message) 88 p.returncode = -666 89 90 watchdog.cancel() # if it's still waiting to run 91 92 # if it timed out, success is False 93 success = (not kill_check.isSet()) and p.returncode >= 0 94 kill_check.clear() 95 return (success, ''.join(stdout_l), stderr) 14 96 15 97 … … 47 129 self.runner_html = os.path.join(here, 'runner.html') 48 130 49 def run(self, spec=None, capture_output=True): 50 """ 51 Run the js tests with envjasmine. 131 def run(self, spec=None, timeout=None): 132 """ 133 Run the js tests with envjasmine, return success (true/false) and 134 the captured stdout data 135 52 136 spec: (relative) path to a spec file (run only that spec) 53 Returns the output 137 timeout: Set it to a given number of seconds and the process running 138 the js tests will be killed passed that time 54 139 """ 55 140 environment = get_environment() … … 85 170 86 171 shell = False 87 stdout = None 88 stderr = None 89 if capture_output: 90 # override if we want to capture the output of the test run 91 stdout = subprocess.PIPE 92 stderr = subprocess.PIPE 93 94 p = subprocess.Popen(command, shell=shell, stdout=stdout, 95 stderr=stderr) 96 (res, stderr) = p.communicate() 97 return res 172 stdin = None 173 stdout = subprocess.PIPE 174 stderr = subprocess.PIPE 175 input_data = '' 176 177 success, stdout, stderr = run_popen_with_timeout( 178 command, timeout, input_data, stdin, stdout, stderr 179 ) 180 181 # success will be true if the subprocess did not timeout, now look 182 # for actual failures if there was not a timeout 183 if success: 184 success = self.did_test_pass(stdout) 185 return success, stdout 186 187 def did_test_pass(self, stdout): 188 for line in stdout.splitlines(): 189 if 'Failed' in line: 190 failed = line.split(':')[1].strip() 191 return failed == '0' 192 return False 98 193 99 194 def write_browser_htmlfile(self):
Note:
See TracChangeset
for help on using the changeset viewer.