o
    ¯bœ$  ã                   @   s  d Z ddlZddlmZ ddlmZ ddlmZ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mZmZmZmZ ddlmZ ddlmZmZ ddlmZ G dd„ deƒZG dd„ deƒZeeƒG dd„ dƒƒZeeƒG dd„ dƒƒZ G dd„ de
ƒZ!dS )z:
This module implements the worker classes.

@since: 12.3
é    N)Úimplementer)ÚDeferred)ÚIAddressÚ
ITransport)ÚProcessProtocol)ÚAMP)ÚFailure)ÚnamedObject)Ú_WORKER_AMP_STDINÚ_WORKER_AMP_STDOUTÚmanagercommandsÚworkercommands)ÚWorkerReporter)Ú
TestLoaderÚ
TrialSuite)ÚTodoc                   @   sB   e Zd ZdZd
dd„Zdd„ Zej e¡ dd„ Z	ej
 e	¡ d	S )ÚWorkerProtocolz5
    The worker-side trial distributed protocol.
    Fc                 C   s   t ƒ | _t| ƒ| _|| _d S ©N)r   Ú_loaderr   Ú_resultÚ_forceGarbageCollection)ÚselfÚforceGarbageCollection© r   ú</usr/lib/python3/dist-packages/twisted/trial/_dist/worker.pyÚ__init__&   s   

zWorkerProtocol.__init__c                 C   s.   | j  |¡}t|g| jƒ}| | j¡ ddiS )z*
        Run a test case by name.
        ÚsuccessT)r   Ú
loadByNamer   r   Úrunr   )r   ÚtestCaseÚcaseÚsuiter   r   r   r   +   s   zWorkerProtocol.runc                 C   s   t  |¡ ddiS )zb
        Set up the worker, moving into given directory for tests to run in
        them.
        r   T)ÚosÚchdir)r   Ú	directoryr   r   r   Ústart6   s   
zWorkerProtocol.startN)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   ÚRunÚ	responderr%   ÚStartr   r   r   r   r   !   s    
	r   c                   @   s¼   e Zd ZdZdd„ Zej e¡ dd„ Zdd„ Z	ej
 e	¡ dd	„ Zej e¡ d
d„ Zej e¡ dd„ Zej e¡ dd„ Zej e¡ dd„ Zej e¡ dd„ Zdd„ Zdd„ ZdS )ÚLocalWorkerAMPz7
    Local implementation of the manager commands.
    c                 C   s   | j  | j¡ ddiS )z0
        Add a success to the reporter.
        r   T)r   Ú
addSuccessÚ	_testCase)r   ÚtestNamer   r   r   r.   F   s   zLocalWorkerAMP.addSuccessc              	   C   sZ   t |ƒ}t||ƒ}tdt|ƒdƒD ]}|j || ||d  t||d  ƒg g f¡ q|S )a   
        Helper to build a C{Failure} with some traceback.

        @param error: An C{Exception} instance.

        @param errorClass: The class name of the C{error} class.

        @param frames: A flat list of strings representing the information need
            to approximatively rebuild C{Failure} frames.

        @return: A L{Failure} instance with enough information about a test
           error.
        r   é   é   é   )r	   r   ÚrangeÚlenÚframesÚappendÚint)r   ÚerrorÚ
errorClassr6   Ú	errorTypeÚfailureÚir   r   r   Ú_buildFailureO   s   
$ÿzLocalWorkerAMP._buildFailurec                 C   ó&   |   |||¡}| j | j|¡ ddiS )z/
        Add an error to the reporter.
        r   T)r>   r   ÚaddErrorr/   )r   r0   r9   r:   r6   r<   r   r   r   r@   e   ó   zLocalWorkerAMP.addErrorc                 C   r?   )z0
        Add a failure to the reporter.
        r   T)r>   r   Ú
addFailurer/   )r   r0   ÚfailÚ	failClassr6   r<   r   r   r   rB   o   rA   zLocalWorkerAMP.addFailurec                 C   ó   | j  | j|¡ ddiS )z-
        Add a skip to the reporter.
        r   T)r   ÚaddSkipr/   )r   r0   Úreasonr   r   r   rF   y   ó   zLocalWorkerAMP.addSkipc                 C   s"   t |ƒ}| j | j||¡ ddiS )z:
        Add an expected failure to the reporter.
        r   T)r   r   ÚaddExpectedFailurer/   )r   r0   r9   ÚtodoÚ_todor   r   r   rI   ‚   s   z!LocalWorkerAMP.addExpectedFailurec                 C   rE   )z<
        Add an unexpected success to the reporter.
        r   T)r   ÚaddUnexpectedSuccessr/   )r   r0   rJ   r   r   r   rL   Œ   rH   z#LocalWorkerAMP.addUnexpectedSuccessc                 C   s"   | j  |d ¡ | j  ¡  ddiS )z4
        Print test output from the worker.
        Ú
r   T)Ú_testStreamÚwriteÚflush)r   Úoutr   r   r   Ú	testWrite•   s   
zLocalWorkerAMP.testWritec                 C   s   | j  | j¡ |S )zL
        Stop the current running test case, forwarding the result.
        )r   ÚstopTestr/   )r   Úresultr   r   r   Ú	_stopTestŸ   s   zLocalWorkerAMP._stopTestc                 C   s<   || _ || _| j |¡ | ¡ }| jtj|d�}| | j¡S )z
        Run a test.
        )r   )	r/   r   Ú	startTestÚidÚ
callRemoter   r*   ÚaddCallbackrU   )r   r   rT   Ú
testCaseIdÚdr   r   r   r   ¦   s   zLocalWorkerAMP.runc                 C   s
   || _ dS )z?
        Set the stream used to log output from tests.
        N)rN   )r   Ústreamr   r   r   ÚsetTestStream±   s   
