o
    WoduM                    @  s  U d dl mZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
Z
d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlm  m Z! ddl"m#Z# dd	l"m$Z$ dd
l"m%Z% ddl&m'Z'm(Z(m)Z) ddl&m*Z+ ddl,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3 ddl4m5Z5m6Z6 ddl7m8Z8 ddl9m:Z:m;Z; ej<rej=d Z>dZ?dZ@dZAdddZBdddZCdddddddZDdd d!ZEdd"d#ZFdd'd(ZGdd)d*ZHdd-d.ZIdd1d2ZJdd4d5ZKd6d7 ZLd8eMd9< eB sejNZLdd<d=ZOG d>d? d?e-ZPejQG d@dA dAejRZSejQG dBdC dCejRZTG dDdE dEZUG dFdG dGZVG dHdI dIeVZWG dJdK dKeVZXG dLdM dMeWZYG dNdO dOeWZZG dPdQ dQeVZ[G dRdS dSZ\G dTdU dUe\Z]e]e\j^e:j_< G dVdW dWe]Z`e`e\j^e:ja< G dXdY dYe\Zbebe\j^e:jc< G dZd[ d[e\Zdede\j^e:je< dd^d_ZfddedfZgddhdiZhddldmZiddqdrZjddudvZk	ddd{d|ZlG d}d~ d~ZmG dd dZnG dd dZodddZpdddZqdddZrdddZsdS )    )annotations)Path)deque)suppress)deepcopyN   )build)environment)mlog)MesonVersionMismatchException	OptionKeymajor_versions_differversion)MesonException
OrderedSetRealPathActionget_wine_shortpath	join_args
split_argssetup_vsenv)get_infodirload_info_file)ExternalProgram)TestProtocolTestSerialisation)TAPParser.TestTAPParser.ErrorTAPParser.VersionTAPParser.PlanTAPParser.UnknownLineTAPParser.BailoutM   c      returnboolc                  C  s   t   } | dkS )Nwindows)platformsystemlower)Zplatname r+   ohome/ych/rk3568/buildroot/output/rockchip_rk3568_recovery/host/lib/python3.10/site-packages/mesonbuild/mtest.py
is_windowsJ   s   r-   c                   C  s
   t jdkS )Ncygwin)sysr(   r+   r+   r+   r,   	is_cygwinN      
r0      )FHWZNaNAsstrintc                 C  s(   d}| D ]}t |}|t| 7 }q|S )Nr   )unicodedataZeast_asian_widthUNIWIDTH_MAPPING)r8   resultcwr+   r+   r,   uniwidthR   s
   
r@   c                  C  st   d} | t jv r&z
tt j|  }W |S  ty%   td|  d d}Y |S w zt }W |S  ty9   d}Y |S w )NZMESON_TESTTHREADSzInvalid value in z, using 1 thread.r   )osenvironr:   
ValueErrorprintmultiprocessing	cpu_count	Exception)ZvarnameZnum_workersr+   r+   r,   determine_worker_countY   s"   

rH   parserargparse.ArgumentParserNonec                 C  s  | j ddtdd | j dddtdd	 | j d
dddd | j dddddd | j ddddd | j dddddd | j dd dtdd	 | j ddttjjdd  | j d!g d"d#d$d%d& | j d'g d(d#d$d)d& | j d*d+d,d-d.d | j d/ddd0d | j d1ddd2d | j d3d4d5d6 | j d7t td8d | j d9d:ddd;d | j d<d=ddd>d | j d?d@td dAdB | j dCd dDdEd | j dFg tdGd | j dHdIdJdK d S )LNz	--maxfailr   zbNumber of failing tests before aborting the test run. (default: 0, to disable aborting on failure))defaulttypehelpz--repeatr   repeatz!Number of times to run the tests.)rL   destrM   rN   z--no-rebuildF
store_truez$Do not rebuild before running tests.)rL   actionrN   z--gdbgdbzRun test under gdb.)rL   rP   rR   rN   z
--gdb-pathgdb_pathz&Path to the gdb binary (default: gdb).)rL   rP   rN   z--listlistzList available tests.z	--wrapperwrapperz)wrapper to run tests with (e.g. Valgrind)-Cwdz#directory to cd into before running)rP   rR   rM   rN   z--suiteinclude_suitesappendZSUITEz,Only run tests belonging to the given suite.)rL   rP   rR   metavarrN   z
--no-suiteexclude_suitesz.Do not run tests belonging to the given suite.z--no-stdsplitTsplitstore_falsez,Do not split stderr and stdout in test logs.z--print-errorlogsz%Whether to print failing tests' logs.z--benchmarkz Run benchmarks instead of tests.z	--logbaseZtestlogzBase name for log file.)rL   rN   z--num-processesz#How many parallel processes to use.z-vz	--verbosez!Do not redirect stdout and stderrz-q--quietz$Produce less output to the terminal.z-tz--timeout-multiplierzDefine a multiplier for test timeout, for example  when running tests in particular conditions they might take more time to execute. (<= 0 to disable timeout))rM   rL   rN   z--setupsetupzWhich test setup to use.z--test-argsz7Arguments to pass to the specified test(s) or all testsargs*zOptional list of test names to run. "testname" to run all tests with that name, "subprojname:testname" to specifically run "testname" from "subprojname", "subprojname:" to run all tests defined by "subprojname".)nargsrN   )	add_argumentr:   r   r   rA   pathabspathrH   float)rI   r+   r+   r,   add_argumentsj   s   








rh   c                 C  s\   | d dkrdnd}z	t | |d W d S  ty-   | jdddd} t | |d Y d S w )N
 endasciibackslashreplaceerrors)rD   UnicodeEncodeErrorencodedecode)r8   rm   r+   r+   r,   
print_safe   s   ru   abc                 C  s   | s|S |s| S | d | S Nrj   r+   )rv   rw   r+   r+   r,   
join_lines   s
   ry   dashcolsc                 C  sL   | s|| S d|  d } t | }|| d }|| |  } | ||| |   S )N r2   )r@   )r8   rz   r{   widthfirstr+   r+   r,   dashes   s   r   retcodec                 C  s   | dk r#|  }zt |j}W n ty   d}Y nw d| d| S | dkr,d|  S | d }zt |j}W n tyC   d}Y nw d|  d| d| d	S )
Nr   Z
SIGinvalidzkilled by signal r|      zexit status z(exit status z or signal ))signalSignalsnamerC   )r   signumsignamer+   r+   r,   returncode_to_status   s"   
r   c                 C     | S Nr+   )xr+   r+   r,   <lambda>   s    r   zT.Callable[[str], str]sh_quoteenvT.Iterable[T.Tuple[str, str]]c                 C  s   d dd | D S )Nrk   c                 S  s    g | ]\}}d  |t|qS )z{}={} )formatr   ).0kvr+   r+   r,   
<listcomp>   s     z$env_tuple_to_str.<locals>.<listcomp>)join)r   r+   r+   r,   env_tuple_to_str      r   c                   @  s   e Zd ZdS )TestExceptionN)__name__
__module____qualname__r+   r+   r+   r,   r      s    r   c                   @  s   e Zd ZdZdZdZdS )ConsoleUserr   r   r2   N)r   r   r   LOGGERGDBSTDOUTr+   r+   r+   r,   r      s    r   c                   @  s   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
Zed#ddZd$ddZd$ddZd$ddZd$ddZd%ddZd&ddZd'd d!Zd"S )(
TestResultPENDINGRUNNINGOKTIMEOUT	INTERRUPTSKIPFAILEXPECTEDFAILUNEXPECTEDPASSERRORr%   r:   c                   C     dS )N   r+   r+   r+   r+   r,   maxlen      zTestResult.maxlenr&   c                 C  s   | t jt jhv S r   )r   r   r   selfr+   r+   r,   is_ok      zTestResult.is_okc                 C  s   | t jt jt jt jt jhv S r   )r   r   r   r   r   r   r   r+   r+   r,   is_bad   s   zTestResult.is_badc                 C  s   | t jt jhvS r   )r   r   r   r   r+   r+   r,   is_finished  r   zTestResult.is_finishedc                 C  s   | t jt jfv S r   )r   r   r   r   r+   r+   r,   
was_killed  r   zTestResult.was_killedr8   r9   mlog.AnsiDecoratorc                 C  sX   |   rtj}||S | tjtjfv rtj}||S |  r%tj}||S tj	}||S r   )
r   r
   redr   r   r   yellowr   ZgreenZblue)r   r8   	decoratorr+   r+   r,   colorize	  s   zTestResult.colorizer   c                 C  s$   dj | j|  d}| ||S )Nz{res:{reslen}})resZreslen)r   valuer   r   get_text)r   r   Z
