
    Vh                        d Z ddlZddlmZ ddlmZ ddlmZ ddlm	Z	m
Z
mZ ddlmZ ddlmZmZ dd	lmZmZmZmZmZ dd
lmZmZ ddlmZ ddlmZ ddlmZm Z  ddl!m"Z" ddl#m$Z$m%Z% d Z& ee       G d d             Z' eee'        ee       G d d             Z( eee'        G d de%      Z) G d de%      Z* G d d      Z+d dZ,e fdZ-dZ. G d de$      Z/y)!z
Tests for (new code in) L{twisted.application.internet}.

@var AT_LEAST_ONE_ATTEMPT: At least enough seconds for L{ClientService} to make
    one attempt.
    N)implementer)verifyClass)internet)ClientServiceStreamServerEndpointServiceTimerService)task)CancelledErrorDeferred)IFileDescriptorReceiverIHalfCloseableProtocolIListeningPortIStreamClientEndpointIStreamServerEndpoint)FactoryProtocol)Clock)StringTransport)formatEventglobalLogPublisher)Failure)SynchronousTestCaseTestCasec                       y)zM
    A fake target function for testing TimerService which does nothing.
    N r       V/home/dcms/DCMS/lib/python3.12/site-packages/twisted/application/test/test_internet.pyfakeTargetFunctionr   )   s     	r   c                   F    e Zd ZdZdZdZdZ e       ZdZ	d Z
d Zd Zd Zy)
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                 "    t               | _        y N)FakePortportselfs    r   __init__zFakeServer.__init__L   s    J	r   c                       xj                   dz  c_         | _        t         fd       _         j                  % j                  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                 :    | j                  j                        S r"   )errbackcancelException)dr&   s    r   <lambda>z#FakeServer.listen.<locals>.<lambda>Z   s    199T=Q=Q3R r   )	canceller)listenAttemptsfactoryr   resultfailImmediatelyr+   )r&   r1   s   ` r   listenzFakeServer.listenO   sX     	q )RS+KK 4 45{{r   c                 N    | j                   j                  | j                         y)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)r2   callbackr$   r%   s    r   startedListeningzFakeServer.startedListening_   s     	TYY'r   c                 N    | j                   j                  j                  d       y)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$   deferredr6   r%   s    r   stoppedListeningzFakeServer.stoppedListeningg   s     			##D)r   )__name__
__module____qualname____doc__r2   r1   r3   r
   r,   r0   r'   r4   r7   r:   r   r   r   r    r    0   s9    ( FGO$&ON (*r   r    c                   &    e Zd ZdZdZd Zd Zd Zy)r#   zs
    Fake L{IListeningPort} implementation.

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

        @return: a L{Deferred} stored in L{FakePort.deferred}
        )r   r9   r%   s    r   stopListeningzFakePort.stopListening~   s     !
}}r   c                      y r"   r   r%   s    r   getHostzFakePort.getHost       r   c                      y r"   r   r%   s    r   startListeningzFakePort.startListening   rD   r   )r;   r<   r=   r>   r9   rA   rC   rF   r   r   r   r#   r#   t   s     Hr   r#   c                   Z    e Zd ZdZd Zd ZddZd Zd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zy)EndpointServiceTestsz4
    Tests for L{twisted.application.internet}.
    c                     t               | _        t               | _        t	        | j                  | j                        | _        y)zp
        Construct a stub server, a stub factory, and a
        L{StreamServerEndpointService} to test.
        N)r    
fakeServerr   r1   r   svcr%   s    r   setUpzEndpointServiceTests.setUp   s,    
 %,y.tMr   c                     | j                   j                          | j                  | j                  | j                  j                         y)z
        L{StreamServerEndpointService.privilegedStartService} calls its
        endpoint's C{listen} method with its factory.
        N)rK   privilegedStartServiceassertIdenticalr1   rJ   r%   s    r   test_privilegedStartServicez0EndpointServiceTests.test_privilegedStartService   s2    
 	'')T\\4??+B+BCr   Nc                     t               | j                  _        d| j                  _        | j                  t         |xs | j                  j                         y)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)ZeroDivisionErrorrJ   r3   rK   _raiseSynchronouslyassertRaisesstartService)r&   thunks     r   (test_synchronousRaiseRaisesSynchronouslyz=EndpointServiceTests.test_synchronousRaiseRaisesSynchronously   s?      +<*=''+$+U-Kdhh6K6KLr   c                 N    | j                  | j                  j                         y)z
        L{StreamServerEndpointService.privilegedStartService} should behave the
        same as C{startService} with respect to
        L{EndpointServiceTests.test_synchronousRaiseRaisesSynchronously}.
        N)rW   rK   rN   r%   s    r   test_synchronousRaisePrivilegedz4EndpointServiceTests.test_synchronousRaisePrivileged   s     	55dhh6U6UVr   c                     | j                   j                          | j                  j                  j	                  t                      | j                  t
              }| j                  t        |      d       y)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)	rK   rU   rJ   r2   r+   rR   flushLoggedErrorsassertEquallenr&   loggeds     r   test_failReportsErrorz*EndpointServiceTests.test_failReportsError   sU     	&&'8':;''(9:Va(r   c                    d| j                   _        | j                   j                          | j                  j                  j                  t                      | j                  t              }| j                  t        |      d       y)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)
