Mercurial > ~astiob > upreckon > hgweb
annotate testcases.py @ 104:8f46e84922f9
Output-only problems are now supported
| author | Oleg Oshmyan <chortos@inbox.lv> | 
|---|---|
| date | Fri, 08 Apr 2011 17:42:30 +0300 | 
| parents | 4e6f231f055f | 
| children | 9f922b11c98a | 
| rev | line source | 
|---|---|
| 77 
69eadc60f4e2
Memory limit is now applied to the RSS when os.wait4 is available
 Oleg Oshmyan <chortos@inbox.lv> parents: 
76diff
changeset | 1 # Copyright (c) 2010-2011 Chortos-2 <chortos@inbox.lv> | 
| 16 | 2 | 
| 43 | 3 # TODO: copy the ansfile if not options.erase even if no validator is used | 
| 4 | |
| 21 | 5 from __future__ import division, with_statement | 
| 6 | |
| 91 | 7 from compat import * | 
| 8 import files, problem, config | |
| 9 from __main__ import options | |
| 21 | 10 | 
| 11 import glob, re, sys, tempfile, time | |
| 12 from subprocess import Popen, PIPE, STDOUT | |
| 13 | |
| 14 import os | |
| 15 devnull = open(os.path.devnull, 'w+') | |
| 16 | |
| 85 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 17 if options.autotime: | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 18 # This is really a dirty hack that assumes that sleep() does not spend | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 19 # the CPU time of the current process and that if clock() measures | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 20 # wall-clock time, then it is more precise than time() is. Both these | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 21 # assumptions are true on all platforms I have tested this on so far, | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 22 # but I am not aware of any guarantee that they will both be true | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 23 # on every other platform. | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 24 c = time.clock() | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 25 time.sleep(1) | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 26 c = time.clock() - c | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 27 if int(c + .5) == 1: | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 28 clock = time.clock | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 29 else: | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 30 clock = time.time | 
| 
741ae3391b61
Moved clock/time detection into platform-specific modules and testcases
 Oleg Oshmyan <chortos@inbox.lv> parents: 
83diff
changeset | 31 | 
| 21 | 32 try: | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 33 from win32 import * | 
| 72 
7520b6bb6636
Windows Error Reporting is now suppressed (at least the dialogs)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
71diff
changeset | 34 except Exception: | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 35 from unix import * | 
| 22 | 36 | 
| 21 | 37 __all__ = ('TestCase', 'load_problem', 'TestCaseNotPassed', | 
| 22 | 38 'TimeLimitExceeded', 'CanceledByUser', 'WrongAnswer', | 
| 39 'NonZeroExitCode', 'CannotStartTestee', | |
| 40 'CannotStartValidator', 'CannotReadOutputFile', | |
| 81 
24752db487c5
Fixed errors in the win32 module
 Oleg Oshmyan <chortos@inbox.lv> parents: 
79diff
changeset | 41 'CannotReadInputFile', 'CannotReadAnswerFile', | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 42 'MemoryLimitExceeded', 'CPUTimeLimitExceeded', | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 43 'WallTimeLimitExceeded') | 
| 21 | 44 | 
| 45 | |
| 46 | |
| 47 # Exceptions | |
| 48 | |
| 49 class TestCaseNotPassed(Exception): __slots__ = () | |
| 90 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 50 class TestCaseSkipped(TestCaseNotPassed): __slots__ = () | 
| 21 | 51 class TimeLimitExceeded(TestCaseNotPassed): __slots__ = () | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 52 class CPUTimeLimitExceeded(TimeLimitExceeded): __slots__ = () | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 53 class WallTimeLimitExceeded(TimeLimitExceeded): __slots__ = () | 
| 77 
69eadc60f4e2
Memory limit is now applied to the RSS when os.wait4 is available
 Oleg Oshmyan <chortos@inbox.lv> parents: 
