Dear all,

  I guess you have tried using the interactive running tool, and somehow get 
frustrated that it is very difficult to use. In particular, it's syntax is 
complicated, and it has no timeouts. (You can manually shut down the frozen 
process though.)

  So after the ordeal I've decided to improve the running tool, and finally 
come to the code below. Here are the improvements:
    -- More intuitive syntax.
    -- Configurable timeout (default to 1 second).

  Hope that it helps you in the later rounds!

  (Googlers: please help me to confirm the copyright situation of the program. 
Thanks!)

Regards,
WC Leung.

Here's some sample output of the program:

D:\Documents\codelite_c++\codejam-2019-qual-d>python interactive_runner.py 
Debug\codejam-2019-qual-d
Judge return code: 1
Judge standard error:
 Case #1 fails:
Answer has wrong number of tokens.

Solution timed out.
Solution standard error:
 testing

Here is the source code of the program:

# Google Code Jam interactive test runner.
# Contributors: Google and WC Leung ([email protected]).
#
# This is only intended as a convenient tool to help contestants test solutions
# locally. In particular, it is not identical to the implementation on our
# server, which is more complex.
#
# To use this program, put "testing_tool.py" in the current directory, and type
#     python interactive_runner.py <cmd_line_solution>
#
# For example:
#     python interactive_runner.py ./my_binary
#
# Usage (copied from python interactive_runner.py -h)
# ==============================================================================
# interactive_runner.py [-h] [-t TIMEOUT] [-j JUDGE] [--test TEST] solution
#
# Google Code Jam interactive test runner.
#
# positional arguments:
#   solution              Command line to the solution program.
#
# optional arguments:
#   -h, --help            show this help message and exit
#   -t TIMEOUT, --timeout TIMEOUT
#                         Timeout in seconds. (default: 1.0)
#   -j JUDGE, --judge JUDGE
#                         Command line to the judge program. (default: python
#                         testing_tool.py)
#   --test TEST           The index of the first test to run. Use the default to
#                         run all tests. (default: 0)

import argparse
import sys
import subprocess
import threading
import time


class SubprocessThread(threading.Thread):
    def __init__(self,
                 args,
                 stdin_pipe=subprocess.PIPE,
                 stdout_pipe=subprocess.PIPE,
                 stderr_pipe=subprocess.PIPE):
        threading.Thread.__init__(self)
        self.p = subprocess.Popen(
            args, stdin=stdin_pipe, stdout=stdout_pipe, stderr=stderr_pipe)

    def run(self):
        try:
            self.return_code = self.p.wait()
            self.stderr = "" if self.p.stderr is None else self.p.stderr.read()
        except (SystemError, OSError):
            self.return_code = -1
            self.stderr = "The process crashed or produced too much output."

    def terminate(self):
        self.p.terminate()
        self.stderr = "" if self.p.stderr is None else self.p.stderr.read()


# Main program
parser = argparse.ArgumentParser(
    description='Google Code Jam interactive test runner.',
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-t', '--timeout', default=1.0,
                    type=float, help='Timeout in seconds.')
parser.add_argument('-j', '--judge', default='python testing_tool.py',
                    help='Command line to the judge program.')
parser.add_argument('--test', default=0, type=int,
                    help='The index of the first test to run. Use the default 
to run all tests.')
parser.add_argument('solution', help='Command line to the solution program.')

args = parser.parse_args()

cmd_parser = argparse.ArgumentParser()
cmd_parser.add_argument('args', nargs=argparse.REMAINDER)

args_solution = cmd_parser.parse_args(args.solution.split())
t_sol = SubprocessThread(args_solution.args)

args_judge = cmd_parser.parse_args(args.judge.split())
args_judge.args.append(str(args.test))
t_judge = SubprocessThread(args_judge.args,
                           stdin_pipe=t_sol.p.stdout,
                           stdout_pipe=t_sol.p.stdin)
t_sol.start()
t_judge.start()

# Execute until timeout.
start = time.time()
t_sol.join(args.timeout)
t_judge.join(max(args.timeout - (time.time() - start), 0))

# Output result.
if t_judge.is_alive():
    print("Judge timed out.")
    t_judge.terminate()
else:
    print("Judge return code:", t_judge.return_code)
print("Judge standard error:\n", t_judge.stderr.decode())

if t_sol.is_alive():
    print("Solution timed out.")
    t_sol.terminate()
else:
    print("Solution return code:", t_sol.return_code)
print("Solution standard error:\n", t_sol.stderr.decode())

-- 
You received this message because you are subscribed to the Google Groups 
"Google Code Jam" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/google-code/4e0f47a3-d46b-4604-9287-513eb29a786e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to