U
    
W[                     @   s  d Z ddlmZm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mZ ddlmZmZ ddlmZ G d	d
 d
eZdd ZG dd dejZG dd dejZG dd deZG dd deZG dd deZG dd deZdd ZG dd dej Z!dS )z)
Test cases for L{twisted.names.server}.
    )divisionabsolute_import)verifyClass)defer)IProtocolFactory)dnserrorresolveserver)failurelog)unittestc                   @   s   e Zd ZdZdd ZdS )RaisedArgumentszD
    An exception containing the arguments raised by L{raiser}.
    c                 C   s   || _ || _d S Nargskwargsselfr   r    r   @/usr/lib/python3/dist-packages/twisted/names/test/test_server.py__init__   s    zRaisedArguments.__init__N)__name__
__module____qualname____doc__r   r   r   r   r   r      s   r   c                  O   s   t | |dS )z
    Raise a L{RaisedArguments} exception containing the supplied arguments.

    Used as a fake when testing the call signatures of  methods and functions.
    N)r   r   r   r   r   raiser   s    r   c                   @   s    e Zd ZdZdd Zdd ZdS )NoResponseDNSServerFactorya  
    A L{server.DNSServerFactory} subclass which does not attempt to reply to any
    received messages.

    Used for testing logged messages in C{messageReceived} without having to
    fake or patch the preceding code which attempts to deliver a response
    message.
    c                 C   s   dS )a  
        Deny all queries.

        @param message: See L{server.DNSServerFactory.allowQuery}
        @param protocol: See L{server.DNSServerFactory.allowQuery}
        @param address: See L{server.DNSServerFactory.allowQuery}

        @return: L{False}
        @rtype: L{bool}
        Fr   )r   messageprotocoladdressr   r   r   
allowQuery0   s    z%NoResponseDNSServerFactory.allowQueryc                 C   s   dS )z
        A noop send reply.

        @param protocol: See L{server.DNSServerFactory.sendReply}
        @param message: See L{server.DNSServerFactory.sendReply}
        @param address: See L{server.DNSServerFactory.sendReply}
        Nr   )r   r   r   r    r   r   r   	sendReply>   s    z$NoResponseDNSServerFactory.sendReplyN)r   r   r   r   r!   r"   r   r   r   r   r   '   s   r   c                   @   s(   e Zd ZdZG dd deZdd ZdS )RaisingDNSServerFactoryz
    A L{server.DNSServerFactory} subclass whose methods raise an exception
    containing the supplied arguments.

    Used for stopping L{messageReceived} and testing the arguments supplied to
    L{allowQuery}.
    c                   @   s   e Zd ZdZdS )z+RaisingDNSServerFactory.AllowQueryArgumentsG
        Contains positional and keyword arguments in C{args}.
        Nr   r   r   r   r   r   r   r   AllowQueryArgumentsR   s   r&   c                 O   s   |  ||dS )aC  
        Raise the arguments supplied to L{allowQuery}.

        @param args: Positional arguments which will be recorded in the raised
            exception.
        @type args: L{tuple}

        @param kwargs: Keyword args which will be recorded in the raised
            exception.
        @type kwargs: L{dict}
        N)r&   r   r   r   r   r!   W   s    z"RaisingDNSServerFactory.allowQueryN)r   r   r   r   	Exceptionr&   r!   r   r   r   r   r#   I   s   r#   c                   @   s(   e Zd ZdZG dd deZdd ZdS )RaisingProtocolzm
    A partial fake L{IProtocol} whose methods raise an exception containing the
    supplied arguments.
    c                   @   s   e Zd ZdZdS )z%RaisingProtocol.WriteMessageArgumentsr$   Nr%   r   r   r   r   WriteMessageArgumentsl   s   r)   c                 O   s   |  ||dS z
        Raises the supplied arguments.

        @param args: Positional arguments
        @type args: L{tuple}

        @param kwargs: Keyword args
        @type kwargs: L{dict}
        N)r)   r   r   r   r   writeMessageq   s    
zRaisingProtocol.writeMessageN)r   r   r   r   r'   r)   r+   r   r   r   r   r(   g   s   r(   c                   @   s   e Zd ZdZdd ZdS )NoopProtocolzT
    A partial fake L{dns.DNSProtocolMixin} with a noop L{writeMessage} method.
    c                 O   s   dS )z
        A noop version of L{dns.DNSProtocolMixin.writeMessage}.

        @param args: Positional arguments
        @type args: L{tuple}

        @param kwargs: Keyword args
        @type kwargs: L{dict}
        Nr   r   r   r   r   r+      s    zNoopProtocol.writeMessageN)r   r   r   r   r+   r   r   r   r   r,      s   r,   c                   @   s(   e Zd ZdZG dd deZdd ZdS )RaisingResolverzm
    A partial fake L{IResolver} whose methods raise an exception containing the
    supplied arguments.
    c                   @   s   e Zd ZdZdS )zRaisingResolver.QueryArgumentsr$   Nr%   r   r   r   r   QueryArguments   s   r.   c                 O   s   |  ||dS r*   )r.   r   r   r   r   query   s    
