| 759 | return not (self.jobs or self.test_list) |
| 760 | |
| 761 | def get_next(self): |
| 762 | while len(self.jobs) < self.num_jobs and self.test_list: |
| 763 | # Add tests |
| 764 | test = self.test_list.popleft() |
| 765 | portseed = len(self.test_list) |
| 766 | portseed_arg = ["--portseed={}".format(portseed)] |
| 767 | log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) |
| 768 | log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) |
| 769 | test_argv = test.split() |
| 770 | testdir = "{}/{}_{}".format(self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed) |
| 771 | tmpdir_arg = ["--tmpdir={}".format(testdir)] |
| 772 | |
| 773 | def proc_wait(task): |
| 774 | task[2].wait() |
| 775 | return task |
| 776 | |
| 777 | task = [ |
| 778 | test, |
| 779 | time.time(), |
| 780 | subprocess.Popen( |
| 781 | [sys.executable, self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg, |
| 782 | text=True, |
| 783 | stdout=log_stdout, |
| 784 | stderr=log_stderr, |
| 785 | ), |
| 786 | testdir, |
| 787 | log_stdout, |
| 788 | log_stderr, |
| 789 | ] |
| 790 | fut = self.executor.submit(proc_wait, task) |
| 791 | self.jobs[fut] = test |
| 792 | assert self.jobs # Must not be empty here |
| 793 | |
| 794 | # Print remaining running jobs when all jobs have been started. |
| 795 | if not self.test_list: |
| 796 | print("Remaining jobs: [{}]".format(", ".join(sorted(self.jobs.values())))) |
| 797 | |
| 798 | dot_count = 0 |
| 799 | while True: |
| 800 | # Return all procs that have finished, if any. Otherwise sleep until there is one. |
| 801 | procs = futures.wait(self.jobs.keys(), timeout=.5, return_when=futures.FIRST_COMPLETED) |
| 802 | self.jobs = {fut: self.jobs[fut] for fut in procs.not_done} |
| 803 | ret = [] |
| 804 | for job in procs.done: |
| 805 | (name, start_time, proc, testdir, log_out, log_err) = job.result() |
| 806 | |
| 807 | log_out.seek(0), log_err.seek(0) |
| 808 | [stdout, stderr] = [log_file.read().decode('utf-8') for log_file in (log_out, log_err)] |
| 809 | log_out.close(), log_err.close() |
| 810 | skip_reason = None |
| 811 | if proc.returncode == TEST_EXIT_PASSED and stderr == "": |
| 812 | status = "Passed" |
| 813 | elif proc.returncode == TEST_EXIT_SKIPPED: |
| 814 | status = "Skipped" |
| 815 | skip_reason = re.search(r"Test Skipped: (.*)", stdout).group(1).strip() |
| 816 | else: |
| 817 | status = "Failed" |
| 818 | |