1010import time
1111
1212from reframe .core .exceptions import (FailureLimitError ,
13+ SkipTestError ,
1314 TaskDependencyError ,
1415 TaskExit )
1516from reframe .core .logging import getlogger
@@ -100,6 +101,17 @@ 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+
107+ # We raise the SkipTestError here and catch it immediately in
108+ # order for `skip()` to get the correct exception context.
109+ try :
110+ raise SkipTestError ('skipped due to skipped dependencies' )
111+ except SkipTestError as e :
112+ task .skip ()
113+ raise TaskExit from e
114+
103115 partname = task .testcase .partition .fullname
104116 task .setup (task .testcase .partition ,
105117 task .testcase .environ ,
@@ -132,12 +144,10 @@ def runcase(self, case):
132144
133145 self ._retired_tasks .append (task )
134146 task .finalize ()
135-
136147 except TaskExit :
137148 return
138149 except ABORT_REASONS as e :
139150 task .abort (e )
140-
141151 raise
142152 except BaseException :
143153 task .fail (sys .exc_info ())
@@ -151,6 +161,10 @@ def on_task_run(self, task):
151161 def on_task_exit (self , task ):
152162 pass
153163
164+ def on_task_skip (self , task ):
165+ msg = str (task .exc_info [1 ])
166+ self .printer .status ('SKIP' , msg , just = 'right' )
167+
154168 def on_task_failure (self , task ):
155169 self ._num_failed_tasks += 1
156170 timings = task .pipeline_timings (['compile_complete' ,
@@ -247,6 +261,8 @@ def _remove_from_running(self, task):
247261 getlogger ().debug2 ('Task was not running' )
248262 pass
249263
264+ # FIXME: The following functions are very similar and they are also reused
265+ # in the serial policy; we should refactor them
250266 def deps_failed (self , task ):
251267 # NOTE: Restored dependencies are not in the task_index
252268 return any (self ._task_index [c ].failed
@@ -257,6 +273,11 @@ def deps_succeeded(self, task):
257273 return all (self ._task_index [c ].succeeded
258274 for c in task .testcase .deps if c in self ._task_index )
259275
276+ def deps_skipped (self , task ):
277+ # NOTE: Restored dependencies are not in the task_index
278+ return any (self ._task_index [c ].skipped
279+ for c in task .testcase .deps if c in self ._task_index )
280+
260281 def on_task_setup (self , task ):
261282 partname = task .check .current_partition .fullname
262283 self ._ready_tasks [partname ].append (task )
@@ -265,6 +286,17 @@ def on_task_run(self, task):
265286 partname = task .check .current_partition .fullname
266287 self ._running_tasks [partname ].append (task )
267288
289+ def on_task_skip (self , task ):
290+ # Remove the task from the running list if it was skipped after the
291+ # run phase
292+ if task .check .current_partition :
293+ partname = task .check .current_partition .fullname
294+ if task .failed_stage in ('run_complete' , 'run_wait' ):
295+ self ._running_tasks [partname ].remove (task )
296+
297+ msg = str (task .exc_info [1 ])
298+ self .printer .status ('SKIP' , msg , just = 'right' )
299+
268300 def on_task_failure (self , task ):
269301 if task .aborted :
270302 return
@@ -308,7 +340,13 @@ def on_task_exit(self, task):
308340 self ._completed_tasks .append (task )
309341
310342 def _setup_task (self , task ):
311- if self .deps_succeeded (task ):
343+ if self .deps_skipped (task ):
344+ try :
345+ raise SkipTestError ('skipped due to skipped dependencies' )
346+ except SkipTestError as e :
347+ task .skip ()
348+ return False
349+ elif self .deps_succeeded (task ):
312350 try :
313351 task .setup (task .testcase .partition ,
314352 task .testcase .environ ,
@@ -346,7 +384,7 @@ def runcase(self, case):
346384 try :
347385 partname = partition .fullname
348386 if not self ._setup_task (task ):
349- if not task .failed :
387+ if not task .skipped and not task . failed :
350388 self .printer .status (
351389 'DEP' , '%s on %s using %s' %
352390 (check .name , partname , environ .name ),
@@ -371,7 +409,7 @@ def runcase(self, case):
371409 else :
372410 self .printer .status ('HOLD' , task .check .info (), just = 'right' )
373411 except TaskExit :
374- if not task .failed :
412+ if not task .failed or not task . skipped :
375413 with contextlib .suppress (TaskExit ):
376414 self ._reschedule (task )
377415
@@ -380,7 +418,6 @@ def runcase(self, case):
380418 # If abort was caused due to failure elsewhere, abort current
381419 # task as well
382420 task .abort (e )
383-
384421 self ._failall (e )
385422 raise
386423
@@ -416,7 +453,8 @@ def split_jobs(tasks):
416453 def _setup_all (self ):
417454 still_waiting = []
418455 for task in self ._waiting_tasks :
419- if not self ._setup_task (task ) and not task .failed :
456+ if (not self ._setup_task (task ) and
457+ not task .failed and not task .skipped ):
420458 still_waiting .append (task )
421459
422460 self ._waiting_tasks [:] = still_waiting
0 commit comments