U
    Â“«j¬  ã                   @   st  d Z ddl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 dd	lmZmZmZmZmZ dd
lmZm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$m%Z% dd„ Z&eeƒG dd„ dƒƒZ'eee'ƒ eeƒG dd„ dƒƒZ(eee'ƒ G dd„ de%ƒZ)G dd„ de%ƒZ*G dd„ dƒZ+d$dd„Z,e fdd „Z-d!Z.G d"d#„ d#e$ƒZ/dS )%zœ
Tests for (new code in) L{twisted.application.internet}.

@var AT_LEAST_ONE_ATTEMPT: At least enough seconds for L{ClientService} to make
    one attempt.
é    N)Úimplementer)ÚverifyClass)Úinternet)ÚClientServiceÚStreamServerEndpointServiceÚTimerService)Útask)ÚCancelledErrorÚDeferred)ÚIFileDescriptorReceiverÚIHalfCloseableProtocolÚIListeningPortÚIStreamClientEndpointÚIStreamServerEndpoint)ÚFactoryÚProtocol)ÚClock)ÚStringTransport)ÚformatEventÚglobalLogPublisher)ÚFailure)ÚSynchronousTestCaseÚTestCasec                   C   s   dS )zM
    A fake target function for testing TimerService which does nothing.
    N© r   r   r   úJ/tmp/pip-unpacked-wheel-59kc99xd/twisted/application/test/test_internet.pyÚfakeTargetFunction)   s    r   c                   @   sF   e Zd ZdZdZdZdZeƒ ZdZ	dd„ Z
dd„ Zdd	„ Zd
d„ ZdS )Ú
FakeServeraq  
    In-memory implementation of L{IStreamServerEndpoint}.

    @ivar result: The L{Deferred} resulting from the call to C{listen}, after
        C{listen} has been called.

    @ivar factory: The factory passed to C{listen}.

    @ivar cancelException: The exception to errback C{self.result} when it is
        cancelled.

    @ivar port: The L{IListeningPort} which C{listen}'s L{Deferred} will fire
        with.

    @ivar listenAttempts: The number of times C{listen} has been invoked.

    @ivar failImmediately: If set, the exception to fail the L{Deferred}
        returned from C{listen} before it is returned.
    Nr   c                 C   s   t ƒ | _d S ©N)ÚFakePortÚport©Úselfr   r   r   Ú__init__L   s    zFakeServer.__init__c                    sF   ˆ  j d7  _ |ˆ _t‡ fdd„d�ˆ _ˆ jdk	r@ˆ j ˆ j¡ ˆ jS )zê
        Return a Deferred and store it for future use.  (Implementation of
        L{IStreamServerEndpoint}).

        @param factory: the factory to listen with

        @return: a L{Deferred} stored in L{FakeServer.result}
        é   c                    s   |   ˆ j¡S r   )ÚerrbackÚcancelException)Údr    r   r   Ú<lambda>Z   ó    z#FakeServer.listen.<locals>.<lambda>)Z	cancellerN)ÚlistenAttemptsÚfactoryr
   ÚresultÚfailImmediatelyr$   )r!   r*   r   r    r   ÚlistenO   s    	
