Skip to content

Commit

Permalink
Merge pull request #133 from kmyk/issue/131
Browse files Browse the repository at this point in the history
 #131: test: add --print-input option
  • Loading branch information
kmyk authored Jan 8, 2018
2 parents a242bf3 + bb48f4a commit 40ec1e2
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 45 deletions.
110 changes: 65 additions & 45 deletions onlinejudge/implementation/command/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,24 +93,34 @@ def f(x):
return True

def test(args):
# prepare
if not args.test:
args.test = glob_with_format(args.format) # by default
if args.ignore_backup:
args.test = drop_backup_or_hidden_files(args.test)
tests = construct_relationship_of_files(args.test, args.format)
# run tests
if args.error: # float mode
match = lambda a, b: compare_as_floats(a, b, args.error)
else:
match = lambda a, b: a == b
rstrip_targets = ' \t\r\n\f\v\0' # ruby's one, follow AnarchyGolf
slowest, slowest_name = -1, ''
ac_count = 0

for name, it in sorted(tests.items()):
is_printed_input = not args.print_input
def print_input():
nonlocal is_printed_input
if not is_printed_input:
is_printed_input = True
with open(it['in']) as inf:
log.emit('input:\n%s', log.bold(inf.read()))

log.emit('')
log.info('%s', name)

# run the binary
with open(it['in']) as inf:
# run
begin = time.perf_counter()
answer, proc = utils.exec_command(args.command, shell=args.shell, stdin=inf, timeout=args.tle)
end = time.perf_counter()
Expand All @@ -122,50 +132,60 @@ def test(args):
slowest_name = name
log.status('time: %f sec', end - begin)
proc.terminate()
# check
is_ac = True
if proc.returncode is None:
log.failure(log.red('TLE'))
is_ac = False
elif proc.returncode != 0:
log.failure(log.red('RE') + ': return code %d', proc.returncode)
is_ac = False
if 'out' in it:
with open(it['out']) as outf:
correct = outf.read()
if args.rstrip:
correct = correct.rstrip(rstrip_targets)
# compare
if args.mode == 'all':
if not match(answer, correct):
log.failure(log.red('WA'))
if not args.silent:
log.emit('output:\n%s', log.bold(answer))
log.emit('expected:\n%s', log.bold(correct))
is_ac = False
elif args.mode == 'line':
answer = answer .splitlines()
correct = correct.splitlines()
for i, (x, y) in enumerate(zip(answer + [ None ] * len(correct), correct + [ None ] * len(answer))):
if x is None and y is None:
break
elif x is None:
log.failure(log.red('WA') + ': line %d: line is nothing: expected "%s"', i, log.bold(y))
is_ac = False
elif y is None:
log.failure(log.red('WA') + ': line %d: unexpected line: output "%s"', i, log.bold(x))
is_ac = False
elif not match(x, y):
log.failure(log.red('WA') + ': line %d: output "%s": expected "%s"', i, log.bold(x), log.bold(y))
is_ac = False
else:
assert False

# check TLE, RE or not
result = 'AC'
if proc.returncode is None:
log.failure(log.red('TLE'))
result = 'TLE'
print_input()
elif proc.returncode != 0:
log.failure(log.red('RE') + ': return code %d', proc.returncode)
result = 'RE'
print_input()

# check WA or not
if 'out' in it:
with open(it['out']) as outf:
correct = outf.read()
if args.rstrip:
correct = correct.rstrip(rstrip_targets)
# compare
if args.mode == 'all':
if not match(answer, correct):
log.failure(log.red('WA'))
print_input()
if not args.silent:
log.emit('output:\n%s', log.bold(answer))
log.emit('expected:\n%s', log.bold(correct))
result = 'WA'
elif args.mode == 'line':
answer = answer .splitlines()
correct = correct.splitlines()
for i, (x, y) in enumerate(zip(answer + [ None ] * len(correct), correct + [ None ] * len(answer))):
if x is None and y is None:
break
elif x is None:
print_input()
log.failure(log.red('WA') + ': line %d: line is nothing: expected "%s"', i, log.bold(y))
result = 'WA'
elif y is None:
print_input()
log.failure(log.red('WA') + ': line %d: unexpected line: output "%s"', i, log.bold(x))
result = 'WA'
elif not match(x, y):
print_input()
log.failure(log.red('WA') + ': line %d: output "%s": expected "%s"', i, log.bold(x), log.bold(y))
result = 'WA'
else:
if not args.silent:
log.emit(log.bold(answer))
if is_ac:
log.success(log.green('AC'))
ac_count += 1
assert False
else:
if not args.silent:
log.emit(log.bold(answer))
if result == 'AC':
log.success(log.green('AC'))
ac_count += 1

# summarize
log.emit('')
log.status('slowest: %f sec (for %s)', slowest, slowest_name)
Expand Down
1 change: 1 addition & 0 deletions onlinejudge/implementation/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def main(args=None):
subparser.add_argument('-s', '--silent', action='store_true', help='don\'t report output and correct answer even if not AC (for --mode all)')
subparser.add_argument('-e', '--error', type=float, help='check as floating point number: correct if its absolute or relative error doesn\'t exceed it')
subparser.add_argument('-t', '--tle', type=float)
subparser.add_argument('-i', '--print-input', action='store_true', help='print input cases if not AC')
subparser.add_argument('--no-ignore-backup', action='store_false', dest='ignore_backup')
subparser.add_argument('--ignore-backup', action='store_true', help='ignore backup files and hidden files (i.e. files like "*~", "\\#*\\#" and ".*") (default)')
subparser.add_argument('test', nargs='*', help='paths of test cases. (if empty: globbed from --format)')
Expand Down

0 comments on commit 40ec1e2

Please sign in to comment.