a
    )¶(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   úElib/python3.9/site-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>)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;   Ú_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:   r/   rB   ÚstopServiceÚaddCallbackÚappendrF   rG   r1   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)r2   r3   r4   r5   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
   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   rY   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)
rZ   rB   Ú
assertTruerL   Ú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)rQ   rZ   rY   rB   rF   )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   Zpatchr   rZ   rB   r>   r^   r[   )r!   rb   r   ra   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)rZ   rB   rO   ÚassertNoResultrF   rL   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)rZ   rB   r0   r.   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   r0   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)r2   r3   r4   r5   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)r2   r3   r4   r5   r"   r   r   r   r   ru   ²  s   ru   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   )ÚbuildProtocolrw   rQ   r   ZmakeConnection)ÚignoredÚprotocolÚ	transport)r*   Úinfor   r   ÚcreateProtocolØ  s
    

zNendpointForTesting.<locals>.ClientTestEndpoint.connect.<locals>.createProtocol)r
   rx   rQ   rP   rv   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   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>ø  r(   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||	fi |¤Ž‰‡‡‡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+   )Ú	__class__ÚapplicationProtocolsr   r   ry   0  s    
zLClientServiceTests.makeReconnector.<locals>.RememberingFactory.buildProtocol)r2   r3   r4   r{   ry   Ú__classcell__r   )r   ÚprotocolType)r   r   ÚRememberingFactory-  s   r“   c                      s(   d ˆ_ ˆjrˆ ¡  ˆ ˆ  ¡ g ¡ d S r   )Z	_protocolrL   rO   rF   ÚgetDelayedCallsr   )r[   r!   Úservicer   r   Ústop9  s    z0ClientServiceTests.makeReconnector.<locals>.stop)	Úupdater   rƒ   r   r   Ú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_   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˜   rF   ZnumPortsrx   ZdoStart)r!   rš   r•   ZfirstAppFactoryZ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›   rO   rd   rw   rF   r|   ÚdisconnectingÚconnectionLostr   Ú	Exceptionrf   ©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#   rX   N)r›   rO   rd   rw   rF   r|   r   rB   rG   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#   rX   )r›   rv   r.   rw   rO   rd   ÚwhenConnectedrB   rF   r|   r   rž   r   rŸ   rf   rG   r>   r   )r!   rš   r•   ÚfirstÚstoppedZnextProtocolZ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›   rO   rf   ÚfailureResultOfr£   r	   rB   rv   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›   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   r.   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   r.   rf   r>   r   )
r!   r[   rš   r•   ÚaÚbÚcZresultAZresultBZ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¸   rX   é   r   N)r   r›   r£   rd   r   rŸ   rv   r$   r>   r¨   r­   r®   rF   rG   r.   rf   r   )r!   r[   rš   r•   Za0Za1Za2Za3Úf1Úf2ZAT_LEAST_TWO_ATTEMPTSZresultA0ZresultA3Za4Z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£   rd   rO   r­   r®   r¨   r	   )r!   r[   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›   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   r.   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   r.   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Ñ     s    z]ClientServiceTests.test_prepareConnectionCalledAfterConnectionMade.<locals>.prepareConnectionF)rÑ   r€   r[   zconnection attempt failedr#   N)	r   r›   rv   r$   rŸ   rF   r­   r®   r.   ©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Ñ   /  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_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Ñ   J  s    zVClientServiceTests.test_prepareConnectionReturnValueIgnored.<locals>.prepareConnectionrÙ   N)re   r›   rf   r£   Z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Õ   ©ZnewProtocolDeferredrØ   r   r   rÑ   Z  s    
zVClientServiceTests.test_prepareConnectionReturningADeferred.<locals>.prepareConnectionrÙ   Nr   )r
   r›   r£   rd   r.   r>   r   rf   )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 ƒ ‚d S r   )rµ   rÏ   r   r   r   rÑ   p  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_prepareConnectionThrowsi  s    ÿ




ÿz/ClientServiceTests.test_prepareConnectionThrowsN)$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‹   þ  sB   ÿ
C:r‹   )F)0r5   rm   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.loggerr   r   Ztwisted.python.failurer   Ztwisted.test.proto_helpersr   Ztwisted.trial.unittestr   r   r   r   r   r9   rW   ru   rƒ   rŠ   r®   r‹   r   r   r   r   Ú<module>   s<   @

  
#