Skip to content

Commit f9f7f89

Browse files
author
TitanSnow
committed
add CompareMismatch & timeout
1 parent 59b9470 commit f9f7f89

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

cyaron/compare.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
import os
1111

1212

13+
class CompareMismatch(ValueError):
14+
def __init__(self, name, mismatch):
15+
super(CompareMismatch, self).__init__(name, mismatch)
16+
self.name = name
17+
self.mismatch = mismatch
18+
19+
1320
class Compare:
1421
@staticmethod
1522
def __compare_two(name, content, std, grader):
@@ -18,7 +25,7 @@ def __compare_two(name, content, std, grader):
1825
info = info if info is not None else ""
1926
log.debug("{}: {} {}".format(name, status, info))
2027
if not result:
21-
raise info
28+
raise CompareMismatch(name, info)
2229

2330
@staticmethod
2431
def __process_file(file):
@@ -111,8 +118,14 @@ def get_std():
111118
raise TypeError('program() missing 1 required non-None keyword-only argument: \'std\' or \'std_program\'')
112119

113120
def do(program_name):
121+
timeout = None
122+
if list_like(program_name) and len(program_name) == 2 and int_like(program_name[-1]):
123+
program_name, timeout = program_name
114124
with open(os.dup(input.input_file.fileno()), 'r', newline='\n') as input_file:
115-
content = make_unicode(subprocess.check_output(program_name, shell=(not list_like(program_name)), stdin=input_file, universal_newlines=True))
125+
if timeout is None:
126+
content = make_unicode(subprocess.check_output(program_name, shell=(not list_like(program_name)), stdin=input_file, universal_newlines=True))
127+
else:
128+
content = make_unicode(subprocess.check_output(program_name, shell=(not list_like(program_name)), stdin=input_file, universal_newlines=True, timeout=timeout))
116129
cls.__compare_two(program_name, content, std, grader)
117130

118131
if job_pool is not None:

cyaron/tests/compare_test.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import sys
44
import shutil
55
import tempfile
6+
import subprocess
67
from cyaron import IO, Compare, log
78
from cyaron.output_capture import captured_output
89
from cyaron.graders.mismatch import *
10+
from cyaron.compare import CompareMismatch
911

1012
log.set_verbose()
1113

@@ -48,7 +50,9 @@ def test_noipstyle_incorrect(self):
4850
try:
4951
with captured_output() as (out, err):
5052
Compare.output("test_another_incorrect.out", std=io)
51-
except TextMismatch as e:
53+
except CompareMismatch as e:
54+
self.assertEqual(e.name, 'test_another_incorrect.out')
55+
e = e.mismatch
5256
self.assertEqual(e.content, 'test123\r\ntest124 ')
5357
self.assertEqual(e.std, 'test123 \ntest123\n\n')
5458
self.assertEqual(str(e), 'On line 2 column 7, read 4, expected 3.')
@@ -74,7 +78,9 @@ def test_fulltext_program(self):
7478
try:
7579
with captured_output() as (out, err):
7680
Compare.program("python correct.py", "python incorrect.py", std=io, input=io, grader="FullText")
77-
except HashMismatch as e:
81+
except CompareMismatch as e:
82+
self.assertEqual(e.name, 'python incorrect.py')
83+
e = e.mismatch
7884
self.assertEqual(e.content, '2\n')
7985
self.assertEqual(e.std, '1\n')
8086
self.assertEqual(e.content_hash, '53c234e5e8472b6ac51c1ae1cab3fe06fad053beb8ebfd8977b010655bfdd3c3')
@@ -106,3 +112,13 @@ def test_concurrent(self):
106112
finally:
107113
for io in ios:
108114
io.close()
115+
116+
def test_timeout(self):
117+
if sys.version_info >= (3, 3):
118+
with IO() as test:
119+
try:
120+
Compare.program(((sys.executable, '-c', '__import__(\'time\').sleep(10)'), 1), std=test, input=test)
121+
except subprocess.TimeoutExpired:
122+
pass
123+
else:
124+
self.assertTrue(False)

cyaron/utils.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ def list_like(data):
1313
return isinstance(data, tuple) or isinstance(data, list)
1414

1515

16+
def int_like(data):
17+
isint = False
18+
try:
19+
isint = isint or isinstance(date, long)
20+
except NameError:
21+
pass
22+
isint = isint or isinstance(data, int)
23+
return isint
24+
25+
1626
def strtolines(str):
1727
lines = str.split('\n')
1828
for i in range(len(lines)):

0 commit comments

Comments
 (0)