76diff
changeset | 54 class MemoryLimitExceeded(TestCaseNotPassed): __slots__ = () | 
| 22 | 55 class CanceledByUser(TestCaseNotPassed): __slots__ = () | 
| 21 | 56 | 
| 57 class WrongAnswer(TestCaseNotPassed): | |
| 58 __slots__ = 'comment' | |
| 59 def __init__(self, comment=''): | |
| 60 self.comment = comment | |
| 61 | |
| 62 class NonZeroExitCode(TestCaseNotPassed): | |
| 63 __slots__ = 'exitcode' | |
| 64 def __init__(self, exitcode): | |
| 65 self.exitcode = exitcode | |
| 66 | |
| 67 class ExceptionWrapper(TestCaseNotPassed): | |
| 68 __slots__ = 'upstream' | |
| 69 def __init__(self, upstream): | |
| 70 self.upstream = upstream | |
| 71 | |
| 72 class CannotStartTestee(ExceptionWrapper): __slots__ = () | |
| 73 class CannotStartValidator(ExceptionWrapper): __slots__ = () | |
| 74 class CannotReadOutputFile(ExceptionWrapper): __slots__ = () | |
| 75 class CannotReadInputFile(ExceptionWrapper): __slots__ = () | |
| 76 class CannotReadAnswerFile(ExceptionWrapper): __slots__ = () | |
| 77 | |
| 78 | |
| 79 | |
| 22 | 80 # Helper context managers | 
| 81 | |
| 82 class CopyDeleting(object): | |
| 83 __slots__ = 'case', 'file', 'name' | |
| 84 | |
| 85 def __init__(self, case, file, name): | |
| 86 self.case = case | |
| 87 self.file = file | |
| 88 self.name = name | |
| 89 | |
| 90 def __enter__(self): | |
| 91 if self.name: | |
| 92 try: | |
| 93 self.file.copy(self.name) | |
| 94 except: | |
| 95 try: | |
| 96 self.__exit__(None, None, None) | |
| 97 except: | |
| 98 pass | |
| 99 raise | |
| 100 | |
| 101 def __exit__(self, exc_type, exc_val, exc_tb): | |
| 102 if self.name: | |
| 103 self.case.files_to_delete.append(self.name) | |
| 104 | |
| 105 | |
| 106 class Copying(object): | |
| 107 __slots__ = 'file', 'name' | |
| 108 | |
| 109 def __init__(self, file, name): | |
| 110 self.file = file | |
| 111 self.name = name | |
| 112 | |
| 113 def __enter__(self): | |
| 114 if self.name: | |
| 115 self.file.copy(self.name) | |
| 116 | |
| 117 def __exit__(self, exc_type, exc_val, exc_tb): | |
| 118 pass | |
| 119 | |
| 120 | |
| 121 | |
| 21 | 122 # Test case types | 
| 16 | 123 | 
| 124 class TestCase(object): | |
| 21 | 125 __slots__ = ('problem', 'id', 'isdummy', 'infile', 'outfile', 'points', | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 126 'process', 'time_started', 'time_stopped', | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 127 'realinname', 'realoutname', 'maxcputime', 'maxwalltime', | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 128 'maxmemory', 'has_called_back', 'files_to_delete', | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 129 'cpu_time_limit_string', 'wall_time_limit_string', | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 130 'time_limit_string') | 
| 104 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 131 needs_realinname = True | 
| 21 | 132 | 
| 133 if ABCMeta: | |
| 134 __metaclass__ = ABCMeta | |
| 16 | 135 | 
| 21 | 136 def __init__(case, prob, id, isdummy, points): | 
| 16 | 137 case.problem = prob | 
| 21 | 138 case.id = id | 
| 139 case.isdummy = isdummy | |
| 140 case.points = points | |
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 141 case.maxcputime = case.problem.config.maxcputime | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 142 case.maxwalltime = case.problem.config.maxwalltime | 
| 21 | 143 case.maxmemory = case.problem.config.maxmemory | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 144 if case.maxcputime: | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 145 case.cpu_time_limit_string = '/%.3f' % case.maxcputime | 
| 21 | 146 else: | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 147 case.cpu_time_limit_string = '' | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 148 if case.maxwalltime: | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 149 case.wall_time_limit_string = '/%.3f' % case.maxwalltime | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 150 else: | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 151 case.wall_time_limit_string = '' | 
| 21 | 152 if not isdummy: | 
| 104 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 153 if case.needs_realinname: | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 154 case.realinname = case.problem.config.testcaseinname | 
| 21 | 155 case.realoutname = case.problem.config.testcaseoutname | 
| 156 else: | |
| 104 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 157 if case.needs_realinname: | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 158 case.realinname = case.problem.config.dummyinname | 
| 21 | 159 case.realoutname = case.problem.config.dummyoutname | 
| 160 | |
| 161 @abstractmethod | |
| 90 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 162 def test(case): | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 163 raise NotImplementedError | 
| 16 | 164 | 
| 22 | 165 def __call__(case, callback): | 
| 166 case.has_called_back = False | |
| 167 case.files_to_delete = [] | |
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 168 case.time_limit_string = case.wall_time_limit_string | 
| 21 | 169 try: | 
| 22 | 170 return case.test(callback) | 
| 21 | 171 finally: | 
| 22 | 172 now = clock() | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 173 if getattr(case, 'time_started', None) is None: | 
| 22 | 174 case.time_started = case.time_stopped = now | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 175 elif getattr(case, 'time_stopped', None) is None: | 
| 22 | 176 case.time_stopped = now | 
| 177 if not case.has_called_back: | |
| 178 callback() | |
| 21 | 179 case.cleanup() | 
| 180 | |
| 90 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 181 @property | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 182 def has_iofiles(case): | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 183 return False | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 184 | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 185 @property | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 186 def has_ansfile(case): | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 187 return False | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 188 | 
| 21 | 189 def cleanup(case): | 
| 190 #if getattr(case, 'infile', None): | |
| 191 # case.infile.close() | |
| 192 #if getattr(case, 'outfile', None): | |
| 193 # case.outfile.close() | |
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 194 if getattr(case, 'process', None) and case.process.returncode is None: | 
| 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 195 # Try KILLing after three unsuccessful TERM attempts in a row | 
| 21 | 196 for i in range(3): | 
| 197 try: | |
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 198 terminate(case.process) | 
| 21 | 199 except Exception: | 
| 200 time.sleep(0) | |
| 201 case.process.poll() | |
| 202 else: | |
| 22 | 203 case.process.wait() | 
| 21 | 204 break | 
| 205 else: | |
| 206 # If killing the process is unsuccessful three times in a row, | |
| 207 # just silently stop trying | |
| 208 for i in range(3): | |
| 209 try: | |
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 210 kill(case.process) | 
| 21 | 211 except Exception: | 
| 212 time.sleep(0) | |
| 213 case.process.poll() | |
| 214 else: | |
| 22 | 215 case.process.wait() | 
| 21 | 216 break | 
| 22 | 217 if case.files_to_delete: | 
| 218 for name in case.files_to_delete: | |
| 219 try: | |
| 220 os.remove(name) | |
| 221 except Exception: | |
| 222 # It can't be helped | |
| 223 pass | |
| 21 | 224 | 
| 225 def open_infile(case): | |
| 226 try: | |
| 227 case.infile = files.File('/'.join((case.problem.name, case.realinname.replace('$', case.id)))) | |
| 228 except IOError: | |
| 229 e = sys.exc_info()[1] | |
| 230 raise CannotReadInputFile(e) | |
| 231 | |
| 232 def open_outfile(case): | |
| 233 try: | |
| 234 case.outfile = files.File('/'.join((case.problem.name, case.realoutname.replace('$', case.id)))) | |
| 235 except IOError: | |
| 236 e = sys.exc_info()[1] | |
| 237 raise CannotReadAnswerFile(e) | |
| 238 | |
| 16 | 239 | 
| 90 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 240 class SkippedTestCase(TestCase): | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 241 __slots__ = () | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 242 | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 243 def test(case, callback): | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 244 raise TestCaseSkipped | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 245 | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 246 | 
| 21 | 247 class ValidatedTestCase(TestCase): | 
| 248 __slots__ = 'validator' | |
| 249 | |
| 250 def __init__(case, *args): | |
| 251 TestCase.__init__(case, *args) | |
| 252 if not case.problem.config.tester: | |
| 253 case.validator = None | |
| 254 else: | |
| 255 case.validator = case.problem.config.tester | |
| 256 | |
| 257 def validate(case, output): | |
| 258 if not case.validator: | |
| 259 # Compare the output with the reference output | |
| 260 case.open_outfile() | |
| 261 with case.outfile.open() as refoutput: | |
| 25 
b500e117080e
Bug fixes and overhead reduction
 Oleg Oshmyan <chortos@inbox.lv> parents: 
