
    Vh2                        d Z ddlZddlZddlZ	 ddlZddlmZ ddlm	Z	m
Z
 ddlmZmZ ddlmZmZ ddlmZmZmZmZmZmZmZmZmZmZmZ ddlmZ dd	lm Z  dd
l!m"Z"  ee	jF                  jI                  e
       d       G d de"             Z% ee	jF                  jI                  e
       d       G d de"             Z&y# e$ r dZY w xY w)z
Whitebox tests for TCP APIs.
    N)skipIf)
interfacesreactor)gatherResultsmaybeDeferred)ProtocolServerFactory)_ACCEPT_ERRORSEAGAINECONNABORTEDEINPROGRESSEMFILEENFILEENOBUFSENOMEMEPERMEWOULDBLOCKPort)log)platform)TestCasez?This test only applies to reactors that implement IReactorFDsetc                   h    e Zd ZdZdZd Zd Zd Z e e	j                         dk(  d      d        Zy	)
PlatformAssumptionsTestsz4
    Test assumptions about platform behaviors.
    i    c                    g | _         t        ddlm} t	         |             dz   }t        j
                  t        j                        | _        t        j                  t        j                  || j                  d   f       |dz   | _	        y y )Nr   )_listOpenFDs      d   )
openSocketsresourcetwisted.internet.processr   len	getrlimitRLIMIT_NOFILEoriginalFileLimit	setrlimitsocketLimit)selfr   newLimits      O/home/dcms/DCMS/lib/python3.12/site-packages/twisted/test/test_tcp_internals.pysetUpzPlatformAssumptionsTests.setUp4   s{     ><>*Q.H%-%7%78N8N%OD"&&43I3I!3L(M  (#~D      c                 ^   | j                   r5| j                   j                         j                          | j                   r5t        ft        j                  t        j
                        d   }t        | j                  d   |      }t        j                  t        j
                  ||f       y y )Nr   r   )	r   popcloser    r#   r$   minr%   r&   )r(   currentHardLimitnewSoftLimits      r*   tearDownz!PlatformAssumptionsTests.tearDownF   s      "((* 
  (11(2H2HI!Lt55a8:JKLx55FV7WX  r,   c                 d    t        j                          }| j                  j                  |       |S )z|
        Create and return a new socket object, also tracking it so it can be
        closed in the test tear down.
        )socketr   append)r(   ss     r*   r5   zPlatformAssumptionsTests.socketR   s(    
 MMO"r,   win32zhWindows requires an unacceptably large amount of resources to provoke this behavior in the naive manner.c                    | j                         }|j                  d       |j                         d   }|j                  d       | j                         }|j	                  d       t        | j                        D ]  }	 | j                           | j                  d       | j                  |j                  d|f      dt        f       | j                  t         j                   |j"                        }| j                  |j                  d   t        t        f       y# t        $ r'}|j                  d   t        t        fv rY d}~  d}~ww xY w)	z
        Test that the platform accept(2) call fails with either L{EMFILE} or
        L{ENOBUFS} when there are too many file descriptors open.
        )	127.0.0.1r   r      Fr   Nz7Could provoke neither EMFILE nor ENOBUFS from platform.r:   )r5   bindgetsocknamelistensetblockingranger'   OSErrorargsr   r   failassertIn
connect_exr   assertRaiseserroraccept)r(   portserverPortNumberclientieexcs          r*   test_acceptOutOfFilesz.PlatformAssumptionsTests.test_acceptOutOfFiles[   s     {{}		"#++-a0A 5! t''( 	QA	Q IIOP 	{,<=>K@P	

 dkk:chhqkFG#45%  66!9 11 s    D  	E)E
EEN)__name__
__module____qualname____doc__r'   r+   r3   r5   r   r   getTyperO    r,   r*   r   r   )   sO    
 K.$
Y g%	5
%6
%6r,   r   c                   \   e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
 e ej                         d	k(  d
      d        Z e ej                         d	k(  d      d        Z eej"                  j%                  d      dk(  d      d        Z e ej                         d	k(  d      d        Zd Zy)SelectReactorTestsz7
    Tests for select-specific failure conditions.
    c                 r    g | _         g | _        t        j                  | j                  j                         y N)portsmessagesr   addObserverr6   r(   s    r*   r+   zSelectReactorTests.setUp   s&    
,,-r,   c                     t        j                  | j                  j                         t	        | j
                  D cg c]  }t        |j                         c}      S c c}w rY   )r   removeObserverr[   r6   r   rZ   r   stopListening)r(   ps     r*   r3   zSelectReactorTests.tearDown   s@    4==//0djjQmAOO<QRRQs   A c                 x    t        |||      }|j                          | j                  j                  |       |S )z
        Create, start, and return a new L{Port}, also tracking it so it can
        be stopped in the test tear down.
        	interface)r   startListeningrZ   r6   )r(   
portNumberfactoryrd   ra   s        r*   rI   zSelectReactorTests.port   s5    
 W	:	

!r,   c                     G fdd      }t               }| j                  d|d      }| j                  |d |              |j                          d}t        j
                     }| j                  D cg c],  }|j                  d      |k(  xr |j                  d	      |k(  . }}| j                  t        |      dd
