U
    
W[;8                     @   s   d Z ddlmZ ddl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 d	dlmZ d	dlmZ d	dlmZ d	dlmZ G dd dejZG dd dejZdS )z+
Test cases for L{twisted.logger._legacy}.
    )timeN)verifyObjectBrokenMethodImplementation)unittest)context)log)Failure   )LogLevel)ILogObserver)formatEvent)LegacyLogObserverWrapper)publishToNewObserverc                   @   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d0S )1LegacyLogObserverWrapperTestsz0
    Tests for L{LegacyLogObserverWrapper}.
    c              
   C   sP   dd }t |}ztt| W n, tk
rJ } z| | W 5 d}~X Y nX dS )zD
        L{LegacyLogObserverWrapper} is an L{ILogObserver}.
        c                 S   s   d S N er   r   A/usr/lib/python3/dist-packages/twisted/logger/test/test_legacy.py<lambda>$       z>LegacyLogObserverWrapperTests.test_interface.<locals>.<lambda>N)r   r   r   r   Zfail)selflegacyObserverobserverr   r   r   r   test_interface    s    z,LegacyLogObserverWrapperTests.test_interfacec                 C   s.   G dd dt }t| }| t|d dS )zJ
        L{LegacyLogObserverWrapper} returns the expected string.
        c                   @   s   e Zd Zdd Zdd ZdS )z?LegacyLogObserverWrapperTests.test_repr.<locals>.LegacyObserverc                 S   s   dS )Nz<Legacy Observer>r   r   r   r   r   __repr__1   s    zHLegacyLogObserverWrapperTests.test_repr.<locals>.LegacyObserver.__repr__c                 S   s   d S r   r   r   r   r   r   __call__4   s    zHLegacyLogObserverWrapperTests.test_repr.<locals>.LegacyObserver.__call__N)__name__
__module____qualname__r   r   r   r   r   r   LegacyObserver0   s   r!   z+LegacyLogObserverWrapper(<Legacy Observer>)N)objectr   assertEqualrepr)r   r!   r   r   r   r   	test_repr,   s    
z'LegacyLogObserverWrapperTests.test_reprc                    s8   g   fdd}t |}|| | t d  d S )z
        Send an event to a wrapped legacy observer and capture the event as
        seen by that observer.

        @param event: an event
        @type event: L{dict}

        @return: the event as observed by the legacy wrapper
        c                    s
     | S r   )appendr   eventsr   r   r   K   r   z7LegacyLogObserverWrapperTests.observe.<locals>.<lambda>   r   )r   r#   len)r   eventr   r   r   r'   r   observe?   s    
z%LegacyLogObserverWrapperTests.observec                 C   sX   | dt  | dd | dtj | t|}| D ]\}}| || q>|S )z
        Send an event to a wrapped legacy observer and verify that its data is
        preserved.

        @param event: an event
        @type event: L{dict}

        @return: the event as observed by the legacy wrapper
        log_time