24diff
changeset | 262 for line, refline in zip_longest(output, refoutput): | 
| 
b500e117080e
Bug fixes and overhead reduction
 Oleg Oshmyan <chortos@inbox.lv> parents: 
24diff
changeset | 263 if refline is not None and not isinstance(refline, basestring): | 
| 21 | 264 line = bytes(line, sys.getdefaultencoding()) | 
| 265 if line != refline: | |
| 22 | 266 raise WrongAnswer | 
| 24 
c23d81f4a1a3
Score returned by TestCase.__call__() is now normalized to 0..1
 Oleg Oshmyan <chortos@inbox.lv> parents: 
23diff
changeset | 267 return 1 | 
| 21 | 268 elif callable(case.validator): | 
| 269 return case.validator(output) | |
| 270 else: | |
| 271 # Call the validator program | |
| 272 output.close() | |
| 23 | 273 if case.problem.config.ansname: | 
| 274 case.open_outfile() | |
| 275 case.outfile.copy(case.problem.config.ansname) | |
| 25 
b500e117080e
Bug fixes and overhead reduction
 Oleg Oshmyan <chortos@inbox.lv> parents: 
24diff
changeset | 276 try: | 
| 
b500e117080e
Bug fixes and overhead reduction
 Oleg Oshmyan <chortos@inbox.lv> parents: 
