def validate(dump_dir, p4_file, log_file, config): try: result = validate_p4(p4_file, dump_dir, config["compiler_bin"], log_file) except TimeoutError: log.error("Validation timed out.") dump_file(TIMEOUT_DIR, p4_file) dump_file(TIMEOUT_DIR, log_file) # reset the dump directory return util.EXIT_FAILURE if result != util.EXIT_SUCCESS: info_file = p4_file.with_suffix("").joinpath( f"{p4_file.stem}_info.json") bug_dir = None if result == util.EXIT_UNDEF: log.error("Found instance of unstable code!") bug_dir = UNDEF_DIR else: log.error("Failed to validate the P4 code!") bug_dir = VALIDATION_BUG_DIR log.error("Rerun the example with:") out_file = bug_dir.joinpath(p4_file.name) log.error("python3 bin/validate_p4_translation -u -i %s", out_file) dump_file(bug_dir, log_file) dump_file(bug_dir, p4_file) dump_file(bug_dir, info_file) if config["do_prune"]: info_file = bug_dir.joinpath(f"{p4_file.stem}_info.json") p4_cmd = f"{PRUNER_BIN} " p4_cmd += f"--config {info_file} " p4_cmd += f" {bug_dir.joinpath(f'{p4_file.stem}.p4')} " p4_cmd += f" --working-dir {bug_dir.joinpath(f'{p4_file.stem}')}" log.info("Pruning P4 file with command %s ", p4_cmd) util.start_process(p4_cmd) return result
def check(idx, config): test_id = generate_id() test_name = f"{test_id}_{idx}" dump_dir = OUTPUT_DIR.joinpath(f"dmp_{test_name}") util.check_dir(dump_dir) log_file = dump_dir.joinpath(f"{test_name}.log") p4_file = dump_dir.joinpath(f"{test_name}.p4") seed = int.from_bytes(os.getrandom(8), "big") log.info("Testing P4 program: %s - Seed: %s", p4_file.name, seed) # generate a random program result, p4_file = generate_p4_prog(P4RANDOM_BIN, p4_file, config, seed) if result.returncode != util.EXIT_SUCCESS: log.error("Failed generate P4 code!") dump_result(result, GENERATOR_BUG_DIR, p4_file) # reset the dump directory util.del_dir(dump_dir) return result.returncode # check compilation result = compile_p4_prog(config["compiler_bin"], p4_file, dump_dir) if result.returncode != util.EXIT_SUCCESS: if not is_known_bug(result): log.error("Failed to compile the P4 code!") log.error("Found a new bug!") dump_result(result, CRASH_BUG_DIR, p4_file) dump_file(CRASH_BUG_DIR, p4_file) if config["do_prune"]: info_file = CRASH_BUG_DIR.joinpath(f"{p4_file.stem}_info.json") info = validation.INFO # customize the main info with the new information info["compiler"] = str(config["compiler_bin"]) info["exit_code"] = result.returncode info["p4z3_bin"] = str(P4Z3_BIN) info["out_dir"] = str(CRASH_BUG_DIR) info["input_file"] = str(p4_file) info["allow_undef"] = False info["err_string"] = result.stderr.decode("utf-8") log.error("Dumping configuration to %s.", info_file) with open(info_file, 'w') as json_file: json.dump(info, json_file, indent=2, sort_keys=True) p4_cmd = f"{PRUNER_BIN} " p4_cmd += f"--config {info_file} " p4_cmd += f" {CRASH_BUG_DIR.joinpath(f'{p4_file.stem}.p4')} " log.error("Pruning P4 file with command %s ", p4_cmd) util.start_process(p4_cmd) # reset the dump directory util.del_dir(dump_dir) return result # check validation if config["do_validate"]: result = validate(dump_dir, p4_file, log_file, config) elif config["use_blackbox"]: result = run_p4_test(dump_dir, p4_file, log_file, config) # reset the dump directory util.del_dir(dump_dir) return result
def run_bmv2_test(out_dir, p4_input): cmd = "python3 " cmd += f"{P4C_DIR}/backends/bmv2/run-bmv2-test.py " cmd += f"{P4C_DIR} -v " cmd += f"-bd {P4C_DIR}/build " cmd += f"{out_dir}/{p4_input.name} " test_proc = util.start_process(cmd, cwd=out_dir) def signal_handler(sig, frame): log.warning("run_tofino_test: Caught Interrupt, exiting...") os.kill(test_proc.pid, signal.SIGINT) sys.exit(1) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) stdout, stderr = test_proc.communicate() return test_proc, stdout, stderr
def run_tofino_test(out_dir, p4_input, stf_file_name): # we need to change the working directory # tofino scripts make some assumptions where to dump files prog_name = p4_input.stem # we need to create a specific test dir in which we can run tests test_dir = out_dir.joinpath("test_dir") util.check_dir(test_dir) util.copy_file(stf_file_name, test_dir) template_name = test_dir.joinpath(f"{prog_name}.py") # use a test template that runs stf tests util.copy_file(f"{FILE_DIR}/tofino_test_template.py", template_name) # initialize the target install log.info("Building the tofino target...") config_cmd = f"{TOFINO_DIR}/pkgsrc/p4-build/configure " config_cmd += f"--with-tofino --with-p4c=bf-p4c " config_cmd += f"--prefix={TOFINO_DIR}/install " config_cmd += f"--bindir={TOFINO_DIR}/install/bin " config_cmd += f"P4_NAME={prog_name} " config_cmd += f"P4_PATH={p4_input.resolve()} " config_cmd += f"P4_VERSION=p4-16 " config_cmd += f"P4_ARCHITECTURE=tna " result = util.exec_process(config_cmd, cwd=out_dir) if result.returncode != util.EXIT_SUCCESS: return result, result.stdout, result.stderr # create the target make_cmd = f"make -C {out_dir} " result = util.exec_process(make_cmd) if result.returncode != util.EXIT_SUCCESS: return result, result.stdout, result.stderr # install the target in the tofino folder make_cmd = f"make install -C {out_dir} " result = util.exec_process(make_cmd) if result.returncode != util.EXIT_SUCCESS: return result, result.stdout, result.stderr procs = [] test_proc = None # start the target in the background log.info("Starting the tofino model...") os_env = os.environ.copy() os_env["SDE"] = f"{TOFINO_DIR}" os_env["SDE_INSTALL"] = f"{TOFINO_DIR}/install" model_cmd = f"{TOFINO_DIR}/run_tofino_model.sh " model_cmd += f"-p {prog_name} " proc = util.start_process(model_cmd, preexec_fn=os.setsid, env=os_env, cwd=out_dir) procs.append(proc) # start the binary for the target in the background log.info("Launching switchd...") os_env = os.environ.copy() os_env["SDE"] = f"{TOFINO_DIR}" os_env["SDE_INSTALL"] = f"{TOFINO_DIR}/install" switch_cmd = f"{TOFINO_DIR}/run_switchd.sh " switch_cmd += f"--arch tofino " switch_cmd += f"-p {prog_name} " proc = util.start_process(switch_cmd, preexec_fn=os.setsid, env=os_env, cwd=out_dir) procs.append(proc) # wait for a bit time.sleep(2) # finally we can run the test log.info("Running the actual test...") test_cmd = f"{TOFINO_DIR}/run_p4_tests.sh " test_cmd += f"-t {test_dir} " os_env = os.environ.copy() os_env["SDE"] = f"{TOFINO_DIR}" os_env["SDE_INSTALL"] = f"{TOFINO_DIR}/install" os_env["PYTHONPATH"] = f"${{PYTHONPATH}}:{FILE_DIR}" test_proc = util.start_process(test_cmd, env=os_env, cwd=out_dir) def signal_handler(sig, frame): log.warning("run_tofino_test: Caught Interrupt, exiting...") cleanup(procs) os.kill(test_proc.pid, signal.SIGINT) os.kill(test_proc.pid, signal.SIGTERM) sys.exit(1) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) stdout, stderr = test_proc.communicate() cleanup(procs) return test_proc, stdout, stderr