zRaisingResolver.queryN)r   r   r   r   r'   r.   r/   r   r   r   r   r-      s   r-   c                   @   s(   e Zd ZdZG dd deZdd ZdS )RaisingCachez}
    A partial fake L{twisted.names.cache.Cache} whose methods raise an exception
    containing the supplied arguments.
    c                   @   s   e Zd ZdZdS )z!RaisingCache.CacheResultArgumentsr$   Nr%   r   r   r   r   CacheResultArguments   s   r1   c                 O   s   |  ||dS r*   )r1   r   r   r   r   cacheResult   s    
zRaisingCache.cacheResultN)r   r   r   r   r'   r1   r2   r   r   r   r   r0      s   r0   c                 O   sD   g }t |j | t j|j ||| | dd |D | dS )a  
    Assert that the callable logs the expected messages when called.

    XXX: Put this somewhere where it can be re-used elsewhere. See #6677.

    @param testCase: The test case controlling the test which triggers the
        logged messages and on which assertions will be called.
    @type testCase: L{unittest.SynchronousTestCase}

    @param expectedMessages: A L{list} of the expected log messages
    @type expectedMessages: L{list}

    @param callable: The function which is expected to produce the
        C{expectedMessages} when called.
    @type callable: L{callable}

    @param args: Positional arguments to be passed to C{callable}.
    @type args: L{list}

    @param kwargs: Keyword arguments to be passed to C{callable}.
    @type kwargs: L{dict}
    c                 S   s   g | ]}|d  d qS )r   r   r   ).0mr   r   r   
<listcomp>   s     z$assertLogMessage.<locals>.<listcomp>N)r   ZaddObserverappendZ
addCleanupZremoveObserverassertEqual)ZtestCaseZexpectedMessagescallabler   r   ZloggedMessagesr   r   r   assertLogMessage   s    
r9   c                   @   s  e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Z d<d= Z!d>d? Z"d@dA Z#dBdC Z$dDdE Z%dFdG Z&dHdI Z'dJdK Z(dLdM Z)dNdO Z*dPdQ Z+dRdS Z,dTdU Z-dVdW Z.dXdY Z/dZd[ Z0d\d] Z1d^d_ Z2d`da Z3dbdc Z4ddde Z5dfdg Z6dhdi Z7djdk Z8dldm Z9dndo Z:dpdq Z;drds Z<dtdu Z=dvdw Z>dxdy Z?dzd{ Z@d|d} ZAd~d ZBdd ZCdS )DNSServerFactoryTestsz/
    Tests for L{server.DNSServerFactory}.
    c                 C   s   |  t jtj dS )zd
        L{server.DNSServerFactory.resolver} is a L{resolve.ResolverChain}
        instance
        N)ZassertIsInstancer
   DNSServerFactoryresolverr	   ZResolverChainr   r   r   r   test_resolverType   s    z'DNSServerFactoryTests.test_resolverTypec                 C   s   |  t jjg  dS )zn
        L{server.DNSServerFactory.resolver} is an empty L{resolve.ResolverChain}
        by default.
        N)r7   r
   r;   r<   	resolversr=   r   r   r   test_resolverDefaultEmpty   s    
z/DNSServerFactoryTests.test_resolverDefaultEmptyc                 C   s&   t  }| tj|gdjj|g dS )z
        L{server.DNSServerFactory.__init__} accepts an C{authorities}
        argument. The value of this argument is a list and is used to extend the
        C{resolver} L{resolve.ResolverChain}.
        )authoritiesNobjectr7   r
   r;   r<   r?   r   ZdummyResolverr   r   r   test_authorities   s    z&DNSServerFactoryTests.test_authoritiesc                 C   s&   t  }| tj|gdjj|g dS )z
        L{server.DNSServerFactory.__init__} accepts a C{caches} argument. The
        value of this argument is a list and is used to extend the C{resolver}
        L{resolve.ResolverChain}.
        cachesNrB   rD   r   r   r   test_caches
  s    z!DNSServerFactoryTests.test_cachesc                 C   s&   t  }| tj|gdjj|g dS )z
        L{server.DNSServerFactory.__init__} accepts a C{clients} argument. The
        value of this argument is a list and is used to extend the C{resolver}
        L{resolve.ResolverChain}.
        clientsNrB   rD   r   r   r   test_clients  s    z"DNSServerFactoryTests.test_clientsc                 C   s\   G dd dt }G dd dt }G dd dt }| tj|g|g|gdjj|||g dS )	zz
        L{server.DNSServerFactory.resolver} contains an ordered list of
        authorities, caches and clients.
        c                   @   s   e Zd ZdS )z@DNSServerFactoryTests.test_resolverOrder.<locals>.DummyAuthorityNr   r   r   r   r   r   r   DummyAuthority*  s   rM   c                   @   s   e Zd ZdS )z<DNSServerFactoryTests.test_resolverOrder.<locals>.DummyCacheNrL   r   r   r   r   
DummyCache-  s   rN   c                   @   s   e Zd ZdS )z=DNSServerFactoryTests.test_resolverOrder.<locals>.DummyClientNrL   r   r   r   r   DummyClient0  s   rO   )rA   rG   rJ   NrB   )r   rM   rN   rO   r   r   r   test_resolverOrder$  s    z(DNSServerFactoryTests.test_resolverOrderc                 C   s   |  t j dS )zI
        L{server.DNSServerFactory.cache} is L{None} by default.
        N)ZassertIsNoner
   r;   cacher=   r   r   r   test_cacheDefault;  s    z'DNSServerFactoryTests.test_cacheDefaultc                 C   s&   t  }| tjt  |gdj| dS )z
        L{server.DNSServerFactory.__init__} assigns the last object in the
        C{caches} list to L{server.DNSServerFactory.cache}.
        rF   N)rC   r7   r
   r;   rQ   rD   r   r   r   test_cacheOverrideB  s
    z(DNSServerFactoryTests.test_cacheOverridec                 C   s   |  t j dS )z
        L{server.DNSServerFactory.canRecurse} is a flag indicating that this
        server is capable of performing recursive DNS lookups. It defaults to
        L{False}.
        N)assertFalser
   r;   