24diff
changeset | 277 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: 
24diff
changeset | 278 except OSError: | 
| 
b500e117080e
Bug fixes and overhead reduction
 Oleg Oshmyan <chortos@inbox.lv> parents: 
24diff
changeset | 279 raise CannotStartValidator(sys.exc_info()[1]) | 
| 21 | 280 comment = case.process.communicate()[0].strip() | 
| 26 | 281 match = re.match(r'(?i)(ok|(?:correct|wrong)(?:(?:\s|_)*answer)?)(?:$|\s+|[.,!:]+\s*)', comment) | 
| 21 | 282 if match: | 
| 283 comment = comment[match.end():] | |
| 284 if not case.problem.config.maxexitcode: | |
| 285 if case.process.returncode: | |
| 286 raise WrongAnswer(comment) | |
| 287 else: | |
| 24 
c23d81f4a1a3
Score returned by TestCase.__call__() is now normalized to 0..1
 Oleg Oshmyan <chortos@inbox.lv> parents: 
23diff
changeset | 288 return 1, comment | 
| 21 | 289 else: | 
| 24 
c23d81f4a1a3
Score returned by TestCase.__call__() is now normalized to 0..1
 Oleg Oshmyan <chortos@inbox.lv> parents: 
23diff
changeset | 290 return case.process.returncode / case.problem.config.maxexitcode, comment | 
| 21 | 291 | 
| 292 | |
| 293 class BatchTestCase(ValidatedTestCase): | |
| 294 __slots__ = () | |
| 295 | |
| 90 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 296 @property | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 297 def has_iofiles(case): | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 298 return (not case.problem.config.stdio or | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 299 case.validator and not callable(case.validator)) | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 300 | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 301 @property | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 302 def has_ansfile(case): | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 303 return case.validator and not callable(case.validator) | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 304 | 
| 22 | 305 def test(case, callback): | 
| 21 | 306 case.open_infile() | 
| 307 if case.problem.config.stdio: | |
| 54 | 308 if options.erase and not case.validator or not case.problem.config.inname: | 
| 22 | 309 # TODO: re-use the same file name if possible | 
| 21 | 310 # FIXME: 2.5 lacks the delete parameter | 
| 311 with tempfile.NamedTemporaryFile(delete=False) as f: | |
| 22 | 312 inputdatafname = f.name | 
| 25 
b500e117080e
Bug fixes and overhead reduction
 Oleg Oshmyan <chortos@inbox.lv> parents: 
