runall/runall.py

93 lines
2.3 KiB
Python
Raw Normal View History

2021-01-26 21:36:26 +00:00
from itertools import product
2021-01-27 12:48:34 +00:00
from multiprocessing import current_process, Pool
2021-01-27 11:42:01 +00:00
import signal
from subprocess import DEVNULL, PIPE, Popen, TimeoutExpired
2021-01-26 21:36:26 +00:00
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ '
2021-01-27 11:42:01 +00:00
# Prevent zombie processes
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
2021-01-27 12:48:34 +00:00
# Current test case pairs used for testing (local to worker process)
current_pairs = None
def set_pairs(pairs):
global current_pairs
current_pairs = pairs
2021-01-26 21:36:26 +00:00
def check_pair(script, instr, outstr):
2021-01-27 11:42:01 +00:00
process = Popen(
["/usr/bin/env", "bash", "-c", "--", script],
stdin=PIPE,
stdout=PIPE,
stderr=DEVNULL,
)
2021-01-27 11:04:14 +00:00
try:
2021-01-27 11:42:01 +00:00
stdout, stderr = process.communicate(instr.encode(), timeout=5)
return process.returncode == 0 and stdout == outstr.encode()
except TimeoutExpired:
try:
process.kill()
stdout, stderr = process.communicate()
except ProcessLookupError:
pass
2021-01-27 11:04:14 +00:00
return False
2021-01-26 21:36:26 +00:00
2021-01-27 12:48:34 +00:00
def check_script(script):
for pair in current_pairs:
2021-01-26 21:36:26 +00:00
if not check_pair(script, *pair):
2021-01-27 12:48:34 +00:00
return script, False
return script, True
def generate_scripts(max_length):
for length in range(max_length + 1):
for letters in product(chars, repeat=length):
yield "".join(letters)
2021-01-26 21:36:26 +00:00
def find_script(pairs, max_length):
candidates = []
2021-01-27 12:48:34 +00:00
chars_count = len(chars)
num_tasks = int((chars_count ** (max_length + 1) - 1) / (chars_count - 1))
done_tasks = 0
2021-01-27 12:48:34 +00:00
with Pool(processes=8, initializer=set_pairs, initargs=(pairs,)) as pool:
for script, result in pool.imap_unordered(
check_script,
generate_scripts(max_length),
chunksize=10,
):
done_tasks += 1
2021-01-26 21:36:26 +00:00
2021-01-27 12:48:34 +00:00
if done_tasks % 10000 == 0:
print(f"Progress: {done_tasks}/{num_tasks}")
2021-01-26 21:36:26 +00:00
2021-01-27 12:48:34 +00:00
if result:
2021-01-27 17:04:15 +00:00
print(f"> Found candidate: '{script}'")
2021-01-26 21:36:26 +00:00
candidates.append(script)
print("Candidates:", candidates)
if __name__ == '__main__':
print("\nSearching for identity")
find_script((
("1", "1"),
2021-01-27 11:41:45 +00:00
("42", "42"),
("1984", "1984"),
2021-01-27 10:44:44 +00:00
), max_length=3)
2021-01-26 21:36:26 +00:00
2021-01-27 12:48:55 +00:00
print("\nSearching for successor")
find_script((
("1", "2"),
("42", "43"),
("1984", "1985"),
), max_length=5)