zFakeServer.listenc                 C   s   | j  | j¡ dS )z°
        Test code should invoke this method after causing C{listen} to be
        invoked in order to fire the L{Deferred} previously returned from
        C{listen}.
        N)r+   Úcallbackr   r    r   r   r   ÚstartedListening_   s    zFakeServer.startedListeningc                 C   s   | j j d¡ dS )a  
        Test code should invoke this method after causing C{stopListening} to
        be invoked on the port fired from the L{Deferred} returned from
        C{listen} in order to cause the L{Deferred} returned from
        C{stopListening} to fire.
        N)r   Údeferredr.   r    r   r   r   ÚstoppedListeningg   s    zFakeServer.stoppedListening)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r+   r*   r,   r	   r%   r)   r"   r-   r/   r1   r   r   r   r   r   0   s   r   c                   @   s,   e Zd ZdZdZdd„ Zdd„ Zdd„ ZdS )	r   zs
    Fake L{IListeningPort} implementation.

    @ivar deferred: The L{Deferred} returned by C{stopListening}.
    Nc                 C   s   t ƒ | _| jS )z`
        Stop listening.

        @return: a L{Deferred} stored in L{FakePort.deferred}
        )r
   r0   r    r   r   r   ÚstopListening~   s    zFakePort.stopListeningc                 C   s   d S r   r   r    r   r   r   ÚgetHost‡   s    zFakePort.getHostc                 C   s   d S r   r   r    r   r   r   ÚstartListening‹   s    zFakePort.startListening)r2   r3   r4   r5   r0   r6   r7   r8   r   r   r   r   r   t   s
   	r   c                   @   sr   e Zd ZdZdd„ Zdd„ Zddd„Zd	d
„ Zd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 )ÚEndpointServiceTestsz4
    Tests for L{twisted.application.internet}.
    c                 C   s$   t ƒ | _tƒ | _t| j| jƒ| _dS )zp
        Construct a stub server, a stub factory, and a
        L{StreamServerEndpointService} to test.
        N)r   Ú
fakeServerr   r*   r   Úsvcr    r   r   r   ÚsetUp˜   s    zEndpointServiceTests.setUpc                 C   s    | j  ¡  |  | j| jj¡ dS )z‡
        L{StreamServerEndpointService.privilegedStartService} calls its
        endpoint's C{listen} method with its factory.
        N)r;   ÚprivilegedStartServiceÚassertIdenticalr*   r:   r    r   r   r   Útest_privilegedStartService¡   s    
z0EndpointServiceTests.test_privilegedStartServiceNc                 C   s*   t ƒ | j_d| j_|  t |p"| jj¡ dS )a@  
        L{StreamServerEndpointService.startService} should raise synchronously
        if the L{Deferred} returned by its wrapped
        L{IStreamServerEndpoint.listen} has already fired with an errback and
        the L{StreamServerEndpointService}'s C{_raiseSynchronously} flag has
        been set.  This feature is necessary to preserve compatibility with old
        behavior of L{twisted.internet.strports.service}, which is to return a
        service which synchronously raises an exception from C{startService}
        (so that, among other things, twistd will not start running).  However,
        since L{IStreamServerEndpoint.listen} may fail asynchronously, it is a
        bad idea to rely on this behavior.

        @param thunk: If specified, a callable to execute in place of
            C{startService}.
        TN)ÚZeroDivisionErrorr:   r,   r;   Ú_raiseSynchronouslyÚassertRaisesÚstartService)r!   Zthunkr   r   r   Ú(test_synchronousRaiseRaisesSynchronously©   s    
z=EndpointServiceTests.test_synchronousRaiseRaisesSynchronouslyc                 C   s   |   | jj¡ dS )zÓ
        L{StreamServerEndpointService.privilegedStartService} should behave the
        same as C{startService} with respect to
        L{EndpointServiceTests.test_synchronousRaiseRaisesSynchronously}.
        N)rD   r;   r=   r    r   r   r   Útest_synchronousRaisePrivileged½   s    z4EndpointServiceTests.test_synchronousRaisePrivilegedc                 C   s8   | j  ¡  | jj tƒ ¡ |  t¡}|  t|ƒd¡ dS )a  
        L{StreamServerEndpointService.startService} and
        L{StreamServerEndpointService.privilegedStartService} should both log
        an exception when the L{Deferred} returned from their wrapped
        L{IStreamServerEndpoint.listen} fails.
        r#   N)	r;   rC   r:   r+   r$   r@   ÚflushLoggedErrorsÚassertEqualÚlen©r!   Zloggedr   r   r   Útest_failReportsErrorÅ   s    

z*EndpointServiceTests.test_failReportsErrorc                 C   s@   d| j _| j  ¡  | jj tƒ ¡ |  t¡}|  t	|ƒd¡ dS )aB  
        L{StreamServerEndpointService.startService} and
        L{StreamServerEndpointService.privilegedStartService} should both log
        an exception when the L{Deferred} returned from their wrapped
        L{IStreamServerEndpoint.listen} fails asynchronously, even if
        C{_raiseSynchronously} is set.
        Tr#   N)
r;   rA   rC   r:   r+   r$   r@   rF   rG   rH   rI   r   r   r   Ú!test_asynchronousFailReportsErrorÑ   s
    

z6EndpointServiceTests.test_asynchronousFailReportsErrorc                 C   s2   t ƒ | j_| j ¡  |  t ¡}|  t|ƒd¡ dS )zŸ
        Without the C{_raiseSynchronously} compatibility flag, failing
        immediately has the same behavior as failing later; it logs the error.
        r#   N)r@   r:   r,   r;   rC   rF   rG   rH   rI   r   r   r   Ú test_synchronousFailReportsErrorß   s    


z5EndpointServiceTests.test_synchronousFailReportsErrorc                 C   s0   | j  ¡  |  | j| jj¡ |  | j jd¡ dS )zÃ
        L{StreamServerEndpointService.startService} sets the C{running} flag,
        and calls its endpoint's C{listen} method with its factory, if it
        has not yet been started.
        TN)r;   rC   r>   r*   r:   rG   Úrunningr    r   r   r   Útest_startServiceUnstartedé   s    
z/EndpointServiceTests.test_startServiceUnstartedc                 C   s6   |   ¡  | j ¡  |  | jjd¡ |  | jjd¡ dS )zš
        L{StreamServerEndpointService.startService} sets the C{running} flag,
        but nothing else, if the service has already been started.
        r#   TN)r?   r;   rC   rG   r:   r)   rM   r    r   r   r   Útest_startServiceStartedó   s    
z-EndpointServiceTests.test_startServiceStartedc                 C   st   | j  ¡  | j ¡  | j  ¡  | j  ¡ }g }| |j¡ |  t	|ƒd¡ | j 
¡  |  t	|ƒd¡ |  | j j¡ dS )zã
        L{StreamServerEndpointService.stopService} calls C{stopListening} on
        the L{IListeningPort} returned from its endpoint, returns the
        C{Deferred} from stopService, and sets C{running} to C{False}.
        r   r#   N)r;   r=   r:   r/   rC   ÚstopServiceÚaddCallbackÚappendrG   rH   r1   ZassertFalserM   ©r!   r+   Úlr   r   r   Útest_stopServiceý   s    




z%EndpointServiceTests.test_stopServicec                 C   sH   | j  ¡  | j  ¡ }g }| |j¡ |  |dg¡ |  |  t¡g ¡ dS )zÚ
        L{StreamServerEndpointService.stopService} cancels the L{Deferred}
        returned by C{listen} if it has not yet fired.  No error will be logged
        about the cancellation of the listen attempt.
        N)r;   r=   rP   ZaddBothrR   rG   rF   r	   rS   r   r   r   Ú#test_stopServiceBeforeStartFinished  s    

z8EndpointServiceTests.test_stopServiceBeforeStartFinishedc                 C   sZ   t ƒ | j_| j ¡  | j ¡ }g }| |j¡ |  |dg¡ |  	t ¡}|  t
|ƒd¡ dS )zá
        L{StreamServerEndpointService.stopService} cancels the L{Deferred}
        returned by C{listen} if it has not fired yet.  An error will be logged
        if the resulting exception is not L{CancelledError}.
        Nr#   )r@   r:   r%   r;   r=   rP   rQ   rR   rG   rF   rH   )r!   r+   rT   ZstoppingErrorsr   r   r   Ú test_stopServiceCancelStartError  s    



z5EndpointServiceTests.test_stopServiceCancelStartError)N)r2   r3   r4   r5   r<   r?   rD   rE   rJ   rK   rL   rN   rO   rU   rV   rW   r   r   r   r   r9   “   s   	



r9   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d„ Z
dd„ Zdd„ Zdd„ ZdS )ÚTimerServiceTestsa)  
    Tests for L{twisted.application.internet.TimerService}.

    @type timer: L{TimerService}
    @ivar timer: service to test

    @type clock: L{task.Clock}
    @ivar clock: source of time

    @type deferred: L{Deferred}
    @ivar deferred: deferred returned by L{TimerServiceTests.call}.
    c                 C   s,   t d| jƒ| _t ¡  | _| j_tƒ | _dS )z1
        Set up a timer service to test.
        é   N)r   ÚcallÚtimerr   r   Úclockr
   r0   r    r   r   r   r<   :  s    zTimerServiceTests.setUpc                 C   s   | j S )z‚
        Function called by L{TimerService} being tested.

        @returns: C{self.deferred}
        @rtype: L{Deferred}
        )r0   r    r   r   r   rZ   B  s    zTimerServiceTests.callc                 C   sV   | j  ¡  |  | j jd¡ |  | j jtj¡ |  | j	| j jj	¡ |  | j jjd¡ dS )z�
        When L{TimerService.startService} is called, it marks itself
        as running, creates a L{task.LoopingCall} and starts it.
        zService is startedzLoopingCall is startedN)
r[   rC   Ú
assertTruerM   ÚassertIsInstanceÚ_loopr   ZLoopingCallr>   r\   r    r   r   r   Útest_startServiceK  s
    
z#TimerServiceTests.test_startServicec                 C   s0   g }|j di f| j_| j ¡  |  dg|¡ dS )zi
        When L{TimerService.startService} is called, it calls the function
        immediately.
        r   N)rR   r[   rZ   rC   rG   )r!   r+   r   r   r   Ú$test_startServiceRunsCallImmediatelyV  s    
z6TimerServiceTests.test_startServiceRunsCallImmediatelyc                    sB   t  ¡ ‰ ‡ fdd„}|  td|¡ | j ¡  |  ˆ | jjj¡ dS )z±
        L{TimerService.startService} uses L{internet._maybeGlobalReactor} to
        choose the reactor to pass to L{task.LoopingCall}
        uses the global reactor.
        c                    s   ˆ S r   r   )ZmaybeReactor©Z
otherClockr   r   ÚgetOtherClockh  s    zKTimerServiceTests.test_startServiceUsesGlobalReactor.<locals>.getOtherClockZ_maybeGlobalReactorN)	r   r   Úpatchr   r[   rC   r>   r_   r\   )r!   rc   r   rb   r   Ú"test_startServiceUsesGlobalReactor`  s
    