24diff
changeset | 313 contextmgr = CopyDeleting(case, case.infile, inputdatafname) | 
| 21 | 314 else: | 
| 315 inputdatafname = case.problem.config.inname | |
| 25 
b500e117080e
Bug fixes and overhead reduction
 Oleg Oshmyan <chortos@inbox.lv> parents: 
24diff
changeset | 316 contextmgr = Copying(case.infile, inputdatafname) | 
| 
b500e117080e
Bug fixes and overhead reduction
 Oleg Oshmyan <chortos@inbox.lv> parents: 
24diff
changeset | 317 with contextmgr: | 
| 79 
ee8a99dcaaed
Renamed configuration variable tasknames to problems
 Oleg Oshmyan <chortos@inbox.lv> parents: 
77diff
changeset | 318 with open(inputdatafname) as infile: | 
| 83 | 319 with tempfile.TemporaryFile('w+') if options.erase and (not case.validator or callable(case.validator)) else open(case.problem.config.outname, 'w+') as outfile: | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 320 call(case.problem.config.path, case=case, stdin=infile, stdout=outfile, stderr=devnull, universal_newlines=True, bufsize=-1) | 
| 62 
593ad09cd69b
Multiple exit code handling fixes
 Oleg Oshmyan <chortos@inbox.lv> parents: 
61diff
changeset | 321 if config.globalconf.force_zero_exitcode and case.process.returncode or case.process.returncode < 0: | 
| 22 | 322 raise NonZeroExitCode(case.process.returncode) | 
| 103 
4e6f231f055f
Fixed race condition resulting in calling back twice from TestCase.test
 Oleg Oshmyan <chortos@inbox.lv> parents: 
99diff
changeset | 323 case.has_called_back = True | 
| 22 | 324 callback() | 
| 325 outfile.seek(0) | |
| 326 return case.validate(outfile) | |
| 21 | 327 else: | 
| 22 | 328 case.infile.copy(case.problem.config.inname) | 
| 82 
06356af50bf9
Finished testcases reorganization and CPU time limit implementation
 Oleg Oshmyan <chortos@inbox.lv> parents: 
81diff
changeset | 329 call(case.problem.config.path, case=case, stdin=devnull, stdout=devnull, stderr=STDOUT) | 
| 62 
593ad09cd69b
Multiple exit code handling fixes
 Oleg Oshmyan <chortos@inbox.lv> parents: 
61diff
changeset | 330 if config.globalconf.force_zero_exitcode and case.process.returncode or case.process.returncode < 0: | 
| 21 | 331 raise NonZeroExitCode(case.process.returncode) | 
| 103 
4e6f231f055f
Fixed race condition resulting in calling back twice from TestCase.test
 Oleg Oshmyan <chortos@inbox.lv> parents: 
99diff
changeset | 332 case.has_called_back = True | 
| 22 | 333 callback() | 
| 21 | 334 with open(case.problem.config.outname, 'rU') as output: | 
| 335 return case.validate(output) | |
| 336 | |
| 337 | |
| 338 # This is the only test case type not executing any programs to be tested | |
| 339 class OutputOnlyTestCase(ValidatedTestCase): | |
| 340 __slots__ = () | |
| 104 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 341 needs_realinname = False | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 342 | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 343 def cleanup(case): | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 344 pass | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 345 | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 346 def test(case, callback): | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 347 case.time_stopped = case.time_started = 0 | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 348 case.has_called_back = True | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 349 callback() | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 350 with open(case.problem.config.outname.replace('$', case.id), 'rU') as output: | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 351 return case.validate(output) | 
| 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 352 | 
| 21 | 353 | 
| 354 class BestOutputTestCase(ValidatedTestCase): | |
| 355 __slots__ = () | |
| 356 | |
| 104 
8f46e84922f9
Output-only problems are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
103diff
changeset | 357 | 
| 21 | 358 # This is the only test case type executing two programs simultaneously | 
| 359 class ReactiveTestCase(TestCase): | |
| 360 __slots__ = () | |
| 361 # The basic idea is to launch the program to be tested and the grader | |
| 362 # and to pipe their standard I/O from and to each other, | |
| 363 # and then to capture the grader's exit code and use it | |
| 26 | 364 # like the exit code of an output validator is used. | 
| 21 | 365 | 
| 366 | |
| 71 
1bee3a0beeb5
Added a 'Sample total' line when using test groups
 Oleg Oshmyan <chortos@inbox.lv> parents: 
