1010import time
1111
1212from reframe .core .exceptions import (FailureLimitError ,
13+ SkipTestError ,
1314 TaskDependencyError ,
1415 TaskExit )
1516from reframe .core .logging import getlogger
@@ -100,6 +101,14 @@ def runcase(self, case):
100101 for c in case .deps if c in self ._task_index ):
101102 raise TaskDependencyError ('dependencies failed' )
102103
104+ if any (self ._task_index [c ].skipped
105+ for c in case .deps if c in self ._task_index ):
106+ try :
107+ raise SkipTestError ('skipped due to skipped dependencies' )
108+ except SkipTestError as e :
109+ task .skip ()
110+ raise TaskExit from e
111+
103112 partname = task .testcase .partition .fullname
104113 task .setup (task .testcase .partition ,
105114 task .testcase .environ ,
@@ -132,12 +141,10 @@ def runcase(self, case):
132141
133142 self ._retired_tasks .append (task )
134143 task .finalize ()
135-
136144 except TaskExit :
137145 return
138146 except ABORT_REASONS as e :
139147 task .abort (e )
140-
141148 raise
142149 except BaseException :
143150 task .fail (sys .exc_info ())
@@ -151,6 +158,10 @@ def on_task_run(self, task):
151158 def on_task_exit (self , task ):
152159 pass
153160
161+ def on_task_skip (self , task ):
162+ msg = str (task .exc_info [1 ])
163+ self .printer .status ('SKIP' , msg , just = 'right' )
164+
154165 def on_task_failure (self , task ):
155166 self ._num_failed_tasks += 1
156167 timings = task .pipeline_timings (['compile_complete' ,
@@ -247,6 +258,8 @@ def _remove_from_running(self, task):
247258 getlogger ().debug2 ('Task was not running' )
248259 pass
249260
261+ # FIXME: The following functions are very similar and they are also reused
262+ # in the serial policy; we should refactor them
250263 def deps_failed (self , task ):
251264 # NOTE: Restored dependencies are not in the task_index
252265 return any (self ._task_index [c ].failed
@@ -257,6 +270,11 @@ def deps_succeeded(self, task):
257270 return all (self ._task_index [c ].succeeded
258271 for c in task .testcase .deps if c in self ._task_index )
259272
273+ def deps_skipped (self , task ):
274+ # NOTE: Restored dependencies are not in the task_index
275+ return any (self ._task_index [c ].skipped
276+ for c in task .testcase .deps if c in self ._task_index )
277+
260278 def on_task_setup (self , task ):
261279 partname = task .check .current_partition .fullname
262280 self ._ready_tasks [partname ].append (task )
@@ -265,6 +283,17 @@ def on_task_run(self, task):
265283 partname = task .check .current_partition .fullname
266284 self ._running_tasks [partname ].append (task )
267285
286+ def on_task_skip (self , task ):
287+ # Remove the task from the running list if it was skipped after the
288+ # run phase
289+ if task .check .current_partition :
290+ partname = task .check .current_partition .fullname
291+ if task .failed_stage in ('run_complete' , 'run_wait' ):
292+ self ._running_tasks [partname ].remove (task )
293+
294+ msg = str (task .exc_info [1 ])
295+ self .printer .status ('SKIP' , msg , just = 'right' )
296+
268297 def on_task_failure (self , task ):
269298 if task .aborted :
270299 return
@@ -308,7 +337,13 @@ def on_task_exit(self, task):
308337 self ._completed_tasks .append (task )
309338
310339 def _setup_task (self , task ):
311- if self .deps_succeeded (task ):
340+ if self .deps_skipped (task ):
341+ try :
342+ raise SkipTestError ('skipped due to skipped dependencies' )
343+ except SkipTestError as e :
344+ task .skip ()
345+ return False
346+ elif self .deps_succeeded (task ):
312347 try :
313348 task .setup (task .testcase .partition ,
314349 task .testcase .environ ,
@@ -346,7 +381,7 @@ def runcase(self, case):
346381 try :
347382 partname = partition .fullname
348383 if not self ._setup_task (task ):
349- if not task .failed :
384+ if not task .skipped and not task . failed :
350385 self .printer .status (
351386 'DEP' , '%s on %s using %s' %
352387 (check .name , partname , environ .name ),
@@ -371,7 +406,7 @@ def runcase(self, case):
371406 else :
372407 self .printer .status ('HOLD' , task .check .info (), just = 'right' )
373408 except TaskExit :
374- if not task .failed :
409+ if not task .failed or not task . skipped :
375410 with contextlib .suppress (TaskExit ):
376411 self ._reschedule (task )
377412
@@ -380,7 +415,6 @@ def runcase(self, case):
380415 # If abort was caused due to failure elsewhere, abort current
381416 # task as well
382417 task .abort (e )
383-
384418 self ._failall (e )
385419 raise
386420
@@ -416,7 +450,8 @@ def split_jobs(tasks):
416450 def _setup_all (self ):
417451 still_waiting = []
418452 for task in self ._waiting_tasks :
419- if not self ._setup_task (task ) and not task .failed :
453+ if (not self ._setup_task (task ) and
454+ not task .failed and not task .skipped ):
420455 still_waiting .append (task )
421456
422457 self ._waiting_tasks [:] = still_waiting
0 commit comments