z4TimerServiceTests.test_startServiceUsesGlobalReactorc                 C   sR   | j  ¡  | j  ¡ }|  |¡ |  d| j j¡ | j tƒ ¡ |  	|  
|¡d¡ dS )z¦
        When L{TimerService.stopService} is called while a call is in progress.
        the L{Deferred} returned doesn't fire until after the call finishes.
        TN)r[   rC   rP   ÚassertNoResultrG   rM   r0   r.   Úobjectr>   ÚsuccessResultOf©r!   r&   r   r   r   Útest_stopServiceWaitso  s    


z'TimerServiceTests.test_stopServiceWaitsc                 C   s8   | j  ¡  | j tƒ ¡ | j  ¡ }|  |  |¡d¡ dS )z•
        When L{TimerService.stopService} is called while a call isn't in progress.
        the L{Deferred} returned has already been fired.
        N)r[   rC   r0   r.   rg   rP   r>   rh   ri   r   r   r   Útest_stopServiceImmediately{  s    

z-TimerServiceTests.test_stopServiceImmediatelyc                 C   sV   | j  ¡  | j ttƒ ƒ¡ |  t¡}|  dt|ƒ¡ | j  	¡ }|  
|  |¡d¡ dS )z´
        When function passed to L{TimerService} returns a deferred that errbacks,
        the exception is logged, and L{TimerService.stopService} doesn't raise an error.
        r#   N)r[   rC   r0   r$   r   r@   rF   rG   rH   rP   r>   rh   )r!   Úerrorsr&   r   r   r   Útest_failedCallLogsError…  s    


z*TimerServiceTests.test_failedCallLogsErrorc                 C   sP   t dtƒ}| ¡  t |¡}| ¡  t |¡}tƒ }t|d|ƒ}|  	||¡ dS )zq
        When pickling L{internet.TimerService}, it won't pickle
        L{internet.TimerService._loop}.
        r#   r_   N©
r   r   rC   ÚpickleÚdumpsrP   Úloadsrg   Úgetattrr>   ©r!   r[   ZdumpedTimerZloadedTimerZnothingÚvaluer   r   r   Ú$test_pickleTimerServiceNotPickleLoop‘  s    


z6TimerServiceTests.test_pickleTimerServiceNotPickleLoopc                 C   sP   t dtƒ}| ¡  t |¡}| ¡  t |¡}tƒ }t|d|ƒ}|  	||¡ dS )zy
        When pickling L{internet.TimerService}, it won't pickle
        L{internet.TimerService._loopFinished}.
        r#   Z_loopFinishedNrn   rs   r   r   r   Ú,test_pickleTimerServiceNotPickleLoopFinished¡  s    