| j                         yc c}w )a  
        Test behavior in the face of an exception from C{accept(2)}.

        On any exception which indicates the platform is unable or unwilling
        to allocate further resources to us, the existing port should remain
        listening, a message should be logged, and the exception should not
        propagate outward from doRead.

        @param socketErrorNumber: The errno to simulate from accept.
        c                       e Zd ZdZ fdZy)9SelectReactorTests._acceptFailureTest.<locals>.FakeSocketzI
            Pretend to be a socket in an overloaded system.
            c                 B    t        t        j                              rY   )rA   osstrerror)r(   socketErrorNumbers    r*   rH   z@SelectReactorTests._acceptFailureTest.<locals>.FakeSocket.accept   s    /=N1OPPr,   NrP   rQ   rR   rS   rH   )rn   s   r*   
FakeSocketrj      s    Qr,   rp   r   r:   rc   r5   z/Could not accept new connection ({acceptError})
log_formatacceptErrorz)Log event for failed accept not found in N)
r	   rI   patchdoReaderrno	errorcoder[   getassertGreaterr"   )	r(   rn   rp   rg   rI   expectedFormatexpectedErrorCodemsgmatchingMessagess	    `       r*   _acceptFailureTestz%SelectReactorTests._acceptFailureTest   s    	Q 	Q  /yyG{y;

4:<0J!OO,=> }}

  %7 @GGM*.??@
 
 	 !@DO	

s   71Cc                 ,    | j                  t              S )a*  
        C{accept(2)} can fail with C{EMFILE} when there are too many open file
        descriptors in the process.  Test that this doesn't negatively impact
        any other existing connections.

        C{EMFILE} mainly occurs on Linux when the open file rlimit is
        encountered.
        )r}   r   r]   s    r*   test_tooManyFilesFromAcceptz.SelectReactorTests.test_tooManyFilesFromAccept        &&v..r,   c                 ,    | j                  t              S )z
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ENOBUFS}.

        This mainly occurs on Windows and FreeBSD, but may be possible on
        Linux and other platforms as well.
        )r}   r   r]   s    r*   test_noBufferSpaceFromAcceptz/SelectReactorTests.test_noBufferSpaceFromAccept   s     &&w//r,   c                 ,    | j                  t              S )z
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ECONNABORTED}.

        It is not clear whether this is actually possible for TCP
        connections on modern versions of Linux.
        )r}   r   r]   s    r*    test_connectionAbortedFromAcceptz3SelectReactorTests.test_connectionAbortedFromAccept   s     &&|44r,   r8   z(Windows accept(2) cannot generate ENFILEc                 ,    | j                  t              S )z
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ENFILE}.

        This can occur on Linux when the system has exhausted (!) its supply
        of inodes.
        )r}   r   r]   s    r*   test_noFilesFromAcceptz)SelectReactorTests.test_noFilesFromAccept   r   r,   z(Windows accept(2) cannot generate ENOMEMc                 ,    | j                  t              S )a  
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ENOMEM}.

        On Linux at least, this can sensibly occur, even in a Python program
        (which eats memory like no ones business), when memory has become
        fragmented or low memory has been filled (d_alloc calls
        kmem_cache_alloc calls kmalloc - kmalloc only allocates out of low
        memory).
        )r}   r   r]   s    r*   test_noMemoryFromAcceptz*SelectReactorTests.test_noMemoryFromAccept   s     &&v..r,   INFRASTRUCTUREAZUREPIPELINESz(Hangs on Azure Pipelines due to firewallc                 8   t               }t        |_        | j                  d|d      | j	                  j
                         g fd}| j	                  |       fd}j                   |              d_        j                          | j                  j                  d       j                   |              j                          | j                  j                  d       j                          | j                  j                  d       y)z
        L{tcp.Port.doRead} increases the number of consecutive
        C{accept} calls it performs if all of the previous C{accept}
        calls succeed; otherwise, it reduces the number to the amount
        of successful calls.
        r   r:   rc   c                  4    D ]  } | j                           y rY   )r/   )rK   clientss    r*   closeAllz7SelectReactorTests.test_acceptScaling.<locals>.closeAll  s    ! r,   c                      t        j                   t         j                  t         j                        } | j                  dj	                         j
                  f       | S )Nr:   )r5   AF_INETSOCK_STREAMconnectgetHostrI   )rK   rI   s    r*   r   z6SelectReactorTests.test_acceptScaling.<locals>.connect  s?    ]]6>>63E3EFFNNK)<)<=>Mr,   r   N)r	   r   protocolrI   
