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