69diff
changeset | 367 class DummyTestContext(problem.TestGroup): | 
| 
1bee3a0beeb5
Added a 'Sample total' line when using test groups
 Oleg Oshmyan <chortos@inbox.lv> parents: 
69diff
changeset | 368 __slots__ = () | 
| 
1bee3a0beeb5
Added a 'Sample total' line when using test groups
 Oleg Oshmyan <chortos@inbox.lv> parents: 
69diff
changeset | 369 def end(self): | 
| 
1bee3a0beeb5
Added a 'Sample total' line when using test groups
 Oleg Oshmyan <chortos@inbox.lv> parents: 
69diff
changeset | 370 say('Sample total: %d/%d tests' % (self.ncorrect, self.ntotal)) | 
| 76 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 371 return 0, 0, self.log | 
| 71 
1bee3a0beeb5
Added a 'Sample total' line when using test groups
 Oleg Oshmyan <chortos@inbox.lv> parents: 
69diff
changeset | 372 | 
| 21 | 373 def load_problem(prob, _types={'batch' : BatchTestCase, | 
| 374 'outonly' : OutputOnlyTestCase, | |
| 375 'bestout' : BestOutputTestCase, | |
| 376 'reactive': ReactiveTestCase}): | |
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 377 # We will need to iterate over these configuration variables twice | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 378 try: | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 379 len(prob.config.dummies) | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 380 except Exception: | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 381 prob.config.dummies = tuple(prob.config.dummies) | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 382 try: | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 383 len(prob.config.tests) | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 384 except Exception: | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 385 prob.config.tests = tuple(prob.config.tests) | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 386 | 
| 23 | 387 if options.legacy: | 
| 388 prob.config.usegroups = False | |
| 58 | 389 newtests = [] | 
| 23 | 390 for i, name in enumerate(prob.config.tests): | 
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 391 # Same here; we'll need to iterate over them twice | 
| 23 | 392 try: | 
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 393 l = len(name) | 
| 23 | 394 except Exception: | 
| 395 try: | |
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 396 name = tuple(name) | 
| 23 | 397 except TypeError: | 
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 398 name = (name,) | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 399 l = len(name) | 
| 58 | 400 if l > 1: | 
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 401 prob.config.usegroups = True | 
| 58 | 402 newtests.append(name) | 
| 403 if prob.config.usegroups: | |
| 404 prob.config.tests = newtests | |
| 405 del newtests | |
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 406 | 
| 76 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 407 # Even if they have duplicate test identifiers, we must honour sequence pointmaps | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 408 if isinstance(prob.config.pointmap, dict): | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 409 def getpoints(i, j, k=None): | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 410 try: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 411 return prob.config.pointmap[i] | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 412 except KeyError: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 413 try: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 414 return prob.config.pointmap[None] | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 415 except KeyError: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 416 return prob.config.maxexitcode or 1 | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 417 elif prob.config.usegroups: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 418 def getpoints(i, j, k): | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 419 try: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 420 return prob.config.pointmap[k][j] | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 421 except LookupError: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 422 return prob.config.maxexitcode or 1 | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 423 else: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 424 def getpoints(i, j): | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 425 try: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 426 return prob.config.pointmap[j] | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 427 except LookupError: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 428 return prob.config.maxexitcode or 1 | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 429 | 
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 430 # First get prob.cache.padoutput right, | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 431 # then yield the actual test cases | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 432 for i in prob.config.dummies: | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 433 s = 'sample ' + str(i).zfill(prob.config.paddummies) | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 434 prob.cache.padoutput = max(prob.cache.padoutput, len(s)) | 
| 16 | 435 if prob.config.usegroups: | 
| 76 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 436 if not isinstance(prob.config.groupweight, dict): | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 437 prob.config.groupweight = dict(enumerate(prob.config.groupweight)) | 
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 438 for group in prob.config.tests: | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 439 for i in group: | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 440 s = str(i).zfill(prob.config.padtests) | 
| 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 441 prob.cache.padoutput = max(prob.cache.padoutput, len(s)) | 
| 89 
3ae6cb69e4ef
Sample total is no longer printed if there are no samples
 Oleg Oshmyan <chortos@inbox.lv> parents: 