rK   rS   rU   rJ   r2   r+   rR   r[   r\   r]   r^   s     r   !test_asynchronousFailReportsErrorz6EndpointServiceTests.test_asynchronousFailReportsError   sa     (,$&&'8':;''(9:Va(r   c                     t               | j                  _        | j                  j	                          | j                  t               }| j                  t        |      d       y)z
        Without the C{_raiseSynchronously} compatibility flag, failing
        immediately has the same behavior as failing later; it logs the error.
        r)   N)rR   rJ   r3   rK   rU   r[   r\   r]   r^   s     r    test_synchronousFailReportsErrorz5EndpointServiceTests.test_synchronousFailReportsError   sH    
 +<*='''(9:Va(r   c                     | j                   j                          | j                  | j                  | j                  j                         | j                  | j                   j                  d       y)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)rK   rU   rO   r1   rJ   r\   runningr%   s    r   test_startServiceUnstartedz/EndpointServiceTests.test_startServiceUnstarted   sL     	T\\4??+B+BC))40r   c                     | j                          | j                  j                          | j                  | j                  j
                  d       | j                  | j                  j                  d       y)z
        L{StreamServerEndpointService.startService} sets the C{running} flag,
        but nothing else, if the service has already been started.
        r)   TN)rP   rK   rU   r\   rJ   r0   rf   r%   s    r   test_startServiceStartedz-EndpointServiceTests.test_startServiceStarted   sT    
 	((*77;))40r   c                    | j                   j                          | j                  j                          | j                   j	                          | j                   j                         }g }|j                  |j                         | j                  t        |      d       | j                  j                          | j                  t        |      d       | j                  | j                   j                         y)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)rK   rN   rJ   r7   rU   stopServiceaddCallbackappendr\   r]   r:   assertFalserf   r&   r2   ls      r   test_stopServicez%EndpointServiceTests.test_stopService   s     	'')((*%%'188$Q#((*Q#))*r   c                    | j                   j                          | j                   j                         }g }|j                  |j                         | j                  |dg       | j                  | j                  t              g        y)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)rK   rN   rk   addBothrm   r\   r[   r
   ro   s      r   #test_stopServiceBeforeStartFinishedz8EndpointServiceTests.test_stopServiceBeforeStartFinished  sh     	'')%%'qxx TF#//?Dr   c                 ^   t               | j                  _        | j                  j	                          | j                  j                         }g }|j                  |j                         | j                  |dg       | j                  t               }| j                  t        |      d       y)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)   )rR   rJ   r,   rK   rN   rk   rl   rm   r\   r[   r]   )r&   r2   rp   stoppingErrorss       r    test_stopServiceCancelStartErrorz5EndpointServiceTests.test_stopServiceCancelStartError  s     +<*=''')%%'188$TF#//0AB^,a0r   r"   )r;   r<   r=   r>   rL   rP   rW   rY   r`   rb   rd   rg   ri   rq   rt   rw   r   r   r   rH   rH      sH    NDM(W
)))11+$E1r   rH   c                   L    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zy)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                     t        d| j                        | _        t        j                         x| _        | j                  _        t               | _        y)z1
        Set up a timer service to test.
           N)r   calltimerr	   r   clockr   r9   r%   s    r   rL   zTimerServiceTests.setUp:  s8     "!TYY/
(,

4
TZZ% 
r   c                     | j                   S )z
        Function called by L{TimerService} being tested.

        @returns: C{self.deferred}
        @rtype: L{Deferred}
        )r9   r%   s    r   r|   zTimerServiceTests.callB  s     }}r   c                    | j                   j                          | j                  | j                   j                  d       | j	                  | j                   j
                  t        j                         | j                  | j                  | j                   j
                  j                         | j                  | j                   j
                  j                  d       y)z
        When L{TimerService.startService} is called, it marks itself
        as running, creates a L{task.LoopingCall} and starts it.
        zService is startedzLoopingCall is startedN)
r}   rU   
assertTruerf   assertIsInstance_loopr	   LoopingCallrO   r~   r%   s    r   test_startServicez#TimerServiceTests.test_startServiceK  s    
 	

!

**,@Adjj..0@0@ATZZ)9)9)?)?@