canRecurser=   r   r   r   test_canRecurseDefaultM  s    z,DNSServerFactoryTests.test_canRecurseDefaultc                 C   s   |  tjdgdjd dS )z~
        L{server.DNSServerFactory.__init__} sets C{canRecurse} to L{True} if it
        is supplied with C{clients}.
        NrI   T)r7   r
   r;   rU   r=   r   r   r   test_canRecurseOverrideV  s     z-DNSServerFactoryTests.test_canRecurseOverridec                 C   s   |  t j dS )zJ
        L{server.DNSServerFactory.verbose} defaults to L{False}.
        N)rT   r
   r;   verboser=   r   r   r   test_verboseDefault_  s    z)DNSServerFactoryTests.test_verboseDefaultc                 C   s   |  tjddj dS )z
        L{server.DNSServerFactory.__init__} accepts a C{verbose} argument which
        overrides L{server.DNSServerFactory.verbose}.
        TrX   N)
assertTruer
   r;   rX   r=   r   r   r   test_verboseOverridef  s    z*DNSServerFactoryTests.test_verboseOverridec                 C   s   |  tttj dS )zL
        L{server.DNSServerFactory} implements L{IProtocolFactory}.
        N)r[   r   r   r
   r;   r=   r   r   r   test_interfacen  s    z$DNSServerFactoryTests.test_interfacec                 C   s   |  tjjtj dS )zU
        L{server.DNSServerFactory.protocol} defaults to L{dns.DNSProtocol}.
        N)assertIsr
   r;   r   r   ZDNSProtocolr=   r   r   r   test_defaultProtocolu  s    z*DNSServerFactoryTests.test_defaultProtocolc                    s^   G dd dt }|   fdd}t }||_|jdd}|  |fi f||j|jf dS )z
        L{server.DNSServerFactory.buildProtocol} builds a protocol by calling
        L{server.DNSServerFactory.protocol} with its self as a positional
        argument.
        c                   @   s   e Zd ZdZdZdZdS )zNDNSServerFactoryTests.test_buildProtocolProtocolOverride.<locals>.FakeProtocolN)r   r   r   factoryr   r   r   r   r   r   FakeProtocol  s   ra   c                     s   |  _ | _ S r   r   r   stubProtocolr   r   fakeProtocolFactory  s    zUDNSServerFactoryTests.test_buildProtocolProtocolOverride.<locals>.fakeProtocolFactoryN)Zaddr)rC   r
   r;   r   ZbuildProtocolr7   r   r   )r   ra   rd   fpr   rb   r   "test_buildProtocolProtocolOverride|  s    
z8DNSServerFactoryTests.test_buildProtocolProtocolOverridec                 C   s   t  }t| g |jd dS )zm
        L{server.DNSServerFactory._verboseLog} does not log messages unless
        C{verbose > 0}.
        Foo BarNr
   r;   r9   Z_verboseLogr   re   r   r   r   test_verboseLogQuiet  s    z*DNSServerFactoryTests.test_verboseLogQuietc                 C   s"   t jdd}t| dg|jd dS )zZ
        L{server.DNSServerFactory._verboseLog} logs a message if C{verbose > 0}.
           rZ   rh   Nri   rj   r   r   r   test_verboseLogVerbose  s    z,DNSServerFactoryTests.test_verboseLogVerbosec                 C   s.   t  }tdd}t| dg|j|ddd dS )z
        L{server.DNSServerFactory.messageReceived} logs about an empty query if
        the message had no queries and C{verbose} is C{>0}.
        rl   rZ   z$Empty query from ('192.0.2.100', 53)Nz192.0.2.1005   r   protor    )r   Messager   r9   messageReceivedr   r4   re   r   r   r   "test_messageReceivedLoggingNoQuery  s    
  z8DNSServerFactoryTests.test_messageReceivedLoggingNoQueryc                 C   sN   t  }|jdt jd |jdt jd tdd}t| dg|j|ddd dS )	z
        L{server.DNSServerFactory.messageReceived} logs the query types of all
        queries in the message if C{verbose} is set to C{1}.
        example.comnametyperl   rZ   z&MX AAAA query from ('192.0.2.100', 53)Nrn   rp   r   rr   addQueryZMXZAAAAr   r9   rs   rt   r   r   r   test_messageReceivedLogging1  s    
  z2DNSServerFactoryTests.test_messageReceivedLogging1c                 C   sN   t  }|jdt jd |jdt jd tdd}t| dg|j|ddd dS )	z
        L{server.DNSServerFactory.messageReceived} logs the repr of all queries
        in the message if C{verbose} is set to C{2}.
        rv   rw      rZ   zT<Query example.com MX IN> <Query example.com AAAA IN> query from ('192.0.2.100', 53)Nrn   rp   rz   rt   r   r   r   test_messageReceivedLogging2  s    
  z2DNSServerFactoryTests.test_messageReceivedLogging2c                    sN   t  }t }t  | tjd fdd |j|ddd | |j	  dS )zv
        L{server.DNSServerFactory.messageReceived} assigns a unix timestamp to
        the received message.
        timec                      s    S r   r   r   tr   r   <lambda>      zEDNSServerFactoryTests.test_messageReceivedTimestamp.<locals>.<lambda>Nrp   )
