o
    b4d                     @   s  d 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 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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& ddl'm(Z( ddl)m*Z*m+Z+ dd Z,dd Z-G dd de+Z.G dd de/Z0dd Z1G dd de+Z2g dZ3eeG dd dZ4eee4 G dd de*Z5G dd  d Z6e(j7e8d!d"Z9d#S )$z.
Test cases for Twisted.names' root resolver.
    )implementer)verifyClass)DeferredTimeoutErrorgatherResultssucceed)IResolverSimple)clientroot)CNAMEENAMEHSINNSOKAMessageNameQueryRecord_ARecord_CNAME	Record_NSRRHeader)DNSNameErrorResolverError)Resolver)MemoryReactor)msg)util)SynchronousTestCaseTestCasec                 C   s   | \}}}|d j S )z
    From the result of a L{Deferred} returned by L{IResolver.lookupAddress},
    return the payload of the first record in the answer section.
    r   payloadresultsansauthadd r(   E/usr/lib/python3/dist-packages/twisted/names/test/test_rootresolve.pygetOnePayload&   s   

r*   c                 C   s   t |  S )z
    From the result of a L{Deferred} returned by L{IResolver.lookupAddress},
    return the first IPv4 address from the answer section.
    )r*   
dottedQuadr$   r(   r(   r)   getOneAddress/   s   r-   c                   @   s   e Zd ZdZdd Zdd Zdd Zg g g efdd	Zd&ddZ	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%S )'RootResolverTestsz3
    Tests for L{twisted.names.root.Resolver}.
    c                 C   s   t  }tg |d}|tdttdgd|}|j \}}|j\\}}t	 }	|	
| | |	jtdttg | |	jg  | |	jg  | |	jg  g }
||
j | |
g  |	jdd= d|	_|	jtdtdd |j|	 d |
d	 S )
aK  
        Invoke L{Resolver._query} and verify that it sends the correct DNS
        query.  Deliver a canned response to the query and return whatever the
        L{Deferred} returned by L{Resolver._query} fires with.

        @param filter: The value to pass for the C{filter} parameter to
            L{Resolver._query}.
        )reactor   foo.example.com)1.1.2.3i  )   N   	5.8.13.21r!   r   )r   r   _queryr   r   r   udpPortspopitem_sentPacketsr   fromStrassertEqualqueriesanswers	authority
additionaladdCallbackappendanswerr   r   	_protocoldatagramReceivedtoStr)selffilterr/   resolverd
portNumber	transportpacketaddressmessageresponser(   r(   r)   
_queryTest<   s.   	
zRootResolverTests._queryTestc              	   C   sJ   |  d\}}}| |tdtddddg | |g  | |g  dS )a)  
        L{Resolver._query} accepts a L{Query} instance and an address, issues
        the query, and returns a L{Deferred} which fires with the response to
        the query.  If a true value is passed for the C{filter} parameter, the
        result is a three-tuple of lists of records.
        Tr0   r4   r   ttlr!   N)rO   r:   r   r   )rE   rA   r=   r>   r(   r(   r)   test_filteredQueryg   s   z$RootResolverTests.test_filteredQueryc              	   C   sd   |  d}| |t | |jg  | |jtdtddddg | |jg  | |j	g  dS )z
        Similar to L{test_filteredQuery}, but for the case where a false value
        is passed for the C{filter} parameter.  In this case, the result is a
        L{Message} instance.
        Fr0   r4   r   rP   r!   N)