z>TimerServiceTests.test_pickleTimerServiceNotPickleLoopFinishedN)r2   r3   r4   r5   r<   rZ   r`   ra   re   rj   rk   rm   ru   rv   r   r   r   r   rX   ,  s   	

rX   c                   @   s   e Zd ZdZdd„ ZdS )ÚConnectInformationaË  
    Information about C{endpointForTesting}

    @ivar connectQueue: a L{list} of L{Deferred} returned from C{connect}.  If
        these are not already fired, you can fire them with no value and they
        will trigger building a factory.

    @ivar constructedProtocols: a L{list} of protocols constructed.

    @ivar passedFactories: a L{list} of L{IProtocolFactory}; the ones actually
        passed to the underlying endpoint / i.e. the reactor.
    c                 C   s   g | _ g | _g | _d S r   )ÚconnectQueueÚconstructedProtocolsÚpassedFactoriesr    r   r   r   r"   À  s    zConnectInformation.__init__N)r2   r3   r4   r5   r"   r   r   r   r   rw   ²  s   rw   Fc                    s,   t tƒG ‡ ‡fdd„dƒƒ}tƒ ‰ˆ|ƒ fS )aD  
    Make a sample endpoint for testing.

    @param fireImmediately: If true, fire all L{Deferred}s returned from
        C{connect} immedaitely.

    @return: a 2-tuple of C{(information, endpoint)}, where C{information} is a
        L{ConnectInformation} describing the operations in progress on
        C{endpoint}.
    c                       s   e Zd Z‡ ‡fdd„ZdS )z.endpointForTesting.<locals>.ClientTestEndpointc                    sD   t ƒ }ˆj ˆ ¡ |j‡ ‡fdd„ƒ}ˆj |¡ ˆr@| d ¡ |S )Nc                    s*   ˆ   d ¡}ˆj |¡ tƒ }| |¡ |S r   )ÚbuildProtocolry   rR   r   ZmakeConnection)ÚignoredÚprotocolÚ	transport)r*   Úinfor   r   ÚcreateProtocolØ  s
    

zNendpointForTesting.<locals>.ClientTestEndpoint.connect.<locals>.createProtocol)r
   rz   rR   rQ   rx   r.   )r!   r*   r+   r€   ©ÚfireImmediatelyr   )r*   r   ÚconnectÔ  s    
z6endpointForTesting.<locals>.ClientTestEndpoint.connectN)r2   r3   r4   rƒ   r   r�   r   r   ÚClientTestEndpointÒ  s   r„   )r   r   rw   )r‚   r„   r   r�   r   ÚendpointForTestingÆ  s    r…   c                    s0   g ‰ˆ   ˆj¡ |  ‡ ‡fdd„¡ ‡fdd„S )a6  
    Catch the global log stream.

    @param testCase: The test case to add a cleanup to.

    @param logPublisher: the log publisher to add and remove observers for.

    @return: a 0-argument callable that returns a list of textual log messages
        for comparison.
    @rtype: L{list} of L{unicode}
    c                      s   ˆ   ˆj¡S r   )ZremoveObserverrR   r   ©ÚlogPublisherÚlogsr   r   r'   ÷  r(   zcatchLogs.<locals>.<lambda>c                      s   dd„ ˆ D ƒS )Nc                 S   s   g | ]}t |ƒ‘qS r   )r   )Ú.0Úeventr   r   r   Ú
<listcomp>ø  s     z/catchLogs.<locals>.<lambda>.<locals>.<listcomp>r   r   )rˆ   r   r   r'   ø  r(   )ZaddObserverrR   Ú
addCleanup)ZtestCaser‡   r   r†   r   Ú	catchLogsé  s    r�   g      Y@c                   @   s   e Zd ZdZddedfdd„Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zddœd d!„Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.d/„ Zd0d1„ Zd2d3„ Zd4d5„ Zd6d7„ Zd8d9„ Zd:d;„ Zd<d=„ Z d>d?„ Z!d@dA„ Z"dBdC„ Z#dDdE„ Z$dS )FÚClientServiceTestsz%
    Tests for L{ClientService}.
    TFc                    sœ   i }|j tƒ d� |  |¡ |d ‰t|d�\}}g  ‰ |_G ‡ ‡‡fdd„dtƒ}	|	ƒ  |_}
t||
f|Ž‰‡‡‡fdd„}ˆ |¡ |r”ˆ ¡  |ˆfS )aL  
        Create a L{ClientService} along with a L{ConnectInformation} indicating
        the connections in progress on its endpoint.

        @param fireImmediately: Should all of the endpoint connection attempts
            fire synchronously?
        @type fireImmediately: L{bool}

        @param startService: Should the L{ClientService} be started before
            being returned?
        @type startService: L{bool}

        @param protocolType: a 0-argument callable returning a new L{IProtocol}
            provider to be used for application-level protocol connections.

        @param kw: Arbitrary keyword arguments to be passed on to
            L{ClientService}

        @return: a 2-tuple of L{ConnectInformation} (for information about test
            state) and L{ClientService} (the system under test).  The
            L{ConnectInformation} has 2 additional attributes;
            C{applicationFactory} and C{applicationProtocols}, which refer to
            the unwrapped protocol factory and protocol instances passed in to
            L{ClientService} respectively.
        ©r\   r\   ©r‚   c                       s$   e Zd Z”Z‡ ‡‡fdd„Z‡  ZS )z>ClientServiceTests.makeReconnector.<locals>.RememberingFactoryc                    s"   ˆrd S t ƒ  |¡}ˆ |¡ |S r   )Úsuperr{   rR   )r!   Úaddrr+   )Ú	__class__ÚapplicationProtocolsÚrefuseConnectionsr   r   r{   5  s
    
zLClientServiceTests.makeReconnector.<locals>.RememberingFactory.buildProtocol)r2   r3   r4   r}   r{   Ú__classcell__r   )r”   ÚprotocolTyper•   )r“   r   ÚRememberingFactory2  s   r˜   c                      s(   d ˆ_ ˆjrˆ ¡  ˆ ˆ  ¡ g ¡ d S r   )Ú	_protocolrM   rP   rG   ÚgetDelayedCallsr   )r\   r!   Úservicer   r   Ústop@  s    z0ClientServiceTests.makeReconnector.<locals>.stop)	Úupdater   r…   r”   r   ÚapplicationFactoryr   rŒ   rC   )r!   r‚   rC   r—   r•   ÚkwZnkwÚcqZendpointr˜   r*   rœ   r   )r”   r\   r—   r•   r!   r›   r   ÚmakeReconnector  s    !



z"ClientServiceTests.makeReconnectorc                 C   s&   | j dd�\}}|  t|jƒd¡ dS )zL
        When the service is started, a connection attempt is made.
        Fr�   r#   N)r¡   rG   rH   rx   )r!   r    r›   r   r   r   r`   M  s    z$ClientServiceTests.test_startServicec                 C   sD   |   ¡ \}}|j}|  |jd¡ |jd }| ¡  |  |jd¡ dS )a!  
        Although somewhat obscure, L{IProtocolFactory} includes both C{doStart}
        and C{doStop} methods; ensure that when these methods are called on the
        factory that was passed to the reactor, the factory that was passed
        from the application receives them.
        r   r#   N)r¡   rž   rG   ZnumPortsrz   ZdoStart)r!   r    r›   ZfirstAppFactoryZfirstPassedFactoryr   r   r   Útest_startStopFactoryT  s    