r   rr   r   rC   patchr
   r   rs   r7   timeReceivedrt   r   r   r   test_messageReceivedTimestamp  s    z3DNSServerFactoryTests.test_messageReceivedTimestampc                 C   s^   t  }t }t }t }| jtj|j|||d}|j\}}| ||||f | |i  dS )z
        L{server.DNSServerFactory.messageReceived} passes all messages to
        L{server.DNSServerFactory.allowQuery} along with the receiving protocol
        and origin address.
        rp   N)	r   rr   rC   r#   assertRaisesr&   rs   r   r7   )r   r   ZdummyProtocoldummyAddressre   er   r   r   r   r   test_messageReceivedAllowQuery  s      
z4DNSServerFactoryTests.test_messageReceivedAllowQueryc                    sj   G dd dt  G  fdddtj}| }| j |jt ddd}|j\\}}}}| |j	tj
 dS )z
        If C{allowQuery} returns C{False},
        L{server.DNSServerFactory.messageReceived} calls L{server.sendReply}
        with a message whose C{rCode} is L{dns.EREFUSED}.
        c                   @   s   e Zd ZdS )zFDNSServerFactoryTests.test_allowQueryFalse.<locals>.SendReplyExceptionNrL   r   r   r   r   SendReplyException  s   r   c                       s    e Zd Zdd Z fddZdS )zKDNSServerFactoryTests.test_allowQueryFalse.<locals>.RaisingDNSServerFactoryc                 _   s   dS )NFr   r   r   r   r   r!     s    zVDNSServerFactoryTests.test_allowQueryFalse.<locals>.RaisingDNSServerFactory.allowQueryc                    s    ||d S r   r   r   r   r   r   r"     s    zUDNSServerFactoryTests.test_allowQueryFalse.<locals>.RaisingDNSServerFactory.sendReplyN)r   r   r   r!   r"   r   r   r   r   r#     s   r#   Nrp   )r'   r
   r;   r   rs   r   rr   r   r7   rCodeZEREFUSED)r   r#   re   r   rq   r   r    r   r   r   r   test_allowQueryFalse  s      z*DNSServerFactoryTests.test_allowQueryFalsec                    sX   dg|_ g   fdd}t }td}t||| ||| |  ||dfg dS )a  
        Assert that the named method is called with the given message when it is
        passed to L{DNSServerFactory.messageReceived}.

        @param methodName: The name of the method which is expected to be
            called.
        @type methodName: L{str}

        @param message: The message which is expected to be passed to the
            C{methodName} method.
        @type message: L{dns.Message}
        Nc                    s     | ||f d S r   r6   r   r   r    ZreceivedMessagesr   r   fakeHandler3  s    z?DNSServerFactoryTests._messageReceivedTest.<locals>.fakeHandler)queriesr,   r
   r;   setattrrs   r7   )r   Z
methodNamer   r   r   r`   r   r   r   _messageReceivedTest!  s    
z*DNSServerFactoryTests._messageReceivedTestc                 C   s   |  dtjtjd dS )z
        L{DNSServerFactory.messageReceived} passes messages with an opcode of
        C{OP_QUERY} on to L{DNSServerFactory.handleQuery}.
        handleQueryZopCodeN)r   r   rr   ZOP_QUERYr=   r   r   r   test_queryMessageReceived=  s     z/DNSServerFactoryTests.test_queryMessageReceivedc                 C   s   |  dtjtjd dS )z
        L{DNSServerFactory.messageReceived} passes messages with an opcode of
        C{OP_INVERSE} on to L{DNSServerFactory.handleInverseQuery}.
        handleInverseQueryr   N)r   r   rr   Z
OP_INVERSEr=   r   r   r    test_inverseQueryMessageReceivedF  s     z6DNSServerFactoryTests.test_inverseQueryMessageReceivedc                 C   s   |  dtjtjd dS )z
        L{DNSServerFactory.messageReceived} passes messages with an opcode of
        C{OP_STATUS} on to L{DNSServerFactory.handleStatus}.
        handleStatusr   N)r   r   rr   Z	OP_STATUSr=   r   r   r   test_statusMessageReceivedO  s     z0DNSServerFactoryTests.test_statusMessageReceivedc                 C   s   |  dtjtjd dS )z
        L{DNSServerFactory.messageReceived} passes messages with an opcode of
        C{OP_NOTIFY} on to L{DNSServerFactory.handleNotify}.
        handleNotifyr   N)r   r   rr   Z	OP_NOTIFYr=   r   r   r   test_notifyMessageReceivedX  s     z0DNSServerFactoryTests.test_notifyMessageReceivedc                 C   s   |  dtjtjd dS )z
        L{DNSServerFactory.messageReceived} passes messages with an opcode of
        C{OP_UPDATE} on to L{DNSServerFactory.handleOther}.

        This may change if the implementation ever covers update messages.
        handleOtherr   N)r   r   rr   Z	OP_UPDATEr=   r   r   r   test_updateMessageReceiveda  s     z0DNSServerFactoryTests.test_updateMessageReceivedc                 C   s   t  t   }}t }|| | |j|g || | |j||g || | |j|g || | |jg  dS )z
        The C{connectionMade} and C{connectionLost} methods of
        L{DNSServerFactory} cooperate to keep track of all L{DNSProtocol}
        objects created by a factory which are connected.
        N)rC   r
   r;   ZconnectionMader7   ZconnectionsZconnectionLost)r   ZprotoAZprotoBr`   r   r   r   test_connectionTrackingl  s    



