U
    
W[d¥  ã                   @   sŠ  d Z ddlmZm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mZ dd	lmZ dd
lmZmZ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! ddl"m#Z# ddl$m%Z%m&Z& ddl'm(Z( dd„ Z)eeƒG dd„ de*ƒƒZ+eee+ƒ eeƒG dd„ de*ƒƒZ,eee+ƒ G dd„ deƒZ-G dd„ deƒZ.G dd„ de*ƒZ/d%dd„Z0e%fd d!„Z1d"Z2G d#d$„ d$eƒZ3d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.
é    )Úabsolute_importÚdivisionN)Úimplementer)ÚverifyClass)ÚFactoryÚProtocol)ÚClock)ÚTestCaseÚSynchronousTestCase)Úinternet)ÚStreamServerEndpointServiceÚTimerServiceÚClientService)ÚDeferredÚCancelledError)ÚIStreamServerEndpointÚIStreamClientEndpointÚIListeningPortÚIHalfCloseableProtocolÚIFileDescriptorReceiver)Útask)ÚFailure)ÚglobalLogPublisherÚformatEvent)ÚStringTransportc                   C   s   dS )zM
    A fake target function for testing TimerService which does nothing.
    N© r   r   r   úH/usr/lib/python3/dist-packages/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__G   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>W   ó    z#FakeServer.listen.<locals>.<lambda>)Z	cancellerN)ÚlistenAttemptsÚfactoryr   ÚresultÚfailImmediatelyr&   )r#   r,   r   r"   r   ÚlistenK   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!   Údeferredr0   r"   r   r   r   ÚstoppedListeningf   s    zFakeServer.stoppedListening)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r-   r,   r.   r   r'   r+   r$   r/   r1   r3   r   r   r   r   r   ,   s   	r   c                   @   s   e Zd ZdZ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   r2   r"   r   r   r   ÚstopListening|   s    zFakePort.stopListening)r4   r5   r6   r7   r2   r8   r   r   r   r   r    s   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;   Ú_raiseSynchronouslyZ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)rC   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;   rB   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   rB   r:   r-   r&   r@   rE   rF   rG   rH   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;   rB   rE   rF   rG   rH   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;   rB   r>   r,   r:   rF   Ú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;   rB   rF   r:   r+   rL   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:   r1   rB   ÚstopServiceÚaddCallbackÚappendrF   rG   r3   ZassertFalserL   ©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=   rO   ZaddBothrQ   rF   rE   r   rR   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=   rO   rP   rQ   rF   rE   rG   )r#   r-   rS   ZstoppingErrorsr   r   r   Ú test_stopServiceCancelStartError  s    



z5EndpointServiceTests.test_stopServiceCancelStartError)N)r4   r5   r6   r7   r<   r?   rC   rD   rI   rJ   rK   rM   rN   rT   rU   rV   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   r2   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}
        )r2   r"   r   r   r   rY   F  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)
rZ   rB   Ú
assertTruerL   ÚassertIsInstanceÚ_loopr   ZLoopingCallr>   r[   r"   r   r   r   Útest_startServiceP  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)rQ   rZ   rY   rB   rF   )r#   r-   r   r   r   Ú$test_startServiceRunsCallImmediately\  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   ÚgetOtherClockn  s    zKTimerServiceTests.test_startServiceUsesGlobalReactor.<locals>.getOtherClockZ_maybeGlobalReactorN)	r   r   Zpatchr   rZ   rB   r>   r^   r[   )r#   rb   r   ra   r   Ú"test_startServiceUsesGlobalReactorg  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)rZ   rB   rO   ÚassertNoResultrF   rL   r2   r0   Úobjectr>   ÚsuccessResultOf©r#   r(   r   r   r   Útest_stopServiceWaitsu  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)rZ   rB   r2   r0   re   rO   r>   rf   rg   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)rZ   rB   r2   r&   r   r@   rE   rF   rG   rO   r>   rf   )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   rB   ÚpickleÚdumpsrO   Úloadsre   Úgetattrr>   ©r#   rZ   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_loopFinishedNrl   rq   r   r   r   Ú,test_pickleTimerServiceNotPickleLoopFinished«  s    