rO   assertIsInstancer   r:   r;   r<   r   r   r=   r>   )rE   rM   r(   r(   r)   test_unfilteredQueryu   s   
z&RootResolverTests.test_unfilteredQueryc                 C   sH   t |d}|j|f|j|f|j|ffD ]\}}|dd |D  q|S )a  
        Create a L{Message} suitable for use as a response to a query.

        @param answers: A C{list} of two-tuples giving data for the answers
            section of the message.  The first element of each tuple is a name
            for the L{RRHeader}.  The second element is the payload.
        @param authority: A C{list} like C{answers}, but for the authority
            section of the response.
        @param additional: A C{list} like C{answers}, but for the
            additional section of the response.
        @param rCode: The response code the message will be created with.

        @return: A new L{Message} initialized with the given values.
        )rCodec              	   S   s*   g | ]\}}t ||jt|d t|dqS )CLASSr!   )r   TYPEgetattrr   ).0namerecordr(   r(   r)   
<listcomp>   s    z.RootResolverTests._respond.<locals>.<listcomp>)r   r<   r=   r>   extend)rE   r<   r=   r>   rU   rN   sectiondatar(   r(   r)   _respond   s   
zRootResolverTests._respond
   c                    s(   dg}t ||} fdd}||_|S )a  
        Create and return a new L{root.Resolver} modified to resolve queries
        against the record data represented by C{servers}.

        @param serverResponses: A mapping from dns server addresses to
            mappings.  The inner mappings are from query two-tuples (name,
            type) to dictionaries suitable for use as **arguments to
            L{_respond}.  See that method for details.
        r1   c              	      sl   t d| j d| |D ]&}z| }W n	 ty   Y qw || jj| jf }t jdi |  S d S )NzQuery for QNAME z at r(   )r   rZ   KeyErrortyper   r`   )queryserverAddressestimeoutrF   addrserverrecordsrE   serverResponsesr(   r)   rd      s   z-RootResolverTests._getResolver.<locals>.query)r   r5   )rE   rk   maximumQueriesrootsrG   rd   r(   rj   r)   _getResolver   s
   


zRootResolverTests._getResolverc                 C   sr   dt fdtdfgdtdfgdidt fddtdfgiid}| |}|d}|t || jd |S )a  
        L{root.Resolver.lookupAddress} looks up the I{A} records for the
        specified hostname by first querying one of the root servers the
        resolver was created with and then following the authority delegations
        until a result is received.
        r0      ns1.example.com34.55.89.144r=   r>   r<   10.0.0.1)r1   5   )rp   rt   r   r   r   rn   lookupAddressr?   r-   r:   rE   serversrG   rH   r(   r(   r)   test_lookupAddress   s   	


z$RootResolverTests.test_lookupAddressc                 C   s   t d}t|_dtfd|fgdtdfgdt dfgdidtfddt dfgiid}| |}|d}|t || j	t d |S )	z
        If a response includes a record with a class different from the one
        in the query, it is ignored and lookup continues until a record with
        the right class is found.
        rr   r0   ro   10.0.0.2)r<   r=   r>   r<   10.0.0.3)rs   rz   rt   )
r   r   rV   r   r   rn   rv   r?   r*   r:   )rE   badClassrx   rG   rH   r(   r(   r)   test_lookupChecksClass   s$   


z(RootResolverTests.test_lookupChecksClassc                 C   s|   dt fddtdfgidt fddtdfgiidt fddtdfgiid}| |}|d}|t || jd |S )z
        If an intermediate response includes no glue records for the
        authorities, separate queries are made to find those addresses.
        r0   r=   s   ns1.example.orgr<   rr   rz   )rs   )rr   rt   ru   rw   r(   r(   r)   test_missingGlue   s"   



z"RootResolverTests.test_missingGluec                 C   s4   ddt fdtiii}| |}|d}| |tS )z
        If a name is missing, L{Resolver.lookupAddress} returns a L{Deferred}
        which fails with L{DNSNameError}.
        rs   r0   rU   )r   r   rn   rv   assertFailurer   rw   r(   r(   r)   test_missingName  s   

z"RootResolverTests.test_missingNamec                 C   s0   ddt fi ii}| |}|d}| |tS )z
        If a query is responded to with no answers or nameserver records, the
        L{Deferred} returned by L{Resolver.lookupAddress} fires with
        L{ResolverError}.
        rs      example.com)r   rn   rv   r   r   rw   r(   r(   r)   test_answerless  s   

z!RootResolverTests.test_answerlessc                 C   sJ   ddt fddtdfgidt fdtiii}| |}|d}| |tS )z
        If there is an error resolving the nameserver in a delegation response,
        the L{Deferred} returned by L{Resolver.lookupAddress} fires with that
        error.
        rs   r   r=   ro   rU   )r   r   r   rn   rv   r   r   rw   r(   r(   r)   test_delegationLookupError.  s   


z,RootResolverTests.test_delegationLookupErrorc                 C   sF   ddt fddtdfgidt fi ii}| |}|d}| |tS )z
        If there are no records in the response to a lookup of a delegation
        nameserver, the L{Deferred} returned by L{Resolver.lookupAddress} fires
        with L{ResolverError}.
        rs   r   r=   ro   )r   r   rn   rv   r   r   rw   r(   r(   r)   test_delegationLookupEmptyB  s   

z,RootResolverTests.test_delegationLookupEmptyc                 C   sf   ddt fdtidtfddtdfgiii}| |}|d}dd }|| || jtd |S )z
        L{Resolver.lookupNameservers} is like L{Resolver.lookupAddress}, except
        it queries for I{NS} records instead of I{A} records.
        rs   r   rU   r<   ro   c                 S   s   | \}}}|d j jS Nr   )r"   rZ   r#   r(   r(   r)   
getOneNamef  s   
z<RootResolverTests.test_lookupNameservers.<locals>.getOneName)	r   r   r   r   rn   lookupNameserversr?   r:   r   )rE   rx   rG   rH   r   r(   r(   r)   test_lookupNameserversT  s   



z(RootResolverTests.test_lookupNameserversc              	   C   s|   ddt fddtdfdtdfgiii}| |}|d}|dd  || jtdttddtdt tddg |S )	z
        If a I{CNAME} record is encountered as the answer to a query for
        another record type, that record is returned as the answer.
        rs   r   r<      example.netz10.0.0.7c                 S      | d S r   r(   r,   r(   r(   r)   <lambda>      z<RootResolverTests.test_returnCanonicalName.<locals>.<lambda>r!   	r   r   r   rn   rv   r?   r:   r   r   rw   r(   r(   r)   test_returnCanonicalNamen  s&   




z*RootResolverTests.test_returnCanonicalNamec              	   C   s   ddt fddtdfgidt fddtdfgiii}| |}|d}|dd  || jtdttddtdt tddg |S )	z
        If no record of the requested type is included in a response, but a
        I{CNAME} record for the query name is included, queries are made to
        resolve the value of the I{CNAME}.
        rs   r   r<   r   z10.0.0.5c                 S   r   r   r(   r,   r(   r(   r)   r     r   z<RootResolverTests.test_followCanonicalName.<locals>.<lambda>r!   r   rw   r(   r(   r)   test_followCanonicalName  s&   


z*RootResolverTests.test_followCanonicalNamec                 C   sH   ddt fddtdfdtdfgiii}| |}|d}| |tS )z
        If there is a cycle between I{CNAME} records in a response, this is
        detected and the L{Deferred} returned by the lookup method fails
        with L{ResolverError}.
        rs   r   r<   r   )r   r   rn   rv   r   r   rw   r(   r(   r)   test_detectCanonicalNameLoop  s   




z.RootResolverTests.test_detectCanonicalNameLoopc                 C   s   dt fddtdfgidt fddtdfgiidt fdtdfgdtdfgdidt fddtd	fgiid
}| |d}| |dt}| |d}|d}|t || j	td	 t
||gS )z
        L{Resolver.lookupAddress} won't issue more queries following
        delegations than the limit passed to its initializer.
        r   r=   ro   r<   rz   s   ns2.example.comr{   rq   z10.0.0.4)rs   r|   )r{   rt         )r   r   r   rn   r   rv   r   r?   r*   r:   r   )rE   rx   failerfailD	succeedersucceedDr(   r(   r)   test_boundedQueries  s0   	!

z%RootResolverTests.test_boundedQueriesN)ra   )__name__
__module____qualname____doc__rO   rR   rT   r   r`   rn   ry   r~   r   r   r   r   r   r   r   r   r   r   r(   r(   r(   r)   r.   7   s&    +
r.   c                   @      e Zd ZdZdd ZdS )ResolverFactoryArgumentszf
    Raised by L{raisingResolverFactory} with the *args and **kwargs passed to
    that function.
    c                 C   s   || _ || _dS )z
        Store the supplied args and kwargs as attributes.

        @param args: Positional arguments.
        @param kwargs: Keyword arguments.
        Nargskwargs)rE   r   r   r(   r(   r)   __init__     
z!ResolverFactoryArguments.__init__N)r   r   r   r   r   r(   r(   r(   r)   r         r   c                  O   s
   t | |)a=  
    Raise a L{ResolverFactoryArguments} exception containing the
    positional and keyword arguments passed to resolverFactory.

    @param args: A L{list} of all the positional arguments supplied by
        the caller.

    @param kwargs: A L{list} of all the keyword arguments supplied by
        the caller.
    )r   r   r(   r(   r)   raisingResolverFactory  s   
r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	 RootResolverResolverFactoryTestsz6
    Tests for L{root.Resolver._resolverFactory}.
    c                 C   s    t dgtd}| |jt dS )z
        L{root.Resolver.__init__} accepts a C{resolverFactory}
        argument and assigns it to C{self._resolverFactory}.
        N)hintsresolverFactory)r   r   assertIs_resolverFactoryrE   rr(   r(   r)   #test_resolverFactoryArgumentPresent  s   zDRootResolverResolverFactoryTests.test_resolverFactoryArgumentPresentc                 C   s    t dgd}| |jtj  dS )z
        L{root.Resolver.__init__} sets L{client.Resolver} as the
        C{_resolverFactory} if a C{resolverFactory} argument is not
        supplied.
        N)r   )r   r   r   r	   r   r(   r(   r)   "test_resolverFactoryArgumentAbsent  s   zCRootResolverResolverFactoryTests.test_resolverFactoryArgumentAbsentc                 C   sJ   t  }tdgt|d}| t|jd}| d|dgdf|j|jf dS )zy
        L{root.Resolver._resolverFactory} is supplied with C{reactor} and
        C{servers} keyword arguments.
        192.0.2.101)r   r   r/   zexample.comr(   )r   rt   )r/   rx   N)	objectr   r   assertRaisesr   rv   r:   r   r   )rE   dummyReactorr   er(   r(   r)   )test_resolverFactoryOnlyExpectedArguments  s   