((002JKr   c                     g }|j                   di f| j                  _        | j                  j                          | j	                  dg|       y)zi
        When L{TimerService.startService} is called, it calls the function
        immediately.
        r"   N)rm   r}   r|   rU   r\   )r&   r2   s     r   $test_startServiceRunsCallImmediatelyz6TimerServiceTests.test_startServiceRunsCallImmediatelyV  sA    
 !=='26



!$(r   c                     t        j                         fd}| j                  t        d|       | j                  j                          | j                  | j                  j                  j                         y)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
otherClocks    r   getOtherClockzKTimerServiceTests.test_startServiceUsesGlobalReactor.<locals>.getOtherClockh  s	    r   _maybeGlobalReactorN)	r	   r   patchr   r}   rU   rO   r   r~   )r&   r   r   s     @r   "test_startServiceUsesGlobalReactorz4TimerServiceTests.test_startServiceUsesGlobalReactor`  sX     ZZ\
	 	

82MB

!Z)9)9)?)?@r   c                 b   | j                   j                          | j                   j                         }| j                  |       | j	                  d| j                   j
                         | j                  j                  t                      | j                  | j                  |      d       y)z
        When L{TimerService.stopService} is called while a call is in progress.
        the L{Deferred} returned doesn't fire until after the call finishes.
        TN)r}   rU   rk   assertNoResultr\   rf   r9   r6   objectrO   successResultOfr&   r-   s     r   test_stopServiceWaitsz'TimerServiceTests.test_stopServiceWaitso  s}    
 	

!JJ""$Atzz112vx(T11!4d;r   c                     | j                   j                          | j                  j                  t	                      | j                   j                         }| j                  | j                  |      d       y)z
        When L{TimerService.stopService} is called while a call isn't in progress.
        the L{Deferred} returned has already been fired.
        N)r}   rU   r9   r6   r   rk   rO   r   r   s     r   test_stopServiceImmediatelyz-TimerServiceTests.test_stopServiceImmediately{  sU    
 	

!vx(JJ""$T11!4d;r   c                 f   | j                   j                          | j                  j                  t	        t                            | j                  t
              }| j                  dt        |             | j                   j                         }| j                  | j                  |      d       y)z
        When function passed to L{TimerService} returns a deferred that errbacks,
        the exception is logged, and L{TimerService.stopService} doesn't raise an error.
        r)   N)r}   rU   r9   r+   r   rR   r[   r\   r]   rk   rO   r   )r&   errorsr-   s      r   test_failedCallLogsErrorz*TimerServiceTests.test_failedCallLogsError  s    
 	

!g&7&9:;''(9:CK(JJ""$T11!4d;r   c                 
   t        dt              }|j                          t        j                  |      }|j                          t        j                  |      }t               }t        |d|      }| j                  ||       y)zq
        When pickling L{internet.TimerService}, it won't pickle
        L{internet.TimerService._loop}.
        r)   r   N
r   r   rU   pickledumpsrk   loadsr   getattrrO   r&   r}   dumpedTimerloadedTimernothingvalues         r   $test_pickleTimerServiceNotPickleLoopz6TimerServiceTests.test_pickleTimerServiceNotPickleLoop  sj     Q 23ll5)ll;/(Wg6We,r   c                 
   t        dt              }|j                          t        j                  |      }|j                          t        j                  |      }t               }t        |d|      }| j                  ||       y)zy
        When pickling L{internet.TimerService}, it won't pickle
        L{internet.TimerService._loopFinished}.
        r)   _loopFinishedNr   r   s         r   ,test_pickleTimerServiceNotPickleLoopFinishedz>TimerServiceTests.test_pickleTimerServiceNotPickleLoopFinished  sj     Q 23ll5)ll;/(_g>We,r   N)r;   r<   r=   r>   rL   r|   r   r   r   r   r   r   r   r   r   r   r   ry   ry   ,  s;    #	L)A