result_strr+   r+   r,   r     s   zTestResult.get_textc                 C  s   t | dS )Nz>>> )r9   r   r   r+   r+   r,   get_command_marker     zTestResult.get_command_markerNr%   r:   r%   r&   )r8   r9   r%   r   )r   r&   r%   r9   r%   r9   )r   r   r   r   r   r   r   r   r   r   r   r   r   staticmethodr   r   r   r   r   r   r   r   r+   r+   r+   r,   r      s(    





r   c                   @  s4  e Zd ZU G dd dejZG dd dejZG dd dejZG dd dejZG d	d
 d
ejZ	G dd dejZ
dZdZdZedZedZedej Zedej ZedZedZedZdZdZdZded< dZdZdZded< dZeZ dZ!d:d+d,Z"d;d0d1Z#d<d5d6Z$d=d8d9Z%dS )>	TAPParserc                   @  s.   e Zd ZU ded< ded< ded< ded< dS )	r   r:   	num_testsr&   lateskippedT.Optional[str]explanationNr   r   r   __annotations__r+   r+   r+   r,   Plan  s
   
 r   c                   @     e Zd ZU ded< dS )r!   r9   messageNr   r+   r+   r+   r,   Bailout#     
 r   c                   @  s8   e Zd ZU ded< ded< ded< ded< dd
dZdS )r   r:   numberr9   r   r   r=   r   r   r%   c                 C  s   | j  d| j  S )Nr|   )r   r   stripr   r+   r+   r,   __str__,  s   zTAPParser.Test.__str__Nr   )r   r   r   r   r   r+   r+   r+   r,   Test&  s   
 r   c                   @  r   )r   r9   r   Nr   r+   r+   r+   r,   Error/  r   r   c                   @  s   e Zd ZU ded< ded< dS )r    r9   r   r:   linenoNr   r+   r+   r+   r,   UnknownLine2  s   
 r   c                   @  r   )r   r:   r   Nr   r+   r+   r+   r,   Version6  r   r   r   r2   r$   zBail out!\s*(.*)z<(?:\s*\#\s*([Ss][Kk][Ii][Pp]\S*|[Tt][Oo][Dd][Oo])\b\s*(.*))?z1\.\.([0-9]+)z'((?:not )?ok)\s*(?:([0-9]+)\s*)?([^#]*)zTAP version ([0-9]+)z
(\s+)---.*z\s+\.\.\.\s*FNzT.Optional[Plan]planr   T.Optional[int]yaml_linenork      okr&   numr:   r   r9   	directiver   r   r%   ET.Generator[T.Union['TAPParser.Test', 'TAPParser.Error'], None, None]c                 c  s    |  }|r|  nd }|d urH| }|dr)|r(| ||tj|V  d S n|dkr>| |||r6tjntj|V  d S | d| dV  | |||rQtj	ntj
|V  d S )Nr   ZTODOzinvalid directive "")r   upper
startswithr   r   r   r   r   r   r   r   )r   r   r   r   r   r   r+   r+   r,   
parse_testO  s   
"zTAPParser.parse_testlinesT.AsyncIterator[str]T.AsyncIterator[TYPE_TAPResult]c                 C sF   |2 z3 d H W }|  |D ]}|V  qq6 |  d D ]}|V  qd S r   
parse_line)r   r   lineeventr+   r+   r,   parse_asynca  s   zTAPParser.parse_asyncioT.Iterator[str]T.Iterator[TYPE_TAPResult]c                 c  s0    |D ]
}|  |E d H  q|  d E d H  d S r   r   )r   r   r   r+   r+   r,   parseh  s   zTAPParser.parser   c              	   c  s   |d ur|  j d7  _ | }| j| jkr9| jdkr4| j|}|r4| j| _| j | _|	d| _
d S | j| _n)| j| jkrb| j|rK| j| _d S || j
rSd S | d| j dV  | j| _| j| jksjJ |rq|drsd S | j|}|r| jr| jjr| js| dV  d| _|  jd7  _|	dd u r| jnt|	d}|| jkr| d	V  | |	dd
k||	d|	d|	dE d H  | j| _d S | j|}|r+| jr| dV  d S t|	d}|dk}|	dr|	d dr|dkr| dV  d}n| dV  | j|| jdk||	dd| _| jV  d S | j|}|rB| |	dV  d| _d S | j|}|ry| j dkrY| dV  d S t|	d| _| jdk ro| dV  d S | j| jdV  d S | || j V  d S | j| jkr| d| j dV  | js| jr| j| jjkr| j| jjk r| d| jj d| j dV  d S | d| jj d| j dV  d S d S d S d S )Nr      z+YAML block not terminated (started on line r   #zunexpected test after late planTr2   zout of order test numbersr   r$         zmore than one plan foundr   r   zinvalid SKIP directive for planzinvalid directive for plan)r   r   r   r   z(version number must be on the first linez$version number should be at least 13r   zToo few tests run (expected z, got zToo many tests run (expected )r   rstripstate_AFTER_TESTr   _RE_YAML_STARTmatch_YAMLr   groupyaml_indent_MAIN_RE_YAML_ENDr   r   _RE_TESTr   r   found_late_testr   r:   r   _RE_PLANr   r   _RE_BAILOUTr   
bailed_out_RE_VERSIONr   r   )r   r   mr   r   r   r+   r+   r,   r   m  s   


"



 $$zTAPParser.parse_line)r   r&   r   r:   r   r9   r   r   r   r   r%   r   )r   r   r%   r   )r   r   r%   r   )r   r   r%   r   )&r   r   r   T
NamedTupler   r   r   r   r   r   r   r   r   recompiler  Z_RE_DIRECTIVEpatternr  r   r  r   r   r   r  r   r   r   r   r   r   r   r   r   r   r   r   r+   r+   r+   r,   r     s<   
 	







r   c                   @  sR   e Zd ZdddZdddZdddZdddZdddZdddZdddZ	dS ) 
TestLoggerr%   rK   c                 C     d S r   r+   r   r+   r+   r,   flush     zTestLogger.flushharness'TestHarness'c                 C  r  r   r+   r   r  r+   r+   r,   start  r  zTestLogger.starttest	'TestRun'c                 C  r  r   r+   r   r  r  r+   r+   r,   
start_test  r  zTestLogger.start_testr8   r9   r   r   c                 C  r  r   r+   )r   r  r  r8   r   r+   r+   r,   log_subtest  r  zTestLogger.log_subtestr=   c                 C  r  r   r+   )r   r  r=   r+   r+   r,   log  r  zTestLogger.logc                   s   d S r   r+   r  r+   r+   r,   finish  s   zTestLogger.finishc                 C  r  r   r+   r   r+   r+   r,   close  r  zTestLogger.closeNr%   rK   r  r  r%   rK   r  r  r  r  r%   rK   )
r  r  r  r  r8   r9   r   r   r%   rK   r  r  r=   r  r%   rK   )
r   r   r   r  r  r  r  r  r  r  r+   r+   r+   r,   r    s    





r  c                   @  s"   e Zd ZddddZdd	d
ZdS )TestFileLoggerreplacefilenamer9   rq   r%   rK   c                 C  s   || _ t|dd|d| _d S )Nr?   utf-8)encodingrq   )r!  openfile)r   r!  rq   r+   r+   r,   __init__  s   zTestFileLogger.__init__c                 C  s   | j r| j   d | _ d S d S r   )r%  r  r   r+   r+   r,   r    s   

zTestFileLogger.closeN)r   )r!  r9   rq   r9   r%   rK   r  )r   r   r   r&  r  r+   r+   r+   r,   r    s    r  c                   @  s   e Zd Zg dZg dZdZdZdZd*dd	Zd*d
dZ	d+ddZ
d*ddZd,ddZd,ddZd-ddZd.ddZd/dd Zd0d#d$Zd/d%d&Zd,d'd(Zd)S )1ConsoleLogger)z..z:.z.:)u   🌑u   🌒u   🌓u   🌔u   🌕u   🌖u   🌗u   🌘u   ✀ u   ―u   ▶ r%   rK   c                 C  s  t  | _d | _d | _d| _d| _|  d| _d| _d| _d| _	zt
d\| _}d| _W n ty:   d| _d| _Y nw t| j| j| jd | _td| j| jd | _| j| _| j| _z| jtjjpcd W d S  ty   td	d
| jd | _tdd
| jd | _d| _| j| _Y d S w )Nr   Frk   r   TP   r2   rn   z8<-z| )r   running_testsprogress_testprogress_taskmax_left_widthstopshould_erase_line
test_countstarted_testsspinner_indexrA   get_terminal_sizer{   is_ttyOSErrorr   SCISSORSHLINEoutput_start
output_endRTRIsubSPINNERspinnerrs   r/   stdoutr#  rr   ASCII_SPINNER)r   _r+   r+   r,   r&    s:   

zConsoleLogger.__init__c                 C  s"   | j rt| j dd d| _ d S d S )Nrk   rl   )r/  rD   r   r+   r+   r,   r    s   
zConsoleLogger.flushr   r9   c                 C  s   t | j|ddd d| _d S )Nrk   )seprm   z[K)rD   r/  )r   r   r+   r+   r,   print_progress  s   
zConsoleLogger.print_progressc                 C  s   | j   d S r   )updatesetr   r+   r+   r,   request_update  r   zConsoleLogger.request_updater  r  c                 C  s  | j d u r|   d S t| jdkr| j d| j }nd| jt| j d | j| j}d|| j| j }| jd t| j | _djdt	
  tt | j j |jd}| j jrg|dj| j j|jd	7 }|d