zJRootResolverResolverFactoryTests.test_resolverFactoryOnlyExpectedArgumentsN)r   r   r   r   r   r   r   r(   r(   r(   r)   r   	  s
    	r   )za.root-servers.netzb.root-servers.netzc.root-servers.netzd.root-servers.netze.root-servers.netzf.root-servers.netzg.root-servers.netzh.root-servers.netzi.root-servers.netzj.root-servers.netzk.root-servers.netzl.root-servers.netzm.root-servers.netc                   @   s    e Zd ZdZdd Zdd ZdS )StubResolverz
    An L{IResolverSimple} implementer which traces all getHostByName
    calls and their deferred results. The deferred results can be
    accessed and fired synchronously.
    c                 C   s   g | _ g | _dS )z
        @type calls: L{list} of L{tuple} containing C{args} and
            C{kwargs} supplied to C{getHostByName} calls.
        @type pendingResults: L{list} of L{Deferred} returned by
            C{getHostByName}.
        N)callspendingResults)rE   r(   r(   r)   r   L  r   zStubResolver.__init__c                 O   s&   | j ||f t }| j| |S )al  
        A fake implementation of L{IResolverSimple.getHostByName}

        @param args: A L{list} of all the positional arguments supplied by
           the caller.

        @param kwargs: A L{list} of all the keyword arguments supplied by
           the caller.

        @return: A L{Deferred} which may be fired later from the test
            fixture.
        )r   r@   r   r   )rE   r   r   rH   r(   r(   r)   getHostByNameV  s   zStubResolver.getHostByNameN)r   r   r   r   r   r   r(   r(   r(   r)   r   D  s    
r   c                   @   sH   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S )BootstrapTestsz%
    Tests for L{root.bootstrap}
    c                 C   s   t t }| |t j dS )zl
        L{root.bootstrap} returns an object which is initially a
        L{root.DeferredResolver}.
        N)r
   	bootstrapr   rS   DeferredResolver)rE   deferredResolverr(   r(   r)   test_returnsDeferredResolverq  s   z+BootstrapTests.test_returnsDeferredResolverc                 C   s,   t  }t| | |jdd tD  dS )z
        The L{IResolverSimple} supplied to L{root.bootstrap} is used to lookup
        the IP addresses of the 13 root name servers.
        c                 S   s   g | ]}|fi fqS r(   r(   )rY   sr(   r(   r)   r\     s    z=BootstrapTests.test_resolves13RootServers.<locals>.<listcomp>N)r   r
   r   r:   r   ROOT_SERVERS)rE   stubResolverr(   r(   r)   test_resolves13RootServersy  s   
z)BootstrapTests.test_resolves13RootServersc                 C   s6   t  }t|}|jD ]}|d q| |t dS )z
        The L{root.DeferredResolver} initially returned by L{root.bootstrap}
        becomes a L{root.Resolver} when the supplied resolver has successfully
        looked up all root hints.
        r   N)r   r
   r   r   callbackrS   r   rE   r   r   rH   r(   r(   r)   test_becomesResolver  s
   

z#BootstrapTests.test_becomesResolverc                 C   s>   t  }t|}|jD ]}|d q| |jdgd  dS )z
        The L{root.Resolver} which eventually replaces L{root.DeferredResolver}
        is supplied with the IP addresses of the 13 root servers.
        r      N)r   r
   r   r   r   r:   r   r   r(   r(   r)   test_resolverReceivesRootHints  s
   

z-BootstrapTests.test_resolverReceivesRootHintsc                    s^   t  }t| t|j}t|}|D ]}|d q|t   fdd}|	| dS )z
        The L{root.Resolver} is eventually created, even if some of the root
        hint lookups fail. Only the working root hint IP addresses are supplied
        to the L{root.Resolver}.
        r   c                    s     jdgd  d S )Nr      r:   r   resr   rE   r(   r)   