z-DNSServerFactoryTests.test_connectionTrackingc                 C   sh   t  }|d |d t }t |_| jtj|j	|t
 dd}|j\\}}| ||jd  dS )z
        L{server.DNSServerFactory.handleQuery} takes the first query from the
        supplied message and dispatches it to
        L{server.DNSServerFactory.resolver.query}.
           one.example.coms   two.example.comNr   r   )r   rr   r{   r
   r;   r-   r<   r   r.   r   r,   r   r7   r   )r   r4   re   r   r/   r   r   r   r   test_handleQuery~  s    

  z&DNSServerFactoryTests.test_handleQueryc                    s   t  }t  G  fdddt}| |_g fdd}||_t }|	d t
 }t }|j|||d t } | | ||||fi fg dS )aC  
        L{server.DNSServerFactory.handleQuery} adds
        L{server.DNSServerFactory.resolver.gotResolverResponse} as a callback to
        the deferred returned by L{server.DNSServerFactory.resolver.query}. It
        is called with the query response, the original protocol, message and
        origin address.
        c                       s   e Zd Z fddZdS )zDDNSServerFactoryTests.test_handleQueryCallback.<locals>.FakeResolverc                    s    S r   r   r   dr   r   r/     s    zJDNSServerFactoryTests.test_handleQueryCallback.<locals>.FakeResolver.queryNr   r   r   r/   r   r   r   r   FakeResolver  s   r   c                     s     | |f d S r   r   r   )gotResolverResponseArgsr   r   fakeGotResolverResponse  s    zODNSServerFactoryTests.test_handleQueryCallback.<locals>.fakeGotResolverResponser   r   N)r
   r;   r   DeferredrC   r<   gotResolverResponser   rr   r{   r,   r   callbackr7   )r   re   r   r   r4   rc   r   ZdummyResponser   )r   r   r   test_handleQueryCallback  s$    

z.DNSServerFactoryTests.test_handleQueryCallbackc                    s   t  }t  G  fdddt}| |_g fdd}||_t }|	d t
 }t }|j|||d tt } | | ||||fi fg dS )a?  
        L{server.DNSServerFactory.handleQuery} adds
        L{server.DNSServerFactory.resolver.gotResolverError} as an errback to
        the deferred returned by L{server.DNSServerFactory.resolver.query}. It
        is called with the query failure, the original protocol, message and
        origin address.
        c                       s   e Zd Z fddZdS )zCDNSServerFactoryTests.test_handleQueryErrback.<locals>.FakeResolverc                    s    S r   r   r   r   r   r   r/     s    zIDNSServerFactoryTests.test_handleQueryErrback.<locals>.FakeResolver.queryNr   r   r   r   r   r     s   r   c                     s     | |f d S r   r   r   )gotResolverErrorArgsr   r   fakeGotResolverError  s    zKDNSServerFactoryTests.test_handleQueryErrback.<locals>.fakeGotResolverErrorr   r   N)r
   r;   r   r   rC   r<   gotResolverErrorr   rr   r{   r,   r   r   Failurer'   Zerrbackr7   )r   re   r   r   r4   rc   r   ZstubFailurer   )r   r   r   test_handleQueryErrback  s$    

z-DNSServerFactoryTests.test_handleQueryErrbackc                 C   st   t  }g }g }g }| jtj|j|||ft t dd}|j\\}}| 	|j
| | 	|j| | 	|j| dS )z
        L{server.DNSServerFactory.gotResolverResponse} accepts a tuple of
        resource record lists and triggers a response message containing those
        resource record lists.
        Nr   r   r    )r
   r;   r   r(   r)   r   r   rr   r   r^   answers	authority
additional)r   re   r   r   r   r   r   r   r   r   r   test_gotResolverResponse  s       z.DNSServerFactoryTests.test_gotResolverResponsec              
   C   sd   t  }t|_t }d|_| jt|jg g g fd|dd}| 	dt