7 }| j  }|rx|d| 7 }|j| j d| j||d}| | d S )Nr   /z{}-{}/{}z[{}] {} z{spaces} {dur:{durlen}}r|   )spacesdurdurlenz/{timeout:{durlen}})timeoutrJ  r8      T)r   r-  leftright)r+  r  lenr*  r1  r0  r   r=  r2  r   r   r:   time	starttimeduration_max_lenrK  get_detailsr-  rC  )r   r  countrM  rN  detailsr   r+   r+   r,   emit_progress"  s:   



zConsoleLogger.emit_progressc                   st   d fdd}t  _ j_tj jd _jr6 js8dt	t
j d _t | _d S d S d S )	Nr%   rK   c                    s   t  } d}  js\j I d H  j  |  |kr1d _|  d }| 	|j jr>jj
tjur>d _jsTjsEqjjdd_jj   jr  d S )Ng        r   Flast)asyncioget_running_looprF  r.  rD  waitclearrP  r+  Zcall_atr   r   r   r*  popaddrV  r  )loopZnext_updater  r   r+   r,   report_progressC  s.   

z,ConsoleLogger.start.<locals>.report_progress   r$      r  )rY  EventrD  r0  maxr{   r-  r4  need_consolerO  r9   ensure_futurer,  )r   r  ra  r+   r`  r,   r  B  s   
zConsoleLogger.startr  r  c              	   C  s   |j r;|jr;|   t|j|t | j|j	t d t|j
 |j  |jr3t| jdd n|js;tdd |  jd7  _| j| | jj|dd |   d S )N)r-  rN  Tr  r   FrW  )verbosecmdliner  rD   r   r
   colorize_consoler-  r   r   r   direct_stdoutr8  needs_parsingr1  r*  r^  move_to_endrF  r  r+   r+   r,   r  i  s   
zConsoleLogger.start_testr=   c                 C  sh   |j s	|jjs	dS |jt |jd}|j r|S | }t|dk r$|S t	t
dd|dd   S )Nrk   )stderr_onlyd   z1Listing only the last 100 lines from a long log.
rj   i)ri  optionsprint_errorlogsget_logr
   rk  rm  
splitlinesrO  r9   Zboldr   )r   r  r=   r  r   r+   r+   r,   shorten_logz  s   
 zConsoleLogger.shorten_logc                 C  sn   |j s|j}|st|j |j  d S t|j |  | ||}|r5t| j t| t| j	 d S d S r   )
ri  rj  rD   r   r   stdoru  r8  ru   r9  )r   r  r=   rj  r  r+   r+   r,   	print_log  s   
zConsoleLogger.print_logr8   r   c                 C  sb   |j s|jjr-| r/|   t|j|t | j	| j
||t ddd |   d S d S d S )N)r-  prefixmiddlerN  Trh  )ri  rq  rr  r   r  rD   r   r
   rk  r-  r;  r   rF  )r   r  r  r8   r=   r+   r+   r,   r    s   zConsoleLogger.log_subtestc                 C  s$  | j | |jtju r#|js|jjr#|   t	|j
 d|j d |jjr,|j s|   |jrI|jrIt	| j t	|j|t | jd nt	|j|t | jddd |js`|j rf| || |jrt	dd |jD ]}t	|dd qqt	dd |js|j rt	dd |   d S )Nz time out (After z	 seconds))r-  Trh  )r*  remover   r   r   ri  rq  rr  r  rD   r   rK  quietr   rj  rl  r9  r   r
   rk  r-  r   rw  warningsrF  )r   r  r=   r?   r+   r+   r,   r    s0   




zConsoleLogger.logc                   sz   d| _ |   | jr| jI d H  |jr5|jjs|jjr5td t|jdD ]\}}t|	|t
  q&t|  d S )NTz
Summary of Failures:
r   )r.  rF  r,  collected_failuresrq  rr  ri  rD   	enumerater   r
   rk  summaryr   r  ir=   r+   r+   r,   r    s   zConsoleLogger.finishNr  )r   r9   r%   rK   r  r  )r  r  r=   r  r%   r9   r  )
r  r  r  r  r8   r9   r=   r   r%   rK   )r   r   r   r?  r<  r6  r7  r:  r&  r  rC  rF  rV  r  r  ru  rw  r  r  r  r+   r+   r+   r,   r'    s$    

 



 
'




r'  c                   @  s*   e Zd ZdddZdd	d
ZdddZdS )TextLogfileBuilderr  r  r%   rK   c                 C  sD   | j dtj   d ttj }| j d| d d S )NzLog of Meson test suite run on 

zInherited environment: )	r%  writedatetimenow	isoformatr   rA   rB   items)r   r  Zinherit_envr+   r+   r,   r    s   zTextLogfileBuilder.startr=   r  c                 C  s:  |j  d|j }| jt|ddd  | jd|j d  tdt|j	}| jd| d  | jdd	|j
  d  | jd
|  d  |jr[| jd|j d  |jry|jjrddnd}| jt|ddd  | j|j |jr| jtdddd  | j|j | jtdddd  d S )NrG  =N   rj   ztest:         z%H:%M:%Szstart time:   zduration:     z%.2fszresult:       zcommand:      r>  outputr)  stderrrk   r  )r   r0  r%  r  r   r   rP  strftimegmtimerQ  durationget_exit_statusrj  rv  rq  r]   stde)r   r  r=   titleZstarttime_strr   r+   r+   r,   r    s"   zTextLogfileBuilder.logc                   sf   |j r!| jd t|j dD ]\}}| j||dd  q| j|  td| j  d S )Nz
Summary of Failures:

r   Frj   zFull log written to )r}  r%  r  r~  r   r  rD   r!  r  r+   r+   r,   r    s   zTextLogfileBuilder.finishNr  r  )r   r   r   r  r  r  r+   r+   r+   r,   r    s    

r  c                   @  s   e Zd Zd
ddZd	S )JsonLogfileBuilderr  r  r=   r  r%   rK   c              	   C  sR   |j |j|jj|j|j|j|j|jd}|j	r|j	|d< | j
t|d  d S )N)r   r>  r=   rQ  r  
returncoder   commandr  rj   )r   rv  r   r   rQ  r  r  r   cmdr  r%  r  jsondumps)r   r  r=   Zjresultr+   r+   r,   r    s   
zJsonLogfileBuilder.logNr  )r   r   r   r  r+   r+   r+   r,   r    s    r  c                   @  s.   e Zd ZdZdddZdddZdddZdS )JunitBuildera  Builder for Junit test results.

    Junit is impossible to stream out, it requires attributes counting the
    total number of tests, failures, skips, and errors in the root element
    and in each test suite. As such, we use a builder class to track each
    test case, and calculate all metadata before writing it out.

    For tests with multiple results (like from a TAP test), we record the
    test as a suite with the project_name.test_name. This allows us to track
    each result separately. For tests with only one result (such as exit-code
    tests) we record each one into a suite with the name project_name. The use
    of the project_name allows us to sort subproject tests separately from
    the root project.
    r!  r9   r%   rK   c                 C  s$   || _ tjddddd| _i | _d S )NZ
testsuites0testsrq   failures)r!  etElementrootsuitesr   r!  r+   r+   r,   r&    s
   
zJunitBuilder.__init__r  r  r  r  c              
   C  s  |j durU|j dD ]G}d|j|j|jd |jd< |dD ]}|jd= q!|dD ]}|jd= q-|d	D ]}|jd