z(ClientServiceTests.test_startStopFactoryc                 C   sV   |   ¡ \}}| ¡ }|  |¡ |jd }|  |jjd¡ | tt	ƒ ƒ¡ |  
|¡ dS )z¸
        When the service is stopped, no further connect attempts are made.  The
        returned L{Deferred} fires when all outstanding connections have been
        stopped.
        r   TN)r¡   rP   rf   ry   rG   r~   ÚdisconnectingÚconnectionLostr   Ú	Exceptionrh   ©r!   r    r›   r&   r}   r   r   r   Útest_stopServiceWhileConnectedb  s    

z1ClientServiceTests.test_stopServiceWhileConnectedc                 C   s„   |   ¡ \}}| ¡ }|  |¡ |jd }|  |jjd¡ | ¡  |  |¡ |  t|jƒd¡ | 	t
tdƒƒ¡ |  t|jƒd¡ dS )z—
        When L{ClientService} is restarted after having been connected, it
        waits to start connecting until after having disconnected.
        r   Tr#   zsynthetic connectionLostrY   N)r¡   rP   rf   ry   rG   r~   r£   rC   rH   r¤   r   r¥   r¦   r   r   r   Ú#test_startServiceWaitsForDisconnectp  s    


z6ClientServiceTests.test_startServiceWaitsForDisconnectc                 C   sæ   | j dd�\}}|jd  d¡ |jd }| ¡ }|  |¡ | ¡ }|  |¡ | ¡  |  |¡ |  |¡ |  |j	j
d¡ | ttdƒƒ¡ |  |¡ |jd  d¡ |  t|jƒd¡ |  |  |¡|jd ¡ | ¡ }|  |¡ dS )	a%  
        When L{ClientService} is stopping - that is,
        L{ClientService.stopService} has been called, but the L{Deferred} it
        returns has not fired yet - calling L{startService} will cause a new
        connection to be made, and new calls to L{whenConnected} to succeed.
        Fr�   r   NTzsynthetic connection lostr#   rY   )r¡   rx   r.   ry   rP   rf   ÚwhenConnectedrC   rG   r~   r£   r¤   r   r¥   rh   rH   r>   r”   )r!   r    r›   ÚfirstÚstoppedZnextProtocolZsecondStoppedr   r   r   Útest_startServiceWhileStopping€  s*    





 ÿz1ClientServiceTests.test_startServiceWhileStoppingc                 C   sj   | j dd�\}}| ¡ }|  |¡ |  | ¡ t¡ | ¡  |jd  d¡ |  	|j
d |  | ¡ ¡¡ dS )a  
        When L{ClientService} is stopped - that is,
        L{ClientService.stopService} has been called and the L{Deferred} it
        returns has fired - calling L{startService} will cause a new connection
        to be made, and new calls to L{whenConnected} to succeed.
        Fr�   éÿÿÿÿN)r¡   rP   rh   ÚfailureResultOfr©   r	   rC   rx   r.   r>   r”   )r!   r    r›   r«   r   r   r   Útest_startServiceWhileStoppedœ  s    
 ÿz0ClientServiceTests.test_startServiceWhileStoppedc                 C   sX   t ttƒG dd„ dtƒƒ}| j|d�\}}|jd }|  t |¡¡ |  t |¡¡ dS )aC  
        If the protocol objects returned by the factory given to
        L{ClientService} provide special "marker" interfaces for their
        transport - L{IHalfCloseableProtocol} or L{IFileDescriptorReceiver} -
        those interfaces will be provided by the protocol objects passed on to
        the reactor.
        c                   @   s   e Zd ZdZdS )zEClientServiceTests.test_interfacesForTransport.<locals>.FancyProtocolz9
            Provider of various interfaces.
            N)r2   r3   r4   r5   r   r   r   r   ÚFancyProtocol¶  s   r°   )r—   r   N)r   r   r   r   r¡   ry   r]   Z
providedBy)r!   r°   r    r›   ZreactorFacingr   r   r   Útest_interfacesForTransport­  s    	
z.ClientServiceTests.test_interfacesForTransportc                 C   sn   t ƒ }| jd|d�\}}|jd  tƒ ¡ | t¡ |  t|jƒd¡ | 	¡ }|jd  tƒ ¡ |  
|¡ dS )zU
        When the service is stopped while retrying, the retry is cancelled.
        F©r‚   r\   r   rY   r#   N)r   r¡   rx   r$   r¥   ÚadvanceÚAT_LEAST_ONE_ATTEMPTrG   rH   rP   rh   ©r!   r\   r    r›   r&   r   r   r   Útest_stopServiceWhileRetryingÁ  s    
