o
    ¯bO£  ã                   @   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mZ ddl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)ÚformatEventÚglobalLogPublisher)ÚFailure)ÚStringTransport)ÚSynchronousTestCaseÚTestCasec                   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__L   s   zFakeServer.__init__c                    sF   ˆ  j d7  _ |ˆ _t‡ fdd„dˆ _ˆ jdu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>)Ú	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_   ó   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.   r0   r3   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
   r2   r    r   r   r   ÚstopListening~   s   zFakePort.stopListeningc                 C   ó   d S r   r   r    r   r   r   ÚgetHost‡   ó   zFakePort.getHostc                 C   r9   r   r   r    r   r   r   ÚstartListening‹   r;   zFakePort.startListening)r4   r5   r6   r7   r2   r8   r:   r<   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!   Ú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)rI   r?   rA   r    r   r   r   Útest_synchronousRaisePrivileged½   r1   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?   rG   r>   r,   r$   rD   ÚflushLoggedErrorsÚassertEqualÚlen©r!   Ú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?   rE   rG   r>   r,   r$   rD   rK   rL   rM   rN   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)rD   r>   r-   r?   rG   rK   rL   rM   rN   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?   rG   rB   r+   r>   rL   Ú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)rC   r?   rG   rL   r>   r*   rS   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?   rA   r>   r0   rG   ÚstopServiceÚaddCallbackÚappendrL   rM   r3   ÚassertFalserS   ©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?   rA   rV   ÚaddBothrX   rL   rK   r	   rZ   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#   )rD   r>   r%   r?   rA   rV   rW   rX   rL   rK   rM   )r!   r,   r[   ÚstoppingErrorsr   r   r   Ú test_stopServiceCancelStartError  s   