= q9|dD ]}|jd= qE| j| qdS |jr@|j d|j }|| j	vsq|j
jdksqJ dtjd|tt|jttdd |jD ttdd |jD ttdd |jD t|jd }| j	|< |jD ]p}tj|dt||d}|jtju rt|d nJ|jtju rt|d n=|jtju rt|d n0|jtju rt|d}d|_n |jtju rt|d}d|_n|jtju rt|d}d|_|jr|jt|d_q|jr,t|d}	|j |	_|jr>t|d}
|j |
_dS dS |j| j	vr^tjd|jd d!d!d!t|jd }| j	|j< n| j	|j }tt |jd" d |jd"< tj|d|j|jt|jd#}|j!tju rt|d tt |jd d |jd< n7|j!tju rt|d tt |jd$ d |jd$< n|j!tju rt|d tt |jd% d |jd%< |jrt|d}	|j |	_|jrt|d}
|j |
_dS dS )&zLog a single test case.Nz.//testsuitez{}.{}.{}r   z.//testcase[@result]r=   z.//testcase[@timestamp]	timestampz.//testcase[@file]r%  z.//testcase[@line]r   .r   zduplicate suiteZ	testsuitec                 s  s&    | ]}|j tjtjhv rd V  qdS r   N)r=   r   r   r   r   rr+   r+   r,   	<genexpr>2  s   
 
z#JunitBuilder.log.<locals>.<genexpr>c                 s  s*    | ]}|j tjtjtjhv rd V  qdS r  )r=   r   r   r   r   r  r+   r+   r,   r  4  s   
 c                 s  s     | ]}|j tju rd V  qdS r  r=   r   r   r  r+   r+   r,   r  6  s    )r   r  rq   r  r   rP  testcase)r   	classnamer   errorZfailurezTest unexpected passed.zTest was interrupted by user.z.Test did not finish before configured timeout.z
system-outz
system-err1r  r  )r   r  rP  rq   r  )"junitfindallr   projectr   attribr  rZ   resultsr  rq  rO   r  r  r9   rO  sumr  Z
SubElementr=   r   r   r   r   r   textr   r   r   rv  r   r  r:   r   )r   r  r  suitecaseZ	suitenameZsubtestr  Zfailouterrr+   r+   r,   r    s   






zJunitBuilder.logc                   s   | j  D ]"}| j| dD ]}tt| jj| t|j|  | jj|< qqt| j}t	| j
d}|j|ddd W d   dS 1 sIw   Y  dS )z9Calculate total test counts and write out the xml result.r  wbr"  T)r#  Zxml_declarationN)r  valuesr  rZ   r9   r:   r  r  ElementTreer$  r!  r  )r   r  r  attrtreefr+   r+   r,   r  p  s   ,"zJunitBuilder.finishN)r!  r9   r%   rK   r  r  )r   r   r   __doc__r&  r  r  r+   r+   r+   r,   r    s
    

\r  c                      s   e Zd ZU dZi Zded< d= fd
dZd>ddZd?ddZe	d@ddZ
e	dAdd ZdBd!d"ZdBd#d$ZdBd%d&ZdCd'd(Ze	dDd*d+ZdCd,d-ZdCd.d/ZdEdFd3d4Ze	dAd5d6ZdGd;d<Z  ZS )HTestRunr   z'T.Dict[TestProtocol, T.Type['TestRun']]PROTOCOL_TO_CLASSr  r   ra   T.Anykwargsr%   c                   s   t  tj|j S r   )super__new__r  r  protocol)clsr  ra   r  	__class__r+   r,   r    r   zTestRun.__new__test_envT.Dict[str, str]r   r9   rK  r   is_parallelr&   ri  c                 C  s   t j| _|| _d | _|| _|| _g | _d | _d | _	d | _
d| _d| _d| _d | _|| _|j| _|j| _d | _|| _|| _g | _d S Nrk   )r   r   r   r  _numr   rK  r  r  rQ  r  rv  r  additional_errorr  r   should_failproject_namer  r  r  ri  r|  )r   r  r  r   rK  r  ri  r+   r+   r,   r&    s(   
zTestRun.__init__r  T.List[str]rK   c                 C  s   t j| _t | _|| _d S r   )r   r   r   rP  rQ  r  )r   r  r+   r+   r,   r    s   

zTestRun.startr:   c                 C  s&   | j d u rt jd7  _tj| _ | j S Nr   )r  r  TEST_NUMr   r+   r+   r,   r     s   
zTestRun.numc                 C  s   | j o
| j o
| j S r   )ri  r  rm  r   r+   r+   r,   rl    s   zTestRun.direct_stdoutc                 C  sT   | j r(tdd | j D }tdd | j D }||kr | dS | d| dS dS )Nc                 s  s    | ]}|j  V  qd S r   )r=   r   r   r   r+   r+   r,   r        z&TestRun.get_results.<locals>.<genexpr>c                 s      | ]	}|j tjuV  qd S r   r  r  r+   r+   r,   r        z subtests passedrG  rk   )r  r  )r   ZpassedZranr+   r+   r,   get_results  s   
zTestRun.get_resultsc                 C  s
   t | jS r   )r   r  r   r+   r+   r,   r    r1   zTestRun.get_exit_statusc                 C  s&   | j tju rdS | jr|  S |  S r  )r   r   r   r  r  r  r   r+   r+   r,   rS    s
   zTestRun.get_detailsc                 C  s   | j tjkr
tj| _ t| j tsJ | jr+| j tjtjfv r+| j tju r'tjntj| _ | j	r;| j	
ds;|  j	d7  _	| jrK| j
dsK|  jd7  _t | j | _d S rx   )r   r   r   r   
isinstancer  r   r   r   rv  endswithr  rP  rQ  r  r   r+   r+   r,   	_complete  s   zTestRun._completer   c                 C  sD   | j sd S t| j ttj  }t|ddd | j D  S )Nr|   c                 s  s    | ]}t |V  qd S r   )r   r  r+   r+   r,   r    s    z"TestRun.cmdline.<locals>.<genexpr>)r  rE  r   r  rA   rB   r   r   )r   Ztest_only_envr+   r+   r,   rj    s   zTestRun.cmdlinec                 C  s$   t   | _t| _tj| _|   d S r   )rP  rQ  GNU_SKIP_RETURNCODEr  r   r   r   r  r   r+   r+   r,   complete_skip  s   
zTestRun.complete_skipc                 C     |    d S r   )r  r   r+   r+   r,   complete     zTestRun.completeFr   ro  c                 C  s   |rdn| j }| js| jrCd}|r-|td|d 7 }||7 }|dd  dkr-|d7 }|td|d 7 }|t| j| j7 }n|}|rS|dd  dkrS|d7 }|S )Nrk   zstdout:rj   ri   zstderr:)rv  r  r  r
   Zcyanr   ry   )r   r   ro  rv  r   r+   r+   r,   rs    s   zTestRun.get_logc                 C  r   )NFr+   r   r+   r+   r,   rm    r   zTestRun.needs_parsingr  r  r   r   c                   s   |2 z3 d H W }q6 d S r   r+   )r   r  r   lr+   r+   r,   r     s   zTestRun.parse)r  r   ra   r  r  r  r%   r  )r  r   r  r  r   r9   rK  r   r  r&   ri  r&   )r  r  r%   rK   r   r   r   r  r%   r   )FF)r   r&   ro  r&   r%   r9   r  r  r   r   r%   rK   )r   r   r   r  r  r   r  r&  r  propertyr   rl  r  r  rS  r  rj  r  r  rs  rm  r   __classcell__r+   r+   r  r,   r  }  s,   
 







r  c                         e Zd Zd fddZ  ZS )TestRunExitCoder%   rK   c                   s\   | j tjkrn | jtkrtj| _ n| jtkrtj| _ nt| jr#tj	ntj
| _ t   d S r   )r   r   r   r  r  r   GNU_ERROR_RETURNCODEr   r&   r   r   r  r  r   r  r+   r,   r    s   



zTestRunExitCode.completer  r   r   r   r  r  r+   r+   r  r,   r    s    r  c                      r  )TestRunGTestr%   rK   c                   sZ   | j j d}| j jrtj| j j|}zt|| _W n	 t	y%   Y nw t
   d S )N.xml)r  r   workdirrA   re   r   r  r   r  FileNotFoundErrorr  r  r  r  r+   r,   r    s   zTestRunGTest.completer  r  r+   r+   r  r,   r    s    r  c                      s6   e Zd ZedddZd fddZdddZ  ZS )
TestRunTAPr%   r&   c                 C  r   NTr+   r   r+   r+   r,   rm    r   zTestRunTAP.needs_parsingrK   c                   sN   | j dkr | j s tj| _| jpd| _|  jd| j  d7  _t   d S )Nr   rk   z'
(test program exited with status code r   )r  r   r   r   r   r  r  r  r   r  r+   r,   r    s
   zTestRunTAP.completer  r  r   r   c           
   	     s  d }g }d}t  |2 ze3 d H W }t|t jr|j}qt|t jr/tj}|| |j	| qt|t j
