o
    ba                     @   s<  d Z ddlZddlmZ ddlmZmZmZmZm	Z	m
Z
 ddlmZmZmZ ddlmZ ddlmZ G dd	 d	ZG d
d deejZG dd deejZG dd deZG dd deZG dd dejZeee	d dG dd deZeee	d dG dd deZeee	d dG dd deZ dS )zG
Tests for implementations of L{IReactorUDP} and L{IReactorMulticast}.
    N)skipIf)defererror
interfacesprotocolreactorudp)DeferredgatherResultsmaybeDeferred)runtime)TestCasec                   @   s0   e Zd ZdZdZdZdd Zdd Zdd ZdS )	Mixinr   Nc                 C   s
   g | _ d S N)packetsself r   7/usr/lib/python3/dist-packages/twisted/test/test_udp.py__init__      
zMixin.__init__c                 C   s0   d| _ | jd ur| jd }| _|d  d S d S N   )startedstartedDeferredcallbackr   dr   r   r   startProtocol   s
   
zMixin.startProtocolc                 C   s
   d| _ d S r   )stoppedr   r   r   r   stopProtocol#   r   zMixin.stopProtocol)	__name__
__module____qualname__r   r   r   r   r   r    r   r   r   r   r      s    r   c                   @   s   e Zd ZdZdZdd ZdS )ServerNr   c                 C   s:   | j ||f | jd ur| jd }| _|d  d S d S r   r   appendpacketReceivedr   )r   dataaddrr   r   r   r   datagramReceived+   s
   
zServer.datagramReceived)r!   r"   r#   r'   refusedr*   r   r   r   r   r$   '   s    r$   c                   @   s,   e Zd ZdZdZdd Zdd Zdd ZdS )	ClientNr   c                 C   s6   | j | | jd ur| jd }| _|d  d S d S r   r%   )r   r(   r   r   r   r   r*   7   s
   
zClient.datagramReceivedc                 C   s,   | j d ur| j d }| _ || || _d S r   )r   errbackfailure)r   r.   r   r   r   r   connectionFailed=   s   


zClient.connectionFailedc                 C   2   | j d ur| j d }| _ |td d| _d S Nyupr   r   r-   r   ConnectionRefusedErrorr+   r   r   r   r   connectionRefusedC      

zClient.connectionRefused)r!   r"   r#   r'   r+   r*   r/   r5   r   r   r   r   r,   2   s    r,   c                   @      e Zd Zdd ZdS )
GoodClientc                 C   r0   r1   r3   r   r   r   r   r5   K   r6   zGoodClient.connectionRefusedN)r!   r"   r#   r5   r   r   r   r   r8   J       r8   c                   @   s   e Zd ZdZdS )BadClientErrorzf
    Raised by BadClient at the end of every datagramReceived call to try and
    screw stuff up.
    N)r!   r"   r#   __doc__r   r   r   r   r:   R   s    r:   c                   @   s$   e Zd ZdZdZdd Zdd ZdS )	BadClientz
    A DatagramProtocol which always raises an exception from datagramReceived.
    Used to test error handling behavior in the reactor for that method.
    Nc                 C   s
   || _ dS )ze
        Set the Deferred which will be called back when datagramReceived is
        called.
        N)r   r   r   r   r   setDeferreda   s   
zBadClient.setDeferredc                 C   s*   | j d ur| j d }| _ || td)NzApplication code is very buggy!)r   r   r:   )r   bytesr)   r   r   r   r   r*   h   s   

zBadClient.datagramReceived)r!   r"   r#   r;   r   r=   r*   r   r   r   r   r<   Y   s
    r<   !This reactor does not support UDPc                   @   sj   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zee	j
ddkddd Zdd Zdd Zdd ZdS )UDPTestsc                    s<   t  }t  }|_tjd|dd  fdd}||S )zu
        The C{type} of the host address of a listening L{DatagramProtocol}'s
        transport is C{"UDP"}.
        r   	127.0.0.1	interfacec                    s      }|jd   S )NUDP)getHostassertEqualtypestopListening)ignoredr)   pr   r   r   	cbStartedz   s   z+UDPTests.test_oldAddress.<locals>.cbStartedr$   r   r	   r   r   	listenUDPaddCallback)r   serverr   rL   r   rJ   r   test_oldAddressq   s
   