z0ClientServiceTests.test_stopServiceWhileRetryingc                 C   sP   t ƒ }| jd|d�\}}|  t|jƒd¡ |  |jd ¡ | ¡ }|  |¡ dS )zv
        When the service is stopped while initially connecting, the connection
        attempt is cancelled.
        Fr²   r#   r   N)r   r¡   rG   rH   rx   rf   rP   rh   rµ   r   r   r   Útest_stopServiceWhileConnectingÎ  s    z2ClientServiceTests.test_stopServiceWhileConnectingc                 C   sš   t ƒ }| j|d�\}}| ¡ }|  | ¡ g ¡ |  |  |¡|jd ¡ |  |jd j	|jd ¡ |  
t|jd ƒt|jd ƒ¡ |  
dt|jd ƒ¡ dS )zy
        When a client connects, the service keeps a reference to the new
        protocol and resets the delay.
        r�   r   r˜   N)r   r¡   r©   rG   rš   r>   rh   r”   ry   r™   ÚassertInÚstrrz   )r!   r\   r    r›   ZawaitingProtocolr   r   r   Útest_clientConnectedÚ  s(     ÿ
 ÿþþz'ClientServiceTests.test_clientConnectedc                 C   s€   t ƒ }| jd|d�\}}|  t|jƒd¡ |jd  ttƒ ƒ¡ | ¡ }|  	|¡ | 
dd„ ¡ | t¡ |  t|jƒd¡ dS )	zŒ
        When a client connection fails, the service removes its reference
        to the protocol and tries again after a timeout.
        Fr²   r#   r   c                 S   s
   |   t¡S r   )Ztrapr	   )r|   r   r   r   r'   ÿ  r(   z@ClientServiceTests.test_clientConnectionFailed.<locals>.<lambda>rY   N)r   r¡   rG   rH   rx   r$   r   r¥   r©   rf   Z
addErrbackr³   r´   )r!   r\   r    r›   r©   r   r   r   Útest_clientConnectionFailedò  s    

z.ClientServiceTests.test_clientConnectionFailedc                 C   sÊ   t ƒ }| j|dd�\}}|  t|jƒd¡ |jd  d¡ |  t|jƒd¡ |  |  | ¡ ¡|j	d ¡ |j
d  ttƒ ƒ¡ | t¡ |  t|jƒd¡ |jd  d¡ |  |  | ¡ ¡|j	d ¡ dS )z~
        When a client connection is lost, the service removes its reference
        to the protocol and calls retry.
        F)r\   r‚   r#   r   NrY   )r   r¡   rG   rH   rx   r.   r>   rh   r©   r”   ry   r¤   r   r¥   r³   r´   ©r!   r\   r    r›   r   r   r   Útest_clientConnectionLost  s"     ÿ
 ÿz,ClientServiceTests.test_clientConnectionLostN)Úreturnc                    s²   t ƒ }ˆ  ‡ ‡fdd„¡ ˆ j|ddd�\}}ˆ  t|jƒd¡ |j d¡ d¡ ˆ  t|jƒd¡ | ¡ ‰ˆ  	ˆ¡ | 
t¡ ˆ  t|jƒd¡ |j d¡ d¡ ˆ  	ˆ¡ dS )	z™
        When the client factory refuses connections by returning None from
        buildProtocol, the factory keeps attempting new connections.
        c                      s   ˆ   ˆt¡S r   )r®   r	   r   ©r!   r©   r   r   r'   "  r(   zAClientServiceTests.test_clientConnectionRefused.<locals>.<lambda>FT)r\   r‚   r•   r#   r   N)r   rŒ   r¡   rG   rH   rx   Úpopr.   r©   rf   r³   r´   r¼   r   r¿   r   Útest_clientConnectionRefused  s     ü


z/ClientServiceTests.test_clientConnectionRefusedc                 C   sT   t ƒ }| j|d�\}}| ¡ }|jd  ttƒ ƒ¡ |  | ¡ t	¡ |  
|j¡ dS )z¸
        When a client connection is lost while the service is stopping, the
        protocol stopping deferred is called and the reference to the protocol
        is removed.
        r�   r   N)r   r¡   rP   ry   r¤   r   ÚIndentationErrorr®   r©   r	   r]   Úcalledrµ   r   r   r   Ú&test_clientConnectionLostWhileStopping>  s    z9ClientServiceTests.test_clientConnectionLostWhileStoppingc                 C   sv   | j ddd�\}}|  t|jƒd¡ | ¡  |  t|jƒd¡ t| ƒ}| ¡  |  t|jƒd¡ |  d|ƒ d ¡ dS )zÀ
        If L{ClientService} is started when it's already started, it will log a
        complaint and do nothing else (in particular it will not make
        additional connections).
        F)r‚   rC   r   r#   z$Duplicate ClientService.startServiceN)r¡   rG   rH   rx   rC   r�   r¸   )r!   r    r›   Úmessagesr   r   r   Útest_startTwiceK  s    z"ClientServiceTests.test_startTwicec           
      C   s®   t ƒ }| jd|d�\}}| ¡ }| ¡ }|jdd�}|  |¡ |  |¡ |  |¡ |jd  d¡ |  |¡}|  |¡}|  |¡}	|  ||¡ |  ||	¡ |  ||jd ¡ dS )z{
        L{ClientService.whenConnected} returns a L{Deferred} that fires when a
        connection is established.
        Fr²   r#   ©ZfailAfterFailuresr   N)	r   r¡   r©   rf   rx   r.   rh   r>   r”   )
r!   r\   r    r›   ÚaÚbÚcZresultAZresultBZresultCr   r   r   Útest_whenConnectedLaterZ  s    





z*ClientServiceTests.test_whenConnectedLaterc                 C   sÐ  t ƒ }| jd|d�\}}| ¡ }|jdd�}|jdd�}|jdd�}|  |¡ |  |¡ |  |¡ |  |¡ ttƒ ƒ}|jd  |¡ |  |¡ |  |  	|t¡|¡ |  |¡ |  |¡ | 
t¡ |  t|jƒd¡ |  |¡ |  |¡ |  |¡ ttƒ ƒ}	|jd  |	¡ |  |¡ |  |  	|t¡|	¡ |  |¡ t}
| 
|
¡ |  t|jƒd¡ |  |¡ |  |¡ |jd  d¡ |  |¡}|  |¡}|  ||¡ |  ||jd ¡ |jdd�}|  |¡}|  ||¡ dS )	z‘
        L{ClientService.whenConnected} returns a L{Deferred} that fails, if
        asked, when some number of connections have failed.
        Fr²   r#   rÇ   rY   é   r   N)r   r¡   r©   rf   r   r¥   rx   r$   r>   r®   r³   r´   rG   rH   r.   rh   r”   )r!   r\   r    r›   Za0Za1Za2Úa3Úf1Úf2ZAT_LEAST_TWO_ATTEMPTSZresultA0ZresultA3Za4ZresultA4r   r   r   Útest_whenConnectedFailso  sN    




