88diff
changeset | 442 if prob.config.dummies: | 
| 
3ae6cb69e4ef
Sample total is no longer printed if there are no samples
 Oleg Oshmyan <chortos@inbox.lv> parents: 
88diff
changeset | 443 yield DummyTestContext() | 
| 
3ae6cb69e4ef
Sample total is no longer printed if there are no samples
 Oleg Oshmyan <chortos@inbox.lv> parents: 
88diff
changeset | 444 for i in prob.config.dummies: | 
| 
3ae6cb69e4ef
Sample total is no longer printed if there are no samples
 Oleg Oshmyan <chortos@inbox.lv> parents: 
88diff
changeset | 445 s = str(i).zfill(prob.config.paddummies) | 
| 99 
9b41934b2e95
Fixed a major regression introduced in changeset 1fb319ec33af
 Oleg Oshmyan <chortos@inbox.lv> parents: 
91diff
changeset | 446 if (yield _types[prob.config.kind](prob, s, True, 0)): | 
| 
9b41934b2e95
Fixed a major regression introduced in changeset 1fb319ec33af
 Oleg Oshmyan <chortos@inbox.lv> parents: 
91diff
changeset | 447 yield | 
| 89 
3ae6cb69e4ef
Sample total is no longer printed if there are no samples
 Oleg Oshmyan <chortos@inbox.lv> parents: 
88diff
changeset | 448 yield problem.test_context_end | 
| 76 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 449 for k, group in enumerate(prob.config.tests): | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 450 if not group: | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 451 continue | 
| 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 452 yield problem.TestGroup(prob.config.groupweight.get(k, prob.config.groupweight.get(None))) | 
| 90 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 453 case_type = _types[prob.config.kind] | 
| 76 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 454 for j, i in enumerate(group): | 
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 455 s = str(i).zfill(prob.config.padtests) | 
| 90 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 456 if not (yield case_type(prob, s, False, getpoints(i, j, k))): | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 457 if options.skim: | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 458 case_type = SkippedTestCase | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 459 else: | 
| 
1fb319ec33af
Skimming mode added (-k/--skim option)
 Oleg Oshmyan <chortos@inbox.lv> parents: 
89diff
changeset | 460 yield | 
| 39 
2b459f9743b4
Test groups are now supported
 Oleg Oshmyan <chortos@inbox.lv> parents: 
27diff
changeset | 461 yield problem.test_context_end | 
| 16 | 462 else: | 
| 463 for i in prob.config.tests: | |
| 21 | 464 s = str(i).zfill(prob.config.padtests) | 
| 465 prob.cache.padoutput = max(prob.cache.padoutput, len(s)) | |
| 466 for i in prob.config.dummies: | |
| 467 s = str(i).zfill(prob.config.paddummies) | |
| 99 
9b41934b2e95
Fixed a major regression introduced in changeset 1fb319ec33af
 Oleg Oshmyan <chortos@inbox.lv> parents: 
91diff
changeset | 468 if (yield _types[prob.config.kind](prob, s, True, 0)): | 
| 
9b41934b2e95
Fixed a major regression introduced in changeset 1fb319ec33af
 Oleg Oshmyan <chortos@inbox.lv> parents: 
91diff
changeset | 469 yield | 
| 76 
0e5ae28e0b2b
Points are now weighted on a test context basis
 Oleg Oshmyan <chortos@inbox.lv> parents: 
72diff
changeset | 470 for j, i in enumerate(prob.config.tests): | 
| 21 | 471 s = str(i).zfill(prob.config.padtests) | 
| 99 
9b41934b2e95
Fixed a major regression introduced in changeset 1fb319ec33af
 Oleg Oshmyan <chortos@inbox.lv> parents: 
91diff
changeset | 472 if (yield _types[prob.config.kind](prob, s, False, getpoints(i, j))): | 
| 
9b41934b2e95
Fixed a major regression introduced in changeset 1fb319ec33af
 Oleg Oshmyan <chortos@inbox.lv> parents: 
91diff
changeset | 473 yield | 