zUDPTests.test_oldAddressc                    sR   t  t  }_tjddd  fdd}fdd}|||S )z
        The L{DatagramProtocol}'s C{startProtocol} and C{stopProtocol}
        methods are called when its transports starts and stops listening,
        respectively.
        r   rA   rB   c                    s$    jd  jd   S )Nr   r   )rF   r   r   rH   rI   port1r   rP   r   r   rL      s   z*UDPTests.test_startStop.<locals>.cbStartedc                    s     jd d S r   )rF   r   rR   )r   rP   r   r   	cbStopped   s   z*UDPTests.test_startStop.<locals>.cbStoppedrM   )r   r   rL   rU   r   rS   r   test_startStop   s   zUDPTests.test_startStopc                    sF   t  t  }_tjddd}dd   fdd}| |S )zr
        Re-listening with the same L{DatagramProtocol} re-invokes the
        C{startProtocol} callback.
        r   rA   rB   c                 S   s   |  S r   rH   )rI   portr   r   r   rL         z'UDPTests.test_rebind.<locals>.cbStartedc                    s*   t   }_tjddd}| |S Nr   rA   rB   )r   r	   r   r   rN   rO   )rI   r   rK   rL   rP   r   r   rU      s   z'UDPTests.test_rebind.<locals>.cbStoppedrM   )r   r   rK   rU   r   r[   r   test_rebind   s   zUDPTests.test_rebindc                    sX   t  t  }_tjddd  fdd}||  fdd}|| |S )z
        A L{CannotListenError} exception is raised when attempting to bind a
        second protocol instance to an already bound port
        r   rA   rB   c                    s>      j  t }jtjtj  j	|dd d S )NrA   rB   )
rF   rE   	transportr$   assertRaisesr   CannotListenErrorr   rN   rX   )rI   server2rX   r   rP   r   r   rL      s   
z*UDPTests.test_bindError.<locals>.cbStartedc                    s      S r   rW   rR   rX   r   r   
cbFinished   rY   z+UDPTests.test_bindError.<locals>.cbFinishedrM   )r   r   rL   rc   r   ra   r   test_bindError   s   

zUDPTests.test_bindErrorc                    s   t  t  }_tjdddt  t   _ fdd}||} fdd}||  fdd	}|| fd
d}|| |S )z
        Datagrams can be sent with the transport's C{write} method and
        received via the C{datagramReceived} callback method.
        r   rA   rB   c                    s   t jd dd_S rZ   )r   rN   port2rR   )clientclientStartedr   r   r   cbServerStarted   s   z2UDPTests.test_sendPackets.<locals>.cbServerStartedc                    s   j dj  j j  }j  }t  }_j d|j|jf ddd|j|jffg fdd tj	 d |gdd	S )
NrA      hello)   a)   bN   cc                    s6   rt   }_|  jjd  |S d S Nr   )r   r	   r'   rO   r]   writepop)rI   nextClientWrite)cbClientSendrf   clientWritesrP   r   r   rq      s   
zHUDPTests.test_sendPackets.<locals>.cbClientStarted.<locals>.cbClientSendTfireOnOneErrback)
r]   connectrE   rX   r   r	   r'   rn   hostDeferredList)rI   cAddrsAddr
serverSend)rf   rP   )rq   rr   r   cbClientStarted   s   


