Trigger the test scripts passed in via the list.
| 447 | print(results) |
| 448 | |
| 449 | class TestHandler: |
| 450 | """ |
| 451 | Trigger the test scripts passed in via the list. |
| 452 | """ |
| 453 | |
| 454 | def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, timeout_duration): |
| 455 | assert num_tests_parallel >= 1 |
| 456 | self.num_jobs = num_tests_parallel |
| 457 | self.tests_dir = tests_dir |
| 458 | self.tmpdir = tmpdir |
| 459 | self.timeout_duration = timeout_duration |
| 460 | self.test_list = test_list |
| 461 | self.flags = flags |
| 462 | self.num_running = 0 |
| 463 | self.jobs = [] |
| 464 | |
| 465 | def get_next(self): |
| 466 | while self.num_running < self.num_jobs and self.test_list: |
| 467 | # Add tests |
| 468 | self.num_running += 1 |
| 469 | test = self.test_list.pop(0) |
| 470 | portseed = len(self.test_list) |
| 471 | portseed_arg = ["--portseed={}".format(portseed)] |
| 472 | log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) |
| 473 | log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) |
| 474 | test_argv = test.split() |
| 475 | testdir = "{}/{}_{}".format(self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed) |
| 476 | tmpdir_arg = ["--tmpdir={}".format(testdir)] |
| 477 | self.jobs.append((test, |
| 478 | time.time(), |
| 479 | subprocess.Popen([sys.executable, self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg, |
| 480 | universal_newlines=True, |
| 481 | stdout=log_stdout, |
| 482 | stderr=log_stderr), |
| 483 | testdir, |
| 484 | log_stdout, |
| 485 | log_stderr)) |
| 486 | if not self.jobs: |
| 487 | raise IndexError('pop from empty list') |
| 488 | dot_count = 0 |
| 489 | while True: |
| 490 | # Return first proc that finishes |
| 491 | time.sleep(.5) |
| 492 | for job in self.jobs: |
| 493 | (name, start_time, proc, testdir, log_out, log_err) = job |
| 494 | if int(time.time() - start_time) > self.timeout_duration: |
| 495 | # In travis, timeout individual tests (to stop tests hanging and not providing useful output). |
| 496 | proc.send_signal(signal.SIGINT) |
| 497 | if proc.poll() is not None: |
| 498 | log_out.seek(0), log_err.seek(0) |
| 499 | [stdout, stderr] = [log_file.read().decode('utf-8') for log_file in (log_out, log_err)] |
| 500 | log_out.close(), log_err.close() |
| 501 | if proc.returncode == TEST_EXIT_PASSED and stderr == "": |
| 502 | status = "Passed" |
| 503 | elif proc.returncode == TEST_EXIT_SKIPPED: |
| 504 | status = "Skipped" |
| 505 | else: |
| 506 | status = "Failed" |