rS| j| |j rCtj}|| |jpNd|j |j qt|t jr_|| qt|t jrr|  jd|j	 7  _tj}q6 |rttd}tttdd |D }|D ]}	| jd|	j| d| d|	j	  q|d	kr| jd
 n| jttdd  tdd | jD rtj}|r| jtj kr|| _d S d S d S )Nr   zsubtest zTAP parsing error: UNKNOWNc                 s  s    | ]}|j V  qd S r   )r   )r   r  r+   r+   r,   r  >  s    z#TestRunTAP.parse.<locals>.<genexpr>zstdout: z: r   zUnknown TAP output lines have been ignored. Please open a feature request to
implement them, or prefix them with a # if they are not TAP syntax.r   z: Unknown TAP output lines for a supported TAP version.
This is probably a bug in the test; if they are not TAP syntax, prefix them with a #c                 s      | ]	}|j tju V  qd S r   r  r   tr+   r+   r,   r  G  r  )!r   r   r  r   r   r   r   r   r  r   r   r  rZ   r=   r   r   r   r   r   r   r  r9   r
   r   rO  re  r|  r   r   allr   r   r   )
r   r  r   r   r|  r   r  unknownr}   r?   r+   r+   r,   r   &  sF   
 (
zTestRunTAP.parser   r  r  )r   r   r   r  rm  r  r   r  r+   r+   r  r,   r    s
    r  c                   @  s$   e Zd ZedddZdd
dZdS )TestRunRustr%   r&   c                 C  r   r  r+   r   r+   r+   r,   rm  R  r   zTestRunRust.needs_parsingr  r  r   r   rK   c                   s  ddd	}d
}|2 z93 d H W }| drC| dsC| d\}}}}|dd}||||}	| j|	 || ||	j |d
7 }q
6 d }
tdd | jD rUt	j
}
ntdd | jD rct	j}
ntdd | jD rpt	j}
|
r}| jt	jkr|
| _d S d S d S )Nnr:   r   r9   r=   r%   r   c                 S  sf   |dkrt | |tjd S |dkrt | |tjd S |dkr't | |tjd S t | |tjd| S )Nr   ZignoredZFAILEDz#Unsupported output from rust test: )r   r   r   r   r   r   r   )r  r   r=   r+   r+   r,   	parse_resW  s   z$TestRunRust.parse.<locals>.parse_resr   ztest ztest resultr|   z::r  c                 s  r  r   r  r  r+   r+   r,   r  m  r  z$TestRunRust.parse.<locals>.<genexpr>c                 s  r  r   )r=   r   r   r  r+   r+   r,   r  p  r  c                 s  r  r   )r=   r   r   r  r+   r+   r,   r  r  r  )r  r:   r   r9   r=   r9   r%   r   )r   r   r]   r   r  rZ   r  r=   r  r   r   anyr   r   r   r   )r   r  r   r  r  r   r@  r   r=   r  r   r+   r+   r,   r   V  s.   

	
zTestRunRust.parseNr   r  )r   r   r   r  rm  r   r+   r+   r+   r,   r  Q  s    r  streamT.Union[None, bytes]c                 C  s:   | d u rdS z|  dW S  ty   | j ddd Y S w )Nrk   r"  z
iso-8859-1ignorerp   )rt   UnicodeDecodeError)r  r+   r+   r,   rt   {  s   rt   readerasyncio.StreamReaderqueue,T.Optional['asyncio.Queue[T.Optional[str]]']console_modec              
     sF  g }zzw|   sjz
| dI d H }W n1 tjy) } z	|j}W Y d }~n d }~w tjyD } z| |jI d H }W Y d }~nd }~ww |rft|}|	| |t
ju r\t|ddd |rf||I d H  |   r	d|W W |r{|d I d H  S S  tjy   d| Y W |r|d I d H  S S w |r|d I d H  w w )N   
rk   T)rm   r  )Zat_eofZ	readuntilrY  ZIncompleteReadErrorpartialZLimitOverrunErrorZreadexactlyconsumedrt   rZ   r   r   rD   putr   CancelledError)r  r  r  Z
stdo_linesZ
line_byteser   r+   r+   r,   read_decode  sD   

r
  fnamec                 C  s   |  dot p
t  S )Nz.exe)r  r-   r0   )r  r+   r+   r,   run_with_mono  s   r  objsT.List[TestSerialisation]c                 C  sb   t | ts
tdt| D ]"}t |tstdtt|ds"tdtt|jtr.t|jtq| S )Nz	<unknown>r   )r  rU   r   coredata_versionr   hasattrr   r   )r  objr+   r+   r,   check_testdata  s   





r  q 'asyncio.Queue[T.Optional[str]]'r   c                 C s.   	 |   I d H }|   |d u rd S |V  qr   )get	task_done)r  itemr+   r+   r,   
queue_iter  s   r  futureasyncio.Futurec                   s*   z| I dH  W dS  t jy   Y dS w )z?Wait for completion of the given future, ignoring cancellation.N)rY  r  )r  r+   r+   r,   r    s   r  futuresT.Iterable[asyncio.Future]rK  T.Optional[T.Union[int, float]]c                   s   d
dd}t  }|du rdn| | }| rD|du s |dkrDt j| |t jd	I dH \}} || |r:||  }| rD|du s |dks ||  dS )a9  Wait for completion of all the given futures, ignoring cancellation.
       If timeout is not None, raise an asyncio.TimeoutError after the given
       time has passed.  asyncio.TimeoutError is only raised if some futures
       have not completed and none have raised exceptions, even if timeout
       is zero.r  r  r%   rK   c                 S  s:   d}| D ]}|  sd}q| s|  q|rtjd S NFT)done	cancelledr=   rY  TimeoutError)r  rM  r  r+   r+   r,   check_futures  s   z#complete_all.<locals>.check_futuresNr   )rK  Zreturn_when)r  r  r%   rK   )rY  rZ  rP  r[  ZFIRST_EXCEPTION)r  rK  r"  r_  Zdeadliner  r+   r+   r,   complete_all  s   
r#  c                   @  sB   e Zd Z	ddd	d
ZdddZdddZd ddZd!ddZdS )"TestSubprocessNpasyncio.subprocess.Processr>  r   r  postwait_fnT.Callable[[], None]c                 C  s4   || _ || _|| _d | _d | _|| _g | _d | _d S r   )_processr>  r  	stdo_task	stde_taskr'  all_futuresr  )r   r%  r>  r  r'  r+   r+   r,   r&    s   
zTestSubprocess.__init__r%   r   c                 C  s   t  | _t| jS r   )rY  Queuer  r  r   r+   r+   r,   stdout_lines  s   

zTestSubprocess.stdout_linesr  r  r  r   CT.Tuple[T.Optional[T.Awaitable[str]], T.Optional[T.Awaitable[str]]]c                   s   d fd	d
}ddd} j d u r+ jd ur+|| jj|}t| _  j j   jd urL jtjj	krL|| jj|}t| _
 j j
  j  j
fS )Nr  r  r  r   r  r   r%   rK   c                   s   t | j|I d H | _d S r   )r
  r  rv  r  r  r  r   r+   r,   collect_stdo  s   z0TestSubprocess.communicate.<locals>.collect_stdoc                   s   t |d |I d H | _d S r   )r
  r  r0  r+   r+   r,   collect_stde  s   z0TestSubprocess.communicate.<locals>.collect_stde)r  r  r  r   r  r   r%   rK   )r*  r>  r)  rY  rg  r,  rZ   r  
subprocessr   r+  )r   r  r  r1  r2  Zdecode_coror+   r   r,   communicate  s   
zTestSubprocess.communicater   c                   sb  | j }zzt rtddddt|jg nLt|jtj	 t
tj tj| ddI d H  W d    n1 s<w   Y  |jd ur\W W | jrP| j  | jrZ| j  d S d S t|jtj t
tj tj| ddI d H  W d    n1 sw   Y  |jd urW W | jr| j  | jr| j  d S d S |  t
tj tj| ddI d H  W d    n1 sw   Y  |jd urW W | jr| j  | jr| j  d S d S W W | jr| j  | jr| j  dS dS  ty   | I d H  Y W | jr| j  | jr| j  d S d S w | jr&| j  | jr0| j  w w )	NZtaskkillz/Fz/Tz/PIDg      ?rK  r   z!Test process could not be killed.)r)  r-   r3  runr9   pidrA   killpgr   SIGTERMr   rY  r!  wait_forr[  r  r*  cancelr+  SIGKILLkillProcessLookupError)r   r%  r+   r+   r,   _kill  st   




	