addCleanupr`   r6   numberAcceptsrt   rx   assertEqual)r(   rg   r   r   r   rI   s       @@r*   test_acceptScalingz%SelectReactorTests.test_acceptScaling  s      /#yyG{y;**+	 	!	
 	wy!4--q1wy! 	++Q/ 	++Q/r,   z'Windows accept(2) cannot generate EPERMc                     ddg G  fdd      }t              D ]1  } j                  t        j                   |       j                         3  j                   j
                   |       j                         dgt               } j                  d|d      }d|_         j                  |d |              |j                           j                  |j                  d       y	)
z
        C{accept(2)} returning C{EPERM} is treated as a transient
        failure and the call retried no more than the maximum number
        of consecutive C{accept(2)} calls.
        {   r   c                        e Zd ZdZ fdZy)LSelectReactorTests.test_permissionFailure.<locals>.FakeSocketWithAcceptLimit
            Pretend to be a socket in an overloaded system whose
            C{accept} method can only be called
            C{maximumNumberOfAccepts} times.
            c                     dxx   dz  cc<   d   kD  rj                  d       t        t        t        j                  t                    )Nr   r   z(Maximum number of accept calls exceeded.)rC   rA   r   rl   rm   )oselfacceptCallsmaximumNumberOfAcceptsr(   s    r*   rH   zSSelectReactorTests.test_permissionFailure.<locals>.FakeSocketWithAcceptLimit.acceptC  sA    A!#q>$::IIHIeR[[%788r,   Nro   )r   r   r(   s   r*   FakeSocketWithAcceptLimitr   <  s    9r,   r   r:   rc   r5   r   N)r@   rF   r5   rG   rH   failureExceptionr	   rI   r   rs   rt   assertEquals)r(   r   _rg   rI   r   r   s   `    @@r*   test_permissionFailurez)SelectReactorTests.test_permissionFailure2  s     "%c	9 	9 -. 	PAfll,E,G,N,NO	P 	$//1J1L1S1STc/yyG{y; 

4#<#>? 	 	$,,a0r,   c                    t        t              }|j                  t        t        t
        g       t        d |D              dz    G fdd      }t               }| j                  d|d      }| j                  |d |              |j                          | j                  t        j                        }| j                  dt        |             | j                  |d   j                   j"                  d          y	)
z}
        A C{socket.error} raised by C{accept(2)} whose C{errno} is
        unknown to the recovery logic is logged.
        c              3   B   K   | ]  }t        |t              s|  y wrY   )
isinstanceint).0rG   s     r*   	<genexpr>zBSelectReactorTests.test_unknownSocketErrorRaise.<locals>.<genexpr>g  s     I%*UC2HIs   r   c                       e Zd ZdZ fdZy)YSelectReactorTests.test_unknownSocketErrorRaise.<locals>.FakeSocketWithUnknownAcceptErrorr   c                     t        d      )Nzunknown socket error message)rA   )r   unknownAcceptErrors    r*   rH   z`SelectReactorTests.test_unknownSocketErrorRaise.<locals>.FakeSocketWithUnknownAcceptError.acceptq  s    02PQQr,   Nro   )r   s   r*    FakeSocketWithUnknownAcceptErrorr   j  s    Rr,   r   r   r:   rc   r5   N)listr
   extendr   r   r   maxr	   rI   rs   rt   flushLoggedErrorsr5   rG   r   r"   valuerB   )r(   knownErrorsr   rg   rI   failuresr   s         @r*   test_unknownSocketErrorRaisez/SelectReactorTests.test_unknownSocketErrorRaise^  s    
 >*FE;78 I;IIAM 		R 	R  /yyG{y;

4#C#EF))&,,7CM*!**//24FGr,   N)rP   rQ   rR   rS   r+   r3   rI   r}   r   r   r   r   r   rT   r   r   rl   environrw   r   r   r   rU   r,   r*   rW   rW      s    
.
S'
R	/05 H')+UV/ W/ H')+UV/ W/ 


'(,<<2'0	'0R H')+TU)1 V)1VHr,   rW   )'rS   ru   rl   r5   r    ImportErrorunittestr   twisted.internetr   r   twisted.internet.deferr   r   twisted.internet.protocolr   r	   twisted.internet.tcpr
   r   r   r   r   r   r   r   r   r   r   twisted.pythonr   twisted.python.runtimer   twisted.trial.unittestr   IReactorFDSet
providedByr   rW   rU   r,   r*   <module>r      s   
  	   0 ? =     + +   ++G44EX6x X6	X6v   ++G44EpH pH	pH{  Hs   C C
C