Mercurial > ~astiob > upreckon > hgweb
view upreckon-vcs @ 80:809b77302b21
Win32-specific module with memory and CPU time limits
The Win32-specific implementation of call() and friends now lives
in module win32, looks clean and in addition is able to enforce memory
and CPU time limits on NT kernels, in particular on Windows 2000 and up
asking the system to terminate the process as soon as or (in the case
of CPU time) almost as soon as the limits are broken. According to my
observations, malloc() in the limited process does not return NULL
when memory usage is close to the limit and instead crashes the process
(which Upreckon happily translates into 'memory limit exceeded').
The catch is that the module is not actually used yet; coming soon.
author | Oleg Oshmyan <chortos@inbox.lv> |
---|---|
date | Wed, 16 Feb 2011 00:01:33 +0000 |
parents | ee8a99dcaaed |
children | 37c4ad87583c |
line wrap: on
line source
#! /usr/bin/env python # Copyright (c) 2009-2011 Chortos-2 <chortos@inbox.lv> from __future__ import division, with_statement import optparse, sys, compat def import_error(e): say('Error: your installation of Upreckon is incomplete;', str(e).lower() + '.', file=sys.stderr) sys.exit(3) from compat import * version = '2.00.0 ($$REV$$)' parser = optparse.OptionParser(version='Upreckon '+version, epilog='Python 2.5 or newer is required.') parser.add_option('-1', dest='legacy', action='store_true', default=False, help='handle configuration files in a way more compatible with test.py 1.x') parser.add_option('-u', '--update', dest='update', action='store_true', default=False, help='update the installed Upreckon to the latest publicly available version') parser.add_option('-p', '--problem', dest='problems', metavar='PROBLEM', action='append', help='test only the PROBLEM (this option can be specified more than once with different problem names, all of which will be tested)') parser.add_option('-m', '--copy-io', dest='copyonly', action='store_true', default=False, help='create a copy of the input/output files of the last test case for manual testing and exit') parser.add_option('-x', '--auto-exit', dest='pause', action='store_false', default=True, help='do not wait for a key to be pressed after finishing testing') 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('-t', '--detect-time', dest='autotime', action='store_true', default=False, help='spend a second detecting the most precise time measurement function') parser.add_option('--no-time-limits', dest='no_maxtime', action='store_true', default=False, help='disable all time limits') options, args = parser.parse_args() parser.destroy() del parser if options.update: try: urllib, urlread = compat.import_urllib() except ImportError: sys.exit('Error: the urllib Python module is missing. Without it, an automatic update is impossible.') latesttext = urlread('http://chortos.selfip.net/~astiob/test.py/version.txt') latest = latesttext.split('.') installed = version.split('.') update = None 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]: say('You are using the latest publicly available version of Upreckon.') sys.exit() if not update: say('Your copy of Upreckon is newer than the publicly available version.') sys.exit() say('A ' + update + ' update to Upreckon is available. Downloading...') sys.stdout.flush() # FIXME: need to update all files! urllib.urlretrieve('http://chortos.selfip.net/~astiob/test.py/test.py', sys.argv[0]) say('Downloaded and installed. Now you are using Upreckon ' + latesttext + '.') sys.exit() import config, itertools, os, subprocess, sys, time if options.legacy: compat.pseudobuiltins += 'xrange', if options.autotime: # This is really a dirty hack that assumes that sleep() does not spend # the CPU time of the current process and that if clock() measures # wall-clock time, then it is more precise than time() is. Both these # assumptions are true on all platforms I have tested this on so far, # but I am not aware of any guarantee that they will both be true # on every other platform. c = time.clock() time.sleep(1) c = time.clock() - c if int(c + .5) == 1: clock = time.clock else: clock = time.time elif sys.platform == 'win32': clock = time.clock else: clock = time.time try: import testcases except ImportError: import_error(sys.exc_info()[1]) try: from testcases import pause except ImportError: pause = None try: globalconf = config.load_global() # Do this check here so that if we have to warn them, we do it as early as possible if options.pause and not pause and not hasattr(globalconf, 'pause'): if os.name == 'posix': globalconf.pause = 'read -s -n 1' say('Warning: configuration variable pause is not defined; it was devised automatically but the choice might be incorrect, so Upreckon might exit immediately after the testing is completed.', file=sys.stderr) sys.stderr.flush() elif os.name == 'nt': globalconf.pause = 'pause' else: sys.exit('Error: configuration variable pause is not defined and cannot be devised automatically.') try: from problem import * except ImportError: import_error(sys.exc_info()[1]) # Support single-problem configurations if globalconf.problems is None: shouldprintnames = False globalconf.multiproblem = False globalconf.problems = os.path.curdir, else: globalconf.multiproblem = True shouldprintnames = True ntasks = 0 nfulltasks = 0 maxscore = 0 realscore = 0 for taskname in (globalconf.problems if not options.problems else options.problems): problem = Problem(taskname) if ntasks and not options.copyonly: say() if shouldprintnames: say(taskname) if options.copyonly: problem.copytestdata() else: real, max = problem.test() ntasks += 1 nfulltasks += real == max realscore += real maxscore += max if options.copyonly: sys.exit() if ntasks != 1: say() say('Grand total: %g/%g weighted points; %d/%d problems solved fully' % (realscore, maxscore, nfulltasks, ntasks)) except KeyboardInterrupt: sys.exit('Exiting due to a keyboard interrupt.') if options.pause: say('Press any key to exit...') sys.stdout.flush() if pause: pause() elif callable(globalconf.pause): globalconf.pause() else: with open(os.devnull, 'w') as devnull: subprocess.call(globalconf.pause, stdout=devnull, stderr=subprocess.STDOUT)