zTestSubprocess._killrK   c                   s   | j }| jt|  zNzt| j|jdI d H  W n7 tjy9   | j	| 
 I d H p0d7  _	tj|_Y n tjyT   | j	| 
 I d H pKd7  _	tj|_Y nw W | jr]|   n	| jrf|   w w |jpkd|_d S )Nr5  rk   r   )r)  r,  rZ   rY  rg  r[  r#  rK  r!  r  r?  r   r   r   r  r   r'  r  )r   r  r%  r+   r+   r,   r[  ;  s(   
zTestSubprocess.waitr   )r%  r&  r>  r   r  r   r'  r(  )r%   r   )r  r  r  r   r%   r/  r  )r  r  r%   rK   )r   r   r   r&  r.  r4  r?  r[  r+   r+   r+   r,   r$    s    


0r$  c                   @  sr   e Zd Zd,d	d
Zd-ddZd-ddZed.ddZed/ddZed0ddZ	d1ddZ
d2d%d&Zd3d)d*Zd+S )4SingleTestRunnerr  r   r   r  r   r9   rq  argparse.Namespacec           
      C  s  || _ || _|  | _| jrU| j jrUtj| j jdg |d  |d< g }| jD ],}|| tj	
|drTt|dd | j jD |ddd | j j|d<  nq(d|vs]|d sj|jsjttd	d
|d< | jjsz| j jd u sz| j jdkr}d }n| jjd u r| j j}n| jjdkrd }n| j j| jj }|jo| jjd	ko| jj }|js| jjo| jj }	t||||||	| _| jjrtj| _d S | jj rtj!| _d S tj"| _d S )Nrk   PATHZwinec                 S  s   g | ]}d | qS )zZ:r+   )r   r%  r+   r+   r,   r   ^  s    z-SingleTestRunner.__init__.<locals>.<listcomp>ZWINEPATH;ZMALLOC_PERTURB_r      r   )#r  rq  _get_cmdr  Zextra_pathsrA   pathsepr   rZ   re   basenamer   r   r  r]   r  	benchmarkr9   randomrandintrS   rK  timeout_multiplierr  num_processesri  r{  r  runobjr   r   r  rl  r   r   )
r   r  r   r   rq  Zwinecmdr>   rK  r  ri  r+   r+   r,   r&  P  sB   
"

" 
zSingleTestRunner.__init__r%   T.Optional[T.List[str]]c                 C  s   | j jd }| jjr| j jrtj|std|d|	dr)ddg| j j S | j j
s8t|r8dg| j j S | j jrl| j j
rl| j jrl| j jd u rLd S | j jrl| j j sbd}t|| j jj| j j | j j S | j jS )	Nr   zThe test program z7 does not exist. Cannot run tests before building them.z.jarjavaz-jarZmonozmThe exe_wrapper defined in the cross file {!r} was not found. Please check the command and/or add it to PATH.)r  r  rq  
no_rebuildZcmd_is_builtrA   re   isfiler   r  is_cross_builtr  Z
cmd_is_exeneeds_exe_wrapperexe_wrapperfoundr   r   get_command)r   Z	testentrymsgr+   r+   r,   _get_test_cmd  s    
zSingleTestRunner._get_test_cmdc                 C  s    |   }|sd S t| j| S r   )rX  TestHarnessget_wrapperrq  )r   Ztest_cmdr+   r+   r,   rE    s   zSingleTestRunner._get_cmdr&   c                 C     | j jS r   )rM  r  r   r+   r+   r,   r       zSingleTestRunner.is_parallelc                 C  r[  r   )rM  r   r   r+   r+   r,   visible_name  r\  zSingleTestRunner.visible_namer   c                 C  r[  r   )rM  rK  r   r+   r+   r,   rK    r\  zSingleTestRunner.timeoutr  r  r  c                   st   | j d u rd| _|| j | j  | jS | j | jj | jj }| j	| || j | 
||I d H  | jS )Nz8Not run because can not execute cross compiled binaries.)r  rv  log_start_testrM  r  r  Zcmd_argsrq  Z	test_argsr  _run_cmd)r   r  r  r+   r+   r,   r6    s   

zSingleTestRunner.runra   r  r>  r  cwdr   r$  c          	        s   j jrttj ttjtj d	fdd}d	 fdd}tj|||||t s.|nd dI d H }t	|||t sA|dS d dS )
Nr%   rK   c                     s(    j jrttjtj d S t  d S r   )rq  rS   r   SIGINTSIG_DFLrA   setsidr+   r   r+   r,   
preexec_fn  s   z4SingleTestRunner._run_subprocess.<locals>.preexec_fnc                     s   j jrttj  d S d S r   )rq  rS   r   ra  r+   Zprevious_sigint_handlerr   r+   r,   r'    s   z5SingleTestRunner._run_subprocess.<locals>.postwait_fn)r>  r  r   r`  rd  )r>  r  r'  r  )
rq  rS   r   	getsignalra  SIG_IGNrY  Zcreate_subprocess_execr-   r$  )	r   ra   r>  r  r   r`  rd  r'  r%  r+   re  r,   _run_subprocess  s$   z SingleTestRunner._run_subprocessr  rK   c                   s8  | j tju rd }d }ntjj}| jjs| jj	stjj
ntjj}g }| jjtju rE| jj}| jjr<tj| jj| jj}|d| d | j|| ||| jj| jjdI d H }| jj	rk| j|| }t|}	nd }	|| j| j \}
}|| jI d H  |	r|	I d H  |
r|
I d H  |r|I d H  | j  d S )Nz--gtest_output=xml:r  )r>  r  r   r`  )r  r   r   rY  r3  PIPErq  r]   rM  rm  r   r  r  r   GTESTr   r  rA   re   r   rZ   rh  r   r   r.  rg  r4  r[  r  )r   r  r  r>  r  Z	extra_cmdZ	gtestnamer%  Z
parse_coroZ
parse_taskr*  r+  r+   r+   r,   r_    sH   




zSingleTestRunner._run_cmdN)r  r   r   r  r   r9   rq  rA  )r%   rN  r   r   )r%   r   )r  r  r%   r  )ra   r  r>  r   r  r   r   r  r`  r   r%   r$  )r  r  r  r  r%   rK   )r   r   r   r&  rX  rE  r  r  r]  rK  r6  rh  r_  r+   r+   r+   r,   r@  N  s    

/


"r@  c                   @  sl  e Zd ZdnddZdoddZdpd
dZdpddZdqddZdrddZdsddZ	dpddZ
dtd!d"Zdud%d&Zdvd(d)Zdwd,d-Zedxd/d0Zedxd1d2Zdyd4d5Z	6	7	8	8	8dzd{dAdBZd|dCdDZdxdEdFZdxdGdHZed}dKdLZed~dOdPZddQdRZddUdVZddWdXZdpdYdZZdpd[d\Zedd]d^Zdd_d`Z ddcddZ!ddhdiZ"ddjdkZ#ddldmZ$d8S )rY  rq  rA  c                 C  s<  || _ g | _d| _d| _d| _d| _d| _d| _d| _d| _	d| _
g | _t | _| j| j d| _d | _d | _| j jr{| j js{d }tj| j jd| j j| _| j jr`tj| | j d }n| j jrl| j jdd}|r{|  jd|dd 7  _|   |   t }| j D ]}|j!D ]}|"| qqt#|| _$d S )Nr   Fz
meson-logs:r@  r)  r|   )%rq  r}  
fail_countexpectedfail_countunexpectedpass_countsuccess_count
skip_counttimeout_countr0  name_max_lenis_runloggersr'  console_loggerrZ   rf  ninjalogfile_baseZlogbaserS   rA   re   r   rX   rV   rG  rZ  r`   r   prepare_buildload_metadatarE  r  r  r^  rU   r  )r   rq  Znamebasessr  r8   r+   r+   r,   r&    sD   

zTestHarness.__init__r%   'ConsoleLogger'c                 C  s   | j sJ | j S r   )ru  r   r+   r+   r,   get_console_logger)  s   
zTestHarness.get_console_loggerrK   c                 C  s6   | j jrd S t | _| jstd td d S d S )Nz%Can't find ninja, can't rebuild test.   )rq  rP  r	   Zdetect_ninjarv  rD   r/   exitr   r+   r+   r,   rx  -  s   
zTestHarness.prepare_buildc              	   C  s   t  }zUt | jj | jjs't| jdg j	}|dkr't
d| jjtt  | _| jjs9| jj| j_| jjrD| d| _n| d| _W t | d S W t | d S t | w )Nzbuild.ninjar   zCould not configure zmeson_benchmark_setup.datzmeson_test_setup.dat)rA   getcwdchdirrq  rX   rP  r3  r6  rv  r  r   r   load
build_datar`   Ztest_setup_default_namerH  
load_testsr  )r   startdirretr+   r+   r,   ry  :  s    zTestHarness.load_metadata	file_namer9   r  c                 C  sf   t d| }| std| jjd|d}tt|}W d    |S 1 s,w   Y  |S )Nzmeson-privatez
Directory z- does not seem to be a Meson build directory.rb)	r   is_filer   rq  rX   r$  r  pickler  )r   r  Zdatafiler  r  r+   r+   r,   r  R  s   
zTestHarness.load_testsr  c                 C  r   r   r+   r   r+   r+   r,   	__enter__Z  r  zTestHarness.__enter__exc_typer  	exc_value	tracebackc                 C  r  r   )close_logfiles)r   r  r  r  r+   r+   r,   __exit__]  r  zTestHarness.__exit__c                 C  s   | j D ]}|  qd | _d S r   )rt  r  ru  r   r  r+   r+   r,   r  `  s   


