示例#1
0
 def check_all_cases_parsed(self):
     for missing_test in self.expected_test_names:
         self.error("Could not find output file for test: ", missing_test)
         testcase = junitparser.TestCase(name=missing_test)
         testcase.result = junitparser.Error(
             message="Could not find output for test " + missing_test)
         self.error_suite.add_testcase(testcase)
示例#2
0
def output_to_junit_suite(xml, output_path, suite_name, good=True):
    suite = junitparser.TestSuite(suite_name)

    with open(output_path, "r") as output_file:
        next(output_file)  # skip first header
        for line in output_file:
            if line[0] == "=":  # stop on next header
                break

            split = line.split()
            case = junitparser.TestCase(split[0])
            exit_code = int(split[1])

            if exit_code == 124:
                # timeout
                case.result = junitparser.Error(split[1])  # TODO error on timeout?
            elif good and exit_code != 0:
                # good run had bad exit code
                case.result = junitparser.Failure(split[1])
            elif not good and exit_code == 0:  # TODO we usually? expect a cheri exception
                # bad run had good exit code
                case.result = junitparser.Failure(split[1])
示例#3
0
def run_parallel(args: argparse.Namespace):
    if args.pretend:
        boot_cheribsd.PRETEND = True
    boot_cheribsd.MESSAGE_PREFIX = "\033[0;35m" + "main process: \033[0m"
    if args.parallel_jobs < 1:
        boot_cheribsd.failure("Invalid number of parallel jobs: ",
                              args.parallel_jobs,
                              exit=True)
    boot_cheribsd.success("Running ", args.parallel_jobs, " parallel jobs")
    # to ensure that all threads have started lit
    mp_barrier = Barrier(parties=args.parallel_jobs + 1, timeout=4 * 60 * 60)
    mp_q = Queue()
    ssh_port_queue = Queue()
    processes = []
    # Extract the kernel + disk image in the main process to avoid race condition:
    kernel_path = boot_cheribsd.maybe_decompress(Path(args.kernel), True, True,
                                                 args) if args.kernel else None
    disk_image_path = boot_cheribsd.maybe_decompress(Path(
        args.disk_image), True, True, args) if args.disk_image else None
    for i in range(args.parallel_jobs):
        shard_num = i + 1
        boot_cheribsd.info(args)
        p = Process(target=run_shard,
                    args=(mp_q, mp_barrier, shard_num, args.parallel_jobs,
                          ssh_port_queue, kernel_path, disk_image_path,
                          args.build_dir))
        p.stage = run_remote_lit_test.MultiprocessStages.FINDING_SSH_PORT
        p.daemon = True  # kill process on parent exit
        p.name = "<LIBCXX test shard " + str(shard_num) + ">"
        p.start()
        processes.append(p)
        atexit.register(p.terminate)
    dump_processes(processes)
    try:
        return run_parallel_impl(args, processes, mp_q, mp_barrier,
                                 ssh_port_queue)
    except BaseException as e:
        boot_cheribsd.info("Got error while running run_parallel_impl (",
                           type(e), "): ", e)
        raise
    finally:
        wait_or_terminate_all_shards(processes, max_time=5, timed_out=False)
        # merge junit xml files
        if args.xunit_output:
            boot_cheribsd.success("Merging JUnit XML outputs")
            result = junitparser.JUnitXml()
            xunit_file = Path(args.xunit_output).absolute()
            dump_processes(processes)
            for i in range(args.parallel_jobs):
                shard_num = i + 1
                shard_file = xunit_file.with_name("shard-" + str(shard_num) +
                                                  "-" + xunit_file.name)
                mp_debug(args, processes[i], processes[i].stage)
                if shard_file.exists():
                    result += junitparser.JUnitXml.fromfile(str(shard_file))
                else:
                    error_msg = "ERROR: could not find JUnit XML " + str(
                        shard_file) + " for shard " + str(shard_num)
                    boot_cheribsd.failure(error_msg, exit=False)
                    error_suite = junitparser.TestSuite(name="failed-shard-" +
                                                        str(shard_num))
                    error_case = junitparser.TestCase(name="cannot-find-file")
                    error_case.classname = "failed-shard-" + str(shard_num)
                    error_case.result = junitparser.Error(message=error_msg)
                    error_suite.add_testcase(error_case)
                    result.add_testsuite(error_suite)
                if processes[
                        i].stage != run_remote_lit_test.MultiprocessStages.EXITED:
                    error_msg = "ERROR: shard " + str(
                        shard_num
                    ) + " did not exit cleanly! Was in stage: " + processes[
                        i].stage.value
                    if hasattr(processes[i], "error_message"):
                        error_msg += "\nError message:\n" + processes[
                            i].error_message
                    error_suite = junitparser.TestSuite(
                        name="bad-exit-shard-" + str(shard_num))
                    error_case = junitparser.TestCase(name="bad-exit-status")
                    error_case.result = junitparser.Error(message=error_msg)
                    error_suite.add_testcase(error_case)
                    result.add_testsuite(error_suite)

            result.update_statistics()
            result.write(str(xunit_file))
            if args.pretend:
                print(xunit_file.read_text())
            boot_cheribsd.success("Done merging JUnit XML outputs into ",
                                  xunit_file)
            print("Duration: ", result.time)
            print("Tests: ", result.tests)
            print("Failures: ", result.failures)
            print("Errors: ", result.errors)
            print("Skipped: ", result.skipped)