log_system-	log_level)
setdefaultr   r
   infor,   dictitemsZassertIn)r   r+   observedkeyvaluer   r   r   forwardAndVerifyS   s    z.LegacyLogObserverWrapperTests.forwardAndVerifyc                 C   s   |  tddd dS )ze
        Basic forwarding: event keys as observed by a legacy observer are the
        same.
        r)   r	   foobarN)r8   r3   r   r   r   r   test_forwardl   s    z*LegacyLogObserverWrapperTests.test_forwardc                 C   s*   t  }| t|d}| |d | dS )zc
        The new-style C{"log_time"} key is copied to the old-style C{"time"}
        key.
        )r-   r   Nr   r8   r3   r#   r   Zstampr+   r   r   r   	test_timet   s    z'LegacyLogObserverWrapperTests.test_timec                 C   s0   t  }| t|d |d}| |d | dS )zr
        The new-style C{"log_time"} key does not step on a pre-existing
        old-style C{"time"} key.
        r)   )r-   r   r   Nr=   r>   r   r   r   test_timeAlreadySet~   s    z1LegacyLogObserverWrapperTests.test_timeAlreadySetc                 C   s$   |  tdd}| |d d dS )zg
        The new-style C{"log_system"} key is copied to the old-style
        C{"system"} key.
        r:   )r.   systemNr8   r3   r#   r   r+   r   r   r   test_system   s    z)LegacyLogObserverWrapperTests.test_systemc                 C   s&   |  tddd}| |d d dS )zv
        The new-style C{"log_system"} key does not step on a pre-existing
        old-style C{"system"} key.
        r:   r;   )r.   rA   rA   NrB   rC   r   r   r   test_systemAlreadySet   s    z3LegacyLogObserverWrapperTests.test_systemAlreadySetc                 C   s2   t t tjd}| t |}| |d d dS )zy
        If the new-style C{"log_system"} key is absent, the old-style
        C{"system"} key is set to C{"-"}.
        )r-   r0   rA   r/   N)r3   r   r
   r2   r,   r#   )r   r+   r5   r   r   r   test_noSystem   s    z+LegacyLogObserverWrapperTests.test_noSystemc                 C   sT   |  ttjdd |  ttjdd |  ttjdd |  ttjdd dS )z
        If explicitly set, the C{isError} key will be preserved when forwarding
        from a new-style logging emitter to a legacy logging observer,
        regardless of log level.
        r)   )r0   isErrorr   N)r8   r3   r
   r2   warnerrorcriticalr   r   r   r   test_levelNotChange   s    z1LegacyLogObserverWrapperTests.test_levelNotChangec                 C   s"   |  ttjd}| d| dS )a)  
        The new-style C{"log_level"} key is not translated to the old-style
        C{"logLevel"} key.

        Events are forwarded from the old module from to new module and are
        then seen by old-style observers.
        We don't want to add unexpected keys to old-style events.
        )r0   logLevelN)r8   r3   r
   r2   assertNotInrC   r   r   r   test_pythonLogLevelNotSet   s    	z7LegacyLogObserverWrapperTests.test_pythonLogLevelNotSetc                 C   s$   |  tdd}| |d d dS )a  
        If a stdlib log level was provided as a string (eg. C{"WARNING"}) in
        the legacy "logLevel" key, it does not get converted to a number.
        The documentation suggested that numerical values should be used but
        this was not a requirement.
        WARNINGrL   rL   NrB   rC   r   r   r   test_stringPythonLogLevel   s    z7LegacyLogObserverWrapperTests.test_stringPythonLogLevelc                 C   s    |  t }| |d d dS )z
        The old-style C{"message"} key is added, even if no new-style
        C{"log_format"} is given, as it is required, but may be empty.
        messager   NrB   rC   r   r   r   test_message   s    z*LegacyLogObserverWrapperTests.test_messagec                 C   s$   |  tdd}| |d d dS )zV
        The old-style C{"message"} key is not modified if it already exists.
        r9   )rR   rR   NrB   rC   r   r   r   test_messageAlreadySet   s    z4LegacyLogObserverWrapperTests.test_messageAlreadySetc                 C   s(   |  tddd}| t|d dS )z
        Formatting is translated such that text is rendered correctly, even
        though old-style logging doesn't use PEP 3101 formatting.
        zHello, {who}!world)
log_formatZwhoHello, world!Nr8   r3   r#   	legacyLogtextFromEventDictrC   r   r   r   test_format   s    
z)LegacyLogObserverWrapperTests.test_formatc                 C   s(   |  tddd}| t|d dS )zo
        Using the message key, which is special in old-style, works for
        new-style formatting.
        zHello, {message}!rU   )rV   rR   rW   NrX   rC   r   r   r   test_formatMessage   s    
z0LegacyLogObserverWrapperTests.test_formatMessagec                 C   s(   |  tddd}| t|d dS )zd
        Formatting is not altered if the old-style C{"format"} key already
        exists.
        zHello!zHowdy!)rV   formatNrX   rC   r   r   r   test_formatAlreadySet   s    
z3LegacyLogObserverWrapperTests.test_formatAlreadySetc                 K   s&   t td}| tf |dd|S )z
        Create a new-style event with a captured failure.

        @param values: Additional values to include in the event.
        @type values: L{dict}

        @return: the new event
        @rtype: L{dict}
        znyargh!	oopsie...)log_failurerV   )r   RuntimeErrorr8   r3   )r   valuesfailurer   r   r   eventWithFailure  s    