zTestHarness.close_logfilesr  T.Optional[TestSerialisation]build.TestSetupc                 C  s   d| j jv r!| j j| jjvrtd| j j d | jj| j j S |jd | j j }|| jjvr?td| j j d|j d | jj| S )Nrk  zUnknown test setup 'z'.zTest setup 'z' not found from project ')rq  r`   r  Ztest_setupsr/   r~  r  )r   r  	full_namer+   r+   r,   get_test_setupe  s   zTestHarness.get_test_setupr   r  c                 C  sl   |  |}|js|j|_|jrd|_|jd u r|j|_|jd u r%|j|_n|jr-td |j	t
j S )NTzBConflict: both test setup and command line specify an exe wrapper.)r  rS   ri  rK  rV   rT  r/   r~  r   get_envrA   rB   copy)r   rq  r  currentr+   r+   r,   merge_setup_optionsp  s   




zTestHarness.merge_setup_optionsr@  c                 C  s   |  |}t| j}| jjr| ||}ntj }|j	|}|
| |jr<|jr<|jr<|j r<t|j |d< t||||S )NZMESON_EXE_WRAPPER)get_pretty_suiter   rq  r`   r  rA   rB   r  r   r  rD  rR  rS  rT  rU  r   rV  r@  )r   r  r   rq  r   r  r+   r+   r,   get_test_runner  s   



zTestHarness.get_test_runnerr=   r  c                 C  s   |j tju r|  jd7  _nT|j tju r|  jd7  _nF|j tju r*|  jd7  _n8|j tjtj	tj
hv r=|  jd7  _n%|j tju rK|  jd7  _n|j tju rY|  jd7  _n	td|j   |j  rm| j| | jD ]}|| | qpd S )Nr   z!Unknown test result encountered: )r   r   r   rq  r   rp  r   ro  r   r   r   rl  r   rm  r   rn  r/   r~  r   r}  rZ   rt  r  )r   r=   r  r+   r+   r,   process_test_result  s$   

zTestHarness.process_test_resultr:   c                 C  s   t t| jS r   )rO  r9   r0  r   r+   r+   r,   numlen     zTestHarness.numlenc                 C  s   d| j  d S )Nr2   )r  r   r+   r+   r,   r-    r  zTestHarness.max_left_widthr   c                 C  s   dj | j|| jdS )Nz{num:{numlen}}/{testcount} )r  r   Z	testcount)r   r  r0  )r   r   r+   r+   r,   get_test_num_prefix  s   zTestHarness.get_test_num_prefixr   rk   Nr   r&   r-  rx  rM  r   ry  rN  c           
      C  s   |d u r
|  |j}t|| j}|d u r|j}|| j d t| t| t| }|dtd| 7 }|d u rSdj|j	||j
| jd d}| }	|	rS|d|	 7 }|| | | S )Nr   r|   z{res} {dur:{durlen}.2f}sr$   )r   rI  rJ  rL  )r  r   re  r-  r   rr  r@   r   r   r   r  rR  rS  )
r   r=   r   r-  rx  rM  ry  rN  Zextra_mid_widthrU  r+   r+   r,   r     s"   &
zTestHarness.formatc                 C  s&   t d| j| j| j| j| j| jS )Nz
            Ok:                 {:<4}
            Expected Fail:      {:<4}
            Fail:               {:<4}
            Unexpected Pass:    {:<4}
            Skipped:            {:<4}
            Timeout:            {:<4}
            )	textwrapdedentr   ro  rm  rl  rn  rp  rq  r   r+   r+   r,   r    s
   zTestHarness.summaryc                 C  s   | j | j | j S r   )rl  rn  rq  r   r+   r+   r,   total_failure_count  s   zTestHarness.total_failure_countc              	     s(   j rtdd _   }|sdS  jjs$t j jj|s$t	d t
 fdd|D  _t jjt| jj  j_t }zJt jj g }t jjD ]&}| fdd|D  |dkryt
dd |D  _td	d |D  _qSt| _ | W t|   S t| w )
Nz*Test harness object can only be used once.Tr   }   c                 3  s    | ]
}t  |V  qd S r   )r@   r  r   r  r   r+   r,   r        z#TestHarness.doit.<locals>.<genexpr>c                 3  s    | ]}  |V  qd S r   )r  r  r   r+   r,   r    r  c                 s  s&    | ]}t tt|jpd V  qdS )r#   N)rO  r9   r:   rK  r   runnerr+   r+   r,   r    s    c                 s  r  r   )r  r   r   r  r+   r+   r,   r    s    )rs  RuntimeError	get_testsrq  rP  rebuild_depsrv  rX   r/   r~  re  rr  minrL  rO  rO   rA   r  r  rangeextendrR  r  rf  r0  	run_testsr  )r   r  r  runnersr  r+   r   r,   doit  s>   




zTestHarness.doitr  T.Tuple[str, str]c                 C  s<   d| v r|  dd}t|dksJ |d |d fS | dfS )Nrk  r   r2   r   rk   )r]   rO  )r  r]   r+   r+   r,   split_suite_string  s
   zTestHarness.split_suite_stringr  r  c                 C  sl   |D ]1}t |\}}| jD ]$}t |\}}|s!||kr!  dS |r(||kr(q|r/||kr/q  dS qdS NTF)rY  r  r  )r  r  r  Z	prj_matchZst_matchZprjstZprjstr+   r+   r,   test_in_suites  s   
zTestHarness.test_in_suitesc                 C  sT   t || jjr
dS | jjrt || jjS | jjr(| |}t ||jr(dS dS r  )rY  r  rq  r\   rY   r`   r  )r   r  r`   r+   r+   r,   test_suitable(  s   
zTestHarness.test_suitabler  *T.Generator[TestSerialisation, None, None]c                 c  sj    | j jD ]-}d|v r|jddd\}}nd|}}|D ]}|r&|j|kr&q|r.|j|kr.q|V  qqdS )a  
        Allow specifying test names like "meson test foo1 foo2", where test('foo1', ...)

        Also support specifying the subproject to run tests from like
        "meson test subproj:" (all tests inside subproj) or "meson test subproj:foo1"
        to run foo1 inside subproj. Coincidentally also "meson test :foo1" to
        run all tests with that name across all subprojects, which is
        identical to "meson test foo1"
        rk  r   )maxsplitrk   N)rq  ra   r]   r  r   )r   r  argZsubprojr   r  r+   r+   r,   tests_from_args8  s   

zTestHarness.tests_from_argsc                   sP    j s	td g S  fdd j D } jjrt |}|s&td g S |S )NzNo tests defined.c                   s   g | ]	}  |r|qS r+   )r  r  r   r+   r,   r   S  s    z)TestHarness.get_tests.<locals>.<listcomp>zNo suitable tests defined.)r  rD   rq  ra   rU   r  )r   r  r+   r   r,   r  N  s   zTestHarness.get_testsc                 C  s   | j D ]}|  qd S r   )rt  r  r  r+   r+   r,   flush_logfiles]  s   

zTestHarness.flush_logfilesc                 C  sT   | j sd S | jt| j d  | jt| j d  | jt| j d dd d S )Nz
.junit.xmlz.jsonz.txtsurrogateescaperp   )rw  rt  rZ   r  r  r  r   r+   r+   r,   open_logfilesa  s
   zTestHarness.open_logfilesc                 C  sH   g }| j r| jdg}| jdkr|g d7 }|dg7 }| jr"|| j7 }|S )Nr_   r   )-exr6  r  quitz--args)rS   rT   rO   rV   )rq  wrapr+   r+   r,   rZ  i  s   



zTestHarness.get_wrapperc                 C  sb   t | jdkr.|jr.t|jd d }ddd |jD }|r%|d7 }|| d |j S |jS )Nr   r   +c                 s  s    | ]
}t |d  V  qdS r  )rY  r  )r   r8   r+   r+   r,   r  y  r  z/TestHarness.get_pretty_suite.<locals>.<genexpr>rk  z / )rO  r  r  rY  r  r   r   )r   r  rvr8   r+   r+   r,   r  v  s   zTestHarness.get_pretty_suiter  T.List[SingleTestRunner]c                 C  sJ   z|    tjdkrtt  t| | W |   d S |   w )Nwin32)	r  r/   r(   rY  Zset_event_loop_policyZWindowsProactorEventLoopPolicyr6  
_run_testsr  )r   r  r+   r+   r,   r    s   
zTestHarness.run_testsr8   r   r   c                 C  s    | j D ]
}|| ||| qd S r   )rt  r  )r   r  r8   r   r  r+   r+   r,   r    s   
zTestHarness.log_subtestc                 C  s   | j D ]}|| | qd S r   )rt  r  )r   r  r  r+   r+   r,   r^    s   
zTestHarness.log_start_testc           	   
     s
  t jjt i dttdt  d fdd}dfdd}dfdddfdd d fdd}d fdd}jD ]}| qUt	j
dkrtdt krstj| ntj| tj| zc|D ]7}|jstI d H  t ||}| |j|< || |jst|I d H  jjdkrjr nqtI d H  W t	j
dkrՈtj tj jD ]
}|I d H  qd S t	j
dkrtj tj jD ]
}|I d H  qw )NF)r   r  r@  r%   rK   c              	     s   4 I d H d sj jdkrjr	 W d   I d H  d S | I d H }| j j}|rJj|krU|j r`   W d   I d H  d S W d   I d H  d S W d   I d H  d S W d   I d H  d S 1 I d H sqw   Y  d S r  )rq  rO   rl  r6  r  maxfailr   r   )r  r   r  )cancel_all_testsinterruptedr   	semaphorer+   r,   run_test  s"   
.z(TestHarness._run_tests.<locals>.run_testr  r  c                   s<   |   s|    |  z| = W d S  ty   Y d S w r   )r   r=   rz  KeyError)r  )r  r*  r+   r,   	test_done  s   
z)TestHarness._run_tests.<locals>.test_donewarnr&   c                   sD      } | | r  td|  |= |  d S )Nz CTRL-C detected, interrupting {})popleftrZ   r  r
   warningr   r;  )r  r  )r  r*  r   r+   r,   cancel_one_test  s   
