@@ -22,6 +22,15 @@ class IrregularSampleFileError(Exception):
22
22
pass
23
23
24
24
25
+ class TestSummary :
26
+ def __init__ (self , success_count : int , has_error_output : bool ):
27
+ self .success_count = success_count
28
+ self .has_error_output = has_error_output
29
+
30
+ def __eq__ (self , other ):
31
+ return self .success_count == other .success_count and self .has_error_output == other .has_error_output
32
+
33
+
25
34
def is_executable_file (file_name ):
26
35
return os .access (file_name , os .X_OK ) and Path (file_name ).is_file () \
27
36
and file_name .find (".cpp" ) == - 1 and not file_name .endswith (".txt" ) # cppやtxtを省くのは一応の Cygwin 対策
@@ -58,16 +67,19 @@ def append(text: str, end='\n'):
58
67
nonlocal res
59
68
res += text + end
60
69
70
+ with open (output_file , "r" ) as f :
71
+ expected_output = f .read ()
72
+
61
73
append (with_color ("[Input]" , Fore .LIGHTMAGENTA_EX ))
62
74
with open (input_file , "r" ) as f :
63
75
append (f .read (), end = '' )
64
76
65
77
append (with_color ("[Expected]" , Fore .LIGHTMAGENTA_EX ))
66
- with open (output_file , "r" ) as f :
67
- append (f .read (), end = '' )
78
+ append (expected_output , end = '' )
68
79
69
80
append (with_color ("[Received]" , Fore .LIGHTMAGENTA_EX ))
70
81
append (exec_res .output , end = '' )
82
+
71
83
if exec_res .status != ExecStatus .NORMAL :
72
84
append (with_color ("Aborted ({})\n " .format (
73
85
exec_res .status .name ), Fore .LIGHTYELLOW_EX ))
@@ -78,8 +90,10 @@ def append(text: str, end='\n'):
78
90
return res
79
91
80
92
81
- def run_for_samples (exec_file : str , sample_pair_list : List [Tuple [str , str ]], timeout_sec : int , knock_out : bool = False ):
93
+ def run_for_samples (exec_file : str , sample_pair_list : List [Tuple [str , str ]], timeout_sec : int , knock_out : bool = False ,
94
+ skip_io_on_success : bool = False ) -> TestSummary :
82
95
success_count = 0
96
+ has_error_output = False
83
97
for in_sample_file , out_sample_file in sample_pair_list :
84
98
# Run program
85
99
exec_res = run_program (exec_file , in_sample_file ,
@@ -90,37 +104,38 @@ def run_for_samples(exec_file: str, sample_pair_list: List[Tuple[str, str]], tim
90
104
answer_text = f .read ()
91
105
92
106
is_correct = exec_res .is_correct_output (answer_text )
93
- passed = is_correct and not exec_res .has_stderr ()
107
+ has_error_output = has_error_output or exec_res .has_stderr ()
94
108
95
- if passed :
96
- message = "{} {elapsed} ms" .format (
97
- with_color ("PASSED" , Fore .LIGHTGREEN_EX ),
98
- elapsed = exec_res .elapsed_ms )
99
- success_count += 1
100
- else :
101
- if is_correct :
109
+ if is_correct :
110
+ if exec_res .has_stderr ():
102
111
message = with_color (
103
112
"CORRECT but with stderr (Please remove stderr!)" , Fore .LIGHTYELLOW_EX )
104
113
else :
105
- if exec_res .status == ExecStatus .NORMAL :
106
- message = with_color ("WA" , Fore .LIGHTRED_EX )
107
- else :
108
- message = with_color (
109
- exec_res .status .name , Fore .LIGHTYELLOW_EX )
114
+ message = "{} {elapsed} ms" .format (
115
+ with_color ("PASSED" , Fore .LIGHTGREEN_EX ),
116
+ elapsed = exec_res .elapsed_ms )
117
+ success_count += 1
118
+ else :
119
+ if exec_res .status == ExecStatus .NORMAL :
120
+ message = with_color ("WA" , Fore .LIGHTRED_EX )
121
+ else :
122
+ message = with_color (
123
+ exec_res .status .name , Fore .LIGHTYELLOW_EX )
110
124
111
125
print ("# {case_name} ... {message}" .format (
112
126
case_name = os .path .basename (in_sample_file ),
113
127
message = message ,
114
128
))
115
129
116
- # Output details for incorrect results.
117
- if not passed :
130
+ # Output details for incorrect results or has stderr .
131
+ if not is_correct or ( exec_res . has_stderr () and not skip_io_on_success ) :
118
132
print ('{}\n ' .format (build_details_str (
119
133
exec_res , in_sample_file , out_sample_file )))
120
- if knock_out :
121
- print ('Stop testing ...' )
122
- break
123
- return success_count
134
+
135
+ if knock_out and not is_correct :
136
+ print ('Stop testing ...' )
137
+ break
138
+ return TestSummary (success_count , has_error_output )
124
139
125
140
126
141
def validate_sample_pair (in_sample_file , out_sample_file ):
@@ -153,13 +168,14 @@ def single_or_none(lst: List):
153
168
154
169
validate_sample_pair (in_sample_file , out_sample_file )
155
170
156
- success_count = run_for_samples (
171
+ test_summary = run_for_samples (
157
172
exec_file , [(in_sample_file , out_sample_file )], timeout_sec )
158
173
159
- return success_count == 1
174
+ return test_summary . success_count == 1 and not test_summary . has_error_output
160
175
161
176
162
- def run_all_tests (exec_file , in_sample_file_list , out_sample_file_list , timeout_sec : int , knock_out : bool ) -> bool :
177
+ def run_all_tests (exec_file , in_sample_file_list , out_sample_file_list , timeout_sec : int , knock_out : bool ,
178
+ skip_stderr_on_success : bool ) -> bool :
163
179
if len (in_sample_file_list ) != len (out_sample_file_list ):
164
180
logging .error ("{0}{1}{2}" .format (
165
181
"The number of the sample inputs and outputs are different.\n " ,
@@ -171,18 +187,23 @@ def run_all_tests(exec_file, in_sample_file_list, out_sample_file_list, timeout_
171
187
validate_sample_pair (in_sample_file , out_sample_file )
172
188
samples .append ((in_sample_file , out_sample_file ))
173
189
174
- success_count = run_for_samples (exec_file , samples , timeout_sec , knock_out )
190
+ test_summary = run_for_samples (
191
+ exec_file , samples , timeout_sec , knock_out , skip_stderr_on_success )
175
192
176
193
if len (samples ) == 0 :
177
194
print ("No test cases" )
178
195
return False
179
- elif success_count != len (samples ):
196
+ elif test_summary . success_count != len (samples ):
180
197
print ("{msg} (passed {success_count} of {total})" .format (
181
198
msg = with_color ("Some cases FAILED" , Fore .LIGHTRED_EX ),
182
- success_count = success_count ,
199
+ success_count = test_summary . success_count ,
183
200
total = len (samples ),
184
201
))
185
202
return False
203
+ elif test_summary .has_error_output :
204
+ print (with_color (
205
+ "Passed all test case but with stderr. (Please remove stderr!)" , Fore .LIGHTYELLOW_EX ))
206
+ return False
186
207
else :
187
208
print (with_color ("Passed all test cases!!!" , Fore .LIGHTGREEN_EX ))
188
209
return True
@@ -233,6 +254,12 @@ def main(prog, args) -> bool:
233
254
action = "store_true" ,
234
255
default = False )
235
256
257
+ parser .add_argument ('--skip-almost-ac-feedback' , '-s' ,
258
+ help = 'Hide inputs and expected/actual outputs if result is correct and there are error outputs'
259
+ ' [Default] False,' ,
260
+ action = 'store_true' ,
261
+ default = False )
262
+
236
263
args = parser .parse_args (args )
237
264
exec_file = args .exec or infer_exec_file (
238
265
glob .glob (os .path .join (args .dir , '*' )))
@@ -246,7 +273,8 @@ def main(prog, args) -> bool:
246
273
glob .glob (os .path .join (args .dir , out_ex_pattern )))
247
274
248
275
if args .num is None :
249
- return run_all_tests (exec_file , in_sample_file_list , out_sample_file_list , args .timeout , args .knock_out )
276
+ return run_all_tests (exec_file , in_sample_file_list , out_sample_file_list , args .timeout , args .knock_out ,
277
+ args .skip_almost_ac_feedback )
250
278
else :
251
279
return run_single_test (exec_file , in_sample_file_list , out_sample_file_list , args .timeout , args .num )
252
280
0 commit comments