Mercurial > ~astiob > upreckon > hgweb
annotate 1.20/test.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 | 5bfa23cd638d |
children |
rev | line source |
---|---|
7 | 1 #! /usr/bin/python |
8 | 2 # Copyright (c) 2009, 2010 Chortos-2 <chortos@inbox.lv> |
7 | 3 |
4 import os, sys, shutil, time, subprocess, filecmp, optparse, signal, tempfile, tarfile, zipfile | |
5 | |
20 | 6 parser = optparse.OptionParser(version='test.py 1.20.3', usage='usage: %prog [options] [problem names] [[path/to/]solution-app] [test case numbers]\n\nTest case numbers can be specified in plain text or as a Python expression\nif there is only one positional argument.\n\nOnly problem names listed in testconf.py are recognized.') |
7 | 7 parser.add_option('-e', '--exclude', dest='exclude', action='append', help='test case number(s) to exclude, as a Python expression; multiple -e options can be supplied') |
8 parser.add_option('-c', '--cleanup', dest='clean', action='store_true', default=False, help='delete the copies of input/output files and exit') | |
9 parser.add_option('-s', '--save-io', dest='erase', action='store_false', default=True, help='do not delete the copies of input/output files after the last test case; create copies of input files and store output in files even if the solution uses standard I/O; delete the stored input/output files if the solution uses standard I/O and the -c/--cleanup option is specified') | |
10 parser.add_option('-m', '--copy-io', dest='copyonly', action='store_true', default=False, help='only create a copy of the input/output files of the last test case for manual testing; to delete them, use options -cs') | |
11 parser.add_option('-x', '--auto-exit', dest='pause', action='store_false', default=True, help='do not wait for a key to be pressed when finished testing') | |
12 parser.add_option('-p', '--python', action='store_true', default=False, help='always parse all positional arguments as a single Python expression (including the first argument even if it names an executable file)') | |
13 parser.add_option('-t', '--detect-time', dest='autotime', action='store_true', default=False, help='spend a second detecting the most precise time measurement function') | |
14 | |
15 options, args = parser.parse_args() | |
16 parser.destroy() | |
17 del parser | |
18 | |
19 globals1 = set(globals()) | |
20 | |
21 # Initialize some configuration variables with default values | |
22 tasknames = ('.',) | |
23 maxtime = 0 | |
24 tests = () | |
25 dummies = () | |
26 testsexcluded = () | |
27 padwithzeroestolength = 0 | |
28 taskweight = 100 | |
29 pointmap = {} | |
30 stdio = False | |
31 dummyinname = '' | |
32 dummyoutname = '' | |
33 tester = '' | |
34 | |
35 def exectestconf_helper(name): | |
36 if os.path.isfile('tests.tar'): | |
37 f = tarfile.open('tests.tar') | |
38 try: | |
39 exec f.extractfile(name).read() in globals() | |
40 f.close() | |
41 return True | |
42 except KeyError: | |
43 f.close() | |
44 if os.path.isfile('tests.zip'): | |
45 f = zipfile.ZipFile('tests.zip') | |
46 try: | |
47 exec f.open(name, 'rU').read() in globals() | |
48 f.close() | |
49 return True | |
50 except KeyError: | |
51 f.close() | |
52 if os.path.isfile('tests.tgz'): | |
53 f = tarfile.open('tests.tgz') | |
54 try: | |
55 exec f.extractfile(name).read() in globals() | |
56 f.close() | |
57 return True | |
58 except KeyError: | |
59 f.close() | |
60 if os.path.isfile('tests.tar.gz'): | |
61 f = tarfile.open('tests.tar.gz') | |
62 try: | |
63 exec f.extractfile(name).read() in globals() | |
64 f.close() | |
65 return True | |
66 except KeyError: | |
67 f.close() | |
68 if os.path.isfile('tests.tbz2'): | |
69 f = tarfile.open('tests.tbz2') | |
70 try: | |
71 exec f.extractfile(name).read() in globals() | |
72 f.close() | |
73 return True | |
74 except KeyError: | |
75 f.close() | |
76 if os.path.isfile('tests.tar.bz2'): | |
77 f = tarfile.open('tests.tar.bz2') | |
78 try: | |
79 exec f.extractfile(name).read() in globals() | |
80 f.close() | |
81 return True | |
82 except KeyError: | |
83 f.close() | |
84 return False | |
85 | |
86 try: | |
87 execfile('testconf.py') | |
88 except IOError, error: | |
89 exc_info = sys.exc_info()[2] | |
90 try: | |
91 execfile('tests/testconf.py') | |
92 except IOError: | |
93 if not exectestconf_helper('testconf.py'): | |
94 raise IOError, (error.errno, 'The configuration file is missing', error.filename), exc_info | |
95 del exc_info | |
96 | |
97 globals2 = set(globals()) | |
98 globals2.remove('globals1') | |
99 globals2 -= globals1 | |
100 del globals1 | |
101 | |
102 shared = {} | |
103 g = globals() | |
104 for k in globals2: | |
105 shared[k] = g[k] | |
106 | |
107 newtasknames = [] | |
108 while len(args) and args[0] in tasknames: | |
109 newtasknames.append(args[0]) | |
110 del args[0] | |
111 if len(newtasknames): | |
112 tasknames = newtasknames | |
113 | |
114 scoresumoveralltasks = 0 | |
115 scoremaxoveralltasks = 0 | |
116 ntasks = 0 | |
117 nfulltasks = 0 | |
118 cwd = '' # At any time this is either '' or taskname + '/' | |
119 | |
120 if options.autotime: | |
121 c = time.clock() | |
122 time.sleep(1) | |
123 c = time.clock() - c | |
124 if int(c + .99999) == 1: | |
125 clock = time.clock | |
126 else: | |
127 clock = time.time | |
128 elif os.name == 'nt': | |
129 clock = time.clock | |
130 else: | |
131 clock = time.time | |
132 | |
133 if options.copyonly: | |
134 options.erase = False | |
135 | |
136 def existstestcase_helper(name): | |
137 if os.path.isfile('tests.tar'): | |
138 f = tarfile.open('tests.tar') | |
139 try: | |
140 f.getmember(name) | |
141 f.close() | |
142 return True | |
143 except KeyError: | |
144 f.close() | |
145 if os.path.isfile('tests.zip'): | |
146 f = zipfile.ZipFile('tests.zip') | |
147 try: | |
148 f.getinfo(name) | |
149 f.close() | |
150 return True | |
151 except KeyError: | |
152 f.close() | |
153 if os.path.isfile('tests.tgz'): | |
154 f = tarfile.open('tests.tgz') | |
155 try: | |
156 f.getmember(name) | |
157 f.close() | |
158 return True | |
159 except KeyError: | |
160 f.close() | |
161 if os.path.isfile('tests.tar.gz'): | |
162 f = tarfile.open('tests.tar.gz') | |
163 try: | |
164 f.getmember(name) | |
165 f.close() | |
166 return True | |
167 except KeyError: | |
168 f.close() | |
169 if os.path.isfile('tests.tbz2'): | |
170 f = tarfile.open('tests.tbz2') | |
171 try: | |
172 f.getmember(name) | |
173 f.close() | |
174 return True | |
175 except KeyError: | |
176 f.close() | |
177 if os.path.isfile('tests.tar.bz2'): | |
178 f = tarfile.open('tests.tar.bz2') | |
179 try: | |
180 f.getmember(name) | |
181 f.close() | |
182 return True | |
183 except KeyError: | |
184 f.close() | |
185 return False | |
186 | |
187 def existstestcase(name): | |
188 if os.path.isfile('tests/' + taskname + '/' + name) or os.path.isfile('tests/' + name): | |
189 return True | |
190 if cwd and (os.path.isfile(oldcwd + '/tests/' + cwd + name) or os.path.isfile(oldcwd + '/tests/' + name)): | |
191 return True | |
192 if existstestcase_helper(taskname + '/' + name) or existstestcase_helper(name): | |
193 return True | |
194 if cwd: | |
195 os.chdir(oldcwd) | |
196 if existstestcase_helper(cwd + name) or existstestcase_helper(name): | |
197 os.chdir(cwd) | |
198 return True | |
199 os.chdir(cwd) | |
200 return False | |
201 | |
202 def opentestcase_helper(name): | |
203 if os.path.isfile('tests.tar'): | |
204 f = tarfile.open('tests.tar') | |
205 try: | |
206 c = f.extractfile(name) | |
207 return c | |
208 except KeyError: | |
209 f.close() | |
210 if os.path.isfile('tests.zip'): | |
211 f = zipfile.ZipFile('tests.zip') | |
212 try: | |
213 c = f.open(name, 'rU') | |
214 f.close() | |
215 return c | |
216 except KeyError: | |
217 f.close() | |
218 if os.path.isfile('tests.tgz'): | |
219 f = tarfile.open('tests.tgz') | |
220 try: | |
221 c = f.extractfile(name) | |
222 return c | |
223 except KeyError: | |
224 f.close() | |
225 if os.path.isfile('tests.tar.gz'): | |
226 f = tarfile.open('tests.tar.gz') | |
227 try: | |
228 c = f.extractfile(name) | |
229 return c | |
230 except KeyError: | |
231 f.close() | |
232 if os.path.isfile('tests.tbz2'): | |
233 f = tarfile.open('tests.tbz2') | |
234 try: | |
235 c = f.extractfile(name) | |
236 return c | |
237 except KeyError: | |
238 f.close() | |
239 if os.path.isfile('tests.tar.bz2'): | |
240 f = tarfile.open('tests.tar.bz2') | |
241 try: | |
242 c = f.extractfile(name) | |
243 return c | |
244 except KeyError: | |
245 f.close() | |
246 return None | |
247 | |
248 def opentestcase(name): | |
249 if os.path.isfile('tests/' + taskname + '/' + name): | |
250 return open('tests/' + taskname + '/' + name, 'rU') | |
251 elif os.path.isfile('tests/' + name): | |
252 return open('tests/' + name, 'rU') | |
253 f = opentestcase_helper(taskname + '/' + name) | |
254 if not f: | |
255 f = opentestcase_helper(name) | |
256 if f: | |
257 return f | |
258 if cwd: | |
259 if os.path.isfile(oldcwd + '/tests/' + cwd + name): | |
260 return open(oldcwd + '/tests/' + cwd + name, 'rU') | |
261 elif os.path.isfile(oldcwd + '/tests/' + name): | |
262 return open(oldcwd + '/tests/' + name, 'rU') | |
263 os.chdir(oldcwd) | |
264 f = opentestcase_helper(cwd + name) | |
265 if not f: | |
266 f = opentestcase_helper(name) | |
267 os.chdir(cwd) | |
268 if f: | |
269 return f | |
270 raise KeyError, 'The test-case-defining file \'' + name + '\' cannot be found' | |
271 | |
272 def copytestcase_helper(name, target): | |
273 if os.path.isfile('tests.tar'): | |
274 f = tarfile.open('tests.tar') | |
275 try: | |
276 m = f.getmember(name) | |
277 m.name = target | |
278 f.extract(m) | |
279 f.close() | |
280 return True | |
281 except KeyError: | |
282 f.close() | |
283 if os.path.isfile('tests.zip'): | |
284 if not target.startswith('/'): | |
285 f = zipfile.ZipFile('tests.zip') | |
286 try: | |
19
d4fc9341664e
Fixed an exception when tests.zip contained test cases in its root
Oleg Oshmyan <chortos@inbox.lv>
parents:
8
diff
changeset
|
287 m = f.getinfo(name) |
7 | 288 m.filename = target |
289 f.extract(m) | |
290 f.close() | |
291 return True | |
292 except KeyError: | |
293 f.close() | |
294 else: | |
295 oldcwd = os.getcwdu() | |
296 os.chdir('/') | |
297 f = zipfile.ZipFile(oldcwd + '/tests.zip') | |
298 try: | |
299 m = f.getinfo(name) | |
20 | 300 m.filename = os.path.relpath(target) |
7 | 301 f.extract(m) |
302 f.close() | |
303 os.chdir(oldcwd) | |
304 return True | |
305 except KeyError: | |
306 f.close() | |
20 | 307 os.chdir(oldcwd) |
7 | 308 if os.path.isfile('tests.tgz'): |
309 f = tarfile.open('tests.tgz') | |
310 try: | |
311 m = f.getmember(name) | |
312 m.name = target | |
313 f.extract(m) | |
314 f.close() | |
315 return True | |
316 except KeyError: | |
317 f.close() | |
318 if os.path.isfile('tests.tar.gz'): | |
319 f = tarfile.open('tests.tar.gz') | |
320 try: | |
321 m = f.getmember(name) | |
322 m.name = target | |
323 f.extract(m) | |
324 f.close() | |
325 return True | |
326 except KeyError: | |
327 f.close() | |
328 if os.path.isfile('tests.tbz2'): | |
329 f = tarfile.open('tests.tbz2') | |
330 try: | |
331 m = f.getmember(name) | |
332 m.name = target | |
333 f.extract(m) | |
334 f.close() | |
335 return True | |
336 except KeyError: | |
337 f.close() | |
338 if os.path.isfile('tests.tar.bz2'): | |
339 f = tarfile.open('tests.tar.bz2') | |
340 try: | |
341 m = f.getmember(name) | |
342 m.name = target | |
343 f.extract(m) | |
344 f.close() | |
345 return True | |
346 except KeyError: | |
347 f.close() | |
348 return False | |
349 | |
350 def copytestcase(name, target): | |
351 if os.path.isfile('tests/' + taskname + '/' + name): | |
352 shutil.copyfile('tests/' + taskname + '/' + name, target) | |
353 return | |
354 elif os.path.isfile('tests/' + name): | |
355 shutil.copyfile('tests/' + name, target) | |
356 return | |
357 if copytestcase_helper(taskname + '/' + name, target) or copytestcase_helper(name, target): | |
358 return | |
359 if cwd: | |
360 if os.path.isfile(oldcwd + '/tests/' + cwd + name): | |
361 shutil.copyfile(oldcwd + '/tests/' + cwd + name, target) | |
362 return | |
363 elif os.path.isfile(oldcwd + '/tests/' + name): | |
364 shutil.copyfile(oldcwd + '/tests/' + name, target) | |
365 return | |
366 os.chdir(oldcwd) | |
367 if copytestcase_helper(cwd + name, target) or copytestcase_helper(name, target): | |
368 os.chdir(cwd) | |
369 return | |
370 os.chdir(cwd) | |
371 raise KeyError, 'The test-case-defining file \'' + name + '\' cannot be found' | |
372 | |
373 # Always chdir if the directory exists but use any existing config | |
374 def chdir_and_exec_testconf(): | |
375 global cwd | |
376 cwd = '' | |
377 if os.path.isdir(taskname): | |
378 os.chdir(taskname) | |
379 if taskname != '.': | |
380 cwd = taskname + '/' | |
381 try: | |
382 execfile('testconf.py', globals()) | |
383 return | |
384 except IOError: | |
385 pass | |
386 if not cwd: | |
387 if os.path.isfile('tests/' + taskname + '/testconf.py'): | |
388 execfile('tests/' + taskname + '/testconf.py', globals()) | |
389 return | |
390 if os.path.isfile('tests/testconf.py'): | |
391 execfile('tests/testconf.py', globals()) | |
392 return | |
393 if exectestconf_helper(taskname + '/testconf.py') or exectestconf_helper('testconf.py'): | |
394 return | |
395 if cwd: | |
396 os.chdir(oldcwd) | |
397 if os.path.isfile('tests/' + cwd + 'testconf.py'): | |
398 execfile('tests/' + cwd + 'testconf.py', globals()) | |
399 os.chdir(cwd) | |
400 return | |
401 if os.path.isfile('tests/testconf.py'): | |
402 execfile('tests/testconf.py', globals()) | |
403 os.chdir(cwd) | |
404 return | |
405 if exectestconf_helper(cwd + 'testconf.py') or exectestconf_helper('testconf.py'): | |
406 os.chdir(cwd) | |
407 return | |
408 if os.path.isfile('testconf.py'): | |
409 execfile('testconf.py', globals()) | |
410 os.chdir(cwd) | |
411 return | |
412 os.chdir(cwd) | |
413 elif os.path.isfile('testconf.py'): | |
414 execfile('testconf.py', globals()) | |
415 return | |
416 raise KeyError, 'The configuration file for task ' + taskname + ' is missing' | |
417 | |
418 try: | |
419 name | |
420 namedefined = True | |
421 except Exception: | |
422 namedefined = False | |
423 | |
424 for taskname in tasknames: | |
425 if ntasks: | |
426 print | |
427 | |
428 try: | |
429 if len(tasknames) > 1: | |
430 print taskname | |
431 except Exception: | |
432 if taskname != '.' or ntasks: | |
433 print taskname | |
434 | |
435 try: del inname | |
436 except NameError: pass | |
437 try: del outname | |
438 except NameError: pass | |
439 try: del ansname | |
440 except NameError: pass | |
441 | |
442 if not namedefined and taskname != '.': | |
443 name = './' + taskname | |
444 for k in shared: | |
445 g[k] = shared[k] | |
446 | |
447 oldcwd = os.getcwdu() | |
448 chdir_and_exec_testconf() | |
449 | |
450 if options.clean: | |
451 try: | |
452 if not stdio or tester: | |
453 if not tester: | |
454 inname | |
455 outname | |
456 if tester: | |
457 ansname | |
458 except NameError, error: | |
459 raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] | |
460 if not options.erase: | |
461 try: | |
462 inname = inname.replace('%', taskname) | |
463 except NameError: | |
464 inname = taskname + '.in' | |
465 try: | |
466 outname = outname.replace('%', taskname) | |
467 except NameError: | |
468 outname = taskname + '.out' | |
469 try: | |
470 ansname = ansname.replace('%', taskname) | |
471 except NameError: | |
472 ansname = taskname + '.ans' | |
473 else: | |
474 inname = inname.replace('%', taskname) | |
475 outname = outname.replace('%', taskname) | |
476 if tester: | |
477 ansname = ansname.replace('%', taskname) | |
478 if not stdio or tester or not options.erase: | |
479 if os.path.exists(inname): os.remove(inname) | |
480 if os.path.exists(outname): os.remove(outname) | |
481 if (tester or not options.erase) and ansname: | |
482 if os.path.exists(ansname): os.remove(ansname) | |
483 continue | |
484 | |
485 try: | |
486 name | |
487 except NameError, error: | |
488 if str(error).count('name') == 1: | |
489 raise NameError, 'configuration ' + str(error), sys.exc_info()[2] | |
490 else: | |
491 raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] | |
492 | |
493 try: | |
494 if not stdio: | |
495 inname | |
496 outname | |
497 testcaseinname | |
498 if tester: | |
499 outname | |
500 if ansname: | |
501 testcaseoutname | |
502 else: | |
503 testcaseoutname | |
504 except NameError, error: | |
505 raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] | |
506 | |
507 if not options.erase: | |
508 try: | |
509 inname | |
510 except NameError: | |
511 inname = taskname + '.in' | |
512 try: | |
513 outname | |
514 except NameError: | |
515 outname = taskname + '.out' | |
516 try: | |
517 ansname | |
518 except NameError: | |
519 ansname = taskname + '.ans' | |
520 | |
521 if options.pause: | |
522 try: | |
523 pause | |
524 except NameError, error: | |
525 if os.name == 'posix': | |
526 pause = 'read -s -n 1' | |
527 print 'Configuration ' + str(error).replace('name ', 'variable ') + '; it was devised automatically but the choice might be incorrect, so test.py might exit immediately after the testing is complete.' | |
528 elif os.name == 'nt': | |
529 pause = 'pause' | |
530 else: | |
531 raise NameError, 'configuration ' + str(error).replace('name ', 'variable ') + ' and cannot be devised automatically', sys.exc_info()[2] | |
532 | |
533 if not dummyinname: | |
534 dummyinname = testcaseinname | |
535 if not dummyoutname and (not tester or ansname): | |
536 dummyoutname = testcaseoutname | |
537 | |
538 dummyinname = dummyinname.replace('%', taskname) | |
539 dummyoutname = dummyoutname.replace('%', taskname) | |
540 testcaseinname = testcaseinname.replace('%', taskname) | |
541 if not stdio or not options.erase: | |
542 inname = inname.replace('%', taskname) | |
543 outname = outname.replace('%', taskname) | |
544 try: | |
545 ansname = ansname.replace('%', taskname) | |
546 except NameError: | |
547 pass | |
548 if tester: | |
549 try: inname = inname.replace('%', taskname) | |
550 except NameError: pass | |
551 outname = outname.replace('%', taskname) | |
552 if ansname: | |
553 ansname = ansname.replace('%', taskname) | |
554 testcaseoutname = testcaseoutname.replace('%', taskname) | |
555 else: | |
556 testcaseoutname = testcaseoutname.replace('%', taskname) | |
557 | |
558 if isinstance(padwithzeroestolength, tuple): | |
559 padwithzeroestolength, paddummieswithzeroestolength = padwithzeroestolength | |
560 else: | |
561 paddummieswithzeroestolength = padwithzeroestolength | |
562 | |
563 if options.python: | |
564 dummies = () | |
565 s = ' '.join(args) | |
566 tests = eval(s) | |
567 try: | |
568 tests.__iter__ | |
569 except AttributeError: | |
570 tests = (tests,) | |
571 elif len(args): | |
572 if os.path.exists(args[0]): | |
573 name = args[0] | |
574 del args[0] | |
575 if len(args) > 1: | |
576 dummies = () | |
577 tests = args | |
578 elif len(args): | |
579 dummies = () | |
580 s = args[0] | |
581 if len(s) < padwithzeroestolength: | |
582 s = s.zfill(padwithzeroestolength) | |
583 if existstestcase(testcaseinname.replace('$', s)): | |
584 tests = (s,) | |
585 else: | |
586 try: | |
587 tests = eval(args[0]) | |
588 try: | |
589 tests.__iter__ | |
590 except AttributeError: | |
591 tests = (tests,) | |
592 except Exception: | |
593 tests = (s,) | |
594 | |
595 if options.exclude: | |
596 testsexcluded = [] | |
597 for i in options.exclude: | |
598 v = eval(i) | |
599 try: | |
600 testsexcluded.extend(v) | |
601 except TypeError: | |
602 testsexcluded.append(v) | |
603 | |
604 # Windows doesn't like paths beginning with .\ and not ending with an extension | |
605 name = os.path.normcase(name) | |
606 if name.startswith('.\\'): | |
607 name = name[2:] | |
608 | |
609 newpointmap = {} | |
610 | |
611 for i in pointmap: | |
612 try: | |
613 for j in i: | |
614 newpointmap[j] = pointmap[i] | |
615 except TypeError: | |
616 newpointmap[i] = pointmap[i] | |
617 | |
618 pointmap = newpointmap | |
619 | |
620 if maxtime > 0: | |
621 strmaxtime = '/%.3f' % maxtime | |
622 else: | |
623 strmaxtime = '' | |
624 | |
625 padoutputtolength = 0 | |
626 ntests = [] | |
627 | |
628 for j in dummies: | |
629 try: | |
630 j.__iter__ | |
631 except AttributeError: | |
632 j = (j,) | |
633 ntests.append((j, True)) | |
634 for i in j: | |
635 s = str(i) | |
636 if len(s) < paddummieswithzeroestolength: | |
637 s = s.zfill(paddummieswithzeroestolength) | |
638 s = 'sample ' + s | |
639 if padoutputtolength < len(s): | |
640 padoutputtolength = len(s) | |
641 | |
642 for j in tests: | |
643 try: | |
644 j.__iter__ | |
645 except AttributeError: | |
646 j = (j,) | |
647 ntests.append((j, False)) | |
648 for i in j: | |
649 s = str(i) | |
650 if len(s) < padwithzeroestolength: | |
651 s = s.zfill(padwithzeroestolength) | |
652 if padoutputtolength < len(s): | |
653 padoutputtolength = len(s) | |
654 | |
655 tests = ntests | |
656 score = maxpoints = ncorrect = ntotal = ncorrectvalued = nvalued = 0 | |
657 | |
658 if options.copyonly: | |
659 j, isdummy = tests[-1] | |
660 if isdummy: | |
661 realinname = dummyinname | |
662 realoutname = dummyoutname | |
663 else: | |
664 realinname = testcaseinname | |
665 realoutname = testcaseoutname | |
666 for i in j: | |
667 if i in testsexcluded and not isdummy: | |
668 continue | |
669 s = str(i) | |
670 if isdummy: | |
671 if len(s) < paddummieswithzeroestolength: | |
672 s = s.zfill(paddummieswithzeroestolength) | |
673 else: | |
674 if len(s) < padwithzeroestolength: | |
675 s = s.zfill(padwithzeroestolength) | |
676 copytestcase(realinname.replace('$', s), inname) | |
677 if ansname: | |
678 copytestcase(realoutname.replace('$', s), ansname) | |
679 continue | |
680 | |
681 for j, isdummy in tests: | |
682 ncorrectgrp = 0 | |
683 ntotalgrp = 0 | |
684 scoregrp = 0 | |
685 maxpointsgrp = 0 | |
686 if isdummy: | |
687 realinname = dummyinname | |
688 realoutname = dummyoutname | |
689 else: | |
690 realinname = testcaseinname | |
691 realoutname = testcaseoutname | |
692 for i in j: | |
693 if i in testsexcluded and not isdummy: | |
694 continue | |
695 ntotalgrp += 1 | |
696 s = str(i) | |
697 if isdummy: | |
698 npoints = 0 | |
699 if len(s) < paddummieswithzeroestolength: | |
700 s = s.zfill(paddummieswithzeroestolength) | |
701 spref = 'sample ' | |
702 else: | |
703 npoints = pointmap.get(None, 1) | |
704 npoints = pointmap.get(i, npoints) | |
705 maxpointsgrp += npoints | |
706 if npoints: | |
707 nvalued += 1 | |
708 if len(s) < padwithzeroestolength: | |
709 s = s.zfill(padwithzeroestolength) | |
710 spref = '' | |
711 print ' ' * (padoutputtolength - len(spref + s)) + spref + s + ':', | |
712 sys.stdout.flush() | |
713 outputdata = open(os.devnull, 'w') | |
714 if stdio: | |
715 f = tempfile.NamedTemporaryFile(delete=False) | |
716 inputdatafname = f.name | |
717 f.close() | |
718 copytestcase(realinname.replace('$', s), inputdatafname) | |
719 inputdata = open(inputdatafname, 'rU') | |
720 if options.erase: | |
721 tempoutput = tempfile.TemporaryFile('w+') | |
722 else: | |
723 tempoutput = open(outname, 'w+') | |
724 try: | |
725 proc = subprocess.Popen(name, stdin=inputdata, stdout=tempoutput, stderr=outputdata, universal_newlines=True) | |
726 except OSError, error: | |
727 raise OSError, 'The program to be tested cannot be launched: ' + str(error), sys.exc_info()[2] | |
728 else: | |
729 if os.path.exists(outname): | |
730 os.remove(outname) | |
731 copytestcase(realinname.replace('$', s), inname) | |
732 try: | |
733 proc = subprocess.Popen(name, stdin=outputdata, stdout=outputdata, stderr=outputdata, universal_newlines=True) | |
734 except OSError, error: | |
735 raise OSError, 'The program to be tested cannot be launched: ' + str(error), sys.exc_info()[2] | |
736 cl = clock() | |
737 if maxtime > 0: | |
738 while 1: | |
739 proc.poll() | |
740 elapsed = clock() - cl | |
741 if proc.returncode == None: | |
742 if elapsed >= maxtime: | |
743 print '%.3f%s s, 0/%d, time limit exceeded' % (elapsed, strmaxtime, npoints) | |
744 sys.stdout.flush() | |
745 while proc.returncode == None: | |
746 try: | |
747 proc.terminate() | |
748 except OSError: | |
749 pass | |
750 except AttributeError: | |
751 try: | |
752 os.kill(proc.pid, signal.SIGTERM) | |
753 except Exception: | |
754 pass | |
755 proc.poll() | |
756 outputdata.close() | |
757 if stdio: | |
758 tempoutput.close() | |
759 break | |
760 else: | |
761 print '%.3f%s s,' % (elapsed, strmaxtime), | |
762 sys.stdout.flush() | |
763 elapsed = 0 | |
764 if stdio: | |
765 tempoutput.seek(0) | |
766 lines = tempoutput.readlines() | |
767 tempoutput.close() | |
768 break | |
769 if elapsed >= maxtime: | |
770 continue | |
771 else: | |
772 data = proc.communicate() | |
773 elapsed = clock() - cl | |
774 print '%.3f%s s,' % (elapsed, strmaxtime), | |
775 sys.stdout.flush() | |
776 if stdio: | |
777 tempoutput.seek(0) | |
778 lines = tempoutput.readlines() | |
779 tempoutput.close() | |
780 outputdata.close() | |
781 if stdio: | |
782 inputdata.close() | |
783 try: | |
784 os.unlink(inputdatafname) | |
785 except Exception: | |
786 pass | |
787 if proc.returncode > 0: | |
788 print '0/%d, non-zero return code %d' % (npoints, proc.returncode) | |
789 sys.stdout.flush() | |
790 elif proc.returncode < 0: | |
791 print '0/%d, terminated by signal %d' % (npoints, -proc.returncode) | |
792 sys.stdout.flush() | |
793 else: | |
794 if not tester: | |
795 if stdio: | |
796 outputdata = opentestcase(realoutname.replace('$', s)) | |
797 r = 0 | |
798 data = outputdata.read().splitlines(True) | |
799 if len(lines) != len(data): | |
800 r = 1 | |
801 else: | |
802 for i in zip(lines, data): | |
803 if i[0] != i[1]: | |
804 r = 1 | |
805 break | |
806 outputdata.close() | |
807 else: | |
808 try: | |
809 inputdata = open(outname, 'rU') | |
810 except IOError: | |
811 print '0/%g, output file not created or not readable' % npoints | |
812 sys.stdout.flush() | |
813 r = None | |
814 else: | |
815 outputdata = opentestcase(realoutname.replace('$', s)) | |
816 r = 0 | |
817 lines = inputdata.readlines() | |
818 data = outputdata.read().splitlines(True) | |
819 if len(lines) != len(data): | |
820 r = 1 | |
821 else: | |
822 for i in zip(lines, data): | |
823 if i[0] != i[1]: | |
824 r = 1 | |
825 break | |
826 inputdata.close() | |
827 outputdata.close() | |
828 else: | |
829 if ansname: | |
830 copytestcase(realoutname.replace('$', s), ansname) | |
831 if stdio: | |
832 try: copytestcase(realinname.replace('$', s), inname) | |
833 except NameError: pass | |
834 outputdata = open(outname, 'w') | |
835 outputdata.writelines(lines) | |
836 outputdata.close() | |
837 try: | |
838 proc = subprocess.Popen(tester, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) | |
839 except OSError, error: | |
840 raise OSError, 'The tester application cannot be launched: ' + str(error), sys.exc_info()[2] | |
841 data = proc.communicate() | |
842 r = proc.returncode | |
843 if tester and data[0]: | |
844 data = ''.join((' (', data[0].strip(), ')')) | |
845 else: | |
846 data = '' | |
847 if r: | |
848 print '0/%g, wrong answer%s' % (npoints, data) | |
849 sys.stdout.flush() | |
850 elif r == 0: | |
851 print '%g/%g, OK%s' % (npoints, npoints, data) | |
852 sys.stdout.flush() | |
853 scoregrp += npoints | |
854 ncorrectgrp += 1 | |
855 if npoints: | |
856 ncorrectvalued += 1 | |
857 if ntotalgrp: | |
858 if scoregrp < maxpointsgrp: | |
859 scoregrp = 0 | |
860 if ntotalgrp > 1: | |
861 print 'Group total: %d/%d tests; %g/%g points' % (ncorrectgrp, ntotalgrp, scoregrp, maxpointsgrp) | |
862 sys.stdout.flush() | |
863 ncorrect += ncorrectgrp | |
864 ntotal += ntotalgrp | |
865 score += scoregrp | |
866 maxpoints += maxpointsgrp | |
867 | |
868 if options.erase: | |
869 if not stdio or tester: | |
870 if os.path.exists(inname): os.remove(inname) | |
871 if os.path.exists(outname): os.remove(outname) | |
872 if tester and ansname: | |
873 if os.path.exists(ansname): os.remove(ansname) | |
874 elif stdio: | |
875 copytestcase(realinname.replace('$', s), inname) | |
876 copytestcase(realoutname.replace('$', s), ansname) | |
877 if nvalued != ntotal: | |
878 print 'Grand total: %d/%d tests (%d/%d valued); %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, ncorrectvalued, nvalued, score, maxpoints, (score*taskweight/maxpoints if not score*taskweight%maxpoints else float(score*taskweight)/maxpoints) if maxpoints else 0, taskweight) | |
879 else: | |
880 print 'Grand total: %d/%d tests; %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, score, maxpoints, (score*taskweight/maxpoints if not score*taskweight%maxpoints else float(score*taskweight)/maxpoints) if maxpoints else 0, taskweight) | |
881 | |
8 | 882 scoresumoveralltasks += (score*taskweight/maxpoints if not score*taskweight%maxpoints else float(score*taskweight)/maxpoints) if maxpoints else 0 |
7 | 883 scoremaxoveralltasks += taskweight |
884 ntasks += 1 | |
885 nfulltasks += int((score == maxpoints) if maxpoints else (taskweight == 0)) | |
886 | |
887 os.chdir(oldcwd) | |
888 | |
889 if options.clean or options.copyonly: | |
890 sys.exit() | |
891 | |
892 if ntasks != 1: | |
893 print | |
894 print 'Grand grand total: %g/%g weighted points; %d/%d problems solved fully' % (scoresumoveralltasks, scoremaxoveralltasks, nfulltasks, ntasks) | |
895 | |
896 if options.pause: | |
897 print 'Press any key to exit... ', | |
898 sys.stdout.flush() | |
19
d4fc9341664e
Fixed an exception when tests.zip contained test cases in its root
Oleg Oshmyan <chortos@inbox.lv>
parents:
8
diff
changeset
|
899 os.system(pause + ' >' + os.devnull) |