z/TestHarness._run_tests.<locals>.cancel_one_testc                     s   dr d sd S d S r  r+   r+   )r  r  r*  r+   r,   r    s   z0TestHarness._run_tests.<locals>.cancel_all_testsc                     s$   rd S    td    d S )NzReceived SIGTERM, exiting)r  r
   r  r+   )r  r  r   r+   r,   sigterm_handler  s
   

z/TestHarness._run_tests.<locals>.sigterm_handlerc                     s|   rd S    ttkr)d d  dk r)  td    d S r1d d S   td dd S )Nri   r   r   zCTRL-C detected, exitingT)rZ   rP  rO  	MAX_CTRLCr  r
   r  r+   )r  r  ctrlc_timesr  r_  r*  r   r+   r,   sigint_handler  s    


z.TestHarness._run_tests.<locals>.sigint_handlerr  r   r   )r  r@  r%   rK   )r  r  r%   rK   )r  r&   r%   rK   r  )rY  	Semaphorerq  rL  r   r  rZ  rt  r  r/   r(   rA   getpgidgetpidZadd_signal_handlerr   ra  r9  r  r#  rg  rZ   r]  Zadd_done_callbackr  rO   rl  Zremove_signal_handlerr  )	r   r  r  r  r  r  r  r  r  r+   )	r  r  r  r  r  r_  r*  r   r  r,   r    s\   

		








zTestHarness._run_tests)rq  rA  )r%   r{  r  )r  r9   r%   r  )r%   r  )r  r  r  r  r  r  r%   rK   )r  r  r%   r  )rq  rA  r  r   r%   r  )r  r   r%   r@  )r=   r  r%   rK   r   )r   r:   r%   r9   )r   rk   NNN)r=   r  r   r&   r-  r:   rx  r9   rM  r   ry  r   rN  r   r%   r9   r   )r  r9   r%   r  )r  r   r  r  r%   r&   )r  r   r%   r&   )r  r  r%   r  )r%   r  )rq  rA  r%   r  )r  r   r%   r9   )r  r  r%   rK   )r  r  r8   r9   r   r   r%   rK   )r  r  r%   rK   )%r   r   r   r&  r|  rx  ry  r  r  r  r  r  r  r  r  r  r  r-  r  r   r  r  r  r   r  r  r  r  r  r  r  rZ  r  r  r  r^  r  r+   r+   r+   r,   rY     sV    

(













%









rY  thc                 C  s&   |   }|D ]	}t| | q| S r   )r  rD   r  )r  r  r  r+   r+   r,   
list_tests  s   r  rv  r  rX   r  c           
        s   dfdd t | dksJ t }t }i }ttddD ]} fd	d
|d D ||d < q|D ]}|jD ]}||v r?q8|| |||  q8q3t| dg t| j	}	|	dkrht
d  dS dS )Nre   r9   r%   c                   s*   t j|  } t jdkr| t jd} | S )NrG  )rA   re   relpathrB  r   )re   )rX   r+   r,   convert_path_to_target  s   
z,rebuild_deps.<locals>.convert_path_to_targetr   targets)kindc                   s   g | ]} |qS r+   r+   )r   r  )r  r+   r,   r     s    z rebuild_deps.<locals>.<listcomp>r!  idrW   zCould not rebuild FT)re   r9   r%   r9   )rO  rE  r   r   dependsrD  r3  r6  sortedr  rD   )
rv  rX   r  r  r  Zintro_targetstargetr  dr  r+   )r  rX   r,   r    s*   


r  rq  rA  c                 C  s  | j rd| _| jr| jrtd dS d }| jr%d| _| jr#td dS d}| jr-| jd }|d urDt|dd}| sDtd| dS t	
| j}td	|jjtd
}t| | jsz|jjtd}|dkrod| _n|dkrztd d| _t| F}z| jrt|W W  d    S | W W  d    S  ty } ztd tjdr|t| W Y d }~W d    dS d }~ww 1 sw   Y  d S )Nr   z3Can not be both quiet and verbose at the same time.Tz9Must not specify both a wrapper and gdb at the same time.rS   r   )Zsilentz"Could not find requested program: r&   Zvsenvbackendnonerv  zEOnly ninja backend is supported to rebuild tests before running them.z!Meson test encountered an error:
ZMESON_FORCE_BACKTRACE)rH  rL  ri  r{  rD   rS   rV   r   rU  r   r  rX   r  castr	   coredataZ
get_optionr   r   rP  rY  rU   r  r  r   rA   rB   r  )rq  Z	check_binexerw   Z
need_vsenvr  r  r	  r+   r+   r,   r6    s\   


r6  ra   c                 C  s&   t jdd}t| || }t|S )Nz
meson test)prog)argparseArgumentParserrh   
parse_argsr6  )ra   rI   rq  r+   r+   r,   run_with_argsM  s   
r  r   )r8   r9   r%   r:   r   )rI   rJ   r%   rK   )r8   r9   r%   rK   )rv   r9   rw   r9   r%   r9   )r8   r9   rz   r9   r{   r:   r%   r9   )r   r:   r%   r9   )r   r   r%   r9   )r  r  r%   r9   )r  r   r  r  r  r   r%   r9   )r  r9   r%   r&   )r  r  r%   r  )r  r  r%   r   )r  r  r%   rK   r   )r  r  rK  r  r%   rK   )r  rY  r%   r&   )rv  r  rX   r9   r  r  r%   r&   )rq  rA  r%   r:   )ra   r  r%   r:   )t
__future__r   pathlibr   collectionsr   
contextlibr   r  r   r  rY  r  enumr  rE   rA   r  r(   rI  r  r   r3  shlexr/   r  rP  typingr  r;   Zxml.etree.ElementTreeetreer  r  rk   r   r	   r
   r  r   r   r   r   r  Zmesonlibr   r   r   r   r   r   r   Zmintror   r   Zprogramsr   Zbackend.backendsr   r   TYPE_CHECKINGUnionZTYPE_TAPResultr  r  r  r-   r0   r<   r@   rH   rh   ru   ry   r   r   r   r   quoter   r   uniqueEnumr   r   r   r  r  r'  r  r  r  r  r  r  ZEXITCODEr  rj  r  ZTAPr  ZRUSTrt   r
  r  r  r  r  r#  r$  r@  rY  r  r  r6  r  r+   r+   r+   r,   <module>   s   $







5


	
1 0 _# z4'





!o 3   
x

4