<<
<- -r   ry   c                       e Zd ZdZd Zy)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                 .    g | _         g | _        g | _        y r"   )connectQueueconstructedProtocolspassedFactoriesr%   s    r   r'   zConnectInformation.__init__  s    $&!!r   N)r;   r<   r=   r>   r'   r   r   r   r   r     s    "r   r   c                 j     t        t               G  f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                       e Zd Z fdZy).endpointForTesting.<locals>.ClientTestEndpointc                     t               }j                  j                         |j                  fd       }j                  j                  |       r|j                  d        |S )Nc                     j                  d       }j                  j                  |       t               }|j	                  |       |S r"   )buildProtocolr   rm   r   makeConnection)ignoredprotocol	transportr1   infos      r   createProtocolzNendpointForTesting.<locals>.ClientTestEndpoint.connect.<locals>.createProtocol  sB    "006))00:+-	''	2r   )r   r   rm   rl   r   r6   )r&   r1   r2   r   fireImmediatelyr   s    `  r   connectz6endpointForTesting.<locals>.ClientTestEndpoint.connect  s`    ZF  ''0     $$V,%Mr   N)r;   r<   r=   r   )r   r   s   r   ClientTestEndpointr     s    	r   r   )r   r   r   )r   r   r   s   ` @r   endpointForTestingr     s;     &'  ($ D#%%%r   c                 t    g j                  j                         | j                  fd       f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                  :     j                  j                        S r"   )removeObserverrm   )logPublisherlogss   r   r.   zcatchLogs.<locals>.<lambda>  s     ; ;DKK H r   c                  @    D  cg c]  } t        |        c} S c c} w r"   )r   )eventr   s    r   r.   zcatchLogs.<locals>.<lambda>  s    D95K&9 9s   )addObserverrm   
addCleanup)testCaser   r   s    `@r   	catchLogsr     s1     DT[[)HI99r   g      Y@c                       e Zd ZdZddedfdZd Zd Zd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd Zd Zd%dZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd  Z d! Z!d" Z"d# Z#d$ Z$y)&ClientServiceTestsz%
    Tests for L{ClientService}.
    TFc                 Z    i }|j                  t                      |j                  |       |d   t        |      \  }}g x|_         G fddt              }	 |	       x|_        }
t        ||
fi | fd} j                  |       |rj                          |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                   *     e Zd ZW Z fdZ xZS )>ClientServiceTests.makeReconnector.<locals>.RememberingFactoryc                 N    ry t         |   |      }j                  |       |S r"   )superr   rm   )r&   addrr2   	__class__applicationProtocolsrefuseConnectionss      r   r   zLClientServiceTests.makeReconnector.<locals>.RememberingFactory.buildProtocol5  s+    $.t4$++F3r   )r;   r<   r=   r   r   __classcell__)r   r   protocolTyper   s   @r   RememberingFactoryr   2  s    #H r   r   c                      d _         j                  rj                          j                   j	                         g        y r"   )	_protocolrf   rk   r\   getDelayedCalls)r~   r&   services   r   stopz0ClientServiceTests.makeReconnector.<locals>.stop@  s9     $G##% U224b9r   )	updater   r   r   r   applicationFactoryr   r   rU   )r&   r   rU   r   r   kwnkwcqendpointr   r1   r   r   r~   r   s   `  ``       @@@r   makeReconnectorz"ClientServiceTests.makeReconnector  s    B 


!

2G)/JH :<;r6	 	 	 +=*>>'9S9	: 	  "7{r   c                 x    | j                  d      \  }}| j                  t        |j                        d       y)zL
        When the service is started, a connection attempt is made.
        Fr   r)   N)r   r\   r]   r   )r&   r   r   s      r   r   z$ClientServiceTests.test_startServiceM  s4     **5*AGR__-q1r   c                     | j                         \  }}|j                  }| j                  |j                  d       |j                  d   }|j                          | j                  |j                  d       y)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   r\   numPortsr   doStart)r&   r   r   firstAppFactoryfirstPassedFactorys        r   test_startStopFactoryz(ClientServiceTests.test_startStopFactoryT  sj     **,G//1115//2""$1115r   c                 <   | j                         \  }}|j                         }| j                  |       |j                  d   }| j	                  |j
                  j                  d       |j                  t        t                            | j                  |       y)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   rk   r   r   r\   r   disconnectingconnectionLostr   	Exceptionr   r&   r   r   r-   r   s        r   test_stopServiceWhileConnectedz1ClientServiceTests.test_stopServiceWhileConnectedb  s     **,G!A**1-++994@	 45Qr   c                    | j                         \  }}|j                         }| j                  |       |j                  d   }| j	                  |j
                  j                  d       |j                          | j                  |       | j	                  t        |j                        d       |j                  t        t        d                   | j	                  t        |j                        d       y)z
        When L{ClientService} is restarted after having been connected, it
        waits to start connecting until after having disconnected.
        r   Tr)   zsynthetic connectionLostr{   N)r   rk   r   r   r\   r   r   rU   r]   r   r   r   r   s        r   #test_startServiceWaitsForDisconnectz6ClientServiceTests.test_startServiceWaitsForDisconnectp  s    
 **,G!A**1-++994@AR445q9	2L(M NOR445q9r   c                 H   | j                  d      \  }}|j                  d   j                  d       |j                  d   }|j	                         }| j                  |       |j                         }| j                  |       |j                          | j                  |       | j                  |       | j                  |j                  j                  d       |j                  t        t        d                   | j                  |       |j                  d   j                  d       | j                  t        |j                        d       | j!                  | j                  |      |j"                  d          |j	                         }| j                  |       y)	a%  
        When L{ClientService} is stopping - that is,
        L{ClientService.stopService} has been called, but the L{Deferred} it
        returns has not fired yet - calling L{startService} will cause a new
        connection to be made, and new calls to L{whenConnected} to succeed.
        Fr   r   NTzsynthetic connection lostr)   r{   )r   r   r6   r   rk   r   whenConnectedrU   r\   r   r   r   r   r   r   r]   rO   r   )r&   r   r   firststoppednextProtocolsecondStoppeds          r   test_startServiceWhileStoppingz1ClientServiceTests.test_startServiceWhileStopping  s\    **5*AG
