# HG changeset patch # User Oleg Oshmyan # Date 1268438366 0 # Node ID 231e3317477df3648b5f2a8bac7882098128ef88 # Parent c87ec78f1faef6c2a61492b9d36be38ee6487e88 More version reporting test.py -> test-svn.py publish.py now generates test.py rather than test-pub.py actually added $Rev$ to test-svn.py's properties diff -r c87ec78f1fae -r 231e3317477d publish.py --- a/publish.py Fri Mar 12 23:53:27 2010 +0000 +++ b/publish.py Fri Mar 12 23:59:26 2010 +0000 @@ -1,12 +1,12 @@ #! /usr/bin/python # Copyright (c) 2009-2010 Chortos-2 -with open('test.py') as t: +with open('test-svn.py') as t: f = t.read() i = f.find('# $Rev: ') j = f.find('\n', i) rev = f[i+8:j-1] f = f[0:i] + f[j+1:] f = f.replace('$$REV$$', rev) -with open('test-pub.py', 'wb') as t: +with open('test.py', 'wb') as t: t.write(f) \ No newline at end of file diff -r c87ec78f1fae -r 231e3317477d test-svn.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-svn.py Fri Mar 12 23:59:26 2010 +0000 @@ -0,0 +1,946 @@ +#! /usr/bin/python +# Copyright (c) 2009-2010 Chortos-2 + +import os, sys, shutil, time, subprocess, filecmp, optparse, signal, tempfile, tarfile, zipfile + +# $Rev: 11$ +version = '1.21.0 (SVN r$$REV$$)' +parser = optparse.OptionParser(version='test.py '+version, usage='usage: %prog [options] [problem names] [[path' + os.path.sep + 'to' + os.path.sep + ']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.') +parser.add_option('-u', '--update', dest='update', action='store_true', default=False, help='check for an updated version of test.py') +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') +parser.add_option('-c', '--cleanup', dest='clean', action='store_true', default=False, help='delete the copies of input/output files and exit') +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') +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 or -cm') +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') +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)') +parser.add_option('-t', '--detect-time', dest='autotime', action='store_true', default=False, help='spend a second detecting the most precise time measurement function') + +options, args = parser.parse_args() +parser.destroy() +del parser + +def update(): + import urllib + homepage = urllib.urlopen('http://chortos.selfip.net/~astiob/test.py/').read() + i = homepage.find("The latest version of test.py is ") + i += len("The latest version of test.py is ") + j = homepage.find(".", i) + latest = homepage[i:j].split('.') + installed = version.split('.') + update = '' + if latest[0] > installed[0]: + update = 'major' + elif latest[0] == installed[0]: + if latest[1] > installed[1]: + update = 'feature' + elif latest[1] == installed[1]: + if latest[2] > installed[2]: + update = 'bug-fixing' + elif latest[2] == installed[2]: + print 'You are using the latest publicly available version of test.py.' + return + if update == '': + print 'Your copy of test.py is newer than the publicly available version.' + return + print 'A ' + update + ' update to test.py is available. Downloading...' + urllib.urlretrieve('http://chortos.selfip.net/~astiob/test.py/test.py', 'test.py') + print 'Downloaded and installed. Now you are using test.py ' + homepage[i:j] + '.' + +if options.update: + update() + sys.exit() + +globals1 = set(globals()) + +# Initialize some configuration variables with default values +tasknames = (os.path.curdir,) +maxtime = 0 +tests = () +dummies = () +testsexcluded = () +padwithzeroestolength = 0 +taskweight = 100 +pointmap = {} +stdio = False +dummyinname = '' +dummyoutname = '' +tester = '' +maxexitcode = 0 + +def exectestconf_helper(name): + if os.path.isfile('tests.tar'): + f = tarfile.open('tests.tar') + try: + exec f.extractfile(name).read() in globals() + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.zip'): + f = zipfile.ZipFile('tests.zip') + try: + exec f.open(name, 'rU').read() in globals() + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tgz'): + f = tarfile.open('tests.tgz') + try: + exec f.extractfile(name).read() in globals() + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tar.gz'): + f = tarfile.open('tests.tar.gz') + try: + exec f.extractfile(name).read() in globals() + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tbz2'): + f = tarfile.open('tests.tbz2') + try: + exec f.extractfile(name).read() in globals() + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tar.bz2'): + f = tarfile.open('tests.tar.bz2') + try: + exec f.extractfile(name).read() in globals() + f.close() + return True + except KeyError: + f.close() + return False + +try: + execfile('testconf.py') +except IOError, error: + exc_info = sys.exc_info()[2] + try: + execfile(os.path.join('tests', 'testconf.py')) + except IOError: + if not exectestconf_helper('testconf.py'): + raise IOError, (error.errno, 'The configuration file is missing', error.filename), exc_info + del exc_info + +globals2 = set(globals()) +globals2.remove('globals1') +globals2 -= globals1 +del globals1 + +shared = {} +g = globals() +for k in globals2: + shared[k] = g[k] + +newtasknames = [] +while len(args) and args[0] in tasknames: + newtasknames.append(args[0]) + del args[0] +if len(newtasknames): + tasknames = newtasknames + +scoresumoveralltasks = 0 +scoremaxoveralltasks = 0 +ntasks = 0 +nfulltasks = 0 +cwd = '' # At any time this is either '' or taskname + +if options.autotime: + c = time.clock() + time.sleep(1) + c = time.clock() - c + if int(c + .99999) == 1: + clock = time.clock + else: + clock = time.time +elif os.name == 'nt': + clock = time.clock +else: + clock = time.time + +if options.copyonly: + options.erase = False + +def existstestcase_helper(name): + if os.path.isfile('tests.tar'): + f = tarfile.open('tests.tar') + try: + f.getmember(name) + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.zip'): + f = zipfile.ZipFile('tests.zip') + try: + f.getinfo(name) + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tgz'): + f = tarfile.open('tests.tgz') + try: + f.getmember(name) + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tar.gz'): + f = tarfile.open('tests.tar.gz') + try: + f.getmember(name) + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tbz2'): + f = tarfile.open('tests.tbz2') + try: + f.getmember(name) + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tar.bz2'): + f = tarfile.open('tests.tar.bz2') + try: + f.getmember(name) + f.close() + return True + except KeyError: + f.close() + return False + +def existstestcase(name): + if os.path.isfile(os.path.join('tests', taskname, name)) or os.path.isfile(os.path.join('tests', name)): + return True + if cwd and (os.path.isfile(os.path.join(oldcwd, 'tests', cwd, name)) or os.path.isfile(os.path.join(oldcwd, 'tests', name))): + return True + if existstestcase_helper(os.path.join(taskname, name)) or existstestcase_helper(name): + return True + if cwd: + os.chdir(oldcwd) + if existstestcase_helper(os.path.join(cwd, name)) or existstestcase_helper(name): + os.chdir(cwd) + return True + os.chdir(cwd) + return False + +def opentestcase_helper(name): + if os.path.isfile('tests.tar'): + f = tarfile.open('tests.tar') + try: + c = f.extractfile(name) + return c + except KeyError: + f.close() + if os.path.isfile('tests.zip'): + f = zipfile.ZipFile('tests.zip') + try: + c = f.open(name, 'rU') + f.close() + return c + except KeyError: + f.close() + if os.path.isfile('tests.tgz'): + f = tarfile.open('tests.tgz') + try: + c = f.extractfile(name) + return c + except KeyError: + f.close() + if os.path.isfile('tests.tar.gz'): + f = tarfile.open('tests.tar.gz') + try: + c = f.extractfile(name) + return c + except KeyError: + f.close() + if os.path.isfile('tests.tbz2'): + f = tarfile.open('tests.tbz2') + try: + c = f.extractfile(name) + return c + except KeyError: + f.close() + if os.path.isfile('tests.tar.bz2'): + f = tarfile.open('tests.tar.bz2') + try: + c = f.extractfile(name) + return c + except KeyError: + f.close() + return None + +def opentestcase(name): + if os.path.isfile(os.path.join('tests', taskname, name)): + return open(os.path.join('tests', taskname, name), 'rU') + elif os.path.isfile(os.path.join('tests', name)): + return open(os.path.join('tests', name), 'rU') + f = opentestcase_helper(os.path.join(taskname, name)) + if not f: + f = opentestcase_helper(name) + if f: + return f + if cwd: + if os.path.isfile(os.path.join(oldcwd, 'tests', cwd, name)): + return open(os.path.join(oldcwd, 'tests', cwd, name), 'rU') + elif os.path.isfile(os.path.join(oldcwd, 'tests', name)): + return open(os.path.join(oldcwd, 'tests', name), 'rU') + os.chdir(oldcwd) + f = opentestcase_helper(os.path.join(cwd, name)) + if not f: + f = opentestcase_helper(name) + os.chdir(cwd) + if f: + return f + raise KeyError, 'The test-case-defining file \'' + name + '\' cannot be found' + +def copytestcase_helper(name, target): + if os.path.isfile('tests.tar'): + f = tarfile.open('tests.tar') + try: + m = f.getmember(name) + m.name = target + f.extract(m) + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.zip'): + if not os.path.isabs(target): + f = zipfile.ZipFile('tests.zip') + m = f.getinfo(name) + try: + m.filename = target + f.extract(m) + f.close() + return True + except KeyError: + f.close() + else: + oldcwd = os.getcwdu() + os.chdir('/') # FIXME: portability? + f = zipfile.ZipFile(os.path.join(oldcwd, 'tests.zip')) + try: + m = f.getinfo(name) + m.filename = target[1:] + f.extract(m) + f.close() + os.chdir(oldcwd) + return True + except KeyError: + f.close() + os.chdir(oldwcd) + if os.path.isfile('tests.tgz'): + f = tarfile.open('tests.tgz') + try: + m = f.getmember(name) + m.name = target + f.extract(m) + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tar.gz'): + f = tarfile.open('tests.tar.gz') + try: + m = f.getmember(name) + m.name = target + f.extract(m) + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tbz2'): + f = tarfile.open('tests.tbz2') + try: + m = f.getmember(name) + m.name = target + f.extract(m) + f.close() + return True + except KeyError: + f.close() + if os.path.isfile('tests.tar.bz2'): + f = tarfile.open('tests.tar.bz2') + try: + m = f.getmember(name) + m.name = target + f.extract(m) + f.close() + return True + except KeyError: + f.close() + return False + +def copytestcase(name, target): + if os.path.isfile(os.path.join('tests', taskname, name)): + shutil.copyfile(os.path.join('tests', taskname, name), target) + return + elif os.path.isfile(os.path.join('tests', name)): + shutil.copyfile(os.path.join('tests', name), target) + return + if copytestcase_helper(os.path.join(taskname, name), target) or copytestcase_helper(name, target): + return + if cwd: + if os.path.isfile(os.path.join(oldcwd, 'tests', cwd, name)): + shutil.copyfile(os.path.join(oldcwd, 'tests', cwd, name), target) + return + elif os.path.isfile(os.path.join(oldcwd, 'tests', name)): + shutil.copyfile(os.path.join(oldcwd, 'tests', name), target) + return + os.chdir(oldcwd) + if copytestcase_helper(os.path.join(cwd, name), target) or copytestcase_helper(name, target): + os.chdir(cwd) + return + os.chdir(cwd) + raise KeyError, 'The test-case-defining file \'' + name + '\' cannot be found' + +# Always chdir if the directory exists but use any existing config +def chdir_and_exec_testconf(): + global cwd + cwd = '' + if os.path.isdir(taskname): + os.chdir(taskname) + if taskname != os.path.curdir: + cwd = taskname + try: + execfile('testconf.py', globals()) + return + except IOError: + pass + if not cwd: + if os.path.isfile(os.path.join('tests', taskname, 'testconf.py')): + execfile(os.path.join('tests', taskname, 'testconf.py'), globals()) + return + if os.path.isfile(os.path.join('tests', 'testconf.py')): + execfile(os.path.join('tests', 'testconf.py'), globals()) + return + if exectestconf_helper(os.path.join(taskname, 'testconf.py')) or exectestconf_helper('testconf.py'): + return + if cwd: + os.chdir(oldcwd) + if os.path.isfile(os.path.join('tests', cwd, 'testconf.py')): + execfile(os.path.join('tests', cwd, 'testconf.py'), globals()) + os.chdir(cwd) + return + if os.path.isfile(os.path.join('tests', 'testconf.py')): + execfile(os.path.join('tests', 'testconf.py'), globals()) + os.chdir(cwd) + return + if exectestconf_helper(os.path.join(cwd, 'testconf.py')) or exectestconf_helper('testconf.py'): + os.chdir(cwd) + return + if os.path.isfile('testconf.py'): + execfile('testconf.py', globals()) + os.chdir(cwd) + return + os.chdir(cwd) + elif os.path.isfile('testconf.py'): + execfile('testconf.py', globals()) + return + raise KeyError, 'The configuration file for task ' + taskname + ' is missing' + +try: + name + namedefined = True +except Exception: + namedefined = False + +for taskname in tasknames: + if ntasks: + print + + try: + if len(tasknames) > 1: + print taskname + except Exception: + if taskname != os.path.curdir or ntasks: + print taskname + + try: del inname + except NameError: pass + try: del outname + except NameError: pass + try: del ansname + except NameError: pass + + if not namedefined and taskname != os.path.curdir: + name = os.path.join(os.path.curdir, taskname) + for k in shared: + g[k] = shared[k] + + oldcwd = os.getcwdu() + chdir_and_exec_testconf() + + if options.clean: + try: + if not stdio or tester: + if not tester: + inname + outname + if tester: + ansname + except NameError, error: + raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] + if not options.erase: + try: + inname = inname.replace('%', taskname) + except NameError: + inname = taskname + '.in' + try: + outname = outname.replace('%', taskname) + except NameError: + outname = taskname + '.out' + try: + ansname = ansname.replace('%', taskname) + except NameError: + ansname = taskname + '.ans' + elif not stdio or tester or not options.erase: + inname = inname.replace('%', taskname) + outname = outname.replace('%', taskname) + if tester: + ansname = ansname.replace('%', taskname) + if not stdio or tester or not options.erase: + if os.path.exists(inname): os.remove(inname) + if os.path.exists(outname): os.remove(outname) + if (tester or not options.erase) and ansname: + if os.path.exists(ansname): os.remove(ansname) + continue + + try: + name + except NameError, error: + if str(error).count('name') == 1: + raise NameError, 'configuration ' + str(error), sys.exc_info()[2] + else: + raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] + + try: + if not stdio: + inname + outname + testcaseinname + if tester: + outname + if ansname: + testcaseoutname + else: + testcaseoutname + except NameError, error: + raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] + + if not options.erase: + try: + inname + except NameError: + inname = taskname + '.in' + try: + outname + except NameError: + outname = taskname + '.out' + try: + ansname + except NameError: + ansname = taskname + '.ans' + + if options.pause: + try: + pause + except NameError, error: + if os.name == 'posix': + pause = 'read -s -n 1' + 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 completed.' + elif os.name == 'nt': + pause = 'pause' + else: + raise NameError, 'configuration ' + str(error).replace('name ', 'variable ') + ' and cannot be devised automatically', sys.exc_info()[2] + + if not dummyinname: + dummyinname = testcaseinname + if not dummyoutname and (not tester or ansname): + dummyoutname = testcaseoutname + + dummyinname = dummyinname.replace('%', taskname) + dummyoutname = dummyoutname.replace('%', taskname) + testcaseinname = testcaseinname.replace('%', taskname) + if not stdio or not options.erase: + inname = inname.replace('%', taskname) + outname = outname.replace('%', taskname) + try: + ansname = ansname.replace('%', taskname) + except NameError: + pass + if tester: + try: inname = inname.replace('%', taskname) + except NameError: pass + outname = outname.replace('%', taskname) + if ansname: + ansname = ansname.replace('%', taskname) + testcaseoutname = testcaseoutname.replace('%', taskname) + else: + testcaseoutname = testcaseoutname.replace('%', taskname) + + if isinstance(padwithzeroestolength, tuple): + padwithzeroestolength, paddummieswithzeroestolength = padwithzeroestolength + else: + paddummieswithzeroestolength = padwithzeroestolength + + if options.python: + dummies = () + s = ' '.join(args) + tests = eval(s) + try: + tests.__iter__ + except AttributeError: + tests = (tests,) + elif len(args): + if os.path.exists(args[0]): + name = args[0] + del args[0] + if len(args) > 1: + dummies = () + tests = args + elif len(args): + dummies = () + s = args[0] + if len(s) < padwithzeroestolength: + s = s.zfill(padwithzeroestolength) + if existstestcase(testcaseinname.replace('$', s)): + tests = (s,) + else: + try: + tests = eval(args[0]) + try: + tests.__iter__ + except AttributeError: + tests = (tests,) + except Exception: + tests = (s,) + + if options.exclude: + testsexcluded = [] + for i in options.exclude: + v = eval(i) + try: + testsexcluded.extend(v) + except TypeError: + testsexcluded.append(v) + + # Windows doesn't like paths beginning with .\ and not ending with an extension + name = os.path.normcase(name) + if os.name == 'nt' and name.startswith('.\\'): + name = name[2:] + + newpointmap = {} + + for i in pointmap: + try: + for j in i: + newpointmap[j] = pointmap[i] + except TypeError: + newpointmap[i] = pointmap[i] + + pointmap = newpointmap + + if not tester: + maxexitcode = 0 + + if maxtime > 0: + strmaxtime = '/%.3f' % maxtime + else: + strmaxtime = '' + + padoutputtolength = 0 + ntests = [] + + for j in dummies: + try: + j.__iter__ + except AttributeError: + j = (j,) + ntests.append((j, True)) + for i in j: + s = str(i) + if len(s) < paddummieswithzeroestolength: + s = s.zfill(paddummieswithzeroestolength) + s = 'sample ' + s + if padoutputtolength < len(s): + padoutputtolength = len(s) + + for j in tests: + try: + j.__iter__ + except AttributeError: + j = (j,) + ntests.append((j, False)) + for i in j: + s = str(i) + if len(s) < padwithzeroestolength: + s = s.zfill(padwithzeroestolength) + if padoutputtolength < len(s): + padoutputtolength = len(s) + + tests = ntests + score = maxpoints = ncorrect = ntotal = ncorrectvalued = nvalued = 0 + + if options.copyonly: + j, isdummy = tests[-1] + if isdummy: + realinname = dummyinname + realoutname = dummyoutname + else: + realinname = testcaseinname + realoutname = testcaseoutname + for i in j: + if i in testsexcluded and not isdummy: + continue + s = str(i) + if isdummy: + if len(s) < paddummieswithzeroestolength: + s = s.zfill(paddummieswithzeroestolength) + else: + if len(s) < padwithzeroestolength: + s = s.zfill(padwithzeroestolength) + copytestcase(realinname.replace('$', s), inname) + if ansname: + copytestcase(realoutname.replace('$', s), ansname) + continue + + for j, isdummy in tests: + ncorrectgrp = 0 + ntotalgrp = 0 + scoregrp = 0 + maxpointsgrp = 0 + if isdummy: + realinname = dummyinname + realoutname = dummyoutname + else: + realinname = testcaseinname + realoutname = testcaseoutname + for i in j: + if i in testsexcluded and not isdummy: + continue + ntotalgrp += 1 + s = str(i) + if isdummy: + npoints = 0 + if len(s) < paddummieswithzeroestolength: + s = s.zfill(paddummieswithzeroestolength) + spref = 'sample ' + else: + npoints = pointmap.get(None, maxexitcode if maxexitcode and isinstance(maxexitcode, int) else 1) + npoints = pointmap.get(i, npoints) + maxpointsgrp += npoints + if npoints: + nvalued += 1 + if len(s) < padwithzeroestolength: + s = s.zfill(padwithzeroestolength) + spref = '' + print ' ' * (padoutputtolength - len(spref + s)) + spref + s + ':', + sys.stdout.flush() + outputdata = open(os.devnull, 'w') + if stdio: + f = tempfile.NamedTemporaryFile(delete=False) + inputdatafname = f.name + f.close() + copytestcase(realinname.replace('$', s), inputdatafname) + inputdata = open(inputdatafname, 'rU') + if options.erase: + tempoutput = tempfile.TemporaryFile('w+') + else: + tempoutput = open(outname, 'w+') + try: + proc = subprocess.Popen(name, stdin=inputdata, stdout=tempoutput, stderr=outputdata, universal_newlines=True) + except OSError, error: + raise OSError, 'The program to be tested cannot be launched: ' + str(error), sys.exc_info()[2] + else: + if os.path.exists(outname): + os.remove(outname) + copytestcase(realinname.replace('$', s), inname) + try: + proc = subprocess.Popen(name, stdin=outputdata, stdout=outputdata, stderr=outputdata, universal_newlines=True) + except OSError, error: + raise OSError, 'The program to be tested cannot be launched: ' + str(error), sys.exc_info()[2] + cl = clock() + if maxtime > 0: + while 1: + proc.poll() + elapsed = clock() - cl + if proc.returncode == None: + if elapsed >= maxtime: + print '%.3f%s s, 0/%d, time limit exceeded' % (elapsed, strmaxtime, npoints) + sys.stdout.flush() + while proc.returncode == None: + try: + proc.terminate() + except OSError: + pass + except AttributeError: + try: + os.kill(proc.pid, signal.SIGTERM) + except Exception: + pass + proc.poll() + outputdata.close() + if stdio: + tempoutput.close() + break + else: + print '%.3f%s s,' % (elapsed, strmaxtime), + sys.stdout.flush() + elapsed = 0 + if stdio: + tempoutput.seek(0) + lines = tempoutput.readlines() + tempoutput.close() + break + if elapsed >= maxtime: + continue + else: + data = proc.communicate() + elapsed = clock() - cl + print '%.3f%s s,' % (elapsed, strmaxtime), + sys.stdout.flush() + if stdio: + tempoutput.seek(0) + lines = tempoutput.readlines() + tempoutput.close() + outputdata.close() + if stdio: + inputdata.close() + try: + os.unlink(inputdatafname) + except Exception: + pass + if proc.returncode > 0: + print '0/%d, non-zero return code %d' % (npoints, proc.returncode) + sys.stdout.flush() + elif proc.returncode < 0: + print '0/%d, terminated by signal %d' % (npoints, -proc.returncode) + sys.stdout.flush() + else: + if not tester: + if stdio: + outputdata = opentestcase(realoutname.replace('$', s)) + r = 0 + data = outputdata.read().splitlines(True) + if len(lines) != len(data): + r = 1 + else: + for i in zip(lines, data): + if i[0] != i[1]: + r = 1 + break + outputdata.close() + else: + try: + inputdata = open(outname, 'rU') + except IOError: + print '0/%g, output file not created or not readable' % npoints + sys.stdout.flush() + r = None + else: + outputdata = opentestcase(realoutname.replace('$', s)) + r = 0 + lines = inputdata.readlines() + data = outputdata.read().splitlines(True) + if len(lines) != len(data): + r = 1 + else: + for i in zip(lines, data): + if i[0] != i[1]: + r = 1 + break + inputdata.close() + outputdata.close() + else: + if ansname: + copytestcase(realoutname.replace('$', s), ansname) + if stdio: + try: copytestcase(realinname.replace('$', s), inname) + except NameError: pass + outputdata = open(outname, 'w') + outputdata.writelines(lines) + outputdata.close() + try: + proc = subprocess.Popen(tester, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) + except OSError, error: + raise OSError, 'The tester application cannot be launched: ' + str(error), sys.exc_info()[2] + data = proc.communicate() + r = proc.returncode + if tester and data[0]: + data = ''.join((' (', data[0].strip(), ')')) + else: + data = '' + if not maxexitcode and r or maxexitcode and not r: + print '0/%g, wrong answer%s' % (npoints, data) + sys.stdout.flush() + elif not maxexitcode and r == 0 or maxexitcode and r >= maxexitcode: + print '%g/%g, OK%s' % (npoints, npoints, data) + sys.stdout.flush() + scoregrp += npoints + ncorrectgrp += 1 + if npoints: + ncorrectvalued += 1 + elif maxexitcode and r != None: + actualpoints = npoints*r/maxexitcode if not npoints*r%maxexitcode else float(npoints*r)/maxexitcode + print '%g/%g, partly OK%s' % (actualpoints, npoints, data) + sys.stdout.flush() + scoregrp += actualpoints + ncorrectgrp += 1 + if npoints: + ncorrectvalued += 1 + if ntotalgrp: + if ncorrectgrp < ntotalgrp: + scoregrp = 0 + if ntotalgrp > 1: + print 'Group total: %d/%d tests; %g/%g points' % (ncorrectgrp, ntotalgrp, scoregrp, maxpointsgrp) + sys.stdout.flush() + ncorrect += ncorrectgrp + ntotal += ntotalgrp + score += scoregrp + maxpoints += maxpointsgrp + + if options.erase: + if not stdio or tester: + if os.path.exists(inname): os.remove(inname) + if os.path.exists(outname): os.remove(outname) + if tester and ansname: + if os.path.exists(ansname): os.remove(ansname) + elif stdio: + copytestcase(realinname.replace('$', s), inname) + copytestcase(realoutname.replace('$', s), ansname) + actualpoints = (score*taskweight/maxpoints if not score*taskweight%maxpoints else float(score*taskweight)/maxpoints) if maxpoints else 0 + if nvalued != ntotal: + print 'Grand total: %d/%d tests (%d/%d valued); %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, ncorrectvalued, nvalued, score, maxpoints, actualpoints, taskweight) + else: + print 'Grand total: %d/%d tests; %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, score, maxpoints, actualpoints, taskweight) + + scoresumoveralltasks += actualpoints + scoremaxoveralltasks += taskweight + ntasks += 1 + nfulltasks += int((score == maxpoints) if maxpoints else (taskweight == 0)) + + os.chdir(oldcwd) + +if options.clean or options.copyonly: + sys.exit() + +if ntasks != 1: + print + print 'Grand grand total: %g/%g weighted points; %d/%d problems solved fully' % (scoresumoveralltasks, scoremaxoveralltasks, nfulltasks, ntasks) + +if options.pause: + print 'Press any key to exit... ', + sys.stdout.flush() + os.system(pause + ' >' + os.devnull) \ No newline at end of file diff -r c87ec78f1fae -r 231e3317477d test.py --- a/test.py Fri Mar 12 23:53:27 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,946 +0,0 @@ -#! /usr/bin/python -# Copyright (c) 2009-2010 Chortos-2 - -import os, sys, shutil, time, subprocess, filecmp, optparse, signal, tempfile, tarfile, zipfile - -# $Rev: 11$ -version = '1.21.0 (SVN r$$REV$$)' -parser = optparse.OptionParser(version='test.py '+version, usage='usage: %prog [options] [problem names] [[path' + os.path.sep + 'to' + os.path.sep + ']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.') -parser.add_option('-u', '--update', dest='update', action='store_true', default=False, help='check for an updated version of test.py') -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') -parser.add_option('-c', '--cleanup', dest='clean', action='store_true', default=False, help='delete the copies of input/output files and exit') -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') -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 or -cm') -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') -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)') -parser.add_option('-t', '--detect-time', dest='autotime', action='store_true', default=False, help='spend a second detecting the most precise time measurement function') - -options, args = parser.parse_args() -parser.destroy() -del parser - -def update(): - import urllib - homepage = urllib.urlopen('http://chortos.selfip.net/~astiob/test.py/').read() - i = homepage.find("The latest version of test.py is ") - i += len("The latest version of test.py is ") - j = homepage.find(".", i) - latest = homepage[i:j].split('.') - installed = version.split('.') - update = '' - if latest[0] > installed[0]: - update = 'major' - elif latest[0] == installed[0]: - if latest[1] > installed[1]: - update = 'feature' - elif latest[1] == installed[1]: - if latest[2] > installed[2]: - update = 'bug-fixing' - elif latest[2] == installed[2]: - print 'You are using the latest publicly available version of test.py.' - return - if update == '': - print 'Your copy of test.py is newer than the publicly available version.' - return - print 'A ' + update + ' update to test.py is available. Downloading...' - urllib.urlretrieve('http://chortos.selfip.net/~astiob/test.py/test.py', 'test.py') - print 'Downloaded and installed. Now you are using test.py ' + homepage[i:j] + '.' - -if options.update: - update() - sys.exit() - -globals1 = set(globals()) - -# Initialize some configuration variables with default values -tasknames = (os.path.curdir,) -maxtime = 0 -tests = () -dummies = () -testsexcluded = () -padwithzeroestolength = 0 -taskweight = 100 -pointmap = {} -stdio = False -dummyinname = '' -dummyoutname = '' -tester = '' -maxexitcode = 0 - -def exectestconf_helper(name): - if os.path.isfile('tests.tar'): - f = tarfile.open('tests.tar') - try: - exec f.extractfile(name).read() in globals() - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.zip'): - f = zipfile.ZipFile('tests.zip') - try: - exec f.open(name, 'rU').read() in globals() - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tgz'): - f = tarfile.open('tests.tgz') - try: - exec f.extractfile(name).read() in globals() - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tar.gz'): - f = tarfile.open('tests.tar.gz') - try: - exec f.extractfile(name).read() in globals() - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tbz2'): - f = tarfile.open('tests.tbz2') - try: - exec f.extractfile(name).read() in globals() - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tar.bz2'): - f = tarfile.open('tests.tar.bz2') - try: - exec f.extractfile(name).read() in globals() - f.close() - return True - except KeyError: - f.close() - return False - -try: - execfile('testconf.py') -except IOError, error: - exc_info = sys.exc_info()[2] - try: - execfile(os.path.join('tests', 'testconf.py')) - except IOError: - if not exectestconf_helper('testconf.py'): - raise IOError, (error.errno, 'The configuration file is missing', error.filename), exc_info - del exc_info - -globals2 = set(globals()) -globals2.remove('globals1') -globals2 -= globals1 -del globals1 - -shared = {} -g = globals() -for k in globals2: - shared[k] = g[k] - -newtasknames = [] -while len(args) and args[0] in tasknames: - newtasknames.append(args[0]) - del args[0] -if len(newtasknames): - tasknames = newtasknames - -scoresumoveralltasks = 0 -scoremaxoveralltasks = 0 -ntasks = 0 -nfulltasks = 0 -cwd = '' # At any time this is either '' or taskname - -if options.autotime: - c = time.clock() - time.sleep(1) - c = time.clock() - c - if int(c + .99999) == 1: - clock = time.clock - else: - clock = time.time -elif os.name == 'nt': - clock = time.clock -else: - clock = time.time - -if options.copyonly: - options.erase = False - -def existstestcase_helper(name): - if os.path.isfile('tests.tar'): - f = tarfile.open('tests.tar') - try: - f.getmember(name) - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.zip'): - f = zipfile.ZipFile('tests.zip') - try: - f.getinfo(name) - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tgz'): - f = tarfile.open('tests.tgz') - try: - f.getmember(name) - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tar.gz'): - f = tarfile.open('tests.tar.gz') - try: - f.getmember(name) - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tbz2'): - f = tarfile.open('tests.tbz2') - try: - f.getmember(name) - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tar.bz2'): - f = tarfile.open('tests.tar.bz2') - try: - f.getmember(name) - f.close() - return True - except KeyError: - f.close() - return False - -def existstestcase(name): - if os.path.isfile(os.path.join('tests', taskname, name)) or os.path.isfile(os.path.join('tests', name)): - return True - if cwd and (os.path.isfile(os.path.join(oldcwd, 'tests', cwd, name)) or os.path.isfile(os.path.join(oldcwd, 'tests', name))): - return True - if existstestcase_helper(os.path.join(taskname, name)) or existstestcase_helper(name): - return True - if cwd: - os.chdir(oldcwd) - if existstestcase_helper(os.path.join(cwd, name)) or existstestcase_helper(name): - os.chdir(cwd) - return True - os.chdir(cwd) - return False - -def opentestcase_helper(name): - if os.path.isfile('tests.tar'): - f = tarfile.open('tests.tar') - try: - c = f.extractfile(name) - return c - except KeyError: - f.close() - if os.path.isfile('tests.zip'): - f = zipfile.ZipFile('tests.zip') - try: - c = f.open(name, 'rU') - f.close() - return c - except KeyError: - f.close() - if os.path.isfile('tests.tgz'): - f = tarfile.open('tests.tgz') - try: - c = f.extractfile(name) - return c - except KeyError: - f.close() - if os.path.isfile('tests.tar.gz'): - f = tarfile.open('tests.tar.gz') - try: - c = f.extractfile(name) - return c - except KeyError: - f.close() - if os.path.isfile('tests.tbz2'): - f = tarfile.open('tests.tbz2') - try: - c = f.extractfile(name) - return c - except KeyError: - f.close() - if os.path.isfile('tests.tar.bz2'): - f = tarfile.open('tests.tar.bz2') - try: - c = f.extractfile(name) - return c - except KeyError: - f.close() - return None - -def opentestcase(name): - if os.path.isfile(os.path.join('tests', taskname, name)): - return open(os.path.join('tests', taskname, name), 'rU') - elif os.path.isfile(os.path.join('tests', name)): - return open(os.path.join('tests', name), 'rU') - f = opentestcase_helper(os.path.join(taskname, name)) - if not f: - f = opentestcase_helper(name) - if f: - return f - if cwd: - if os.path.isfile(os.path.join(oldcwd, 'tests', cwd, name)): - return open(os.path.join(oldcwd, 'tests', cwd, name), 'rU') - elif os.path.isfile(os.path.join(oldcwd, 'tests', name)): - return open(os.path.join(oldcwd, 'tests', name), 'rU') - os.chdir(oldcwd) - f = opentestcase_helper(os.path.join(cwd, name)) - if not f: - f = opentestcase_helper(name) - os.chdir(cwd) - if f: - return f - raise KeyError, 'The test-case-defining file \'' + name + '\' cannot be found' - -def copytestcase_helper(name, target): - if os.path.isfile('tests.tar'): - f = tarfile.open('tests.tar') - try: - m = f.getmember(name) - m.name = target - f.extract(m) - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.zip'): - if not os.path.isabs(target): - f = zipfile.ZipFile('tests.zip') - m = f.getinfo(name) - try: - m.filename = target - f.extract(m) - f.close() - return True - except KeyError: - f.close() - else: - oldcwd = os.getcwdu() - os.chdir('/') # FIXME: portability? - f = zipfile.ZipFile(os.path.join(oldcwd, 'tests.zip')) - try: - m = f.getinfo(name) - m.filename = target[1:] - f.extract(m) - f.close() - os.chdir(oldcwd) - return True - except KeyError: - f.close() - os.chdir(oldwcd) - if os.path.isfile('tests.tgz'): - f = tarfile.open('tests.tgz') - try: - m = f.getmember(name) - m.name = target - f.extract(m) - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tar.gz'): - f = tarfile.open('tests.tar.gz') - try: - m = f.getmember(name) - m.name = target - f.extract(m) - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tbz2'): - f = tarfile.open('tests.tbz2') - try: - m = f.getmember(name) - m.name = target - f.extract(m) - f.close() - return True - except KeyError: - f.close() - if os.path.isfile('tests.tar.bz2'): - f = tarfile.open('tests.tar.bz2') - try: - m = f.getmember(name) - m.name = target - f.extract(m) - f.close() - return True - except KeyError: - f.close() - return False - -def copytestcase(name, target): - if os.path.isfile(os.path.join('tests', taskname, name)): - shutil.copyfile(os.path.join('tests', taskname, name), target) - return - elif os.path.isfile(os.path.join('tests', name)): - shutil.copyfile(os.path.join('tests', name), target) - return - if copytestcase_helper(os.path.join(taskname, name), target) or copytestcase_helper(name, target): - return - if cwd: - if os.path.isfile(os.path.join(oldcwd, 'tests', cwd, name)): - shutil.copyfile(os.path.join(oldcwd, 'tests', cwd, name), target) - return - elif os.path.isfile(os.path.join(oldcwd, 'tests', name)): - shutil.copyfile(os.path.join(oldcwd, 'tests', name), target) - return - os.chdir(oldcwd) - if copytestcase_helper(os.path.join(cwd, name), target) or copytestcase_helper(name, target): - os.chdir(cwd) - return - os.chdir(cwd) - raise KeyError, 'The test-case-defining file \'' + name + '\' cannot be found' - -# Always chdir if the directory exists but use any existing config -def chdir_and_exec_testconf(): - global cwd - cwd = '' - if os.path.isdir(taskname): - os.chdir(taskname) - if taskname != os.path.curdir: - cwd = taskname - try: - execfile('testconf.py', globals()) - return - except IOError: - pass - if not cwd: - if os.path.isfile(os.path.join('tests', taskname, 'testconf.py')): - execfile(os.path.join('tests', taskname, 'testconf.py'), globals()) - return - if os.path.isfile(os.path.join('tests', 'testconf.py')): - execfile(os.path.join('tests', 'testconf.py'), globals()) - return - if exectestconf_helper(os.path.join(taskname, 'testconf.py')) or exectestconf_helper('testconf.py'): - return - if cwd: - os.chdir(oldcwd) - if os.path.isfile(os.path.join('tests', cwd, 'testconf.py')): - execfile(os.path.join('tests', cwd, 'testconf.py'), globals()) - os.chdir(cwd) - return - if os.path.isfile(os.path.join('tests', 'testconf.py')): - execfile(os.path.join('tests', 'testconf.py'), globals()) - os.chdir(cwd) - return - if exectestconf_helper(os.path.join(cwd, 'testconf.py')) or exectestconf_helper('testconf.py'): - os.chdir(cwd) - return - if os.path.isfile('testconf.py'): - execfile('testconf.py', globals()) - os.chdir(cwd) - return - os.chdir(cwd) - elif os.path.isfile('testconf.py'): - execfile('testconf.py', globals()) - return - raise KeyError, 'The configuration file for task ' + taskname + ' is missing' - -try: - name - namedefined = True -except Exception: - namedefined = False - -for taskname in tasknames: - if ntasks: - print - - try: - if len(tasknames) > 1: - print taskname - except Exception: - if taskname != os.path.curdir or ntasks: - print taskname - - try: del inname - except NameError: pass - try: del outname - except NameError: pass - try: del ansname - except NameError: pass - - if not namedefined and taskname != os.path.curdir: - name = os.path.join(os.path.curdir, taskname) - for k in shared: - g[k] = shared[k] - - oldcwd = os.getcwdu() - chdir_and_exec_testconf() - - if options.clean: - try: - if not stdio or tester: - if not tester: - inname - outname - if tester: - ansname - except NameError, error: - raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] - if not options.erase: - try: - inname = inname.replace('%', taskname) - except NameError: - inname = taskname + '.in' - try: - outname = outname.replace('%', taskname) - except NameError: - outname = taskname + '.out' - try: - ansname = ansname.replace('%', taskname) - except NameError: - ansname = taskname + '.ans' - elif not stdio or tester or not options.erase: - inname = inname.replace('%', taskname) - outname = outname.replace('%', taskname) - if tester: - ansname = ansname.replace('%', taskname) - if not stdio or tester or not options.erase: - if os.path.exists(inname): os.remove(inname) - if os.path.exists(outname): os.remove(outname) - if (tester or not options.erase) and ansname: - if os.path.exists(ansname): os.remove(ansname) - continue - - try: - name - except NameError, error: - if str(error).count('name') == 1: - raise NameError, 'configuration ' + str(error), sys.exc_info()[2] - else: - raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] - - try: - if not stdio: - inname - outname - testcaseinname - if tester: - outname - if ansname: - testcaseoutname - else: - testcaseoutname - except NameError, error: - raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] - - if not options.erase: - try: - inname - except NameError: - inname = taskname + '.in' - try: - outname - except NameError: - outname = taskname + '.out' - try: - ansname - except NameError: - ansname = taskname + '.ans' - - if options.pause: - try: - pause - except NameError, error: - if os.name == 'posix': - pause = 'read -s -n 1' - 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 completed.' - elif os.name == 'nt': - pause = 'pause' - else: - raise NameError, 'configuration ' + str(error).replace('name ', 'variable ') + ' and cannot be devised automatically', sys.exc_info()[2] - - if not dummyinname: - dummyinname = testcaseinname - if not dummyoutname and (not tester or ansname): - dummyoutname = testcaseoutname - - dummyinname = dummyinname.replace('%', taskname) - dummyoutname = dummyoutname.replace('%', taskname) - testcaseinname = testcaseinname.replace('%', taskname) - if not stdio or not options.erase: - inname = inname.replace('%', taskname) - outname = outname.replace('%', taskname) - try: - ansname = ansname.replace('%', taskname) - except NameError: - pass - if tester: - try: inname = inname.replace('%', taskname) - except NameError: pass - outname = outname.replace('%', taskname) - if ansname: - ansname = ansname.replace('%', taskname) - testcaseoutname = testcaseoutname.replace('%', taskname) - else: - testcaseoutname = testcaseoutname.replace('%', taskname) - - if isinstance(padwithzeroestolength, tuple): - padwithzeroestolength, paddummieswithzeroestolength = padwithzeroestolength - else: - paddummieswithzeroestolength = padwithzeroestolength - - if options.python: - dummies = () - s = ' '.join(args) - tests = eval(s) - try: - tests.__iter__ - except AttributeError: - tests = (tests,) - elif len(args): - if os.path.exists(args[0]): - name = args[0] - del args[0] - if len(args) > 1: - dummies = () - tests = args - elif len(args): - dummies = () - s = args[0] - if len(s) < padwithzeroestolength: - s = s.zfill(padwithzeroestolength) - if existstestcase(testcaseinname.replace('$', s)): - tests = (s,) - else: - try: - tests = eval(args[0]) - try: - tests.__iter__ - except AttributeError: - tests = (tests,) - except Exception: - tests = (s,) - - if options.exclude: - testsexcluded = [] - for i in options.exclude: - v = eval(i) - try: - testsexcluded.extend(v) - except TypeError: - testsexcluded.append(v) - - # Windows doesn't like paths beginning with .\ and not ending with an extension - name = os.path.normcase(name) - if os.name == 'nt' and name.startswith('.\\'): - name = name[2:] - - newpointmap = {} - - for i in pointmap: - try: - for j in i: - newpointmap[j] = pointmap[i] - except TypeError: - newpointmap[i] = pointmap[i] - - pointmap = newpointmap - - if not tester: - maxexitcode = 0 - - if maxtime > 0: - strmaxtime = '/%.3f' % maxtime - else: - strmaxtime = '' - - padoutputtolength = 0 - ntests = [] - - for j in dummies: - try: - j.__iter__ - except AttributeError: - j = (j,) - ntests.append((j, True)) - for i in j: - s = str(i) - if len(s) < paddummieswithzeroestolength: - s = s.zfill(paddummieswithzeroestolength) - s = 'sample ' + s - if padoutputtolength < len(s): - padoutputtolength = len(s) - - for j in tests: - try: - j.__iter__ - except AttributeError: - j = (j,) - ntests.append((j, False)) - for i in j: - s = str(i) - if len(s) < padwithzeroestolength: - s = s.zfill(padwithzeroestolength) - if padoutputtolength < len(s): - padoutputtolength = len(s) - - tests = ntests - score = maxpoints = ncorrect = ntotal = ncorrectvalued = nvalued = 0 - - if options.copyonly: - j, isdummy = tests[-1] - if isdummy: - realinname = dummyinname - realoutname = dummyoutname - else: - realinname = testcaseinname - realoutname = testcaseoutname - for i in j: - if i in testsexcluded and not isdummy: - continue - s = str(i) - if isdummy: - if len(s) < paddummieswithzeroestolength: - s = s.zfill(paddummieswithzeroestolength) - else: - if len(s) < padwithzeroestolength: - s = s.zfill(padwithzeroestolength) - copytestcase(realinname.replace('$', s), inname) - if ansname: - copytestcase(realoutname.replace('$', s), ansname) - continue - - for j, isdummy in tests: - ncorrectgrp = 0 - ntotalgrp = 0 - scoregrp = 0 - maxpointsgrp = 0 - if isdummy: - realinname = dummyinname - realoutname = dummyoutname - else: - realinname = testcaseinname - realoutname = testcaseoutname - for i in j: - if i in testsexcluded and not isdummy: - continue - ntotalgrp += 1 - s = str(i) - if isdummy: - npoints = 0 - if len(s) < paddummieswithzeroestolength: - s = s.zfill(paddummieswithzeroestolength) - spref = 'sample ' - else: - npoints = pointmap.get(None, maxexitcode if maxexitcode and isinstance(maxexitcode, int) else 1) - npoints = pointmap.get(i, npoints) - maxpointsgrp += npoints - if npoints: - nvalued += 1 - if len(s) < padwithzeroestolength: - s = s.zfill(padwithzeroestolength) - spref = '' - print ' ' * (padoutputtolength - len(spref + s)) + spref + s + ':', - sys.stdout.flush() - outputdata = open(os.devnull, 'w') - if stdio: - f = tempfile.NamedTemporaryFile(delete=False) - inputdatafname = f.name - f.close() - copytestcase(realinname.replace('$', s), inputdatafname) - inputdata = open(inputdatafname, 'rU') - if options.erase: - tempoutput = tempfile.TemporaryFile('w+') - else: - tempoutput = open(outname, 'w+') - try: - proc = subprocess.Popen(name, stdin=inputdata, stdout=tempoutput, stderr=outputdata, universal_newlines=True) - except OSError, error: - raise OSError, 'The program to be tested cannot be launched: ' + str(error), sys.exc_info()[2] - else: - if os.path.exists(outname): - os.remove(outname) - copytestcase(realinname.replace('$', s), inname) - try: - proc = subprocess.Popen(name, stdin=outputdata, stdout=outputdata, stderr=outputdata, universal_newlines=True) - except OSError, error: - raise OSError, 'The program to be tested cannot be launched: ' + str(error), sys.exc_info()[2] - cl = clock() - if maxtime > 0: - while 1: - proc.poll() - elapsed = clock() - cl - if proc.returncode == None: - if elapsed >= maxtime: - print '%.3f%s s, 0/%d, time limit exceeded' % (elapsed, strmaxtime, npoints) - sys.stdout.flush() - while proc.returncode == None: - try: - proc.terminate() - except OSError: - pass - except AttributeError: - try: - os.kill(proc.pid, signal.SIGTERM) - except Exception: - pass - proc.poll() - outputdata.close() - if stdio: - tempoutput.close() - break - else: - print '%.3f%s s,' % (elapsed, strmaxtime), - sys.stdout.flush() - elapsed = 0 - if stdio: - tempoutput.seek(0) - lines = tempoutput.readlines() - tempoutput.close() - break - if elapsed >= maxtime: - continue - else: - data = proc.communicate() - elapsed = clock() - cl - print '%.3f%s s,' % (elapsed, strmaxtime), - sys.stdout.flush() - if stdio: - tempoutput.seek(0) - lines = tempoutput.readlines() - tempoutput.close() - outputdata.close() - if stdio: - inputdata.close() - try: - os.unlink(inputdatafname) - except Exception: - pass - if proc.returncode > 0: - print '0/%d, non-zero return code %d' % (npoints, proc.returncode) - sys.stdout.flush() - elif proc.returncode < 0: - print '0/%d, terminated by signal %d' % (npoints, -proc.returncode) - sys.stdout.flush() - else: - if not tester: - if stdio: - outputdata = opentestcase(realoutname.replace('$', s)) - r = 0 - data = outputdata.read().splitlines(True) - if len(lines) != len(data): - r = 1 - else: - for i in zip(lines, data): - if i[0] != i[1]: - r = 1 - break - outputdata.close() - else: - try: - inputdata = open(outname, 'rU') - except IOError: - print '0/%g, output file not created or not readable' % npoints - sys.stdout.flush() - r = None - else: - outputdata = opentestcase(realoutname.replace('$', s)) - r = 0 - lines = inputdata.readlines() - data = outputdata.read().splitlines(True) - if len(lines) != len(data): - r = 1 - else: - for i in zip(lines, data): - if i[0] != i[1]: - r = 1 - break - inputdata.close() - outputdata.close() - else: - if ansname: - copytestcase(realoutname.replace('$', s), ansname) - if stdio: - try: copytestcase(realinname.replace('$', s), inname) - except NameError: pass - outputdata = open(outname, 'w') - outputdata.writelines(lines) - outputdata.close() - try: - proc = subprocess.Popen(tester, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) - except OSError, error: - raise OSError, 'The tester application cannot be launched: ' + str(error), sys.exc_info()[2] - data = proc.communicate() - r = proc.returncode - if tester and data[0]: - data = ''.join((' (', data[0].strip(), ')')) - else: - data = '' - if not maxexitcode and r or maxexitcode and not r: - print '0/%g, wrong answer%s' % (npoints, data) - sys.stdout.flush() - elif not maxexitcode and r == 0 or maxexitcode and r >= maxexitcode: - print '%g/%g, OK%s' % (npoints, npoints, data) - sys.stdout.flush() - scoregrp += npoints - ncorrectgrp += 1 - if npoints: - ncorrectvalued += 1 - elif maxexitcode and r != None: - actualpoints = npoints*r/maxexitcode if not npoints*r%maxexitcode else float(npoints*r)/maxexitcode - print '%g/%g, partly OK%s' % (actualpoints, npoints, data) - sys.stdout.flush() - scoregrp += actualpoints - ncorrectgrp += 1 - if npoints: - ncorrectvalued += 1 - if ntotalgrp: - if ncorrectgrp < ntotalgrp: - scoregrp = 0 - if ntotalgrp > 1: - print 'Group total: %d/%d tests; %g/%g points' % (ncorrectgrp, ntotalgrp, scoregrp, maxpointsgrp) - sys.stdout.flush() - ncorrect += ncorrectgrp - ntotal += ntotalgrp - score += scoregrp - maxpoints += maxpointsgrp - - if options.erase: - if not stdio or tester: - if os.path.exists(inname): os.remove(inname) - if os.path.exists(outname): os.remove(outname) - if tester and ansname: - if os.path.exists(ansname): os.remove(ansname) - elif stdio: - copytestcase(realinname.replace('$', s), inname) - copytestcase(realoutname.replace('$', s), ansname) - actualpoints = (score*taskweight/maxpoints if not score*taskweight%maxpoints else float(score*taskweight)/maxpoints) if maxpoints else 0 - if nvalued != ntotal: - print 'Grand total: %d/%d tests (%d/%d valued); %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, ncorrectvalued, nvalued, score, maxpoints, actualpoints, taskweight) - else: - print 'Grand total: %d/%d tests; %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, score, maxpoints, actualpoints, taskweight) - - scoresumoveralltasks += actualpoints - scoremaxoveralltasks += taskweight - ntasks += 1 - nfulltasks += int((score == maxpoints) if maxpoints else (taskweight == 0)) - - os.chdir(oldcwd) - -if options.clean or options.copyonly: - sys.exit() - -if ntasks != 1: - print - print 'Grand grand total: %g/%g weighted points; %d/%d problems solved fully' % (scoresumoveralltasks, scoremaxoveralltasks, nfulltasks, ntasks) - -if options.pause: - print 'Press any key to exit... ', - sys.stdout.flush() - os.system(pause + ' >' + os.devnull) \ No newline at end of file