z2UDPTests.test_sendPackets.<locals>.cbClientStartedc                    s`    j  }j  } jd|j|jffg |j|jf}jd|fd|fd|fg d S )Nri   rj   rk   rl   )r]   rE   rF   r   rv   rX   )rI   rx   ry   
clientAddrrf   r   rP   r   r   cbSendsFinished   s   

z2UDPTests.test_sendPackets.<locals>.cbSendsFinishedc                    s$   t jt  jt jjgddS NTrs   )r   rw   r   rH   re   rR   )rT   r   r   r   rc      s   
z-UDPTests.test_sendPackets.<locals>.cbFinished)r$   r   r	   r   r   rN   r8   rO   )r   serverStartedrh   r   r{   r~   rc   r   )rf   rg   rT   r   rP   r   test_sendPackets   s   




	zUDPTests.test_sendPacketsINFRASTRUCTUREAZUREPIPELINESz"Hangs on Pipelines due to firewallc                    s   t   t  } _tjd ddt t  }_tjdddtj||gdd} fdd}|| fdd	}|| |S )
z
        A L{ConnectionRefusedError} exception is raised when a connection
        attempt is actively refused by the other end.

        Note: This test assumes no one is listening on port 80 UDP.
        r   rA   rB   Trs   c                    s^   t   } _ jdd tdD ]} jd|f  jd|f d q|tj	S )NrA   P   
      %d)rA   r   )
r   r	   r   r]   ru   rangern   assertFailurer   r4   )rI   r5   ir}   r   r   rL     s   z2UDPTests.test_connectionRefused.<locals>.cbStartedc                    s"   t jt  jt jgddS r   )r   rw   r   rH   rR   )rX   re   r   r   rc   )  s   

z3UDPTests.test_connectionRefused.<locals>.cbFinished)	r8   r   r	   r   r   rN   r$   rw   rO   )r   rg   r   r   rL   rc   r   )rf   rX   re   r   rP   r   test_connectionRefused  s   


	zUDPTests.test_connectionRefusedc                 C   sV   t  }tjd|dd}| tj|jjdd |jdd | t|jjdd |	 S )a   
        A call to the transport's connect method fails with an
        L{InvalidAddressError} when a non-IP address is passed as the host
        value.

        A call to a transport's connect method fails with a L{RuntimeError}
        when the transport is already connected.
        r   rA   rB   	localhostr   )
r8   r   rN   r^   r   InvalidAddressErrorr]   ru   RuntimeErrorrH   )r   rf   rX   r   r   r   test_badConnect5  s   	zUDPTests.test_badConnectc                    s   t  fdd}| t tjdddfdd}|   tt	dg  fd	d
  S )zr
        When datagramReceived raises an exception it is logged but the port
        is not disconnected.
        c                    s*     t} t|ddt|f  dS )z
            Flush the exceptions which the reactor should have logged and make
            sure they're actually there.
               z'Incorrectly found %d errors, expected 2N)flushLoggedErrorsr:   rF   len)ignerrsr   r   r   cbCompletedN  s   
z8UDPTests.test_datagramReceivedError.<locals>.cbCompletedr   rA   rB   c                    s   t j fddS )z
            Disconnect the port we started and pass on whatever was given to us
            in case it was a Failure.
            c                        S r   r   r   resultr   r   <lambda>b      zHUDPTests.test_datagramReceivedError.<locals>.cbCleanup.<locals>.<lambda>)r   r   rH   addBothr   rb   r   r   	cbCleanup]  s   z6UDPTests.test_datagramReceivedError.<locals>.cbCleanup<   c                     s   sz d W n ty     Y nw jdd ddf } t }| j	| j
jf  fdd}fdd	}||| |j td
|jtd dS )a6  
            Send one packet to the listening BadClient.  Set up a 0.1 second
            timeout to do re-transmits in case the packet is dropped.  When two
            packets have been received by the BadClient, stop sending and let
            the finalDeferred's callbacks do some assertions.
            zNot enough packets receivedNzUDP Protocol lost its transportr   r   c                    s<      |  tdkrtd jd dS   dS )z
                A packet arrived.  Cancel the timeout for it, record it, and
                maybe finish the test.
                r   r   N)cancelr&   r   r   	callLaterr   )packet)finalDeferredmakeAttemptsucceededAttemptstimeoutCallr   r   cbPacketReceived  s
   

zRUDPTests.test_datagramReceivedError.<locals>.makeAttempt.<locals>.cbPacketReceivedc                    s
      dS )a  
                The packet wasn't received quickly enough.  Try sending another
                one.  It doesn't matter if the packet for which this was the
                timeout eventually arrives: makeAttempt throws away the
                Deferred on which this function is the errback, so when
                datagramReceived callbacks, so it won't be on this Deferred, so
                it won't raise an AlreadyCalledError.
                Nr   )err)r   r   r   ebPacketTimeout  s   
	zQUDPTests.test_datagramReceivedError.<locals>.makeAttempt.<locals>.ebPacketTimeoutg?z&Timed out in testDatagramReceivedError)fail	Exceptionr-   failIfIdenticalr]   ro   r   r	   r=   rn   rv   rX   addCallbacks
addErrbackr   r   r   TimeoutError)r   packetDeferredr   r   )r)   attemptsrf   r   r   r   r   )r   r   r   s  s,   
z8UDPTests.test_datagramReceivedError.<locals>.makeAttempt)
r   r	   rO   r<   r   rN   r   rE   listr   )r   r   r   r   )r)   r   rf   r   r   rX   r   r   r   test_datagramReceivedErrorG  s   



:z#UDPTests.test_datagramReceivedErrorc                 C   sR   G dd d}t dt }| |_|dd | | jg}| t|d dS )ai  
        C{'<broadcast>'} is an alternative way to say C{'255.255.255.255'}
        ({socket.gethostbyname("<broadcast>")} returns C{'255.255.255.255'}),
        so because it becomes a valid IP address, no deprecation warning about
        passing hostnames to L{twisted.internet.udp.Port.write} needs to be
        emitted by C{write()} in this case.
        c                   @   r7   )z6UDPTests.test_NoWarningOnBroadcast.<locals>.fakeSocketc                 S   s   d S r   r   )r   foobarr   r   r   sendto  s   z=UDPTests.test_NoWarningOnBroadcast.<locals>.fakeSocket.sendtoN)r!   r"   r#   r   r   r   r   r   
fakeSocket  r9   r   r   s   test)z<broadcast>i  N)	r   Portr$   socketrn   flushWarningstest_NoWarningOnBroadcastrF   r   )r   r   rK   warningsr   r   r   r     s   	z"UDPTests.test_NoWarningOnBroadcastN)r!   r"   r#   rQ   rV   r\   rd   r   r   osenvirongetr   r   r   r   r   r   r   r   r@   o   s    D
)ir@   c                   @   s8   e Zd ZdZeedsdZdd Zdd Z	dd	 Z
dS )
ReactorShutdownInteractionTestsz!Test reactor shutdown interactionNr?   c                 C   s    t  | _tjd| jdd| _dS )zStart a UDP portr   rA   rB   N)r$   rP   r   rN   rX   r   r   r   r   setUp  s   z%ReactorShutdownInteractionTests.setUpc                 C   s
   | j  S )zStop the UDP port)rX   rH   r   r   r   r   tearDown  s   
z(ReactorShutdownInteractionTests.tearDownc                    sh   t   t   }j_ fdd}|| fdd} | jjddjj jf  S )z0Test reactor shutdown while in a recvfrom() loopc                    s    j j  td jd  d S rm   )rP   r]   connectionLostr   r   r   rR   finishedr   r   r   pktRece  s   zQReactorShutdownInteractionTests.testShutdownFromDatagramReceived.<locals>.pktRecec                    s       d S r   )r   rR   r   r   r   flushErrors  s   zUReactorShutdownInteractionTests.testShutdownFromDatagramReceived.<locals>.flushErrorss@                                                                   rA   )	r   r	   rP   r'   rO   r]   rn   rE   rX   )r   prr   r   r   r   r    testShutdownFromDatagramReceived  s   

z@ReactorShutdownInteractionTests.testShutdownFromDatagramReceived)r!   r"   r#   r;   r   IReactorUDPr   skipr   r   r   r   r   r   r   r     s    r   'This reactor does not support multicastc                   @   s   e Zd Zejddkrej rdZ	e
edsdZ	dd Zdd	 Zd
d Zdd Zdd Zdd Zeej o>ej  ddd Zdd Zeej ddd ZdS )MulticastTestsr   r   z Does not work on Azure PipelinesNr   c                 C   sN   t  | _t | _td| j| _td| j| _| jj	d| jj
 j d S )Nr   rA   )r$   rP   r,   rf   r   listenMulticastrT   re   r]   ru   rE   rX   r   r   r   r   r     s
   zMulticastTests.setUpc                 C   s   t t| jjt| jjgS r   )r
   r   rT   rH   re   r   r   r   r   r     s
   

zMulticastTests.tearDownc                 C   sF   | j | jfD ]}| |j d |jd | |j d qd S )Nr   r   )rf   rP   rF   r]   getTTLsetTTL)r   or   r   r   testTTL  s
   zMulticastTests.testTTLc                    sx    jj d jj  jjd} fdd}||  fdd}|| fdd}|| |S )	zv
        Test that after loopback mode has been set, multicast packets are
        delivered to their sender.
        r   225.0.0.250c                    s(   t   }j_jjdd jf |S )Nri   r   r	   rP   r'   r]   rn   rX   rI   r   r)   r   r   r   cbJoined*  s   z.MulticastTests.test_loopback.<locals>.cbJoinedc                    sf    tjjd jjd  jj d jjdd jf t	 }t
d|jd  |S )Nr   r   ri   r   )rF   r   rP   r   r]   setLoopbackModegetLoopbackModern   rX   r	   r   r   r   r   r   r   r   cbPacket1  s   z.MulticastTests.test_loopback.<locals>.cbPacketc                    s     t jjd d S r   )rF   r   rP   r   rR   r   r   r   
cbNoPacket>  s   z0MulticastTests.test_loopback.<locals>.cbNoPacket)rF   rP   r]   r   rE   	joinGrouprO   )r   joinedr   r   r   r   r   r   test_loopback!  s   


zMulticastTests.test_loopbackc                    sj      jj d    jj d  jjd} jjd}t||g} fdd}|| |S )zK
        Test C{getOutgoingInterface} and C{setOutgoingInterface}.
        z0.0.0.0rA   c                    s,      jj d    jj d d S )NrA   )rF   rf   r]   getOutgoingInterfacerP   rR   r   r   r   cbInterfacesP  s   z3MulticastTests.test_interface.<locals>.cbInterfaces)rF   rf   r]   r   rP   setOutgoingInterfacer
   rO   )r   d1d2r   r   r   r   r   test_interfaceE  s   
zMulticastTests.test_interfacec                    sT    j jd} fdd}||  fdd}||  fdd}|| |S )zE
        Test that multicast a group can be joined and left.
        r   c                        j jdS Nr   )rf   r]   
leaveGrouprR   r   r   r   clientJoined]     z3MulticastTests.test_joinLeave.<locals>.clientJoinedc                    r   r   )rP   r]   r   rR   r   r   r   
clientLeftb  r   z1MulticastTests.test_joinLeave.<locals>.clientLeftc                    r   r   )rP   r]   r   rR   r   r   r   serverJoinedg  r   z3MulticastTests.test_joinLeave.<locals>.serverJoined)rf   r]   r   rO   )r   r   r   r   r   r   r   r   test_joinLeaveW  s   


zMulticastTests.test_joinLeavez2Windows' UDP multicast is not yet fully supported.c                 C   s   |  | jjdtjS )z
        Test that an attempt to join an address which is not a multicast
        address fails with L{error.MulticastJoinError}.
        rA   )r   rf   r]   r   r   MulticastJoinErrorr   r   r   r   test_joinFailureo  s   
zMulticastTests.test_joinFailurec                    sv   t  tdjj  jjd} fdd}|| fdd}|| fdd}|| |S )	zn
        Test that a multicast group can be joined and messages sent to and
        received from it.
        r   r   c                    s&   t   }j_jdd jf |S )N   hello worldr   r   r   )r)   cr   r   r   r     s   z/MulticastTests.test_multicast.<locals>.cbJoinedc                    s      jjd d d d S Nr   r   )rF   rP   r   rR   r   r   r   r     s   z/MulticastTests.test_multicast.<locals>.cbPacketc                    s    t j}| fdd |S )Nc                    r   r   r   r   passthroughr   r   r     r   z@MulticastTests.test_multicast.<locals>.cleanup.<locals>.<lambda>)r   rH   rO   r   r   )rK   r   r   cleanup  s   
z.MulticastTests.test_multicast.<locals>.cleanup)r$   r   r   rP   r]   rE   r   rO   )r   r   r   r   r   r   )r)   r   rK   r   r   test_multicast}  s   


zMulticastTests.test_multicastzjon non-linux platforms it appears multiple processes can listen, but not multiple sockets in same process?c                    s   t   tjd dd jt  tjdddtjjg} fdd}|	|  fdd}|	| fd	d
}|
| |S )z
        Test that multiple sockets can listen on the same multicast port and
        that they both receive multicast messages directed to that address.
        r   T)listenMultipler   c                    s6   t   } _t   }_ jdf t||gS )Nr   )r	   r'   r]   rn   r
   )rI   r   r   )firstClientportnosecondClienttheGroupr   r   r     s   z5MulticastTests.test_multiListen.<locals>.serverJoinedc                    s0     jd d d  jd d d d S r   )rF   r   rR   )r   r   r   r   r   
gotPackets  s   z3MulticastTests.test_multiListen.<locals>.gotPacketsc                    s.   t tjtjg}| fdd |S )Nc                    r   r   r   r   r   r   r   r     r   zBMulticastTests.test_multiListen.<locals>.cleanup.<locals>.<lambda>)r
   r   rH   rO   r   )	firstPort
secondPortr   r   r     s   z0MulticastTests.test_multiListen.<locals>.cleanup)r$   r   r   rE   rX   r
   rP   r]   r   rO   r   )r   r   r   r   r   r   )r   r   r   r   r   r   r   r   test_multiListen  s&   




zMulticastTests.test_multiListen)r!   r"   r#   r   r   r   r   platformisMacOSXr   r   IReactorMulticastr   r   r   r   r   r   r   r   	isWindowsisVistar   r   r   r   r   r   r   r     s0    $

 r   )!r;   r   unittestr   twisted.internetr   r   r   r   r   r   twisted.internet.deferr	   r
   r   twisted.pythonr   twisted.trial.unittestr   r   DatagramProtocolr$   ConnectedDatagramProtocolr,   r8   r   r:   r<   r   r@   r   r   r   r   r   r   r   <module>   s0      W6