Mercurial > ~astiob > upreckon > hgweb
diff upreckon/testcases.py @ 174:e0b2fbd7ebe0
Improved built-in output validator; added conf. var. binary
The built-in output validator now reads blocks rather than lines, which
should make it faster. There is also a new configuration variable called
binary, which defaults to False and specifies whether the built-in output
validator should not try to translate line breaks. Finally, when binary
is false, the built-in output validator now translates line breaks even
if it the reference output is in a tape archive.
author | Oleg Oshmyan <chortos@inbox.lv> |
---|---|
date | Sat, 18 Jun 2011 02:55:17 +0100 |
parents | 8198aa2ed20d |
children | 88e1e6786f67 |
line wrap: on
line diff
--- a/upreckon/testcases.py Thu Jun 16 01:24:10 2011 +0100 +++ b/upreckon/testcases.py Sat Jun 18 02:55:17 2011 +0100 @@ -13,7 +13,7 @@ from subprocess import Popen, PIPE, STDOUT import os -devnull = open(os.path.devnull, 'w+') +devnull = open(os.path.devnull, 'w+b') class DummySignalIgnorer(object): def __enter__(self): pass @@ -179,13 +179,38 @@ def validate(case, output): if not case.validator: # Compare the output with the reference output + buffer = refbuffer = crlfhalf = refcrlfhalf = ''.encode() + crlf = '\r\n'.encode('ascii') case.open_outfile() with case.outfile.open() as refoutput: - for line, refline in zip_longest(output, refoutput): - if refline is not None and not isinstance(refline, basestring): - line = bytes(line, sys.getdefaultencoding()) - if line != refline: + while True: + data = output.read(4096 - len(buffer)) + refdata = refoutput.read(4096 - len(refbuffer)) + if not case.problem.config.binary: + data, refdata = crlfhalf + data, refcrlfhalf + refdata + size, refsize = len(data), len(refdata) + if data and data != crlfhalf and data[-1] == crlf[0]: + size -= 1 + crlfhalf = data[-1:] + else: + crlfhalf = ''.encode() + if refdata and refdata != refcrlfhalf and refdata[-1] == crlf[0]: + refsize -= 1 + refcrlfhalf = refdata[-1:] + else: + refcrlfhalf = ''.encode() + data = data[:size].replace(crlf, crlf[1:]) + data = data.replace(crlf[:1], crlf[1:]) + refdata = refdata[:refsize].replace(crlf, crlf[1:]) + refdata = refdata.replace(crlf[:1], crlf[1:]) + buffer += data + refbuffer += refdata + if not (buffer or refbuffer or crlfhalf or refcrlfhalf): + break + size = min(len(buffer), len(refbuffer)) + if buffer[:size] != refbuffer[:size]: raise WrongAnswer + buffer, refbuffer = buffer[size:], refbuffer[size:] return 1 elif callable(case.validator): return case.validator(output) @@ -238,7 +263,7 @@ inputdatafname = case.problem.config.inname contextmgr = Copying(case.infile, inputdatafname) with contextmgr: - with tempfile.TemporaryFile('w+') if options.erase and (not case.validator or callable(case.validator)) else open(case.problem.config.outname, 'w+') as outfile: + with tempfile.TemporaryFile('w+b') if options.erase and (not case.validator or callable(case.validator)) else open(case.problem.config.outname, 'w+b') as outfile: with open(inputdatafname) as infile: call(case.problem.config.path, case=case, stdin=infile, stdout=outfile, stderr=devnull) if config.globalconf.force_zero_exitcode and case.process.returncode or case.process.returncode < 0: @@ -255,7 +280,7 @@ case.has_called_back = True callback() try: - output = open(case.problem.config.outname, 'rU') + output = open(case.problem.config.outname, 'rb') except IOError: raise CannotReadOutputFile(sys.exc_info()[1]) with output as output: @@ -275,7 +300,7 @@ case.has_called_back = True callback() try: - output = open(case.problem.config.outname.replace('$', case.id), 'rU') + output = open(case.problem.config.outname.replace('$', case.id), 'rb') except IOError: raise CannotReadOutputFile(sys.exc_info()[1]) with output as output: