U
    
W[+d                     @   s  d 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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 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 Z,dd Z-G dd deZ.G dd de/Z0dd Z1G dd deZ2ddddddd d!d"d#d$d%d&gZ3eeG d'd( d(e4Z5eee5 G d)d* d*e
Z6G d+d, d,Z7ej8e9d-d.Z:d/S )0z.
Test cases for Twisted.names' root resolver.
    )implementer)verifyClass)msg)util)SynchronousTestCaseTestCase)DeferredsucceedgatherResultsTimeoutError)IResolverSimple)clientroot)Resolver)INHSANSCNAMEOKENAMERecord_CNAMENameQueryMessageRRHeaderRecord_A	Record_NS)DNSNameErrorResolverError)MemoryReactorc                 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resultsZansZ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(   Z
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   ZudpPortspopitemZ_sentPacketsr   ZfromStrassertEqualqueriesanswers	authority
additionaladdCallbackappendanswerr   r   Z	_protocolZdatagramReceivedZtoStr)selffilterr,   resolverdZ
portNumberZ	transportZpacketZaddressmessageresponser&   r&   r'   
_queryTest0   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.
        Tr-   r1   r   Zttlr!   N)rB   r4   r   r   )r<   r;   r7   r8   r&   r&   r'   test_filteredQuery\   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.
        Fr-   r1   r   rC   r!   N)
rB   assertIsInstancer   r4   r5   r6   r   r   r7   r8   )r<   r@   r&   r&   r'   test_unfilteredQueryk   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   ZTYPEgetattrr   ).0namerecordr&   r&   r'   
<listcomp>   s   z.RootResolverTests._respond.<locals>.<listcomp>)r   r6   r7   r8   extend)r<   r6   r7   r8   rG   rA   Z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.
        r.   c              	      sj   t d| j|f  |D ]N}z| }W n tk
r>   Y qY nX || jj| jf }t jf |  S d S )NzQuery for QNAME %s at %r)r   rK   KeyErrortyper	   rP   )queryZserverAddressesZtimeoutr=   ZaddrZserverZrecordsr<   serverResponsesr&   r'   rT      s    
z-RootResolverTests._getResolver.<locals>.query)r   r2   )r<   rV   ZmaximumQueriesrootsr>   rT   r&   rU   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.
        r-      ns1.example.com34.55.89.144r7   r8   r6   10.0.0.1)r.   5   )rZ   r^   r   r   r   rX   lookupAddressr9   r*   r4   r<   serversr>   r?   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.
        r\   r-   rY   10.0.0.2)r6   r7   r8   r6   10.0.0.3)r]   rd   r^   )
r   r   rH   r   r   rX   r`   r9   r(   r4   )r<   ZbadClassrb   r>   r?   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.
        r-   r7   s   ns1.example.orgr6   r\   rd   )r]   )r\   r^   r_   ra   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}.
        r]   r-   rG   )r   r   rX   r`   assertFailurer   ra   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}.
        r]      example.com)r   rX   r`   ri   r   ra   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.
        r]   rk   r7   rY   rG   )r   r   r   rX   r`   ri   r   ra   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}.
        r]   rk   r7   rY   )r   r   rX   r`   ri   r   ra   r&   r&   r'   test_delegationLookupEmpty:  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.
        r]   rk   rG   r6   rY   c                 S   s   | \}}}|d j jS Nr   )r"   rK   r#   r&   r&   r'   
getOneName_  s    
z<RootResolverTests.test_lookupNameservers.<locals>.getOneName)	r   r   r   r   rX   ZlookupNameserversr9   r4   r   )r<   rb   r>   r?   rp   r&   r&   r'   test_lookupNameserversN  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.
        r]   rk   r6      example.netz10.0.0.7c                 S   s   | d S ro   r&   r)   r&   r&   r'   <lambda>v      z<RootResolverTests.test_returnCanonicalName.<locals>.<lambda>r!   	r   r   r   rX   r`   r9   r4   r   r   ra   r&   r&   r'   test_returnCanonicalNameg  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}.
        r]   rk   r6   rr   z10.0.0.5c                 S   s   | d S ro   r&   r)   r&   r&   r'   rs     rt   z<RootResolverTests.test_followCanonicalName.<locals>.<lambda>r!   ru   ra   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}.
        r]   rk   r6   rr   )r   r   rX   r`   ri   r   ra   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.
        rk   r7   rY   r6   rd   s   ns2.example.comre   r[   z10.0.0.4)r]   rf   )re   r^         )r   r   r   rX   ri   r`   r   r9   r(   r4   r
   )r<   rb   ZfailerZfailDZ	succeederZsucceedDr&   r&   r'   test_boundedQueries  s<    	   ! 

z%RootResolverTests.test_boundedQueriesN)rQ   )__name__
__module____qualname____doc__rB   rD   rF   r   rP   rX   rc   rg   rh   rj   rl   rm   rn   rq   rv   rw   rx   r{   r&   r&   r&   r'   r+   ,   s$   ,
r+   c                   @   s   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)r<   r   r   r&   r&   r'   __init__  s    z!ResolverFactoryArguments.__init__N)r|   r}   r~   r   r   r&   r&   r&   r'   r     s   r   c                  O   s   t | |dS )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.
    N)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r<   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   r^   )r,   rb   N)	objectr   r   ZassertRaisesr   r`   r4   r   r   )r<   Z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)r<   r&   r&   r'   r   A  s    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   )r<   r   r   r?   r&   r&   r'   getHostByNameL  s    zStubResolver.getHostByNameN)r|   r}   r~   r   r   r   r&   r&   r&   r'   r   :  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   rE   ZDeferredResolver)r<   deferredResolverr&   r&   r'   test_returnsDeferredResolverh  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&   )rJ   sr&   r&   r'   rM   z  s     z=BootstrapTests.test_resolves13RootServers.<locals>.<listcomp>N)r   r   r   r4   r   ROOT_SERVERS)r<   stubResolverr&   r&   r'   test_resolves13RootServersq  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   callbackrE   r   r<   r   r   r?   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   r4   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      r4   r   resr   r<   r&   r'   
checkHints  s    zFBootstrapTests.test_continuesWhenSomeRootHintsFail.<locals>.checkHintsN)
r   r   r   iterr   nextr   errbackr   addBothr<   r   r$   Zd1r?   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   Z
addCleanupZ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   d  s   	r   c                   @   s   e Zd ZdZdd ZdS )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   )r<   akwr&   r&   r'   rT     s    zStubDNSDatagramProtocol.queryN)r|   r}   r~   r   rT   r&   r&   r&   r'   r     s   r   zbtwisted.names.root.retry is deprecated since Twisted 10.0.  Use a Resolver object for retry logic.)categoryr@   N);r   Zzope.interfacer   Zzope.interface.verifyr   Ztwisted.python.logr   Ztwisted.trialr   Ztwisted.trial.unittestr   r   Ztwisted.internet.deferr   r	   r
   r   Ztwisted.internet.interfacesr   Ztwisted.namesr   r   Ztwisted.names.rootr   Ztwisted.names.dnsr   r   r   r   r   r   r   r   r   r   r   r   r   r   Ztwisted.names.errorr   r   Ztwisted.names.test.test_utilr    r(   r*   r+   	Exceptionr   r   r   r   r   r   r   r   suppressDeprecationWarningZ_retrySuppressionr&   r&   r&   r'   <module>   sX   @		   5,%
l
