annotate 2.00/testcases.py @ 40:af9c45708987

Cemented a decision previously being unsure about The mere presense of the tasknames configuration variable now always makes problem names to be printed. This is not new, but the old behaviour (only printing names if we test more than one problem), previously commented out, has now been removed altogether.
author Oleg Oshmyan <chortos@inbox.lv>
date Sun, 05 Dec 2010 14:34:24 +0100
parents 2b459f9743b4
children 164395af969d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
1 #! /usr/bin/env python
16
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
2 # Copyright (c) 2010 Chortos-2 <chortos@inbox.lv>
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
3
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
4 from __future__ import division, with_statement
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
5
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
6 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
7 from compat import *
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
8 import files, problem, config
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
9 except ImportError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
10 import __main__
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
11 __main__.import_error(sys.exc_info()[1])
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
12 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
13 from __main__ import clock, options
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
14
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
15 import glob, re, sys, tempfile, time
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
16 from subprocess import Popen, PIPE, STDOUT
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
17
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
18 import os
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
19 devnull = open(os.path.devnull, 'w+')
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
20
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
21 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
22 from signal import SIGTERM, SIGKILL
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
23 except ImportError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
24 SIGTERM = 15
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
25 SIGKILL = 9
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
26
16
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
27 try:
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
28 from _subprocess import TerminateProcess
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
29 except ImportError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
30 # CPython 2.5 does define _subprocess.TerminateProcess even though it is
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
31 # not used in the subprocess module, but maybe something else does not
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
32 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
33 import ctypes
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
34 TerminateProcess = ctypes.windll.kernel32.TerminateProcess
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
35 except (ImportError, AttributeError):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
36 TerminateProcess = None
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
37
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
38
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
39 # Do the hacky-wacky dark magic needed to catch presses of the Escape button.
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
40 # If only Python supported forcible termination of threads...
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
41 if not sys.stdin.isatty():
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
42 canceled = init_canceled = lambda: False
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
43 pause = None
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
44 else:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
45 try:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
46 # Windows has select() too, but it is not the select() we want
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
47 import msvcrt
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
48 except ImportError:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
49 try:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
50 import select, termios, tty, atexit
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
51 except ImportError:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
52 # It cannot be helped!
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
53 # Silently disable support for killing the program being tested
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
54 canceled = init_canceled = lambda: False
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
55 pause = None
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
56 else:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
57 def cleanup(old=termios.tcgetattr(sys.stdin.fileno())):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
58 termios.tcsetattr(sys.stdin.fileno(), termios.TCSAFLUSH, old)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
59 atexit.register(cleanup)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
60 del cleanup
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
61 tty.setcbreak(sys.stdin.fileno())
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
62 def canceled(select=select.select, stdin=sys.stdin, read=sys.stdin.read):
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
63 while select((stdin,), (), (), 0)[0]:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
64 if read(1) == '\33':
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
65 return True
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
66 return False
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
67 def init_canceled():
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
68 while select.select((sys.stdin,), (), (), 0)[0]:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
69 sys.stdin.read(1)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
70 def pause():
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
71 sys.stdin.read(1)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
72 else:
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
73 def canceled(kbhit=msvcrt.kbhit, getch=msvcrt.getch):
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
74 while kbhit():
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
75 c = getch()
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
76 if c == '\33':
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
77 return True
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
78 elif c == '\0':
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
79 # Let's hope no-one is fiddling with this
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
80 getch()
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
81 return False
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
82 def init_canceled():
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
83 while msvcrt.kbhit():
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
84 msvcrt.getch()
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
85 def pause():
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
86 msvcrt.getch()
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
87
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
88
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
89 __all__ = ('TestCase', 'load_problem', 'TestCaseNotPassed',
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
90 'TimeLimitExceeded', 'CanceledByUser', 'WrongAnswer',
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
91 'NonZeroExitCode', 'CannotStartTestee',
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
92 'CannotStartValidator', 'CannotReadOutputFile',
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
93 'CannotReadInputFile', 'CannotReadAnswerFile')
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
94
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
95
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
96
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
97 # Exceptions
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
98
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
99 class TestCaseNotPassed(Exception): __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
100 class TimeLimitExceeded(TestCaseNotPassed): __slots__ = ()
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
101 class CanceledByUser(TestCaseNotPassed): __slots__ = ()
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
102
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
103 class WrongAnswer(TestCaseNotPassed):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
104 __slots__ = 'comment'
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
105 def __init__(self, comment=''):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
106 self.comment = comment
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
107
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
108 class NonZeroExitCode(TestCaseNotPassed):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
109 __slots__ = 'exitcode'
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
110 def __init__(self, exitcode):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
111 self.exitcode = exitcode
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
112
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
113 class ExceptionWrapper(TestCaseNotPassed):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
114 __slots__ = 'upstream'
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
115 def __init__(self, upstream):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
116 self.upstream = upstream
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
117
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
118 class CannotStartTestee(ExceptionWrapper): __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
119 class CannotStartValidator(ExceptionWrapper): __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
120 class CannotReadOutputFile(ExceptionWrapper): __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
121 class CannotReadInputFile(ExceptionWrapper): __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
122 class CannotReadAnswerFile(ExceptionWrapper): __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
123
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
124
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
125
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
126 # Helper context managers
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
127
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
128 class CopyDeleting(object):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
129 __slots__ = 'case', 'file', 'name'
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
130
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
131 def __init__(self, case, file, name):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
132 self.case = case
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
133 self.file = file
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
134 self.name = name
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
135
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
136 def __enter__(self):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
137 if self.name:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
138 try:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
139 self.file.copy(self.name)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
140 except:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
141 try:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
142 self.__exit__(None, None, None)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
143 except:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
144 pass
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
145 raise
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
146
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
147 def __exit__(self, exc_type, exc_val, exc_tb):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
148 if self.name:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
149 self.case.files_to_delete.append(self.name)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
150
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
151
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
152 class Copying(object):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
153 __slots__ = 'file', 'name'
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
154
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
155 def __init__(self, file, name):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
156 self.file = file
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
157 self.name = name
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
158
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
159 def __enter__(self):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
160 if self.name:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
161 self.file.copy(self.name)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
162
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
163 def __exit__(self, exc_type, exc_val, exc_tb):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
164 pass
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
165
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
166
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
167
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
168 # Test case types
16
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
169
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
170 class TestCase(object):
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
171 __slots__ = ('problem', 'id', 'isdummy', 'infile', 'outfile', 'points',
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
172 'process', 'time_started', 'time_stopped', 'time_limit_string',
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
173 'realinname', 'realoutname', 'maxtime', 'maxmemory',
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
174 'has_called_back', 'files_to_delete')
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
175
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
176 if ABCMeta:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
177 __metaclass__ = ABCMeta
16
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
178
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
179 def __init__(case, prob, id, isdummy, points):
16
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
180 case.problem = prob
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
181 case.id = id
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
182 case.isdummy = isdummy
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
183 case.points = points
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
184 case.maxtime = case.problem.config.maxtime
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
185 case.maxmemory = case.problem.config.maxmemory
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
186 if case.maxtime:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
187 case.time_limit_string = '/%.3f' % case.maxtime
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
188 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
189 case.time_limit_string = ''
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
190 if not isdummy:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
191 case.realinname = case.problem.config.testcaseinname
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
192 case.realoutname = case.problem.config.testcaseoutname
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
193 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
194 case.realinname = case.problem.config.dummyinname
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
195 case.realoutname = case.problem.config.dummyoutname
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
196
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
197 @abstractmethod
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
198 def test(case): raise NotImplementedError
16
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
199
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
200 def __call__(case, callback):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
201 case.has_called_back = False
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
202 case.files_to_delete = []
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
203 try:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
204 return case.test(callback)
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
205 finally:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
206 now = clock()
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
207 if not getattr(case, 'time_started', None):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
208 case.time_started = case.time_stopped = now
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
209 elif not getattr(case, 'time_stopped', None):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
210 case.time_stopped = now
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
211 if not case.has_called_back:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
212 callback()
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
213 case.cleanup()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
214
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
215 def cleanup(case):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
216 #if getattr(case, 'infile', None):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
217 # case.infile.close()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
218 #if getattr(case, 'outfile', None):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
219 # case.outfile.close()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
220 if getattr(case, 'process', None):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
221 # Try killing after three unsuccessful TERM attempts in a row
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
222 # (except on Windows, where TERMing is killing)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
223 for i in range(3):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
224 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
225 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
226 case.process.terminate()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
227 except AttributeError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
228 # Python 2.5
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
229 if TerminateProcess and hasattr(proc, '_handle'):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
230 # Windows API
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
231 TerminateProcess(proc._handle, 1)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
232 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
233 # POSIX
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
234 os.kill(proc.pid, SIGTERM)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
235 except Exception:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
236 time.sleep(0)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
237 case.process.poll()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
238 else:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
239 case.process.wait()
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
240 break
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
241 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
242 # If killing the process is unsuccessful three times in a row,
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
243 # just silently stop trying
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
244 for i in range(3):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
245 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
246 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
247 case.process.kill()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
248 except AttributeError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
249 # Python 2.5
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
250 if TerminateProcess and hasattr(proc, '_handle'):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
251 # Windows API
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
252 TerminateProcess(proc._handle, 1)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
253 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
254 # POSIX
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
255 os.kill(proc.pid, SIGKILL)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
256 except Exception:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
257 time.sleep(0)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
258 case.process.poll()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
259 else:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
260 case.process.wait()
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
261 break
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
262 if case.files_to_delete:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
263 for name in case.files_to_delete:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
264 try:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
265 os.remove(name)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
266 except Exception:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
267 # It can't be helped
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
268 pass
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
269
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
270 def open_infile(case):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
271 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
272 case.infile = files.File('/'.join((case.problem.name, case.realinname.replace('$', case.id))))
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
273 except IOError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
274 e = sys.exc_info()[1]
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
275 raise CannotReadInputFile(e)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
276
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
277 def open_outfile(case):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
278 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
279 case.outfile = files.File('/'.join((case.problem.name, case.realoutname.replace('$', case.id))))
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
280 except IOError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
281 e = sys.exc_info()[1]
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
282 raise CannotReadAnswerFile(e)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
283
16
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
284
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
285 class ValidatedTestCase(TestCase):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
286 __slots__ = 'validator'
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
287
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
288 def __init__(case, *args):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
289 TestCase.__init__(case, *args)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
290 if not case.problem.config.tester:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
291 case.validator = None
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
292 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
293 case.validator = case.problem.config.tester
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
294
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
295 def validate(case, output):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
296 if not case.validator:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
297 # Compare the output with the reference output
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
298 case.open_outfile()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
299 with case.outfile.open() as refoutput:
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
300 for line, refline in zip_longest(output, refoutput):
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
301 if refline is not None and not isinstance(refline, basestring):
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
302 line = bytes(line, sys.getdefaultencoding())
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
303 if line != refline:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
304 raise WrongAnswer
24
c23d81f4a1a3 Score returned by TestCase.__call__() is now normalized to 0..1
Oleg Oshmyan <chortos@inbox.lv>
parents: 23
diff changeset
305 return 1
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
306 elif callable(case.validator):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
307 return case.validator(output)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
308 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
309 # Call the validator program
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
310 output.close()
23
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
311 if case.problem.config.ansname:
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
312 case.open_outfile()
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
313 case.outfile.copy(case.problem.config.ansname)
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
314 try:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
315 case.process = Popen(case.validator, stdin=devnull, stdout=PIPE, stderr=STDOUT, universal_newlines=True, bufsize=-1)
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
316 except OSError:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
317 raise CannotStartValidator(sys.exc_info()[1])
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
318 comment = case.process.communicate()[0].strip()
26
5bbb68833868 Output text improvements
Oleg Oshmyan <chortos@inbox.lv>
parents: 25
diff changeset
319 match = re.match(r'(?i)(ok|(?:correct|wrong)(?:(?:\s|_)*answer)?)(?:$|\s+|[.,!:]+\s*)', comment)
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
320 if match:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
321 comment = comment[match.end():]
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
322 if not case.problem.config.maxexitcode:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
323 if case.process.returncode:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
324 raise WrongAnswer(comment)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
325 else:
24
c23d81f4a1a3 Score returned by TestCase.__call__() is now normalized to 0..1
Oleg Oshmyan <chortos@inbox.lv>
parents: 23
diff changeset
326 return 1, comment
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
327 else:
24
c23d81f4a1a3 Score returned by TestCase.__call__() is now normalized to 0..1
Oleg Oshmyan <chortos@inbox.lv>
parents: 23
diff changeset
328 return case.process.returncode / case.problem.config.maxexitcode, comment
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
329
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
330
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
331 class BatchTestCase(ValidatedTestCase):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
332 __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
333
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
334 def test(case, callback):
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
335 init_canceled()
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
336 if sys.platform == 'win32' or not case.maxmemory:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
337 preexec_fn = None
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
338 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
339 def preexec_fn():
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
340 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
341 import resource
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
342 maxmemory = int(case.maxmemory * 1048576)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
343 resource.setrlimit(resource.RLIMIT_AS, (maxmemory, maxmemory))
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
344 # I would also set a CPU time limit but I do not want the time
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
345 # that passes between the calls to fork and exec to be counted in
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
346 except MemoryError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
347 # We do not have enough memory for ourselves;
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
348 # let the parent know about this
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
349 raise
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
350 except Exception:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
351 # Well, at least we tried
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
352 pass
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
353 case.open_infile()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
354 case.time_started = None
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
355 if case.problem.config.stdio:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
356 if options.erase and not case.validator:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
357 # TODO: re-use the same file name if possible
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
358 # FIXME: 2.5 lacks the delete parameter
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
359 with tempfile.NamedTemporaryFile(delete=False) as f:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
360 inputdatafname = f.name
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
361 contextmgr = CopyDeleting(case, case.infile, inputdatafname)
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
362 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
363 inputdatafname = case.problem.config.inname
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
364 contextmgr = Copying(case.infile, inputdatafname)
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
365 with contextmgr:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
366 # FIXME: this U doesn't do anything good for the child process, does it?
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
367 with open(inputdatafname, 'rU') as infile:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
368 with tempfile.TemporaryFile('w+') if options.erase and not case.validator else open(case.problem.config.outname, 'w+') as outfile:
23
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
369 # TODO: make sure outfile.file is passed to Popen if needed
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
370 try:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
371 try:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
372 case.process = Popen(case.problem.config.path, stdin=infile, stdout=outfile, stderr=devnull, universal_newlines=True, bufsize=-1, preexec_fn=preexec_fn)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
373 except MemoryError:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
374 # If there is not enough memory for the forked test.py,
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
375 # opt for silent dropping of the limit
26
5bbb68833868 Output text improvements
Oleg Oshmyan <chortos@inbox.lv>
parents: 25
diff changeset
376 # TODO: show a warning somewhere
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
377 case.process = Popen(case.problem.config.path, stdin=infile, stdout=outfile, stderr=devnull, universal_newlines=True, bufsize=-1)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
378 except OSError:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
379 raise CannotStartTestee(sys.exc_info()[1])
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
380 case.time_started = clock()
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
381 time_next_check = case.time_started + .15
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
382 if not case.maxtime:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
383 while True:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
384 exitcode, now = case.process.poll(), clock()
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
385 if exitcode is not None:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
386 case.time_stopped = now
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
387 break
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
388 # For some reason (probably Microsoft's fault),
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
389 # msvcrt.kbhit() is slow as hell
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
390 else:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
391 if now >= time_next_check:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
392 if canceled():
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
393 raise CanceledByUser
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
394 else:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
395 time_next_check = now + .15
27
dc4be35d17e0 Bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 26
diff changeset
396 time.sleep(0)
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
397 else:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
398 time_end = case.time_started + case.maxtime
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
399 while True:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
400 exitcode, now = case.process.poll(), clock()
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
401 if exitcode is not None:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
402 case.time_stopped = now
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
403 break
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
404 elif now >= time_end:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
405 raise TimeLimitExceeded
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
406 else:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
407 if now >= time_next_check:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
408 if canceled():
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
409 raise CanceledByUser
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
410 else:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
411 time_next_check = now + .15
27
dc4be35d17e0 Bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 26
diff changeset
412 time.sleep(0)
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
413 if config.globalconf.force_zero_exitcode and case.process.returncode:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
414 raise NonZeroExitCode(case.process.returncode)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
415 callback()
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
416 case.has_called_back = True
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
417 outfile.seek(0)
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
418 return case.validate(outfile)
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
419 else:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
420 case.infile.copy(case.problem.config.inname)
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
421 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
422 try:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
423 case.process = Popen(case.problem.config.path, stdin=devnull, stdout=devnull, stderr=STDOUT, preexec_fn=preexec_fn)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
424 except MemoryError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
425 # If there is not enough memory for the forked test.py,
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
426 # opt for silent dropping of the limit
26
5bbb68833868 Output text improvements
Oleg Oshmyan <chortos@inbox.lv>
parents: 25
diff changeset
427 # TODO: show a warning somewhere
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
428 case.process = Popen(case.problem.config.path, stdin=devnull, stdout=devnull, stderr=STDOUT)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
429 except OSError:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
430 raise CannotStartTestee(sys.exc_info()[1])
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
431 case.time_started = clock()
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
432 time_next_check = case.time_started + .15
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
433 if not case.maxtime:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
434 while True:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
435 exitcode, now = case.process.poll(), clock()
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
436 if exitcode is not None:
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
437 case.time_stopped = now
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
438 break
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
439 else:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
440 if now >= time_next_check:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
441 if canceled():
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
442 raise CanceledByUser
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
443 else:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
444 time_next_check = now + .15
27
dc4be35d17e0 Bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 26
diff changeset
445 time.sleep(0)
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
446 else:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
447 time_end = case.time_started + case.maxtime
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
448 while True:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
449 exitcode, now = case.process.poll(), clock()
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
450 if exitcode is not None:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
451 case.time_stopped = now
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
452 break
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
453 elif now >= time_end:
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
454 raise TimeLimitExceeded
25
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
455 else:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
456 if now >= time_next_check:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
457 if canceled():
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
458 raise CanceledByUser
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
459 else:
b500e117080e Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents: 24
diff changeset
460 time_next_check = now + .15
27
dc4be35d17e0 Bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 26
diff changeset
461 time.sleep(0)
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
462 if config.globalconf.force_zero_exitcode and case.process.returncode:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
463 raise NonZeroExitCode(case.process.returncode)
22
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
464 callback()
f07b7a431ea6 Further 2.00 work
Oleg Oshmyan <chortos@inbox.lv>
parents: 21
diff changeset
465 case.has_called_back = True
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
466 with open(case.problem.config.outname, 'rU') as output:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
467 return case.validate(output)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
468
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
469
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
470 # This is the only test case type not executing any programs to be tested
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
471 class OutputOnlyTestCase(ValidatedTestCase):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
472 __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
473 def cleanup(case): pass
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
474
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
475 class BestOutputTestCase(ValidatedTestCase):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
476 __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
477
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
478 # This is the only test case type executing two programs simultaneously
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
479 class ReactiveTestCase(TestCase):
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
480 __slots__ = ()
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
481 # The basic idea is to launch the program to be tested and the grader
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
482 # and to pipe their standard I/O from and to each other,
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
483 # and then to capture the grader's exit code and use it
26
5bbb68833868 Output text improvements
Oleg Oshmyan <chortos@inbox.lv>
parents: 25
diff changeset
484 # like the exit code of an output validator is used.
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
485
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
486
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
487 def load_problem(prob, _types={'batch' : BatchTestCase,
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
488 'outonly' : OutputOnlyTestCase,
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
489 'bestout' : BestOutputTestCase,
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
490 'reactive': ReactiveTestCase}):
39
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
491 # We will need to iterate over these configuration variables twice
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
492 try:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
493 len(prob.config.dummies)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
494 except Exception:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
495 prob.config.dummies = tuple(prob.config.dummies)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
496 try:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
497 len(prob.config.tests)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
498 except Exception:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
499 prob.config.tests = tuple(prob.config.tests)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
500
23
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
501 if options.legacy:
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
502 prob.config.usegroups = False
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
503 prob.config.tests = list(prob.config.tests)
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
504 for i, name in enumerate(prob.config.tests):
39
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
505 # Same here; we'll need to iterate over them twice
23
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
506 try:
39
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
507 l = len(name)
23
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
508 except Exception:
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
509 try:
39
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
510 name = tuple(name)
23
c1f52b5d80d6 Compatibility and bug fixes
Oleg Oshmyan <chortos@inbox.lv>
parents: 22
diff changeset
511 except TypeError:
39
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
512 name = (name,)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
513 l = len(name)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
514 if len(name) > 1:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
515 prob.config.usegroups = True
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
516 break
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
517 elif not len(name):
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
518 prob.config.tests[i] = (name,)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
519
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
520 # First get prob.cache.padoutput right,
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
521 # then yield the actual test cases
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
522 for i in prob.config.dummies:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
523 s = 'sample ' + str(i).zfill(prob.config.paddummies)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
524 prob.cache.padoutput = max(prob.cache.padoutput, len(s))
16
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
525 if prob.config.usegroups:
39
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
526 for group in prob.config.tests:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
527 for i in group:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
528 s = str(i).zfill(prob.config.padtests)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
529 prob.cache.padoutput = max(prob.cache.padoutput, len(s))
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
530 for i in prob.config.dummies:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
531 s = str(i).zfill(prob.config.paddummies)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
532 yield _types[prob.config.kind](prob, s, True, 0)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
533 for group in prob.config.tests:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
534 yield problem.TestGroup()
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
535 for i in group:
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
536 s = str(i).zfill(prob.config.padtests)
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
537 yield _types[prob.config.kind](prob, s, False, prob.config.pointmap.get(i, prob.config.pointmap.get(None, prob.config.maxexitcode if prob.config.maxexitcode else 1)))
2b459f9743b4 Test groups are now supported
Oleg Oshmyan <chortos@inbox.lv>
parents: 27
diff changeset
538 yield problem.test_context_end
16
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
539 else:
f2279b7602d3 Initial 2.00 commit
Oleg Oshmyan <chortos@inbox.lv>
parents:
diff changeset
540 for i in prob.config.tests:
21
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
541 s = str(i).zfill(prob.config.padtests)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
542 prob.cache.padoutput = max(prob.cache.padoutput, len(s))
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
543 for i in prob.config.dummies:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
544 s = str(i).zfill(prob.config.paddummies)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
545 yield _types[prob.config.kind](prob, s, True, 0)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
546 for i in prob.config.tests:
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
547 s = str(i).zfill(prob.config.padtests)
ec6f1a132109 A pretty usable version
Oleg Oshmyan <chortos@inbox.lv>
parents: 16
diff changeset
548 yield _types[prob.config.kind](prob, s, False, prob.config.pointmap.get(i, prob.config.pointmap.get(None, prob.config.maxexitcode if prob.config.maxexitcode else 1)))