##D)''*%%'G$,,.L)L)G$66=WY/J%KLMW%
##D)R445q9  .0G0G0J	
  ++-M*r   c                    | j                  d      \  }}|j                         }| j                  |       | j                  |j	                         t
               |j                          |j                  d   j                  d       | j                  |j                  d   | j                  |j	                                      y)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   rk   r   failureResultOfr   r
   rU   r   r6   rO   r   )r&   r   r   r   s       r   test_startServiceWhileStoppedz0ClientServiceTests.test_startServiceWhileStopped  s     **5*AG%%'W%W224nE
$$T*##B')=)=g>S>S>U)V	
r   c                 (   t        t        t               G d dt                     }| j	                  |      \  }}|j
                  d   }| j                  t        j                  |             | j                  t        j                  |             y)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                       e Zd ZdZy)EClientServiceTests.test_interfacesForTransport.<locals>.FancyProtocolz9
            Provider of various interfaces.
            N)r;   r<   r=   r>   r   r   r   FancyProtocolr    s    r   r  )r   r   N)r   r   r   r   r   r   r   
providedBy)r&   r  r   r   reactorFacings        r   test_interfacesForTransportz.ClientServiceTests.test_interfacesForTransport  s     
+-D	E	H 	 
F	
 ***FG//2/::=IJ.99-HIr   c                    t               }| j                  d|      \  }}|j                  d   j                  t	                      |j                  t               | j                  t        |j                        d       |j                         }|j                  d   j                  t	                      | j                  |       y)zU
        When the service is stopped while retrying, the retry is cancelled.
        Fr   r~   r   r{   r)   N)r   r   r   r+   r   advanceAT_LEAST_ONE_ATTEMPTr\   r]   rk   r   r&   r~   r   r   r-   s        r   test_stopServiceWhileRetryingz0ClientServiceTests.test_stopServiceWhileRetrying  s     **5*NG