z5EndpointServiceTests.test_stopServiceCancelStartErrorr   )r4   r5   r6   r7   r@   rC   rI   rJ   rP   rQ   rR   rT   rU   r\   r^   r`   r   r   r   r   r=   “   s    	



r=   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   rc   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)
rd   rG   Ú
assertTruerS   ÚassertIsInstanceÚ_loopr   ÚLoopingCallrB   re   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)rX   rd   rc   rG   rL   )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 r   r   )ÚmaybeReactor©Ú
otherClockr   r   ÚgetOtherClockh  ó   zKTimerServiceTests.test_startServiceUsesGlobalReactor.<locals>.getOtherClockÚ_maybeGlobalReactorN)	r   r   Úpatchr   rd   rG   rB   rh   re   )r!   rp   r   rn   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)rd   rG   rV   ÚassertNoResultrL   rS   r2   r/   ÚobjectrB   Ú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)rd   rG   r2   r/   rv   rV   rB   rw   rx   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)rd   rG   r2   r$   r   rD   rK   rL   rM   rV   rB   rw   )r!   Úerrorsr&   r   r   r   Útest_failedCallLogsError…  s   


z*TimerServiceTests.test_failedCallLogsErrorc                 C   óP   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#   rh   N©
r   r   rG   ÚpickleÚdumpsrV   Úloadsrv   ÚgetattrrB   ©r!   rd   ÚdumpedTimerÚloadedTimerÚnothingÚvaluer   r   r   Ú$test_pickleTimerServiceNotPickleLoop‘  ó   


z6TimerServiceTests.test_pickleTimerServiceNotPickleLoopc                 C   r}   )zy
        When pickling L{internet.TimerService}, it won't pickle
        L{internet.TimerService._loopFinished}.
        r#   Ú_loopFinishedNr~   rƒ   r   r   r   Ú,test_pickleTimerServiceNotPickleLoopFinished¡  r‰   z>TimerServiceTests.test_pickleTimerServiceNotPickleLoopFinishedN)r4   r5   r6   r7   r@   rc   rj   rk   rt   ry   rz   r|   rˆ   r‹   r   r   r   r   ra   ,  s    	

ra   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   rŒ   ²  s    rŒ   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   )ÚbuildProtocolrŽ   rX   r   ÚmakeConnection)ÚignoredÚprotocolÚ	transport)r+   Úinfor   r   ÚcreateProtocolØ  s
   

zNendpointForTesting.<locals>.ClientTestEndpoint.connect.<locals>.createProtocol)r
   r   rX   rW   r   r/   )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   rŒ   )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   )ÚremoveObserverrX   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'   ø  s    )ÚaddObserverrX   Ú
addCleanup)Ú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||	fi |¤Ž‰‡‡‡fdd„}
ˆ |
¡ |rKˆ ¡  |ˆ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.
        ©re   re   ©r˜   c                       s"   e Zd Z”Z‡ ‡fdd„Z‡  ZS )z>ClientServiceTests.makeReconnector.<locals>.RememberingFactoryc                    s   t ƒ  |¡}ˆ |¡ |S r   )Úsuperr   rX   )r!   Úaddrr,   )Ú	__class__ÚapplicationProtocolsr   r   r   0  s   
zLClientServiceTests.makeReconnector.<locals>.RememberingFactory.buildProtocol)r4   r5   r6   r“   r   Ú__classcell__r   )r­   ÚprotocolType)r¬   r   ÚRememberingFactory-  s    r°   c                      s(   d ˆ_ ˆjr
ˆ ¡  ˆ ˆ  ¡ g ¡ d S r   )Ú	_protocolrS   rV   rL   ÚgetDelayedCallsr   )re   r!   Úservicer   r   Ústop9  s   z0ClientServiceTests.makeReconnector.<locals>.stop)	Úupdater   r›   r­   r   ÚapplicationFactoryr   r¤   rG   )r!   r˜   rG   r¯   ÚkwÚnkwÚcqÚendpointr°   r+   r´   r   )r­   re   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»   rL   rM   r   )r!   r¹   r³   r   r   r   rj   F  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¶   rL   ÚnumPortsr   ÚdoStart)r!   r¹   r³   ÚfirstAppFactoryÚfirstPassedFactoryr   r   r   Útest_startStopFactoryM  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»   rV   ru   rŽ   rL   r”   ÚdisconnectingÚconnectionLostr   Ú	Exceptionrw   ©r!   r¹   r³   r&   r“   r   r   r   Útest_stopServiceWhileConnected[  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#   rb   N)r»   rV   ru   rŽ   rL   r”   rÁ   rG   rM   rÂ   r   rÃ   rÄ   r   r   r   Ú#test_startServiceWaitsForDisconnecti  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#   rb   )r»   r   r/   rŽ   rV   ru   ÚwhenConnectedrG   rL   r”   rÁ   rÂ   r   rÃ   rw   rM   rB   r­   )r!   r¹   r³   ÚfirstÚstoppedÚnextProtocolÚsecondStoppedr   r   r   Útest_startServiceWhileStoppingy  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»   rV   rw   ÚfailureResultOfrÇ   r	   rG   r   r/   rB   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)r4   r5   r6   r7   r   r   r   r   ÚFancyProtocol¯  s    rÐ   )r¯   r   N)r   r   r   r   r»   rŽ   rf   Ú
providedBy)r!   rÐ   r¹   r³   Ú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˜   re   r   rb   r#   N)r   r»   r   r$   rÃ   ÚadvanceÚAT_LEAST_ONE_ATTEMPTrL   rM   rV   rw   ©r!   re   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»   rL   rM   r   ru   rV   rw   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Ç   rL   r²   rB   rw   r­   )r!   re   r¹   r³   Ú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   )Útrapr	   )r’   r   r   r   r'   í  s   
 z@ClientServiceTests.test_clientConnectionFailed.<locals>.<lambda>rb   N)r   r»   rL   rM   r   r$   r   rÃ   rÇ   ru   Ú
addErrbackrÕ   rÖ   )r!   re   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)re   r˜   r#   r   Nrb   )r   r»   rL   rM   r   r/   rB   rw   rÇ   r­   rŽ   rÂ   r   rÃ   rÕ   rÖ   )r!   re   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»   rV   rŽ   rÂ   r   ÚIndentationErrorrÎ   rÇ   r	   rf   Ú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˜   rG   r   r#   z$Duplicate ClientService.startServiceN)r»   rL   rM   r   rG   r¦   ÚassertIn)r!   r¹   r³   Ú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#   ©ÚfailAfterFailuresr   N)	r   r»   rÇ   ru   r   r/   rw   rB   r­   )
r!   re   r¹   r³   ÚaÚbÚcÚresultAÚresultBÚresultCr   r   r   Útest_whenConnectedLater"  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æ   rb   é   r   N)r   r»   rÇ   ru   r   rÃ   r   r$   rB   rÎ   rÕ   rÖ   rL   rM   r/   rw   r­   )r!   re   r¹   r³   Úa0Úa1Úa2Úa3Úf1Úf2ÚAT_LEAST_TWO_ATTEMPTSÚresultA0ÚresultA3Úa4ÚresultA4r   r   r   Útest_whenConnectedFails7  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Ç   ru   rV   rÕ   rÖ   rÎ   r	   )r!   re   r¹   r³   rè   ré   rê   r   r   r   Útest_whenConnectedStopServiceq  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»   r   r$   rÃ   rV   rL   r²   rw   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˜   rG   re   N©r   r»   rV   ÚassertIsNonerw   )r!   re   Ú_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Ç   r   r$   rÃ   rV   rg   rÎ   r‡   r	   )r!   re   r¹   r³   ÚbeforeErrbackAndStopÚ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»   r   r/   rV   rŽ   rÂ   r   rà   rw   ©r!   re   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»   r   r/   rV   rG   rŽ   rÂ   r   rà   rw   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!   re   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                    ó   ˆ d  d7  < d S ©Nr   r#   r   ©Ú_proto©Úpreparesr   r   ÚprepareConnectionú  ó   z[ClientServiceTests.test_prepareConnectionCalledWhenServiceStarts.<locals>.prepareConnectionT)r  rG   r#   N)r»   rL   ©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   ©rX   ©Úproto©ÚnewProtocolsr   r   r  	  s   zVClientServiceTests.test_prepareConnectionCalledWithProtocol.<locals>.prepareConnection©r  r   N)r»   rB   rŽ   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                    r  r  r   r  r  r   r   r    r  z]ClientServiceTests.test_prepareConnectionCalledAfterConnectionMade.<locals>.prepareConnectionF)r  r˜   re   zconnection attempt failedr#   N)	r   r»   r   r$   rÃ   rL   rÕ   rÖ   r/   ©r!   r  re   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                    r  r  r   r  r  r   r   r  /  r  zUClientServiceTests.test_prepareConnectionCalledOnReconnect.<locals>.prepareConnection©r  re   r#   rb   N)	r   r»   rL   rŽ   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                    rl   r   r   r  ©Úsentinelr   r   r  J  rq   zVClientServiceTests.test_prepareConnectionReturnValueIgnored.<locals>.prepareConnectionr  N)rv   r»   rw   rÇ   ÚassertNotIdentical)r!   r  r¹   r³   r,   r   r!  r   Ú(test_prepareConnectionReturnValueIgnored?  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  ©ÚnewProtocolDeferredr  r   r   r  Z  s   
zVClientServiceTests.test_prepareConnectionReturningADeferred.<locals>.prepareConnectionr  Nr   )r
   r»   rÇ   ru   r/   rB   r­   rw   )r!   r  r¹   r³   ÚwhenConnectedDeferredr   r%  r   Ú(test_prepareConnectionReturningADeferredR  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 ƒ ‚r   )rà   r  r   r   r   r  p  s   zJClientServiceTests.test_prepareConnectionThrows.<locals>.prepareConnectionr  rb   ræ   N)
r   r»   rÇ   ru   rÕ   rÖ   rB   rà   rÎ   Útype)r!   re   r  r¹   r³   r'  r   r   r   Útest_prepareConnectionThrowsi  s   
ÿ



ÿz/ClientServiceTests.test_prepareConnectionThrowsN)$r4   r5   r6   r7   r   r»   rj   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    
ÿC:r§   )F)0r7   r   Úzope.interfacer   Úzope.interface.verifyr   Útwisted.applicationr   Útwisted.application.internetr   r   r   Útwisted.internetr   Útwisted.internet.deferr	   r
   Útwisted.internet.interfacesr   r   r   r   r   Útwisted.internet.protocolr   r   Útwisted.internet.taskr   Útwisted.loggerr   r   Útwisted.python.failurer   Útwisted.test.proto_helpersr   Útwisted.trial.unittestr   r   r   r   r   r=   ra   rŒ   r›   r¦   rÖ   r§   r   r   r   r   Ú<module>   s>   
@
  
#