99import asyncio
1010import logging
1111import os
12+ import signal
1213import sys
1314import time
1415from typing import (
@@ -147,7 +148,7 @@ def __init__(
147148 self ._timeout = 0.0 if timeout < 0.0 else timeout
148149 self ._max_workers = 1 if max_workers < 1 else max_workers
149150 self ._results = []
150- self ._stop = False
151+ self ._stop_cnt = 0
151152 self ._stopped = False
152153 self ._running_tests_sem = asyncio .Semaphore (1 )
153154 self ._schedule_lock = asyncio .Lock ()
@@ -203,7 +204,12 @@ def stopped(self) -> bool:
203204
204205 async def stop (self ) -> None :
205206 self ._logger .info ("Stopping tests execution" )
206- self ._stop = True
207+ self ._stop_cnt += 1
208+
209+ if self ._stop_cnt > 1 :
210+ # by stopping SUT first, we cause scheduler to complete
211+ # current test immediatelly without waiting
212+ await self ._sut .stop ()
207213
208214 try :
209215 # we enter in the semaphore queue in order to get highest
@@ -217,7 +223,7 @@ async def stop(self) -> None:
217223 async with self ._schedule_lock :
218224 pass
219225 finally :
220- self ._stop = False
226+ self ._stop_cnt = 0
221227 self ._stopped = True
222228
223229 self ._logger .info ("All tests have been completed" )
@@ -227,7 +233,7 @@ async def _run_test(self, test: Test) -> None:
227233 Run a single test and populate the results array.
228234 """
229235 async with self ._running_tests_sem :
230- if self ._stop :
236+ if self ._stop_cnt > 0 :
231237 self ._logger .info ("Test '%s' has been stopped" , test .name )
232238 return None
233239
@@ -284,6 +290,19 @@ async def _run_test(self, test: Test) -> None:
284290 except asyncio .TimeoutError :
285291 status = self .KERNEL_TIMEOUT
286292
293+ # raise kernel errors at the end so we can collect test results
294+ if status == self .KERNEL_TAINTED :
295+ await libkirk .events .fire ("kernel_tainted" , tainted_msg )
296+ raise KernelTaintedError ()
297+
298+ if status == self .KERNEL_PANIC :
299+ await libkirk .events .fire ("kernel_panic" )
300+ raise KernelPanicError ()
301+
302+ if status == self .KERNEL_TIMEOUT :
303+ await libkirk .events .fire ("sut_not_responding" )
304+ raise KernelTimeoutError ()
305+
287306 # create test results and save it
288307 if status not in [self .STATUS_OK , self .KERNEL_TAINTED ]:
289308 test_data = {
@@ -294,6 +313,12 @@ async def _run_test(self, test: Test) -> None:
294313 "exec_time" : exec_time ,
295314 }
296315
316+ # we won't consider killed tests, unless they have been
317+ # killed by kirk by forcibly stop
318+ if test_data ["returncode" ] == - signal .SIGKILL :
319+ self ._logger .info ("Test killed: %s" , test .name )
320+ return
321+
297322 results = await self ._framework .read_result (
298323 test ,
299324 test_data ["stdout" ],
@@ -304,19 +329,6 @@ async def _run_test(self, test: Test) -> None:
304329 self ._logger .debug ("results=%s" , results )
305330 self ._results .append (results )
306331
307- # raise kernel errors at the end so we can collect test results
308- if status == self .KERNEL_TAINTED :
309- await libkirk .events .fire ("kernel_tainted" , tainted_msg )
310- raise KernelTaintedError ()
311-
312- if status == self .KERNEL_PANIC :
313- await libkirk .events .fire ("kernel_panic" )
314- raise KernelPanicError ()
315-
316- if status == self .KERNEL_TIMEOUT :
317- await libkirk .events .fire ("sut_not_responding" )
318- raise KernelTimeoutError ()
319-
320332 await libkirk .events .fire ("test_completed" , results )
321333 await self ._write_kmsg (test , results )
322334
@@ -380,11 +392,10 @@ async def schedule(self, jobs: List[Any]) -> None:
380392 exc_name = err .__class__ .__name__
381393 self ._logger .info ("%s caught during tests execution" , exc_name )
382394
383- raise_exc = not self ._stop
384395 async with self ._running_tests_sem :
385396 pass
386397
387- if raise_exc :
398+ if self . _stop_cnt == 0 :
388399 self ._logger .info ("Propagating %s exception" , exc_name )
389400 raise err
390401
0 commit comments