checkHints  s   zFBootstrapTests.test_continuesWhenSomeRootHintsFail.<locals>.checkHintsN)
r   r
   r   iterr   nextr   errbackr   addBothrE   r   r$   d1rH   r   r(   r   r)   #test_continuesWhenSomeRootHintsFail  s   

z2BootstrapTests.test_continuesWhenSomeRootHintsFailc                    sn   t  }t| t|j}t|}|D ]}|t  q|t   fdd}|| 	j
t dS )z
        The L{root.Resolver} is eventually created, even if all of the root hint
        lookups fail. Pending and new lookups will then fail with
        AttributeError.
        c                    s     jg  d S Nr   r   r   r(   r)   r     s   zEBootstrapTests.test_continuesWhenAllRootHintsFail.<locals>.checkHintsN)r   r
   r   r   r   r   r   r   r   
addCleanupflushLoggedErrorsr   r(   r   r)   "test_continuesWhenAllRootHintsFail  s   


z1BootstrapTests.test_continuesWhenAllRootHintsFailc                 C   s<   t  }tj|td}|jD ]}|d q| |jt dS )z
        L{root.bootstrap} accepts a C{resolverFactory} argument which is passed
        as an argument to L{root.Resolver} when it has successfully looked up
        root hints.
        )r   r   N)r   r
   r   r   r   r   r   r   r   r(   r(   r)   test_passesResolverFactory  s   
z)BootstrapTests.test_passesResolverFactoryN)r   r   r   r   r   r   r   r   r   r   r   r(   r(   r(   r)   r   l  s    	r   c                   @   r   )StubDNSDatagramProtocolz
    A do-nothing stand-in for L{DNSDatagramProtocol} which can be used to avoid
    network traffic in tests where that kind of thing doesn't matter.
    c                 O   s   t  S r   )r   )rE   akwr(   r(   r)   rd     s   zStubDNSDatagramProtocol.queryN)r   r   r   r   rd   r(   r(   r(   r)   r     r   r   zbtwisted.names.root.retry is deprecated since Twisted 10.0.  Use a Resolver object for retry logic.)categoryrM   N):r   zope.interfacer   zope.interface.verifyr   twisted.internet.deferr   r   r   r   twisted.internet.interfacesr   twisted.namesr	   r
   twisted.names.dnsr   r   r   r   r   r   r   r   r   r   r   r   r   r   twisted.names.errorr   r   twisted.names.rootr   twisted.names.test.test_utilr   twisted.python.logr   twisted.trialr   twisted.trial.unittestr   r    r*   r-   r.   	Exceptionr   r   r   r   r   r   r   suppressDeprecationWarning_retrySuppressionr(   r(   r(   r)   <module>   s@   @	   6*
$f