|tjg g g df|j|jf dS )z
        L{server.DNSServerFactory.gotResolverResponse} calls
        L{server.DNSServerFactory._responseFromMessage} to generate a response.
        rl   Nr   r   )r   r   r   r   r   )r   r   _responseFromMessager   rr   r   r   r   r   r7   dictOKr   r   r   r`   requestr   r   r   r   0test_gotResolverResponseCallsResponseFromMessage  s(      
  
zFDNSServerFactoryTests.test_gotResolverResponseCallsResponseFromMessagec                 C   s4   t  }tjddd}|j|df}| || dS )z
        L{server.DNSServerFactory._responseFromMessage} generates a response
        message which is a copy of the request message.
        F)answerrecAvr   N)r
   r;   r   rr   r   ZassertIsNotr   r`   r   responser   r   r   "test_responseFromMessageNewMessage  s    z8DNSServerFactoryTests.test_responseFromMessageNewMessagec                 C   sT   t  }d|_|jtjddd}d|_|jtjddd}| d|j|jf dS )z
        L{server.DNSServerFactory._responseFromMessage} generates a response
        message whose C{recAV} attribute is L{True} if
        L{server.DNSServerFactory.canRecurse} is L{True}.
        TF)r   r   TFN)r
   r;   rU   r   r   rr   r7   r   r   r`   Z	response1Z	response2r   r   r   *test_responseFromMessageRecursionAvailable  s    


z@DNSServerFactoryTests.test_responseFromMessageRecursionAvailablec                 C   s6   t  }t }d|_|j|d}| |j|j dS )z
        L{server.DNSServerFactory._responseFromMessage} generates a response
        message whose C{timeReceived} attribute has the same value as that found
        on the request.
        i  r   N)r
   r;   r   rr   r   r   r7   r   r   r   r   $test_responseFromMessageTimeReceived&  s
    z:DNSServerFactoryTests.test_responseFromMessageTimeReceivedc                 C   s6   t  }t }d|_|j|d}| |j|j dS )z
        L{server.DNSServerFactory._responseFromMessage} generates a response
        message whose C{maxSize} attribute has the same value as that found
        on the request.
        r   r   N)r
   r;   r   rr   ZmaxSizer   r7   r   r   r   r   test_responseFromMessageMaxSize4  s
    z5DNSServerFactoryTests.test_responseFromMessageMaxSizec                 C   s   |  tjtjj dS )z{
        L{server.DNSServerFactory} has a C{_messageFactory} attribute which is
        L{dns.Message} by default.
        N)r^   r   rr   r
   r;   _messageFactoryr=   r   r   r   test_messageFactoryB  s    z)DNSServerFactoryTests.test_messageFactoryc              
   C   sd   t  }| tdt t }| jt|j|tj	d}| 
dt|j|tj	|jddf|j|jf dS )a4  
        L{server.DNSServerFactory._responseFromMessage} calls
        C{dns._responseFromMessage} to generate a response
        message from the request message. It supplies the request message and
        other keyword arguments which should be passed to the response message
        initialiser.
        r   r   r   r   F)ZresponseConstructorr   r   r   authN)r
   r;   r   r   r   rr   r   r   r   r   r7   r   r   rU   r   r   r   r   r   r   +test_responseFromMessageCallsMessageFactoryJ  s$       
zADNSServerFactoryTests.test_responseFromMessageCallsMessageFactoryc                 C   sX   t  }|jt tjddgd}|jt tjddgd}| d|j|jf dS )z
        L{server.DNSServerFactory._responseFromMessage} marks the response
        message as authoritative if any of the answer records are authoritative.
        T)r   )r   r   Fr   N)r
   r;   r   r   rr   RRHeaderr7   r   r   r   r   r   ,test_responseFromMessageAuthoritativeMessagec  s      
zBDNSServerFactoryTests.test_responseFromMessageAuthoritativeMessagec              	   C   sR   t dd}t g}t g}t g}t| dg|j|||ft t dd dS )z
        L{server.DNSServerFactory.gotResolverResponse} logs the total number of
        records in the response if C{verbose > 0}.
        rl   rZ   zLookup found 3 recordsNr   )r   r   r   r9   r   r,   rr   )r   re   r   r   r   r   r   r   test_gotResolverResponseLoggings  s    



  z5DNSServerFactoryTests.test_gotResolverResponseLoggingc                 C   s   t t gd}t }|d t g}g }g }| jtj|j|||ft	 |dd}|j
\\}\}}	}
}| |jjd | || | |	| | |
| dS )z
        L{server.DNSServerFactory.gotResolverResponse} caches the response if at
        least one cache was provided in the constructor.
        rF   s   example.comNr   )r   r0   r   rr   r{   r   r   r1   r   r,   r   r7   rx   r^   )r   re   r4   ZexpectedAnswersZexpectedAuthorityZexpectedAdditionalr   r/   r   r   r   r   r   r   r   test_gotResolverResponseCaching  s&    

  z5DNSServerFactoryTests.test_gotResolverResponseCachingc                 C   sb   t  }t|_t }d|_| jt|jt	
t d|dd}| dt|tjdf|j|jf dS )z
        L{server.DNSServerFactory.gotResolverError} calls
        L{server.DNSServerFactory._responseFromMessage} to generate a response.
        rl   Nr   r   r   )r   r   r   r   rr   r   r   r   r   r   r   r   DomainErrorr7   r   ENAMEr   r   r   r   r   r   -test_gotResolverErrorCallsResponseFromMessage  s       
zCDNSServerFactoryTests.test_gotResolverErrorCallsResponseFromMessagec                 C   sL   t  }| jtj|jt|t t	 dd}|j
\\}}| |j| dS )a{  
        L{server.DNSServerFactory.gotResolver} accepts a L{failure.Failure} and
        triggers a response message whose rCode corresponds to the DNS error
        contained in the C{Failure}.

        @param responseError: The L{Exception} instance which is expected to
            trigger C{expectedMessageCode} when it is supplied to
            C{gotResolverError}
        @type responseError: L{Exception}

        @param expectedMessageCode: The C{rCode} which is expected in the
            message returned by C{gotResolverError} in response to
            C{responseError}.
        @type expectedMessageCode: L{int}
        Nr   )r
   r;   r   r(   r)   r   r   r   r   rr   r   r7   r   )r   ZresponseErrorZexpectedMessageCodere   r   r   r   r   r   r   _assertMessageRcodeForError  s      z1DNSServerFactoryTests._assertMessageRcodeForErrorc                 C   s   |  t tj dS )z
        L{server.DNSServerFactory.gotResolver} triggers a response message with
        an C{rCode} of L{dns.ENAME} if supplied with a L{error.DomainError}.
        N)r   r   r   r   r   r=   r   r   r    test_gotResolverErrorDomainError  s    z6DNSServerFactoryTests.test_gotResolverErrorDomainErrorc                 C   s   |  t tj dS )z
        L{server.DNSServerFactory.gotResolver} triggers a response message with
        an C{rCode} of L{dns.ENAME} if supplied with a
        L{error.AuthoritativeDomainError}.
        N)r   r   ZAuthoritativeDomainErrorr   r   r=   r   r   r   -test_gotResolverErrorAuthoritativeDomainError  s     zCDNSServerFactoryTests.test_gotResolverErrorAuthoritativeDomainErrorc                 C   s.   |  t tj | t}| t|d dS )z
        L{server.DNSServerFactory.gotResolver} triggers a response message with
        an C{rCode} of L{dns.ESERVER} if supplied with another type of error and
        logs the error.
        rl   N)r   KeyErrorr   ZESERVERZflushLoggedErrorsr7   len)r   r   r   r   r   test_gotResolverErrorOtherError  s    
z5DNSServerFactoryTests.test_gotResolverErrorOtherErrorc              	   C   s8   t dd}t| dg|jtt t t	 dd dS )zZ
        L{server.DNSServerFactory.gotResolver} logs a message if C{verbose > 0}.
        rl   rZ   zLookup failedNr   )
r   r9   r   r   r   r   r   r,   r   rr   rj   r   r   r   test_gotResolverErrorLogging  s    
  z2DNSServerFactoryTests.test_gotResolverErrorLoggingc                    s   t  }g   fdd|_tjddd}t t g|_t t g|_t t g|_|j	t
t d|dd | tjdddg  dS )	z
        L{server.DNSServerFactory.gotResolverError} does not allow request
        attributes to leak into the response ie it sends a response with AD, CD
        set to 0 and empty response record sections.
        c                    s
     |S r   r   r   r   r    Z	responsesr   r   r     r   zUDNSServerFactoryTests.test_gotResolverErrorResetsResponseAttributes.<locals>.<lambda>TZauthenticDataZcheckingDisabledNr      r   r   )r
   r;   r"   r   rr   rC   r   r   r   r   r   r   r   r   r7   r   r`   r   r   r   r   -test_gotResolverErrorResetsResponseAttributes  s    
  zCDNSServerFactoryTests.test_gotResolverErrorResetsResponseAttributesc                    s   t  }g   fdd|_tjddd}t t g|_t t g|_t t g|_|j	g g g fd|dd | 