""9;/*+R__-q1!
""9;/Qr   c                    t               }| j                  d|      \  }}| j                  t        |j                        d       | j                  |j                  d          |j                         }| j                  |       y)zv
        When the service is stopped while initially connecting, the connection
        attempt is cancelled.
        Fr	  r)   r   N)r   r   r\   r]   r   r   rk   r   r  s        r   test_stopServiceWhileConnectingz2ClientServiceTests.test_stopServiceWhileConnecting  sp    
 **5*NGR__-q1BOOA./!Qr   c                 6   t               }| j                  |      \  }}|j                         }| j                  |j	                         g        | j                  | j                  |      |j                  d          | j                  |j                  d   j                  |j                  d          | j                  t        |j                  d         t        |j                  d                | j                  dt        |j                  d                y)zy
        When a client connects, the service keeps a reference to the new
        protocol and resets the delay.
        r   r   r   N)r   r   r   r\   r   rO   r   r   r   r   assertInstrr   )r&   r~   r   r   awaitingProtocols        r   test_clientConnectedz'ClientServiceTests.test_clientConnected  s    
 ***7G"002..0"5  !12B4K4KA4N	
 	##A&00"2I2I!2L	
 	''*+''*+	
 	 ""1%&	
r   c                    t               }| j                  d|      \  }}| j                  t        |j                        d       |j                  d   j                  t        t                            |j                         }| j                  |       |j                  d        |j                  t               | j                  t        |j                        d       y)z
        When a client connection fails, the service removes its reference
        to the protocol and tries again after a timeout.
        Fr	  r)   r   c                 ,    | j                  t              S r"   )trapr
   )r   s    r   r.   z@ClientServiceTests.test_clientConnectionFailed.<locals>.<lambda>  s    n1M r   r{   N)r   r   r\   r]   r   r+   r   r   r   r   
addErrbackr
  r  r&   r~   r   r   r   s        r   test_clientConnectionFailedz.ClientServiceTests.test_clientConnectionFailed  s    
 **5*NGR__-q1
""79;#78--/M* 	  !MN*+R__-q1r   c                    t               }| j                  |d      \  }}| j                  t        |j                        d       |j                  d   j                  d       | j                  t        |j                        d       | j                  | j                  |j                               |j                  d          |j                  d   j                  t        t                            |j                  t               | j                  t        |j                        d       |j                  d   j                  d       | j                  | j                  |j                               |j                  d          y)z~
        When a client connection is lost, the service removes its reference
        to the protocol and calls retry.
        F)r~   r   r)   r   Nr{   )r   r   r\   r]   r   r6   rO   r   r   r   r   r   r   r   r
  r  )r&   r~   r   r   s       r   test_clientConnectionLostz,ClientServiceTests.test_clientConnectionLost  s2   
 ***NGR__-q1
##D)R__-q1  !6!6!892;R;RST;U	
 	"11')+2FG*+R__-q1
##D)  !6!6!892;R;RST;U	
r   Nc                     t               } j                   fd        j                  |dd      \  }} j                  t	        |j
                        d       |j
                  j                  d      j                  d        j                  t	        |j
                        d       |j                          j                         |j                  t                j                  t	        |j
                        d       |j
                  j                  d      j                  d        j                         y)z
        When the client factory refuses connections by returning None from
        buildProtocol, the factory keeps attempting new connections.
        c                  0     j                  t              S r"   )r   r
   )r&   r   s   r   r.   zAClientServiceTests.test_clientConnectionRefused.<locals>.<lambda>"  s     4 4]N S r   FT)r~   r   r   r)   r   N)r   r   r   r\   r]   r   popr6   r   r   r
  r  r  s   `   @r   test_clientConnectionRefusedz/ClientServiceTests.test_clientConnectionRefused  s    
 
 	ST**!"	 + 
G 	R__-q1
A''-R__-q1--/M* 	*+R__-q1
A''-M*r   c                 >   t               }| j                  |      \  }}|j                         }|j                  d   j	                  t        t                            | j                  |j                         t               | j                  |j                         y)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   rk   r   r   r   IndentationErrorr   r   r
   r   calledr  s        r   &test_clientConnectionLostWhileStoppingz9ClientServiceTests.test_clientConnectionLostWhileStopping>  s{     ***7G!
"11':J:L2MNW224nE!r   c                    | j                  dd      \  }}| j                  t        |j                        d       |j	                          | j                  t        |j                        d       t        |       }|j	                          | j                  t        |j                        d       | j                  d |       d          y)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   rU   r   r)   z$Duplicate ClientService.startServiceN)r   r\   r]   r   rU   r   r  )r&   r   r   messagess       r   test_startTwicez"ClientServiceTests.test_startTwiceK  s     **5u*UGR__-q1R__-q1T?R__-q1<hjmLr   c                 6   t               }| j                  d|      \  }}|j                         }|j                         }|j                  d      }| j                  |       | j                  |       | j                  |       |j                  d   j                  d       | j                  |      }| j                  |      }| j                  |      }	| j                  ||       | j                  ||	       | j                  ||j                  d          y)z{
        L{ClientService.whenConnected} returns a L{Deferred} that fires when a
        connection is established.
        Fr	  r)   failAfterFailuresr   N)	r   r   r   r   r   r6   r   rO   r   )
r&   r~   r   r   abcresultAresultBresultCs
             r   test_whenConnectedLaterz*ClientServiceTests.test_whenConnectedLaterZ  s    
 **5*NG!!#!!#!!A!6AAA
##D)&&q)&&q)&&q)Wg.Wg.Wb&=&=a&@Ar   c                 @   t               }| j                  d|      \  }}|j                         }|j                  d      }|j                  d      }|j                  d      }| j                  |       | j                  |       | j                  |       | j                  |       t	        t                     }|j                  d   j                  |       | j                  |       | j                  | j                  |t
              |       | j                  |       | j                  |       |j                  t               | j                  t        |j                        d       | j                  |       | j                  |       | j                  |       t	        t                     }	|j                  d   j                  |	       | j                  |       | j                  | j                  |t
              |	       | j                  |       t        }
|j                  |
       | j                  t        |j                        d       | j                  |       | j                  |       |j                  d   j                  d       | j                  |      }| j                  |      }| j                  ||       | j                  ||j                   d          |j                  d      }| j                  |      }| j                  ||       y)	z
        L{ClientService.whenConnected} returns a L{Deferred} that fails, if
        asked, when some number of connections have failed.
        Fr	  r)   r)  r{      r   N)r   r   r   r   r   r   r   r+   rO   r   r
  r  r\   r]   r6   r   r   )r&   r~   r   r   a0a1a2a3f1f2AT_LEAST_TWO_ATTEMPTSresultA0resultA3a4resultA4s                  r   test_whenConnectedFailsz*ClientServiceTests.test_whenConnectedFailso  s   
 **5*NG""$""Q"7""Q"7""Q"7BBBBY[!
""2&BT11"i@"EBB*+R__-q1BBBY[!
""2&BT11"i@"EB 4+,R__-q1BB
##D)''+''+Xx0Xr'>'>q'AB ""Q"7''+Xx0r   c                    t               }| j                  d|      \  }}|j                         }|j                         }|j                  d      }| j                  |       | j                  |       | j                  |       |j	                          |j                  t               | j                  |t               | j                  |t               | j                  |t               y)z
        L{ClientService.whenConnected} returns a L{Deferred} that fails when
        L{ClientService.stopService} is called.
        Fr	  r)   r)  N)	r   r   r   r   rk   r
  r  r   r
   )r&   r~   r   r   r+  r,  r-  s          r   test_whenConnectedStopServicez0ClientServiceTests.test_whenConnectedStopService  s    
 **5*NG!!#!!#!!A!6AAA*+Q/Q/Q/r   c                 ,   t               }| j                  d|      \  }}|j                  j                  d      j	                  t        d             |j                         }| j                  |j                         g        | j                  |       y)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+   r   rk   r\   r   r   r  s        r   test_retryCancelledz&ClientServiceTests.test_retryCancelled  s{     **5*NG
A&&y'AB!..0"5Qr   c                     t               }| j                  dd|      \  }}|j                         }| j                  | j	                  |             y)z
        Calling L{ClientService.stopService} before
        L{ClientService.startService} returns a L{Deferred} that has
        already fired with L{None}.
        F)r   rU   r~   Nr   r   rk   assertIsNoner   )r&   r~   _r   r-   s        r   "test_stopServiceBeforeStartServicez5ClientServiceTests.test_stopServiceBeforeStartService  sT     ))!U * 

7 !$..q12r   c                    t               }| j                  d|      \  }}|j                         }|j                  d   j	                  t        d             |j                          |j                         }| j                  | j                  |      j                  t               | j                  | j                  |      j                  t               y)z
        L{ClientService.whenConnected} returns a L{Deferred} that
        errbacks with L{CancelledError} if
        L{ClientService.stopService} is called between connection
        attempts.
        Fr	  r   rC  N)r   r   r   r   r+   r   rk   r   r   r   r
   )r&   r~   r   r   beforeErrbackAndStopafterErrbackAndStops         r   'test_whenConnectedErrbacksOnStopServicez:ClientServiceTests.test_whenConnectedErrbacksOnStopService  s     **5*NG&446 	""9_#=>%335  !56<<n	
 	  !45;;^	
r   c                 b   t               }| j                  d|      \  }}|j                  d   j                  d       |j	                         }|j	                         }|j
                  d   j                  t        t                            | j                  |       | j                  |       y)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   r6   rk   r   r   r   r"  r   r&   r~   r   r   firstStopDeferredsecondStopDeferreds         r   "test_stopServiceWhileDisconnectingz5ClientServiceTests.test_stopServiceWhileDisconnecting  s     **5*NG
##D) $//1$002 	"11':J:L2MN.//0r   c                    t               }| j                  d|      \  }}|j                  d   j                  d       |j	                         }|j                          |j	                         }|j                  d   j                  t        t                            | j                  |       | j                  |       y)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   r6   rk   rU   r   r   r   r"  r   rO  s         r   test_stopServiceWhileRestartingz2ClientServiceTests.test_stopServiceWhileRestarting  s     **5*NG
##D) $//1$002 	"11':J:L2MN.//0r   c                    t               }| j                  d|      \  }}|j                         }|j                         }| j                  | j	                  |             | j                  | j	                  |             y)z
        Calling L{ClientService.stopService} on a stopped service
        returns a L{Deferred} that has already fired with L{None}.
        Fr	  NrF  )r&   r~   rH  r   rP  rQ  s         r    test_stopServiceOnStoppedServicez3ClientServiceTests.test_stopServiceOnStoppedService  sv    
 ))%u)M
7#//1$002$../@AB$../ABCr   c                 l    dgfd}| j                  |d      \  }}| j                  dd          y)z
        The C{prepareConnection} callable is called after
        L{ClientService.startService} once the connection is made.
        r   c                      dxx   dz  cc<   y Nr   r)   r   _protopreparess    r   prepareConnectionz[ClientServiceTests.test_prepareConnectionCalledWhenServiceStarts.<locals>.prepareConnection2      QK1Kr   T)r]  rU   r)   N)r   r\   )r&   r]  r   r   r\  s       @r   -test_prepareConnectionCalledWhenServiceStartsz@ClientServiceTests.test_prepareConnectionCalledWhenServiceStarts+  sG    
 3	 **/d + 