示例#4
0
    def handle_testcase(self, o: Path, tools: list):
        stem = o.stem
        assert stem.startswith(self.test_prefix), stem
        exit_code_str = o.read_text(encoding="utf-8",
                                    errors="replace").rstrip()
        testcase = junitparser.TestCase(name=stem)
        try:
            index = self.expected_test_names.index(stem)
        except ValueError:
            self.error("Found output for unknown test: ", o)
            testcase.result = junitparser.Error(
                message="UNEXPECTED TEST NAME: " + o.name)
            testcase.system_out = exit_code_str
            self.error_suite.add_testcase(testcase)
            return
        # test has been handled -> remove from expected list
        del self.expected_test_names[index]
        if o.with_suffix(".stderr").exists():
            stderr = o.with_suffix(
                ".stderr").read_bytes().rstrip()  # type: bytes
            stderr = stderr.replace(b"\x00", b"\\0")
            testcase.system_err = stderr.decode("utf-8", errors="replace")
        try:
            exit_code = int(exit_code_str)
        except ValueError:
            self.error("Malformed output for test: ", o)
            testcase.result = junitparser.Error(
                message="INVALID OUTPUT FILE CONTENTS: " + o.name)
            testcase.system_out = exit_code_str
            self.error_suite.add_testcase(testcase)
            return

        signaled = os.WIFSIGNALED(exit_code)
        exited = os.WIFEXITED(exit_code)
        testcase.system_out = "WIFSIGNALED={} WIFEXITED={}, WTERMSIG={}, WEXITSTATUS={} WCOREDUMP={}".format(
            signaled, exited, os.WTERMSIG(exit_code),
            os.WEXITSTATUS(exit_code), os.WCOREDUMP(exit_code))
        # -ok testcases are expected to run succesfully -> exit code zero
        if stem.endswith("-ok"):
            if not exited or os.WEXITSTATUS(exit_code) != 0:
                # This is not just a failure, it means something is seriously wrong if the good case fails
                self.error("One of the good test cases failed: ", o)
                testcase.result = junitparser.Error(
                    message="Expected exit code 0 but got " + exit_code_str)
            self.ok_suite.add_testcase(testcase)
        else:
            # all others should crash
            if stem.endswith("-min"):
                suite = self.min_suite
            elif stem.endswith("-med"):
                suite = self.med_suite
            elif stem.endswith("-large"):
                suite = self.large_suite
            else:
                self.error("Malformed output for test: ", o)
                testcase.result = junitparser.Error(
                    message="INVALID OUTPUT FILE FOUND: " + o.name)
                self.error_suite.add_testcase(testcase)
                return
            if exit_code == 1 and testcase.system_err and testcase.system_err.startswith(
                    "This test needs a CWD with length"):
                testcase.result = junitparser.Skipped(
                    message="This test needs a large working directory")

            # Handle tool-specific exit codes:
            if "effectivesan" in tools:
                # We do not instruct EffectiveSan to terminate on first error:
                if "BOUNDS ERROR:\n" not in testcase.system_err:
                    testcase.result = junitparser.Failure(
                        message=
                        "EffectiveSan did not detect a bounds error. Exit code "
                        + exit_code_str)
            elif "softboundcets" in tools:
                # We do not instruct EffectiveSan to terminate on first error:
                if "Softboundcets: Memory safety violation detected" not in testcase.system_err:
                    testcase.result = junitparser.Failure(
                        message=
                        "SoftBoundCETS did not detect a bounds error. Exit code "
                        + exit_code_str)
            else:
                # Otherwise we assume that the test must be killed by a signal
                if not signaled:
                    # test should fail with a signal: (162 for CHERI)
                    # TODO: for CHERI check that it was signal 34?
                    testcase.result = junitparser.Failure(
                        message=
                        "Expected test to be killed by a SIGNAL but got exit code "
                        + exit_code_str)
            suite.add_testcase(testcase)