tjdddg  dS )	a  
        L{server.DNSServerFactory.gotResolverResponse} does not allow request
        attributes to leak into the response ie it sends a response with AD, CD
        set to 0 and none of the records in the request answer sections are
        copied to the response.
        c                    s
     |S r   r   r   r   r   r   r     r   zXDNSServerFactoryTests.test_gotResolverResponseResetsResponseAttributes.<locals>.<lambda>Tr   Nr   r   r   )r
   r;   r"   r   rr   rC   r   r   r   r   r7   r   r   r   r   0test_gotResolverResponseResetsResponseAttributes  s    
  zFDNSServerFactoryTests.test_gotResolverResponseResetsResponseAttributesc                 C   sZ   t  }t }t }| jtj|jt ||d}|j	\}}| 
|||f | 
|i  dS )z
        If L{server.DNSServerFactory.sendReply} is supplied with a protocol
        *and* an address tuple it will supply that address to
        C{protocol.writeMessage}.
        r   N)r   rr   rC   r
   r;   r   r(   r)   r"   r   r7   )r   r4   r   re   r   r   r   r   r   r   test_sendReplyWithAddress+  s    
z/DNSServerFactoryTests.test_sendReplyWithAddressc                 C   sR   t  }t }| jtj|jt |dd}|j\}}| 	||f | 	|i  dS )z
        If L{server.DNSServerFactory.sendReply} is supplied with a protocol but
        no address tuple it will supply only a message to
        C{protocol.writeMessage}.
        Nr   )
r   rr   r
   r;   r   r(   r)   r"   r   r7   )r   r4   re   r   r   r   r   r   r   test_sendReplyWithoutAddress?  s    
z2DNSServerFactoryTests.test_sendReplyWithoutAddressc                 C   sN   |  tjddd  t }d|_tjdd}t| ddg|jt	 |d	d
 d	S )z
        If L{server.DNSServerFactory.sendReply} logs a "no answers" message if
        the supplied message has no answers.
        r   c                   S   s   dS NiQ r   r   r   r   r   r   W  r   zFDNSServerFactoryTests.test_sendReplyLoggingNoAnswers.<locals>.<lambda>Q r}   rZ   zReplying with no answers Processed query in 1.000 secondsNr   )
