<s> import os <EOL> import contextlib <EOL> import collections <EOL> import datetime <EOL> import json <EOL> import signal <EOL> import traceback <EOL> import time <EOL> import StringIO <EOL> import sys <EOL> import threading <EOL> import Queue <EOL> from qisys import ui <EOL> import qisys . command <EOL> import qisys . error <EOL> import qitest . result <EOL> class TestQueue ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , tests ) : <EOL> self . tests = tests <EOL> self . test_logger = TestLogger ( tests ) <EOL> self . task_queue = Queue . Queue ( ) <EOL> self . launcher = None <EOL> self . results = collections . OrderedDict ( ) <EOL> self . ok = False <EOL> self . _interrupted = False <EOL> self . elapsed_time = <NUM_LIT:0> <EOL> self . _workers = list ( ) <EOL> def run ( self , num_jobs = <NUM_LIT:1> , repeat_until_fail = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> if repeat_until_fail == <NUM_LIT:0> : <EOL> self . _run_once ( num_jobs ) <EOL> return self . ok <EOL> ui . info ( ui . blue , "<STR_LIT>" , ui . reset , "<STR_LIT>" ) <EOL> num_runs = <NUM_LIT:0> <EOL> while num_runs < repeat_until_fail : <EOL> ui . info ( ui . bold , "<STR_LIT>" % ( num_runs + <NUM_LIT:1> ) ) <EOL> self . _run_once ( num_jobs ) <EOL> ui . info ( ) <EOL> if self . ok : <EOL> num_runs += <NUM_LIT:1> <EOL> else : <EOL> break <EOL> return self . ok <EOL> def _run_once ( self , num_jobs ) : <EOL> """<STR_LIT>""" <EOL> if not self . tests : <EOL> ui . warning ( "<STR_LIT>" ) <EOL> signal . signal ( signal . SIGINT , self . sigint_handler ) <EOL> start = datetime . datetime . now ( ) <EOL> self . _run ( num_jobs = num_jobs ) <EOL> signal . signal ( signal . SIGINT , signal . default_int_handler ) <EOL> end = datetime . datetime . now ( ) <EOL> delta = end - start <EOL> self . elapsed_time = float ( delta . microseconds ) / <NUM_LIT:10> ** <NUM_LIT:6> + delta . seconds <EOL> self . summary ( ) <EOL> return self . ok <EOL> def _run ( self , num_jobs = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> if not self . launcher : <EOL> ui . error ( "<STR_LIT>" ) <EOL> return <EOL> for i , test in enumerate ( self . tests ) : <EOL> self . task_queue . put ( ( test , i ) ) <EOL> if num_jobs == <NUM_LIT:1> : <EOL> self . test_logger . single_job = True <EOL> for i in range ( <NUM_LIT:0> , num_jobs ) : <EOL> worker = TestWorker ( self . task_queue , i ) <EOL> worker . launcher = self . launcher <EOL> worker . launcher . worker_index = i <EOL> worker . test_logger = self . test_logger <EOL> worker . results = self . results <EOL> self . _workers . append ( worker ) <EOL> worker . start ( ) <EOL> while not self . task_queue . empty ( ) and not self . _interrupted : <EOL> time . sleep ( <NUM_LIT:0.1> ) <EOL> for worker_thread in self . _workers : <EOL> worker_thread . join ( ) <EOL> def summary ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . tests : <EOL> self . ok = False <EOL> return <EOL> num_tests = len ( self . results ) <EOL> failures = [ x for x in self . results . values ( ) if x . ok is False ] <EOL> num_failed = len ( failures ) <EOL> message = "<STR_LIT>" % ( num_tests , self . elapsed_time ) <EOL> ui . info ( message ) <EOL> self . ok = ( not failures ) and not self . _interrupted <EOL> if self . ok : <EOL> ui . info ( ui . green , "<STR_LIT>" ) <EOL> else : <EOL> if num_failed != <NUM_LIT:0> : <EOL> ui . error ( num_failed , "<STR_LIT>" ) <EOL> if failures : <EOL> max_len = max ( len ( x . test [ "<STR_LIT:name>" ] ) for x in failures ) <EOL> for i , failure in enumerate ( failures ) : <EOL> ui . info_count ( i , num_failed , <EOL> ui . blue , failure . test [ "<STR_LIT:name>" ] . ljust ( max_len + <NUM_LIT:2> ) , <EOL> ui . reset , * failure . message ) <EOL> self . write_failures ( failures ) <EOL> errors = [ x for x in failures if x . error ] <EOL> if errors : <EOL> raise qisys . error . Error ( "<STR_LIT>" ) <EOL> def sigint_handler ( self , * args ) : <EOL> """<STR_LIT>""" <EOL> def double_sigint ( signum , frame ) : <EOL> sys . exit ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) <EOL> qisys . command . SIGINT_EVENT . set ( ) <EOL> ui . warning ( "<STR_LIT>" , <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . _interrupted = True <EOL> for worker in self . _workers : <EOL> worker . stop ( ) <EOL> signal . signal ( signal . SIGINT , double_sigint ) <EOL> def write_failures ( self , failures ) : <EOL> path = self . launcher . project . sdk_directory <EOL> fail_json = os . path . join ( path , "<STR_LIT>" ) <EOL> fail_names = [ x . test [ "<STR_LIT:name>" ] for x in failures ] <EOL> with open ( fail_json , "<STR_LIT:w>" ) as fp : <EOL> json . dump ( fail_names , fp ) <EOL> def handle_errors ( self , errors ) : <EOL> message = [ ui . red ] <EOL> for error in errors : <EOL> message . extend ( [ error . test [ "<STR_LIT:name>" ] , "<STR_LIT::>" ] ) <EOL> message . extend ( error . message ) <EOL> message . append ( "<STR_LIT:\n>" ) <EOL> ui . error ( * message ) <EOL> raise qisys . error . Error ( ) <EOL> class TestWorker ( threading . Thread ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , queue , worker_index ) : <EOL> super ( TestWorker , self ) . __init__ ( name = "<STR_LIT>" % worker_index ) <EOL> self . index = worker_index <EOL> self . queue = queue <EOL> self . launcher = None <EOL> self . test_logger = None <EOL> self . results = dict ( ) <EOL> self . _should_stop = False <EOL> def stop ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _should_stop = True <EOL> def run ( self ) : <EOL> while not self . _should_stop : <EOL> try : <EOL> test , index = self . queue . get_nowait ( ) <EOL> except Queue . Empty : <EOL> return <EOL> self . test_logger . on_start ( test , index ) <EOL> result = None <EOL> try : <EOL> result = self . launcher . launch ( test ) <EOL> except Exception , e : <EOL> result = qitest . result . TestResult ( test ) <EOL> result . ok = False <EOL> result . message = ui . message_for_exception ( e , <EOL> "<STR_LIT>" ) <EOL> result . error = True <EOL> if not self . _should_stop : <EOL> self . test_logger . on_completed ( test , index , result . message ) <EOL> self . results [ test [ "<STR_LIT:name>" ] ] = result <EOL> self . queue . task_done ( ) <EOL> class TestLogger ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , tests ) : <EOL> self . mutex = threading . Lock ( ) <EOL> self . tests = tests <EOL> try : <EOL> self . max_len = max ( ( len ( x [ "<STR_LIT:name>" ] ) for x in self . tests ) ) <EOL> except ValueError : <EOL> self . max_len = <NUM_LIT:0> <EOL> self . single_job = False <EOL> def on_start ( self , test , index ) : <EOL> """<STR_LIT>""" <EOL> if self . single_job : <EOL> self . _info ( test , index , ( ) , end = "<STR_LIT>" ) <EOL> return <EOL> with self . mutex : <EOL> self . _info ( test , index , ( "<STR_LIT>" , ) ) <EOL> def on_completed ( self , test , index , message ) : <EOL> """<STR_LIT>""" <EOL> if self . single_job : <EOL> ui . info ( * message ) <EOL> return <EOL> with self . mutex : <EOL> self . _info ( test , index , message ) <EOL> def _info ( self , test , index , message , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> ui . info_count ( index , len ( self . tests ) , <EOL> ui . blue , test [ "<STR_LIT:name>" ] . ljust ( self . max_len + <NUM_LIT:2> ) , <EOL> ui . reset , * message , ** kwargs ) </s>