G 	HQK(r   c                     g fd}| j                  |      \  }}| j                  |j                  d   d          y)zf
        The C{prepareConnection} callable is passed the connected protocol
        instance.
        c                 (    j                  |        y r"   rm   )protonewProtocolss    r   r]  zVClientServiceTests.test_prepareConnectionCalledWithProtocol.<locals>.prepareConnectionA  s    &r   r]  r   N)r   rO   r   )r&   r]  r   r   rd  s       @r   (test_prepareConnectionCalledWithProtocolz;ClientServiceTests.test_prepareConnectionCalledWithProtocol:  sN    
 	' **/ + 
G 	R44Q7aIr   c                 `   dgfd}t               }| j                  |d|      \  }}|j                  d   j                  t	        d             | j                  dd          |j                  t               |j                  d   j                  d       | j                  dd          y)zf
        The C{prepareConnection} callback is invoked only once a connection is
        made.
        r   c                      dxx   dz  cc<   y rY  r   rZ  s    r   r]  z]ClientServiceTests.test_prepareConnectionCalledAfterConnectionMade.<locals>.prepareConnectionP  r^  r   F)r]  r   r~   zconnection attempt failedr)   N)	r   r   r   r+   r   r\   r
  r  r6   r&   r]  r~   r   r   r\  s        @r   /test_prepareConnectionCalledAfterConnectionMadezBClientServiceTests.test_prepareConnectionCalledAfterConnectionMadeI  s    
 3	 **/e + 
G 	""9-H#IJHQK(*+
##D)HQK(r   c                 2   dgfd}t               }| j                  ||      \  }}| j                  dd          |j                  d   j	                  t        t                            |j                  t               | j                  dd          y)z
        The C{prepareConnection} callback is invoked each time a connection is
        made, including on reconnection.
        r   c                      dxx   dz  cc<   y rY  r   rZ  s    r   r]  zUClientServiceTests.test_prepareConnectionCalledOnReconnect.<locals>.prepareConnectiong  r^  r   r]  r~   r)   r{   N)	r   r   r\   r   r   r   r"  r
  r  ri  s        @r   'test_prepareConnectionCalledOnReconnectz:ClientServiceTests.test_prepareConnectionCalledOnReconnect`  s    
 3	 **/u + 
G 	HQK( 	"11':J:L2MN*+HQK(r   c                     t               fd}| j                  |      \  }}| j                  |j                               }| j	                  |       y)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 r"   r   )rc  sentinels    r   r]  zVClientServiceTests.test_prepareConnectionReturnValueIgnored.<locals>.prepareConnection  s    Or   re  N)r   r   r   r   assertNotIdentical)r&   r]  r   r   r2   rq  s        @r   (test_prepareConnectionReturnValueIgnoredz;ClientServiceTests.test_prepareConnectionReturnValueIgnoredw  sT     8	 **=N*OG%%g&;&;&=>&1r   c                    g t               fd}| j                  |      \  }}|j                         }| j                  |       j	                  d       | j                  |j                  d   | j                  |             y)z
        The C{prepareConnection} callable returns a deferred and calls to
        L{ClientService.whenConnected} wait until it fires.
        c                 *    j                  |        S r"   rb  )rc  newProtocolDeferredrd  s    r   r]  zVClientServiceTests.test_prepareConnectionReturningADeferred.<locals>.prepareConnection  s    &&&r   re  Nr   )r   r   r   r   r6   rO   r   r   )r&   r]  r   r   whenConnectedDeferredrv  rd  s        @@r   (test_prepareConnectionReturningADeferredz;ClientServiceTests.test_prepareConnectionReturningADeferred  s    
 &j	' **=N*OG ' 5 5 712$$T*##A&(<(<=R(S	
