@@ -399,6 +399,8 @@ def __init__(self, config = None, hyper = qemu):
399399
400400 self ._exit_status = None
401401 self ._exit_msg = ""
402+ self ._exit_complete = False
403+
402404 self ._config = load_single_config (config )
403405 self ._on_success = lambda (line ) : self .exit (exit_codes ["SUCCESS" ], nametag + " All tests passed" )
404406 self ._on_panic = self .panic
@@ -432,23 +434,44 @@ def wait(self):
432434 def poll (self ):
433435 return self ._hyper .poll ()
434436
435- def exit (self , status , msg ):
437+ # Stop the VM with exit status / msg.
438+ # set keep_running to indicate that the program should continue
439+ def exit (self , status , msg , keep_running = False ):
440+
441+ # Exit may have been called allready
442+ if self ._exit_complete :
443+ return
444+
436445 self ._exit_status = status
446+ self ._exit_msg = msg
437447 self .stop ()
438- info ("Exit called with status" , self ._exit_status , "(" ,get_exit_code_name (self ._exit_status ),")" )
439- info ("Calling on_exit" )
448+
440449 # Change back to test source
441450 os .chdir (self ._root )
442- self ._on_exit ()
451+
452+
453+ info ("Exit called with status" , self ._exit_status , "(" ,get_exit_code_name (self ._exit_status ),")" )
454+ info ("Message:" , msg , "Keep running: " , keep_running )
455+
456+ if keep_running :
457+ return
458+
459+ if self ._on_exit :
460+ info ("Calling on_exit" )
461+ self ._on_exit ()
462+
463+
443464 if status == 0 :
444- # Print success message and return to caller
465+ if self ._on_exit_success :
466+ info ("Calling on_exit_success" )
467+ self ._on_exit_success ()
468+
445469 print color .SUCCESS (msg )
446- info ( "Calling on_exit_success" )
447- return self . _on_exit_success ()
470+ self . _exit_complete = True
471+ return
448472
449- # Print fail message and exit with appropriate code
450- print color .EXIT_ERROR (get_exit_code_name (status ), msg )
451- sys .exit (status )
473+ self ._exit_complete = True
474+ program_exit (status , msg )
452475
453476 # Default timeout event
454477 def timeout (self ):
@@ -474,23 +497,29 @@ def panic(self, panic_line):
474497 # Events - subscribable
475498 def on_output (self , output , callback ):
476499 self ._on_output [ output ] = callback
500+ return self
477501
478502 def on_success (self , callback , do_exit = True ):
479503 if do_exit :
480504 self ._on_output ["SUCCESS" ] = lambda (line ) : [callback (line ), self ._on_success (line )]
481505 else : self ._on_output ["SUCCESS" ] = callback
506+ return self
482507
483508 def on_panic (self , callback ):
484509 self ._on_output ["PANIC" ] = lambda (line ) : [callback (line ), self ._on_panic (line )]
510+ return self
485511
486512 def on_timeout (self , callback ):
487513 self ._on_timeout = callback
514+ return self
488515
489516 def on_exit_success (self , callback ):
490517 self ._on_exit_success = callback
518+ return self
491519
492520 def on_exit (self , callback ):
493521 self ._on_exit = callback
522+ return self
494523
495524 # Read a line from the VM's standard out
496525 def readline (self ):
@@ -542,20 +571,23 @@ def cmake(self, args = []):
542571 def clean (self ):
543572 print INFO , "Cleaning cmake build folder"
544573 subprocess .call (["rm" ,"-rf" ,"build" ])
574+ return self
545575
546576 def find_exit_trigger (self , line ):
547577
548- # Special case for end-of-transmission, e.g. on panic
549- if line == EOT :
550- if not self ._exit_status : self ._exit_status = exit_codes ["VM_EOT" ]
551- return True
552-
553578 # Kernel reports service exit status
554- if line .startswith (" [ Kernel ] service exited with status" ):
579+ if (line .startswith (" [ Kernel ] service exited with status" ) or
580+ line .startswith (" [ main ] returned with status" )):
581+
555582 self ._exit_status = int (line .split (" " )[- 1 ].rstrip ())
556583 self ._exit_msg = "Service exited with status " + str (self ._exit_status )
557584 return True
558585
586+ # Special case for end-of-transmission, e.g. on panic
587+ if line == EOT :
588+ self ._exit_status = exit_codes ["VM_EOT" ]
589+ return True
590+
559591 return False
560592
561593
@@ -583,6 +615,7 @@ def boot(self, timeout = 60, multiboot = True, kernel_args = "booted with vmrunn
583615
584616 # This might be a reboot
585617 self ._exit_status = None
618+ self ._exit_complete = False
586619 self ._timeout_after = timeout
587620
588621 # Start the timeout thread
@@ -628,18 +661,23 @@ def boot(self, timeout = 60, multiboot = True, kernel_args = "booted with vmrunn
628661 # possibly normal vm shutdown
629662 if self .poll () != None :
630663
631- info ("No exit status, and no poll - getting final output" )
632- data , err = self ._hyper .get_final_output ()
664+ info ("No poll - getting final output" )
665+ try :
666+ data , err = self ._hyper .get_final_output ()
667+
668+ # Print stderr if exit status wasnt 0
669+ if err and self .poll () != 0 :
670+ print color .WARNING ("Stderr: \n " + err )
633671
634- # Print stderr if exit status wasnt 0
635- if err and self .poll () != 0 :
636- print color .WARNING ("Stderr: \n " + err )
672+ # Parse the last output from vm
673+ lines = data .split ("\n " )
674+ for line in lines :
675+ print color .VM (line )
676+ self .find_exit_trigger (line )
677+ # Note: keep going. Might find panic after service exit
637678
638- # Parse the last output from vm
639- lines = data .split ("\n " )
640- for line in lines :
641- print color .VM (line )
642- self .find_exit_trigger (line )
679+ except Exception as e :
680+ pass
643681
644682 # We should now have an exit status, either from a callback or VM EOT / exit msg.
645683 if self ._exit_status != None :
@@ -700,11 +738,19 @@ def load_single_config(path = default_json):
700738
701739def program_exit (status , msg ):
702740 global vms
741+
742+ info ("Program exit called with status" , status , "(" ,get_exit_code_name (status ),")" )
743+ info ("Stopping all vms" )
744+
703745 for vm in vms :
704746 vm .stop ().wait ()
705- info ("Exit called with status" , status , "(" ,get_exit_code_name (status ),")" )
706- # Print fail message and exit with appropriate code
707- print color .EXIT_ERROR (get_exit_code_name (status ), msg )
747+
748+ # Print status message and exit with appropriate code
749+ if (status ):
750+ print color .EXIT_ERROR (get_exit_code_name (status ), msg )
751+ else :
752+ print color .SUCCESS (msg )
753+
708754 sys .exit (status )
709755
710756
0 commit comments