z*ClientServiceTests.test_whenConnectedFailsc                 C   sŒ   t ƒ }| jd|d�\}}| ¡ }| ¡ }|jdd�}|  |¡ |  |¡ |  |¡ | ¡  | t¡ |  |t¡ |  |t¡ |  |t¡ dS )z†
        L{ClientService.whenConnected} returns a L{Deferred} that fails when
        L{ClientService.stopService} is called.
        Fr²   r#   rÇ   N)	r   r¡   r©   rf   rP   r³   r´   r®   r	   )r!   r\   r    r›   rÈ   rÉ   rÊ   r   r   r   Útest_whenConnectedStopService©  s    



z0ClientServiceTests.test_whenConnectedStopServicec                 C   sT   t ƒ }| jd|d�\}}|j d¡ tdƒ¡ | ¡ }|  | ¡ g ¡ |  	|¡ dS )zÎ
        When L{ClientService.stopService} is called while waiting between
        connection attempts, the pending reconnection attempt is cancelled and
        the service is stopped immediately.
        Fr²   r   úno connectionN)
r   r¡   rx   rÀ   r$   r¥   rP   rG   rš   rh   rµ   r   r   r   Útest_retryCancelled¼  s    z&ClientServiceTests.test_retryCancelledc                 C   s6   t ƒ }| jdd|d�\}}| ¡ }|  |  |¡¡ dS )z¦
        Calling L{ClientService.stopService} before
        L{ClientService.startService} returns a L{Deferred} that has
        already fired with L{None}.
        F)r‚   rC   r\   N©r   r¡   rP   ZassertIsNonerh   )r!   r\   Ú_r›   r&   r   r   r   Ú"test_stopServiceBeforeStartServiceÉ  s      ÿ
z5ClientServiceTests.test_stopServiceBeforeStartServicec                 C   sp   t ƒ }| jd|d�\}}| ¡ }|jd  tdƒ¡ | ¡  | ¡ }|  |  |¡j	t
¡ |  |  |¡j	t
¡ dS )zÊ
        L{ClientService.whenConnected} returns a L{Deferred} that
        errbacks with L{CancelledError} if
        L{ClientService.stopService} is called between connection
        attempts.
        Fr²   r   rÒ   N)r   r¡   r©   rx   r$   r¥   rP   r^   r®   rt   r	   )r!   r\   r    r›   ZbeforeErrbackAndStopZafterErrbackAndStopr   r   r   Ú'test_whenConnectedErrbacksOnStopServiceÖ  s    
 ÿ
 ÿz:ClientServiceTests.test_whenConnectedErrbacksOnStopServicec                 C   sf   t ƒ }| jd|d�\}}|jd  d¡ | ¡ }| ¡ }|jd  ttƒ ƒ¡ |  	|¡ |  	|¡ dS )zí
        Calling L{ClientService.stopService} twice after it has
        connected (that is, stopping it while it is disconnecting)
        returns a L{Deferred} each time that fires when the
        disconnection has completed.
        Fr²   r   N)
r   r¡   rx   r.   rP   ry   r¤   r   rÂ   rh   ©r!   r\   r    r›   ÚfirstStopDeferredÚsecondStopDeferredr   r   r   Ú"test_stopServiceWhileDisconnectingï  s    
z5ClientServiceTests.test_stopServiceWhileDisconnectingc                 C   sn   t ƒ }| jd|d�\}}|jd  d¡ | ¡ }| ¡  | ¡ }|jd  tt	ƒ ƒ¡ |  
|¡ |  
|¡ dS )z²
        Calling L{ClientService.stopService} after calling a
        reconnection attempt returns a L{Deferred} that fires when the
        disconnection has completed.
        Fr²   r   N)r   r¡   rx   r.   rP   rC   ry   r¤   r   rÂ   rh   rØ   r   r   r   Útest_stopServiceWhileRestarting  s    
z2ClientServiceTests.test_stopServiceWhileRestartingc                 C   sL   t ƒ }| jd|d�\}}| ¡ }| ¡ }|  |  |¡¡ |  |  |¡¡ dS )zŽ
        Calling L{ClientService.stopService} on a stopped service
        returns a L{Deferred} that has already fired with L{None}.
        Fr²   NrÔ   )r!   r\   rÕ   r›   rÙ   rÚ   r   r   r   Ú test_stopServiceOnStoppedService  s    z3ClientServiceTests.test_stopServiceOnStoppedServicec                    s8   dg‰ ‡ fdd„}| j |dd�\}}|  dˆ d ¡ dS )z†
        The C{prepareConnection} callable is called after
        L{ClientService.startService} once the connection is made.
        r   c                    s   ˆ d  d7  < d S ©Nr   r#   r   ©Z_proto©Zpreparesr   r   ÚprepareConnection2  s    z[ClientServiceTests.test_prepareConnectionCalledWhenServiceStarts.<locals>.prepareConnectionT)rá   rC   r#   N)r¡   rG   ©r!   rá   r    r›   r   rà   r   Ú-test_prepareConnectionCalledWhenServiceStarts+  s     ÿ