r   c                 d   t               }d }| j                  ||      \  }}|j                  d      }| j                  |       |j	                  t
               | j                  |       |j	                  t
               | j                  t        | j                  |      j                         y)zs
        The connection attempt counts as a failure when the
        C{prepareConnection} callable throws.
        c                     t               r"   )r"  )r[  s    r   r]  zJClientServiceTests.test_prepareConnectionThrows.<locals>.prepareConnection  s    "$$r   rm  r{   r)  N)
r   r   r   r   r
  r  rO   r"  r   type)r&   r~   r]  r   r   rw  s         r   test_prepareConnectionThrowsz/ClientServiceTests.test_prepareConnectionThrows  s    
 	% **/u + 
G !( 5 5 5 J12*+12*+d223HINN	
r   )returnN)%r;   r<   r=   r>   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r   r$  r'  r1  r?  rA  rD  rI  rM  rR  rT  rV  r_  rf  rj  rn  rs  rx  r|  r   r   r   r   r     s     HT26 : +8
"J( 
 
02"
*$+L"MB*81t0& 3
21.10D)J).).2&
.
r   r   )F)0r>   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.internet.testingr   twisted.loggerr   r   twisted.python.failurer   twisted.trial.unittestr   r   r   r    r#   rH   ry   r   r   r   r  r   r   r   r   <module>r     s   
  & - ( 
 " ;  8 ' 4 : * @	 "#=* =* $=*@ !: . ^  6 !: .V18 V1rC- C-L" "( &F &8 :$  z

, z

r   