z>TimerServiceTests.test_pickleTimerServiceNotPickleLoopFinishedN)r4   r5   r6   r7   r<   rY   r_   r`   rc   rh   ri   rk   rs   rt   r   r   r   r   rW   /  s   	
rW   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)r4   r5   r6   r7   r$   r   r   r   r   ru   ½  s   ru   Fc                    s.   t tƒG ‡ ‡fdd„dtƒƒ}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   )ÚbuildProtocolrw   rQ   r   ZmakeConnection)ÚignoredÚprotocolÚ	transport)r,   Úinfor   r   ÚcreateProtocolá  s
    

zNendpointForTesting.<locals>.ClientTestEndpoint.connect.<locals>.createProtocol)r   rx   rQ   rP   rv   r0   )r#   r,   r-   r~   ©ÚfireImmediatelyr}   )r,   r   ÚconnectÞ  s    
z6endpointForTesting.<locals>.ClientTestEndpoint.connectN)r4   r5   r6   r   r   r   r   r   ÚClientTestEndpointÜ  s   r‚   )r   r   re   ru   )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removeObserverrQ   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   )Ú.0Zeventr   r   r   Ú
<listcomp>   s     z/catchLogs.<locals>.<lambda>.<locals>.<listcomp>r   r   )r†   r   r   r)      r*   )ZaddObserverrQ   Ú
addCleanup)ZtestCaser…   r   r„   r   Ú	catchLogsñ  s    rŠ   g      Y@c                   @   s  e Zd ZdZdde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„ 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/d0„ Zd1d2„ Zd3d4„ Zd5d6„ Zd7d8„ Zd9d:„ Z d;d<„ Z!d=d>„ Z"d?d@„ Z#dAS )BÚClientServiceTestsz%
    Tests for L{ClientService}.
    Tc           
         sž   i }|j tƒ d |  |¡ |d ‰t|d\}}g  ‰|_G ‡ ‡‡fdd„dt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   t ˆ | ƒ |¡}ˆ |¡ |S r   )Úsuperry   rQ   )r#   Zaddrr-   )ÚRememberingFactoryÚ	__class__ÚapplicationProtocolsr   r   ry   6  s    
zLClientServiceTests.makeReconnector.<locals>.RememberingFactory.buildProtocol)r4   r5   r6   r{   ry   Ú__classcell__r   )r   r‘   ÚprotocolType)r   r   r   4  s   r   c                      s(   d ˆ_ ˆjrˆ ¡  ˆ ˆ  ¡ g ¡ d S r   )Z	_protocolrL   rO   rF   ÚgetDelayedCallsr   )r[   r#   Úservicer   r   Ústop>  s    z0ClientServiceTests.makeReconnector.<locals>.stop)
Úupdater   rƒ   r‘   r   re   ÚapplicationFactoryr   r‰   rB   )
r#   r€   rB   r“   ÚkwZnkwÚcqZendpointr,   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›   rF   rG   rv   )r#   rš   r•   r   r   r   r_   K  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˜   rF   ZnumPortsrx   ZdoStart)r#   rš   r•   ZfirstAppFactoryZfirstPassedFactoryr   r   r   Útest_startStopFactoryS  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›   rO   rd   rw   rF   r|   ÚdisconnectingÚconnectionLostr   Ú	Exceptionrf   ©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ƒ ƒ¡ |  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%   rX   N)r›   rO   rd   rw   rF   r|   r   rB   rG   rž   r   rŸ   r    r   r   r   Ú#test_startServiceWaitsForDisconnectq  s    


z6ClientServiceTests.test_startServiceWaitsForDisconnectc                 C   sä   | j dd\}}|jd  d¡ |jd }| ¡ }|  |¡ | ¡ }|  |¡ | ¡  |  |¡ |  |¡ |  |j	j
d¡ | ttƒ ƒ¡ |  |¡ |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   NTr%   rX   )r›   rv   r0   rw   rO   rd   ÚwhenConnectedrB   rF   r|   r   rž   r   rŸ   rf   rG   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›   rO   rf   ÚfailureResultOfr£   r   rB   rv   r0   r>   r‘   )r#   rš   r•   r¥   r   r   r   Útest_startServiceWhileStoppedž  s    
ÿz0ClientServiceTests.test_startServiceWhileStoppedc                 C   sZ   t ttƒG dd„ dt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)r4   r5   r6   r7   r   r   r   r   ÚFancyProtocol·  s   rª   )r“   r   N)	r   r   r   r   re   r›   rw   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   rX   r%   N)r   r›   rv   r&   rŸ   ÚadvanceÚAT_LEAST_ONE_ATTEMPTrF   rG   rO   rf   ©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›   rF   rG   rv   rd   rO   rf   r¯   r   r   r   Útest_stopServiceWhileConnectingÐ  s    z2ClientServiceTests.test_stopServiceWhileConnectingc                 C   sJ   t ƒ }| j|d\}}| ¡ }|  | ¡ g ¡ |  |  |¡|jd ¡ dS )zy
        When a client connects, the service keeps a reference to the new
        protocol and resets the delay.
        rŒ   r   N)r   r›   r£   rF   r”   r>   rf   r‘   )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   )rz   r   r   r   r)   ø  r*   z@ClientServiceTests.test_clientConnectionFailed.<locals>.<lambda>rX   N)r   r›   rF   rG   rv   r&   r   rŸ   r£   rd   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   NrX   )r   r›   rF   rG   rv   r0   r>   rf   r£   r‘   rw   rž   r   rŸ   r­   r®   )r#   r[   rš   r•   r   r   r   Útest_clientConnectionLostý  s    ÿ
ÿz,ClientServiceTests.test_clientConnectionLostc                 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›   rO   rw   rž   r   ÚIndentationErrorr¨   r£   r   r\   Z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€   rB   r   r%   z$Duplicate ClientService.startServiceN)r›   rF   rG   rv   rB   rŠ   ZassertIn)r#   rš   r•   Zmessagesr   r   r   Útest_startTwice  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£   rd   rv   r0   rf   r>   r‘   )
r#   r[   rš   r•   ÚaÚbÚcZresultAZresultBZresultCr   r   r   Útest_whenConnectedLater0  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¸   rX   é   r   N)r   r›   r£   rd   r   rŸ   rv   r&   r>   r¨   r­   r®   rF   rG   r0   rf   r‘   )r#   r[   rš   r•   Za0Za1Za2Za3Úf1Úf2ZAT_LEAST_TWO_ATTEMPTSZresultA0ZresultA3Za4ZresultA4r   r   r   Útest_whenConnectedFailsF  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£   rd   rO   r­   r®   r¨   r   )r#   r[   rš   r•   r¹   rº   r»   r   r   r   Útest_whenConnectedStopService  s    



z0ClientServiceTests.test_whenConnectedStopServicec                 C   sR   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›   rv   r&   rŸ   rO   rF   r”   rf   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€   rB   r[   N©r   r›   rO   ZassertIsNonerf   )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£   rv   r&   rŸ   rO   r]   r¨   rr   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›   rv   r0   rO   rw   rž   r   rµ   rf   ©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›   rv   r0   rO   rB   rw   rž   r   rµ   rf   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   ÚprepareConnection  s    z[ClientServiceTests.test_prepareConnectionCalledWhenServiceStarts.<locals>.prepareConnectionT)rÑ   rB   r%   N)r›   rF   ©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   ©rQ   ©Úproto©ÚnewProtocolsr   r   rÑ   "  s    zVClientServiceTests.test_prepareConnectionCalledWithProtocol.<locals>.prepareConnection©rÑ   r   N)r›   r>   rw   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Ñ   2  s    z]ClientServiceTests.test_prepareConnectionCalledAfterConnectionMade.<locals>.prepareConnectionF)rÑ   r€   r[   zconnection attempt failedr%   N)	r   r›   rv   r&   rŸ   rF   r­   r®   r0   ©r#   rÑ   r[   rš   r•   r   rÐ   r   Ú/test_prepareConnectionCalledAfterConnectionMade+  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Ñ   J  s    zUClientServiceTests.test_prepareConnectionCalledOnReconnect.<locals>.prepareConnection©rÑ   r[   r%   rX   N)	r   r›   rF   rw   rž   r   rµ   r­   r®   rÛ   r   rÐ   r   Ú'test_prepareConnectionCalledOnReconnectC  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Ñ   e  s    zVClientServiceTests.test_prepareConnectionReturnValueIgnored.<locals>.prepareConnectionrÙ   N)re   r›   rf   r£   ZassertNotIdentical)r#   rÑ   rš   r•   r-   r   rß   r   Ú(test_prepareConnectionReturnValueIgnoredZ  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Ñ   v  s    
zVClientServiceTests.test_prepareConnectionReturningADeferred.<locals>.prepareConnectionrÙ   Nr   )r   r›   r£   rd   r0   r>   r‘   rf   )r#   rÑ   rš   r•   ÚwhenConnectedDeferredr   râ   r   Ú(test_prepareConnectionReturningADeferredn  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Ý   rX   r¸   N)
r   r›   r£   rd   r­   r®   r>   rµ   r¨   Útype)r#   r[   rÑ   rš   r•   rã   r   r   r   Útest_prepareConnectionThrows…  s    ÿ





ÿz/ClientServiceTests.test_prepareConnectionThrowsN)$r4   r5   r6   r7   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‹     sD   ÿ
@;r‹   )F)4r7   Z
__future__r   r   rm   Zzope.interfacer   Zzope.interface.verifyr   Ztwisted.internet.protocolr   r   Ztwisted.internet.taskr   Ztwisted.trial.unittestr	   r
   Ztwisted.applicationr   Ztwisted.application.internetr   r   r   Ztwisted.internet.deferr   r   Ztwisted.internet.interfacesr   r   r   r   r   Ztwisted.internetr   Ztwisted.python.failurer   Ztwisted.loggerr   r   Ztwisted.test.proto_helpersr   r   re   r   r    r9   rW   ru   rƒ   rŠ   r®   r‹   r   r   r   r   Ú<module>   s>   B

 ' 
 