r   r
   r   r   rr   r   r;   r9   r"   r,   rt   r   r   r   test_sendReplyLoggingNoAnswersR  s    z4DNSServerFactoryTests.test_sendReplyLoggingNoAnswersc                 C   s   |  tjddd  t }|jtjtdd |j	tjtdd |j
tjtdd d|_tjdd}t| d	d
ddg|jt |dd dS )z
        If L{server.DNSServerFactory.sendReply} logs a message for answers,
        authority, additional if the supplied a message has records in any of
        those sections.
        r   c                   S   s   dS r   r   r   r   r   r   r   j  r   zHDNSServerFactoryTests.test_sendReplyLoggingWithAnswers.<locals>.<lambda>z	127.0.0.1)Zpayloadr   r}   rZ   z*Answers are <A address=127.0.0.1 ttl=None>z+Authority is <A address=127.0.0.1 ttl=None>z,Additional is <A address=127.0.0.1 ttl=None>r   Nr   )r   r
   r   r   rr   r   r6   r   ZRecord_Ar   r   r   r;   r9   r"   r,   rt   r   r   r    test_sendReplyLoggingWithAnswersd  s&    z6DNSServerFactoryTests.test_sendReplyLoggingWithAnswersc                 C   sF   t  }| jtj|jt t dd}|j\\}}| 	|j
tj dS )z
        L{server.DNSServerFactory.handleInverseQuery} triggers the sending of a
        response message with C{rCode} set to L{dns.ENOTIMP}.
        Nr   )r
   r;   r   r(   r)   r   r   rr   r   r7   r   ENOTIMPr   re   r   r   r   r   r   r   test_handleInverseQuery}  s      z-DNSServerFactoryTests.test_handleInverseQueryc                 C   s,   t dd}t| dg|jt t dd dS )zz
        L{server.DNSServerFactory.handleInverseQuery} logs the message origin
        address if C{verbose > 0}.
        rl   rZ   zInverse query from ('::1', 53)z::1ro   r   N)r   r9   r   r   rr   r,   rj   r   r   r   test_handleInverseQueryLogging  s    
z4DNSServerFactoryTests.test_handleInverseQueryLoggingc                 C   sF   t  }| jtj|jt t dd}|j\\}}| 	|j
tj dS )z
        L{server.DNSServerFactory.handleStatus} triggers the sending of a
        response message with C{rCode} set to L{dns.ENOTIMP}.
        Nr   )r
   r;   r   r(   r)   r   r   rr   r   r7   r   r   r   r   r   r   test_handleStatus  s      z'DNSServerFactoryTests.test_handleStatusc                 C   s,   t dd}t| dg|jt t dd dS )zt
        L{server.DNSServerFactory.handleStatus} logs the message origin address
        if C{verbose > 0}.
        rl   rZ   zStatus request from ('::1', 53)r   r   N)r   r9   r   r   rr   r,   rj   r   r   r   test_handleStatusLogging  s    
z.DNSServerFactoryTests.test_handleStatusLoggingc                 C   sF   t  }| jtj|jt t dd}|j\\}}| 	|j
tj dS )z
        L{server.DNSServerFactory.handleNotify} triggers the sending of a
        response message with C{rCode} set to L{dns.ENOTIMP}.
        Nr   )r
   r;   r   r(   r)   r   r   rr   r   r7   r   r   r   r   r   r   test_handleNotify  s      z'DNSServerFactoryTests.test_handleNotifyc                 C   s,   t dd}t| dg|jt t dd dS )zt
        L{server.DNSServerFactory.handleNotify} logs the message origin address
        if C{verbose > 0}.
        rl   rZ   zNotify message from ('::1', 53)r   r   N)r   r9   r   r   rr   r,   rj   r   r   r   test_handleNotifyLogging  s    
z.DNSServerFactoryTests.test_handleNotifyLoggingc                 C   sF   t  }| jtj|jt t dd}|j\\}}| 	|j
tj dS )z
        L{server.DNSServerFactory.handleOther} triggers the sending of a
        response message with C{rCode} set to L{dns.ENOTIMP}.
        Nr   )r
   r;   r   r(   r)   r   r   rr   r   r7   r   r   r   r   r   r   test_handleOther  s      z&DNSServerFactoryTests.test_handleOtherc                 C   s,   t dd}t| dg|jt t dd dS )zs
        L{server.DNSServerFactory.handleOther} logs the message origin address
        if C{verbose > 0}.
        rl   rZ   z$Unknown op code (0) from ('::1', 53)r   r   N)r   r9   r   r   rr   r,   rj   r   r   r   test_handleOtherLogging  s    
z-DNSServerFactoryTests.test_handleOtherLoggingN)Dr   r   r   r   r>   r@   rE   rH   rK   rP   rR   rS   rV   rW   rY   r\   r]   r_   rg   rk   rm   ru   r|   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r:      s   

						$$
r:   N)"r   Z
__future__r   r   Zzope.interface.verifyr   Ztwisted.internetr   Ztwisted.internet.interfacesr   Ztwisted.namesr   r   r	   r
   Ztwisted.pythonr   r   Ztwisted.trialr   r'   r   r   r;   r   r#   rC   r(   r,   r-   r0   r9   ZTestCaser:   r   r   r   r   <module>   s"   

"#