z.LegacyLogObserverWrapperTests.eventWithFailurec                 C   s>   |   }| |d |d  | |d  | |d d dS )z}
        Captured failures in the new style set the old-style C{"failure"},
        C{"isError"}, and C{"why"} keys.
        rc   r`   rG   whyr_   N)rd   assertIsZ
assertTruer#   rC   r   r   r   test_failure  s    z*LegacyLogObserverWrapperTests.test_failurec                 C   s,   t td}| j|d}| |d | dS )v
        Captured failures in the new style do not step on a pre-existing
        old-style C{"failure"} key.
        zWeak salsa!)rc   rc   N)r   ra   rd   rf   )r   rc   r+   r   r   r   test_failureAlreadySet   s    z4LegacyLogObserverWrapperTests.test_failureAlreadySetc                 C   s    | j dd}| |d d dS )zv
        Captured failures in the new style do not step on a pre-existing
        old-style C{"isError"} key.
        r   rG   rG   Nrd   r#   rC   r   r   r   test_isErrorAlreadySet*  s    z4LegacyLogObserverWrapperTests.test_isErrorAlreadySetc                 C   s    | j dd}| |d d dS )rh   Zblah)re   re   Nrk   rC   r   r   r   test_whyAlreadySet3  s    z0LegacyLogObserverWrapperTests.test_whyAlreadySetN)r   r   r    __doc__r   r%   r,   r8   r<   r?   r@   rD   rE   rF   rK   rN   rQ   rS   rT   r[   r\   r^   rd   rg   ri   rl   rm   r   r   r   r   r      s0   

			
	r   c                   @   sp   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S )PublishToNewObserverTestsz,
    Tests for L{publishToNewObserver}.
    c                 C   s   g | _ | j j| _d S r   )r(   r&   r   r   r   r   r   setUpB  s    zPublishToNewObserverTests.setUpc                 O   sD   t tjpi  }|| ||d< t |d< d|kr@d|d< |S )aX  
        Return a basic old-style event as would be created by L{legacyLog.msg}.

        @param message: a message event value in the legacy event format
        @type message: L{tuple} of L{bytes}

        @param values: additional event values in the legacy event format
        @type event: L{dict}

        @return: a legacy event
        rR   r   rG   r   )r   getrY   ZILogContextcopyupdater   )r   rR   rb   r+   r   r   r   legacyEventG  s    

z%PublishToNewObserverTests.legacyEventc                 C   s*   t | j|  tj | t| jd dS )z6
        The observer is called exactly once.
        r)   N)r   r   rt   rY   rZ   r#   r*   r(   r   r   r   r   test_observed\  s      z'PublishToNewObserverTests.test_observedc                 C   s8   t | j|  tj | | jd d | jd d  dS )zc
        The old-style C{"time"} key is copied to the new-style C{"log_time"}
        key.
        r   r-   r   Nr   r   rt   rY   rZ   r#   r(   r   r   r   r   r?   f  s       z#PublishToNewObserverTests.test_timec                 C   sD   dd }|  dd}||}t| j|| | t| jd | dS )z
        A published old-style event should format as text in the same way as
        the given C{textFromEventDict} callable would format it.
        c                 S   s   d td | d S )N  rR   )joinreversed)r+   r   r   r   rZ   x  s    zAPublishToNewObserverTests.test_message.<locals>.textFromEventDictzHello,zworld!r   N)rt   r   r   r#   r   r(   )r   rZ   r+   textr   r   r   rS   s  s
    z&PublishToNewObserverTests.test_messagec                 C   s0   t | j|  tj | | jd d tj dS )zL
        Published event should have log level of L{LogLevel.info}.
        r   r0   N)	r   r   rt   rY   rZ   r#   r(   r
   r2   r   r   r   r   test_defaultLogLevel  s      z.PublishToNewObserverTests.test_defaultLogLevelc                 C   s4   t | j| jddtj | | jd d tj dS )z
        If C{"isError"} is set to C{1} (true) on the legacy event, the
        C{"log_level"} key should get set to L{LogLevel.critical}.
        r)   rj   r   r0   N)	r   r   rt   rY   rZ   r#   r(   r
   rJ   r   r   r   r   test_isError  s    
z&PublishToNewObserverTests.test_isErrorc                 C   s6   t | j| jtjdtj | | jd d t	j
 dS )z
        If the old-style C{"logLevel"} key is set to a standard library logging
        level, using a predefined (L{int}) constant, the new-style
        C{"log_level"} key should get set to the corresponding log level.
        rP   r   r0   N)r   r   rt   
py_loggingrO   rY   rZ   r#   r(   r
   rH   r   r   r   r   test_stdlibLogLevel  s    z-PublishToNewObserverTests.test_stdlibLogLevelc                 C   s4   t | j| jddtj | | jd d tj dS )z
        If the old-style C{"logLevel"} key is set to a standard library logging
        level, using a string value, the new-style C{"log_level"} key should
        get set to the corresponding log level.
        rO   rP   r   r0   N)	r   r   rt   rY   rZ   r#   r(   r
   rH   r   r   r   r   test_stdlibLogLevelWithString  s    
z7PublishToNewObserverTests.test_stdlibLogLevelWithStringc                 C   s.   t | j| jddtj | d| jd  dS )z
        If the old-style C{"logLevel"} key is set to a standard library logging
        level, using an unknown value, the new-style C{"log_level"} key should
        not get set.
        zFoo!!!!!rP   r0   r   N)r   r   rt   rY   rZ   rM   r(   r   r   r   r   test_stdlibLogLevelWithGarbage  s    
z8PublishToNewObserverTests.test_stdlibLogLevelWithGarbagec                 C   s.   t | j|  tj | | jd d d dS )z
        Published event should have a namespace of C{"log_legacy"} to indicate
        that it was forwarded from legacy logging.
        r   Zlog_namespaceZ
log_legacyNrv   r   r   r   r   test_defaultNamespace  s      z/PublishToNewObserverTests.test_defaultNamespacec                 C   s8   t | j|  tj | | jd d | jd d  dS )zg
        The old-style C{"system"} key is copied to the new-style
        C{"log_system"} key.
        r   r.   rA   Nrv   r   r   r   r   rD     s       z%PublishToNewObserverTests.test_systemN)r   r   r    rn   rp   rt   ru   r?   rS   r|   r}   r   r   r   r   rD   r   r   r   r   ro   =  s   

ro   )rn   r   Zloggingr~   Zzope.interface.verifyr   r   Ztwisted.trialr   Ztwisted.pythonr   r   rY   Ztwisted.python.failurer   Z_levelsr
   Z	_observerr   Z_formatr   Z_legacyr   r   ZTestCaser   ro   r   r   r   r   <module>   s      $