Skip to content

Commit cc4ada1

Browse files
committed
Add ability to check failed tests w/ fragile list
Added ability to check failed tests w/ fragile list to be sure that the current fail equal to the issue mentioned in the fragile list. Fragile list should consist of the results files checksums with mentioned issues in the format: fragile = <basename of the test> ; gh-<issue> md5sum:<checksum> Closes #189.
1 parent 838ef34 commit cc4ada1

File tree

5 files changed

+30
-9
lines changed

5 files changed

+30
-9
lines changed

lib/test.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import sys
99
import traceback
1010
from functools import partial
11+
from hashlib import md5
1112

1213
try:
1314
from cStringIO import StringIO
@@ -250,9 +251,12 @@ def run(self, server):
250251
color_stdout("[ updated ]\n", schema='test_new')
251252
else:
252253
has_result = os.path.exists(self.tmp_result)
254+
result_checksum = ''
253255
if has_result:
254256
shutil.copy(self.tmp_result, self.reject)
255-
short_status = 'fail'
257+
with open(self.tmp_result, mode='rb') as result_file:
258+
result_checksum = md5(result_file.read()).hexdigest()
259+
short_status = 'fail:' + result_checksum
256260
color_stdout("[ fail ]\n", schema='test_fail')
257261

258262
where = ""

lib/test_suite.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@ def fragile_tests(self):
183183
res.append(test)
184184
return res
185185

186+
def fragile_checksums(self):
187+
res = []
188+
for fragile in self.ini['fragile']:
189+
checksum = re.split(r'md5sum:', fragile)
190+
if not checksum[0]:
191+
res.append(checksum[1])
192+
return res
193+
186194
def gen_server(self):
187195
try:
188196
return Server(self.ini, test_suite=self)

lib/worker.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import copy
33
import functools
44
import os
5+
import re
56
import signal
67
import traceback
78
import yaml
@@ -340,12 +341,15 @@ def run_loop(self, task_queue, result_queue, is_fragile):
340341
' result file checksum "%s" rerunning ...\n'
341342
% (task_id[0], task_id[1], short_status), schema='error')
342343
short_status = self.run_task(task_id)
344+
fail_checksum = re.split(r'fail:', short_status)
345+
if fragile_checksums and not fail_checksum[1] in fragile_checksums:
346+
break
343347
retries_left = retries_left - 1
344348
else:
345349
short_status = self.run_task(task_id)
346350

347351
result_queue.put(self.wrap_result(task_id, short_status))
348-
if not lib.Options().args.is_force and short_status == 'fail':
352+
if not lib.Options().args.is_force and re.match(r'^fail:.*', short_status):
349353
color_stdout(
350354
'Worker "%s" got failed test; stopping the server...\n'
351355
% self.name, schema='test_var')

listeners.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,16 @@ def process_result(self, obj):
3636
if not isinstance(obj, WorkerTaskResult):
3737
return
3838

39-
if obj.short_status not in self.stats:
40-
self.stats[obj.short_status] = 0
41-
self.stats[obj.short_status] += 1
39+
# cut off additional result information from result
40+
short_status = obj.short_status.split(':')[0]
41+
if short_status not in self.stats:
42+
self.stats[short_status] = 0
43+
self.stats[short_status] += 1
4244

43-
if obj.short_status == 'fail':
45+
if short_status == 'fail':
4446
self.failed_tasks.append((obj.task_id,
4547
obj.worker_name,
48+
obj.short_status.split(':')[1],
4649
obj.show_reproduce_content))
4750

4851
def print_statistics(self):
@@ -56,9 +59,10 @@ def print_statistics(self):
5659
return False
5760

5861
color_stdout('Failed tasks:\n', schema='test_var')
59-
for task_id, worker_name, show_reproduce_content in self.failed_tasks:
62+
for task_id, worker_name, md5sum, show_reproduce_content in self.failed_tasks:
6063
logfile = self.get_logfile(worker_name)
6164
color_stdout('- %s' % yaml.safe_dump(task_id), schema='test_var')
65+
color_stdout('# results file checksum: %s\n' % md5sum)
6266
color_stdout('# logfile: %s\n' % logfile)
6367
reproduce_file_path = get_reproduce_file(worker_name)
6468
color_stdout('# reproduce file: %s\n' % reproduce_file_path)
@@ -160,7 +164,7 @@ def process_result(self, obj):
160164
if not isinstance(obj, WorkerTaskResult):
161165
return
162166

163-
if obj.short_status == 'fail':
167+
if re.match(r'^fail:.*', obj.short_status):
164168
color_stdout('[Main process] Got failed test; '
165169
'gently terminate all workers...\n',
166170
schema='test_var')

test-run.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151

5252
import multiprocessing
5353
import os
54+
import re
5455
import sys
5556
import time
5657

@@ -159,7 +160,7 @@ def main_loop_consistent(failed_test_ids):
159160
worker = task_group['gen_worker'](worker_id)
160161
for task_id in task_ids:
161162
short_status = worker.run_task(task_id)
162-
if short_status == 'fail':
163+
if re.match(r'^fail:.*', short_status):
163164
reproduce_file_path = \
164165
lib.worker.get_reproduce_file(worker.name)
165166
color_stdout('Reproduce file %s\n' %

0 commit comments

Comments
 (0)