import re import subprocess BIN = "./lab3" STAT_RE = re.compile( r"STAT:.*size=(\d+).*depth=(\d+).*min_size=(\d+).*processes=(\d+).*valid=(\d+).*time=([\d.]+)" ) def run(args): p = subprocess.run([BIN, *args], text=True, capture_output=True) if p.returncode != 0: print("STDOUT:\n", p.stdout) print("STDERR:\n", p.stderr) raise AssertionError(f"command failed: {args}") m = STAT_RE.search(p.stderr) assert m and m.group(5) == "1", f"bad stat: {p.stderr}" return p, m def ints(s): return [int(x) for x in s.split()] if s.strip() else [] def test_01_printed_small_random_array_sorted(): p, _ = run(["--size", "97", "--depth", "3", "--min-size", "8", "--print"]) a = ints(p.stdout) assert len(a) == 97 assert a == sorted(a) def test_02_seed_makes_random_input_reproducible(): a = run( ["--size", "128", "--depth", "2", "--min-size", "8", "--seed", "42", "--print"] )[0].stdout b = run( ["--size", "128", "--depth", "2", "--min-size", "8", "--seed", "42", "--print"] )[0].stdout c = run( ["--size", "128", "--depth", "2", "--min-size", "8", "--seed", "43", "--print"] )[0].stdout assert a == b assert a != c def test_03_zero_depth_sequential_fallback(): _, m = run(["--size", "1000", "--depth", "0", "--min-size", "1"]) assert m.group(4) == "1" def test_04_depth_two_full_tree_process_count(): _, m = run(["--size", "4096", "--depth", "2", "--min-size", "16"]) assert m.group(4) == "7", m.group(0) def test_05_depth_three_full_tree_process_count(): _, m = run(["--size", "8192", "--depth", "3", "--min-size", "16"]) assert m.group(4) == "15", m.group(0) def test_06_min_size_stops_forking(): _, m = run(["--size", "1000", "--depth", "5", "--min-size", "1000"]) assert m.group(4) == "1", m.group(0) def test_07_odd_size_sorted_correctly(): p, _ = run( ["--size", "999", "--depth", "4", "--min-size", "17", "--seed", "77", "--print"] ) a = ints(p.stdout) assert len(a) == 999 assert a == sorted(a) def test_08_single_element_array(): p, m = run(["--size", "1", "--depth", "5", "--min-size", "1", "--print"]) a = ints(p.stdout) assert len(a) == 1 assert m.group(4) == "1" def test_09_empty_array(): p, m = run(["--size", "0", "--depth", "5", "--min-size", "1", "--print"]) assert p.stdout.strip() == "" assert m.group(4) == "1" def test_10_timeline_log_has_events_and_pid_fields(): p, _ = run(["--size", "128", "--depth", "2", "--min-size", "8", "--log"]) assert "START PID=" in p.stdout assert "END PID=" in p.stdout assert "PPID=" in p.stdout assert "depth=" in p.stdout def test_11_help_has_no_mode_argument(): p = subprocess.run([BIN, "--help"], text=True, capture_output=True) assert p.returncode == 0 assert "--mode" not in p.stdout assert "--seed" in p.stdout def test_12_unknown_mode_is_rejected(): p = subprocess.run([BIN, "--mode", "random"], text=True, capture_output=True) assert p.returncode != 0 assert "unknown argument" in p.stderr if __name__ == "__main__": tests = [ test_01_printed_small_random_array_sorted, test_02_seed_makes_random_input_reproducible, test_03_zero_depth_sequential_fallback, test_04_depth_two_full_tree_process_count, test_05_depth_three_full_tree_process_count, test_06_min_size_stops_forking, test_07_odd_size_sorted_correctly, test_08_single_element_array, test_09_empty_array, test_10_timeline_log_has_events_and_pid_fields, test_11_help_has_no_mode_argument, test_12_unknown_mode_is_rejected, ] for t in tests: t() print(f"OK {t.__name__}")