zLocalWorkerAMP.setTestStreamN)r&   r'   r(   r)   r.   r   Ú
AddSuccessr+   r>   r@   ÚAddErrorrB   Ú
AddFailurerF   ÚAddSkiprI   ÚAddExpectedFailurerL   ÚAddUnexpectedSuccessrR   Ú	TestWriterU   r   r]   r   r   r   r   r-   A   s(    r-   c                   @   s   e Zd ZdZdS )ÚLocalWorkerAddressz
    A L{IAddress} implementation meant to provide stub addresses for
    L{ITransport.getPeer} and L{ITransport.getHost}.
    N)r&   r'   r(   r)   r   r   r   r   re   ¸   s    re   c                   @   s@   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )ÚLocalWorkerTransportzi
    A stub transport implementation used to support L{AMP} over a
    L{ProcessProtocol} transport.
    c                 C   s
   || _ d S r   )Ú
_transport)r   Ú	transportr   r   r   r   Ç   s   
zLocalWorkerTransport.__init__c                 C   s   | j  t|¡ dS )z,
        Forward data to transport.
        N©rg   ÚwriteToChildr
   ©r   Údatar   r   r   rO   Ê   s   zLocalWorkerTransport.writec                 C   s   |D ]	}| j  t|¡ qdS )zP
        Emulate C{writeSequence} by iterating data in the C{sequence}.
        Nri   )r   Úsequencerl   r   r   r   ÚwriteSequenceÐ   s   ÿz"LocalWorkerTransport.writeSequencec                 C   s   | j  ¡  dS )z'
        Closes the transport.
        N)rg   ÚloseConnection©r   r   r   r   ro   ×   s   z#LocalWorkerTransport.loseConnectionc                 C   ó   t ƒ S ©z:
        Return a L{LocalWorkerAddress} instance.
        ©re   rp   r   r   r   ÚgetHostÝ   ó   zLocalWorkerTransport.getHostc                 C   rq   rr   rs   rp   r   r   r   ÚgetPeerã   ru   zLocalWorkerTransport.getPeerN)
r&   r'   r(   r)   r   rO   rn   ro   rt   rv   r   r   r   r   rf   À   s    rf   c                   @   sH   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dS )ÚLocalWorkeraX  
    Local process worker protocol. This worker runs as a local process and
    communicates via stdin/out.

    @ivar _ampProtocol: The L{AMP} protocol instance used to communicate with
        the worker.

    @ivar _logDirectory: The directory where logs will reside.

    @ivar _logFile: The name of the main log file for tests output.
    c                 C   s   || _ || _|| _tƒ | _d S r   )Ú_ampProtocolÚ_logDirectoryÚ_logFiler   ÚendDeferred)r   ÚampProtocolÚlogDirectoryÚlogFiler   r   r   r   ÷   s   zLocalWorker.__init__c                 C   s´   | j  t| jƒ¡ tj | j¡st | j¡ t	tj 
| jd¡dƒ| _t	tj 
| jd¡dƒ| _t	tj 
| j| j¡dddd�| _| j  | j¡ | j}| j jtj|d�}| d	d
„ ¡ dS )zL
        When connection is made, create the AMP protocol instance.
        zout.logÚwbzerr.logÚwzutf-8Ústrict)ÚencodingÚerrors)r$   c                 S   s   d S r   r   )Úxr   r   r   Ú<lambda>  s    z,LocalWorker.connectionMade.<locals>.<lambda>N)rx   ÚmakeConnectionrf   rh   r"   ÚpathÚexistsry   ÚmakedirsÚopenÚjoinÚ_outLogÚ_errLogrz   Ú_testLogr]   rX   r   r,   Ú
addErrback)r   r}   r[   r   r   r   ÚconnectionMadeý   s   üzLocalWorker.connectionMadec                 C   s"   | j  ¡  | j ¡  | j ¡  dS )zk
        On connection lost, close the log files that we're managing for stdin
        and stdout.
        N)rŒ   Úcloser�   rŽ   ©r   rG   r   r   r   ÚconnectionLost  s   

zLocalWorker.connectionLostc                 C   s&   |   |¡ | j  |¡ | j |¡ dS )z’
        When the process closes, call C{connectionLost} for cleanup purposes
        and forward the information to the C{_ampProtocol}.
        N)r“   rx   r{   Úcallbackr’   r   r   r   ÚprocessEnded  s   
zLocalWorker.processEndedc                 C   ó   | j  |¡ dS )z8
        Send data received from stdout to log.
        N)rŒ   rO   rk   r   r   r   ÚoutReceived(  s   zLocalWorker.outReceivedc                 C   r–   )z*
        Write error data to log.
        N)r�   rO   rk   r   r   r   ÚerrReceived/  s   zLocalWorker.errReceivedc                 C   s*   |t kr| j |¡ dS t | ||¡ dS )zT
        Handle data received on the specific pipe for the C{_ampProtocol}.
        N)r   rx   ÚdataReceivedr   ÚchildDataReceived)r   ÚchildFDrl   r   r   r   rš   5  s   zLocalWorker.childDataReceivedN)r&   r'   r(   r)   r   r�   r“   r•   r—   r˜   rš   r   r   r   r   rw   ê   s    		rw   )"r)   r"   Úzope.interfacer   Útwisted.internet.deferr   Útwisted.internet.interfacesr   r   Útwisted.internet.protocolr   Útwisted.protocols.ampr   Útwisted.python.failurer   Útwisted.python.reflectr	   Útwisted.trial._distr
   r   r   r   Ú"twisted.trial._dist.workerreporterr   Útwisted.trial.runnerr   r   Útwisted.trial.unittestr   r   r-   re   rf   rw   r   r   r   r   Ú<module>   s(    w)