z@ClientServiceTests.test_prepareConnectionCalledWhenServiceStartsc                    s:   g ‰ ‡ fdd„}| j |d�\}}|  |jd ˆ d ¡ dS )zf
        The C{prepareConnection} callable is passed the connected protocol
        instance.
        c                    s   ˆ   | ¡ d S r   ©rR   ©Úproto©ÚnewProtocolsr   r   rá   A  s    zVClientServiceTests.test_prepareConnectionCalledWithProtocol.<locals>.prepareConnection©rá   r   N)r¡   r>   ry   râ   r   rç   r   Ú(test_prepareConnectionCalledWithProtocol:  s    ÿ
z;ClientServiceTests.test_prepareConnectionCalledWithProtocolc                    s~   dg‰ ‡ fdd„}t ƒ }| j|d|d�\}}|jd  tdƒ¡ |  dˆ d ¡ | t¡ |jd  d¡ |  dˆ d ¡ dS )	zf
        The C{prepareConnection} callback is invoked only once a connection is
        made.
        r   c                    s   ˆ d  d7  < d S rÞ   r   rß   rà   r   r   rá   P  s    z]ClientServiceTests.test_prepareConnectionCalledAfterConnectionMade.<locals>.prepareConnectionF)rá   r‚   r\   zconnection attempt failedr#   N)	r   r¡   rx   r$   r¥   rG   r³   r´   r.   ©r!   rá   r\   r    r›   r   rà   r   Ú/test_prepareConnectionCalledAfterConnectionMadeI  s      ÿ

zBClientServiceTests.test_prepareConnectionCalledAfterConnectionMadec                    sn   dg‰ ‡ fdd„}t ƒ }| j||d�\}}|  dˆ d ¡ |jd  ttƒ ƒ¡ | t¡ |  dˆ d ¡ dS )z�
        The C{prepareConnection} callback is invoked each time a connection is
        made, including on reconnection.
        r   c                    s   ˆ d  d7  < d S rÞ   r   rß   rà   r   r   rá   g  s    zUClientServiceTests.test_prepareConnectionCalledOnReconnect.<locals>.prepareConnection©rá   r\   r#   rY   N)	r   r¡   rG   ry   r¤   r   rÂ   r³   r´   rë   r   rà   r   Ú'test_prepareConnectionCalledOnReconnect`  s     ÿ

z:ClientServiceTests.test_prepareConnectionCalledOnReconnectc                    s@   t ƒ ‰ ‡ fdd„}| j|d�\}}|  | ¡ ¡}|  ˆ |¡ dS )a?  
        The C{prepareConnection} return value is ignored when it does not
        indicate a failure. Even though the callback participates in the
        internal new-connection L{Deferred} chain for error propagation
        purposes, any successful result does not affect the ultimate return
        value.
        c                    s   ˆ S r   r   rå   ©Úsentinelr   r   rá   ‚  s    zVClientServiceTests.test_prepareConnectionReturnValueIgnored.<locals>.prepareConnectionré   N)rg   r¡   rh   r©   ZassertNotIdentical)r!   rá   r    r›   r+   r   rï   r   Ú(test_prepareConnectionReturnValueIgnoredw  s
    	z;ClientServiceTests.test_prepareConnectionReturnValueIgnoredc                    s`   g ‰t ƒ ‰ ‡ ‡fdd„}| j|d�\}}| ¡ }|  |¡ ˆ  d¡ |  |jd |  |¡¡ dS )z�
        The C{prepareConnection} callable returns a deferred and calls to
        L{ClientService.whenConnected} wait until it fires.
        c                    s   ˆ  | ¡ ˆ S r   rä   rå   ©ZnewProtocolDeferredrè   r   r   rá   ’  s    
zVClientServiceTests.test_prepareConnectionReturningADeferred.<locals>.prepareConnectionré   Nr   )r
   r¡   r©   rf   r.   r>   r”   rh   )r!   rá   r    r›   ÚwhenConnectedDeferredr   rò   r   Ú(test_prepareConnectionReturningADeferredŠ  s    

 ÿz;ClientServiceTests.test_prepareConnectionReturningADeferredc                 C   sl   t ƒ }dd„ }| j||d�\}}|jdd�}|  |¡ | t¡ |  |¡ | t¡ |  t|  |¡j	¡ dS )zs
        The connection attempt counts as a failure when the
        C{prepareConnection} callable throws.
        c                 S   s
   t ƒ ‚d S r   )rÂ   rß   r   r   r   rá   ¨  s    zJClientServiceTests.test_prepareConnectionThrows.<locals>.prepareConnectionrí   rY   rÇ   N)
r   r¡   r©   rf   r³   r´   r>   rÂ   r®   Útype)r!   r\   rá   r    r›   ró   r   r   r   Útest_prepareConnectionThrows¡  s     ÿ




 
ÿz/ClientServiceTests.test_prepareConnectionThrows)%r2   r3   r4   r5   r   r¡   r`   r¢   r§   r¨   r¬   r¯   r±   r¶   r·   rº   r»   r½   rÁ   rÄ   rÆ   rË   rÐ   rÑ   rÓ   rÖ   r×   rÛ   rÜ   rÝ   rã   rê   rì   rî   rñ   rô   rö   r   r   r   r   rŽ   þ  sJ   û
J&:rŽ   )F)0r5   ro   Zzope.interfacer   Zzope.interface.verifyr   Ztwisted.applicationr   Ztwisted.application.internetr   r   r   Ztwisted.internetr   Ztwisted.internet.deferr	   r
   Ztwisted.internet.interfacesr   r   r   r   r   Ztwisted.internet.protocolr   r   Ztwisted.internet.taskr   Ztwisted.internet.testingr   Ztwisted.loggerr   r   Ztwisted.python.failurer   Ztwisted.trial.unittestr   r   r   r   r   r9   rX   rw   r…   r�   r´   rŽ   r   r   r   r   Ú<module>   s<   @

  
#