a
    )(bbG                     @   s*  d Z ddlmZmZ ddlmZmZmZmZ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mZ d	dlmZm Z m!Z!m"Z"m#Z$ d	dl%m&Z& d	dl'm(Z( d	dl)m*Z* ee+e+dddZ,G dd deZ-G dd deZ.G dd deZ/dS )z$
Tests for L{twisted.logger._json}.
    )BytesIOStringIO)IOAnyListOptionalSequencecast)implementer)BrokenMethodImplementation)verifyObject)Failure)TestCase   )extractField)formatEvent)globalLogPublisher)ILogObserverLogEvent)eventAsJSONeventFromJSONeventsFromJSONLogFilejsonFileLogObserverlog)LogLevel)Logger)LogPublisher)testCase	savedJSONreturnc                 C   s"   |  |t | |dd |S )a*  
    Assert a few things about the result of L{eventAsJSON}, then return it.

    @param testCase: The L{TestCase} with which to perform the assertions.
    @param savedJSON: The result of L{eventAsJSON}.

    @return: C{savedJSON}

    @raise AssertionError: If any of the preconditions fail.
    
r   )assertIsInstancestrassertEqualcount)r   r    r%   <lib/python3.9/site-packages/twisted/logger/test/test_json.pysavedJSONInvariants!   s    r'   c                   @   s   e Zd ZdZeedddZddddZddd	d
ZddddZ	ddddZ
ddddZddddZddddZddddZddddZddddZdS )SaveLoadTestsz2
    Tests for loading and saving log events.
    eventr   c                 C   s   t | t|S )z
        Serialize some an events, assert some things about it, and return the
        JSON.

        @param event: An event.

        @return: JSON.
        )r'   r   )selfr*   r%   r%   r&   savedEventJSON6   s    	zSaveLoadTests.savedEventJSONNr   c                 C   s   |  t| i i  dS )zX
        Saving and loading an empty dictionary results in an empty dictionary.
        Nr#   r   r,   r+   r%   r%   r&   test_simpleSaveLoadA   s    z!SaveLoadTests.test_simpleSaveLoadc                 C   s&   |  t| dddddd dS )a  
        Saving and loading a dictionary with some simple values in it results
        in those same simple values in the output; according to JSON's rules,
        though, all dictionary keys must be L{str} and any non-L{str}
        keys will be converted.
        r   4)   31r3   Nr.   r/   r%   r%   r&   test_saveLoadG   s    zSaveLoadTests.test_saveLoadc                 C   s,   |  t| dt ddddid dS )zx
        Saving and loading an object which cannot be represented in JSON will
        result in a placeholder.
        r   r4   unpersistableTNr#   r   r,   objectr/   r%   r%   r&   test_saveUnPersistableS   s    z$SaveLoadTests.test_saveUnPersistablec                 C   s,   |  t| dt ddddid dS )zD
        Non-ASCII keys and values can be saved and loaded.
        u   䌡)u   ሴr3   r7   TNr8   r/   r%   r%   r&   test_saveNonASCII]   s    zSaveLoadTests.test_saveNonASCIIc                 C   sJ   dt tdi}|ddi | t| |dt tddi dS )zx
        Any L{bytes} objects will be saved as if they are latin-1 so they can
        be faithfully re-loaded.
        Zhello   s   skippedZokaycharmapN)bytesrangeupdater#   r   r,   decode)r+   
inputEventr%   r%   r&   test_saveBytesf   s    zSaveLoadTests.test_saveBytesc                 C   s>   G dd d}d|dd}t | |}| t|d dS )a
  
        Saving and loading an object which cannot be represented in JSON, but
        has a string representation which I{can} be saved as JSON, will result
        in the same string formatting; any extractable fields will retain their
        data types.
        c                   @   s*   e Zd ZeddddZedddZdS )z@SaveLoadTests.test_saveUnPersistableThenFormat.<locals>.ReprableN)valuer   c                 S   s
   || _ d S NrD   )r+   rD   r%   r%   r&   __init__~   s    zISaveLoadTests.test_saveUnPersistableThenFormat.<locals>.Reprable.__init__r-   c                 S   s   dS )NZreprabler%   r/   r%   r%   r&   __repr__   s    zISaveLoadTests.test_saveUnPersistableThenFormat.<locals>.Reprable.__repr__)__name__
__module____qualname__r9   rG   r"   rH   r%   r%   r%   r&   Reprable}   s   rL   z{object} {object.value}   
log_formatr9   z
reprable 7N)r   r,   r#   r   )r+   rL   rB   ZoutputEventr%   r%   r&    test_saveUnPersistableThenFormatu   s    z.SaveLoadTests.test_saveUnPersistableThenFormatc                 C   s`   G dd d}t d| d}t| |}| td|d | ttd| | ttd| dS )	zs
        L{extractField} can extract fields from an object that's been saved and
        loaded from JSON.
        c                   @   s   e Zd ZddddZdS )z8SaveLoadTests.test_extractingFieldsPostLoad.<locals>.ObjNr-   c                 S   s
   d| _ d S )NY  rF   r/   r%   r%   r&   rG      s    zASaveLoadTests.test_extractingFieldsPostLoad.<locals>.Obj.__init__)rI   rJ   rK   rG   r%   r%   r%   r&   Obj   s   rR   z{object.value}rN   zobject.valuerQ   r9   N)dictr   r,   r#   r   assertRaisesKeyError)r+   rR   rB   loadedEventr%   r%   r&   test_extractingFieldsPostLoad   s    z+SaveLoadTests.test_extractingFieldsPostLoadc                 C   s   g }t tt|jd}zdd  W n$ tyF   t }|d| Y n0 | t|d t	| 
|d d }| |t | |t | | t dS )zl
        Round-tripping a failure through L{eventAsJSON} preserves its class and
        structure.
        observerr2   r   za message about failurelog_failureN)r   r	   r   appendZeroDivisionErrorr   failurer#   lenr   r,   r!   Z
assertTrueZcheckZgetTracebackr"   )r+   eventsr   fZloadedr%   r%   r&   test_failureStructurePreserved   s    z,SaveLoadTests.test_failureStructurePreservedc                 C   s0   t tjd}t| |}| |d tj dS )zo
        It's important that the C{log_level} key remain a
        L{constantly.NamedConstant} object.
        	log_levelrc   N)rS   r   warnr   r,   ZassertIs)r+   rB   rV   r%   r%   r&   test_saveLoadLevel   s    z SaveLoadTests.test_saveLoadLevelc                 C   s   t d}| |tdd dS )z
        If a saved bit of JSON (let's say, from a future version of Twisted)
        were to persist a different log_level, it will resolve as None.
        zZ{"log_level": {"name": "other", "__class_uuid__": "02E59486-F24D-46AD-8224-3ACDF2A5732A"}}Nrb   )r   r#   rS   )r+   rV   r%   r%   r&   test_saveLoadUnknownLevel   s    z'SaveLoadTests.test_saveLoadUnknownLevel)rI   rJ   rK   __doc__r   r"   r,   r0   r6   r:   r;   rC   rP   rW   ra   re   rf   r%   r%   r%   r&   r(   1   s   
		r(   c                   @   sZ   e Zd ZdZddddZdedddd	Zddd
dZddddZddddZ	dS )FileLogObserverTestsz+
    Tests for L{jsonFileLogObserver}.
    Nr-   c                 C   sp   t  V}t|}ztt| W n. tyL } z| | W Y d}~n
d}~0 0 W d   n1 sb0    Y  dS )zh
        A L{FileLogObserver} returned by L{jsonFileLogObserver} is an
        L{ILogObserver}.
        N)r   r   r   r   r   Zfail)r+   
fileHandlerY   er%   r%   r&   test_interface   s    z#FileLogObserverTests.test_interface)recordSeparatorr   c                 C   s\   t  B}t||}tdd}|| | | | d W d   n1 sN0    Y  dS )a!  
        Asserts that an observer created by L{jsonFileLogObserver} with the
        given arguments writes events serialized as JSON text, using the given
        record separator.

        @param recordSeparator: C{recordSeparator} argument to
            L{jsonFileLogObserver}
        r2   xz	{"x": 1}
N)r   r   rS   r#   getvalue)r+   rm   ri   rY   r*   r%   r%   r&   assertObserverWritesJSON   s
    	

z-FileLogObserverTests.assertObserverWritesJSONc                 C   s   |    dS )z
        A L{FileLogObserver} created by L{jsonFileLogObserver} writes events
        serialzed as JSON text to a file when it observes events.
        By default, the record separator is C{"\x1e"}.
        Nrq   r/   r%   r%   r&   (test_observeWritesDefaultRecordSeparator   s    z=FileLogObserverTests.test_observeWritesDefaultRecordSeparatorc                 C   s   | j dd dS )z
        A L{FileLogObserver} created by L{jsonFileLogObserver} writes events
        serialzed as JSON text to a file when it observes events.
        This test sets the record separator to C{""}.
         rm   Nrr   r/   r%   r%   r&   &test_observeWritesEmptyRecordSeparator   s    z;FileLogObserverTests.test_observeWritesEmptyRecordSeparatorc                    s   t  }t }g }|tt|j |t| t|d}zdd  W n tyb   |	d Y n0 t |
 }tt|}tt dd fdd}|| || dS )	z
        A L{FileLogObserver} created by L{jsonFileLogObserver} writes failures
        serialized as JSON text to a file when it observes events.
        rX   r2   r   zfailed as expectedN)	logEventsr   c                    s`     t| d | \} d| |d } |t | }  |jjj	dt
	d d S )Nr2   rZ   co)r#   r^   ZassertInr!   r   ZgetTracebackObjecttb_framef_codeco_filenamerstrip__file__)rw   ZfailureEventZfailureObjectZtracebackObjectr/   r%   r&   checkEvents  s    z@FileLogObserverTests.test_failureFormatting.<locals>.checkEvents)r   r   addObserverr	   r   r[   r   r   BaseExceptionr]   rp   listr   r   r   )r+   ioZ	publisherZloggedZloggerreaderZdeserializedr~   r%   r/   r&   test_failureFormatting   s    
z+FileLogObserverTests.test_failureFormatting)rl   )
rI   rJ   rK   rg   rk   r"   rq   rs   rv   r   r%   r%   r%   r&   rh      s   rh   c                   @   s   e Zd ZdZddddZddddZd$ee ee	 e
dd	d
dZddddZddddZddddZddddZddddZddddZddddZddddZddddZddddZddd d!Zddd"d#ZdS )%LogFileReaderTestsz-
    Tests for L{eventsFromJSONLogFile}.
    Nr-   c                    s6   g  _ tttd d fdd}| _t| d S )Nr)   c                    s&   | d t jkr"d| v r" j|  d S )NZlog_namespacerecord)jsonLog	namespaceerrorEventsr[   )r*   r/   r%   r&   rY     s    z*LogFileReaderTests.setUp.<locals>.observer)r   r
   r   r   logObserverr   r   )r+   rY   r%   r/   r&   setUp  s
    zLogFileReaderTests.setUpc                 C   s   t | j d S rE   )r   ZremoveObserverr   r/   r%   r%   r&   tearDown&  s    zLogFileReaderTests.tearDown   )inFilerm   
bufferSizer   c                 C   sJ   t t|||}| t|ddi | t|ddi | tt| dS )a|  
        Test that L{eventsFromJSONLogFile} reads two pre-defined events from a
        file: C{{"x": 1}} and C{{"y": 2}}.

        @param inFile: C{inFile} argument to L{eventsFromJSONLogFile}
        @param recordSeparator: C{recordSeparator} argument to
            L{eventsFromJSONLogFile}
        @param bufferSize: C{bufferSize} argument to L{eventsFromJSONLogFile}
        ro   r2   yr   N)iterr   r#   nextrT   StopIteration)r+   r   rm   r   r_   r%   r%   r&   _readEvents)  s    zLogFileReaderTests._readEventsc                 C   sH   t d,}| | | t| jd W d   n1 s:0    Y  dS )z
        L{eventsFromJSONLogFile} reads events from a file and automatically
        detects use of C{"\x1e"} as the record separator.
        {"x": 1}
{"y": 2}
r   Nr   r   r#   r^   r   r+   ri   r%   r%   r&   &test_readEventsAutoWithRecordSeparator>  s    

z9LogFileReaderTests.test_readEventsAutoWithRecordSeparatorc                 C   sH   t d,}| | | t| jd W d   n1 s:0    Y  dS )z
        L{eventsFromJSONLogFile} reads events from a file and automatically
        detects use of C{""} as the record separator.
        z{"x": 1}
{"y": 2}
r   Nr   r   r%   r%   r&   'test_readEventsAutoEmptyRecordSeparatorG  s    

z:LogFileReaderTests.test_readEventsAutoEmptyRecordSeparatorc                 C   sL   t d0}| j|dd | t| jd W d   n1 s>0    Y  dS )z{
        L{eventsFromJSONLogFile} reads events from a file and is told to use
        a specific record separator.
        z{"x": 1}
{"y": 2}
ru   r   Nr   r   r%   r%   r&   &test_readEventsExplicitRecordSeparatorP  s    
z9LogFileReaderTests.test_readEventsExplicitRecordSeparatorc                 C   sL   t d0}| j|dd | t| jd W d   n1 s>0    Y  dS )zM
        L{eventsFromJSONLogFile} handles buffering a partial event.
        r   r2   r   r   Nr   r   r%   r%   r&   test_readEventsPartialBufferZ  s    
z/LogFileReaderTests.test_readEventsPartialBufferc                 C   s   t d|}tt|}| t|ddi | tt| | t| jd | | jd d d | | jd d d	 W d
   n1 s0    Y  d
S )zF
        If the JSON text for a record is truncated, skip it.
        z{"x": 1{"y": 2}
r   r   r2   r   rO   z0Unable to read truncated JSON record: {record!r}r   s   {"x": 1N	r   r   r   r#   r   rT   r   r^   r   r+   ri   r_   r%   r%   r&   test_readTruncatedc  s    
z%LogFileReaderTests.test_readTruncatedc                 C   sl   t dP}tt|}| t|ddi | tt| | t| jd W d   n1 s^0    Y  dS )zc
        If the file being read from vends L{str}, strings decode from JSON
        as-is.
        u   {"currency": "€"}
currency   €r   Nr   r   r%   r%   r&   test_readUnicodeu  s
    
z#LogFileReaderTests.test_readUnicodec                 C   sl   t dP}tt|}| t|ddi | tt| | t| jd W d   n1 s^0    Y  dS )zh
        If the file being read from vends L{bytes}, strings decode from JSON as
        UTF-8.
        s   {"currency": "€"}
r   r   r   N	r   r   r   r#   r   rT   r   r^   r   r   r%   r%   r&   test_readUTF8Bytes  s
    
z%LogFileReaderTests.test_readUTF8Bytesc                 C   sp   t dT}tt|dd}| t|ddi | tt| | t| jd W d   n1 sb0    Y  dS )z
        If the JSON text for a record is truncated in the middle of a two-byte
        Unicode codepoint, we don't want to see a codec exception and the
        stream is read properly when the additional data arrives.
        s   {"x": "€"}
   r   ro   r   r   Nr   r   r%   r%   r&   test_readTruncatedUTF8Bytes  s
    
z.LogFileReaderTests.test_readTruncatedUTF8Bytesc                 C   s   t d|}tt|}| t|ddi | tt| | t| jd | | jd d d | | jd d d	 W d
   n1 s0    Y  d
S )zh
        If the JSON text for a record contains invalid UTF-8 text, ignore that
        record.
        s   {"x": ""}
{"y": 2}
r   r   r2   r   rO   z2Unable to decode UTF-8 for JSON record: {record!r}r   s   {"x": ""}
Nr   r   r%   r%   r&   test_readInvalidUTF8Bytes  s    
z,LogFileReaderTests.test_readInvalidUTF8Bytesc                 C   s   t d|}tt|}| t|ddi | tt| | t| jd | | jd d d | | jd d d	 W d
   n1 s0    Y  d
S )zD
        If the JSON text for a record is invalid, skip it.
        z{"x": }
{"y": 2}
r   r   r2   r   rO   &Unable to read JSON record: {record!r}r   s   {"x": }
Nr   r   r%   r%   r&   test_readInvalidJSON  s    
z'LogFileReaderTests.test_readInvalidJSONc                 C   s   t dd}t|}| tt| | t| jd | | jd d d | | jd d d W d   n1 sr0    Y  dS )	zI
        Multiple events without a record separator are skipped.
        z{"x": 1}
{"y": 2}
r2   r   rO   r   r   s   {"x": 1}
{"y": 2}
N)r   r   rT   r   r   r#   r^   r   r   r%   r%   r&   test_readUnseparated  s    
z'LogFileReaderTests.test_readUnseparatedc                 C   sz   t dd}t V}t|}|| |d t|}| t||f | t| jd W d   n1 sl0    Y  dS )z
        Data written by a L{FileLogObserver} returned by L{jsonFileLogObserver}
        and read by L{eventsFromJSONLogFile} is reconstructed properly.
        r2   rn   r   N)	rS   r   r   seekr   r#   tupler^   r   )r+   r*   ri   rY   r_   r%   r%   r&   test_roundTrip  s    

z!LogFileReaderTests.test_roundTrip)Nr   )rI   rJ   rK   rg   r   r   r   r   r   r"   intr   r   r   r   r   r   r   r   r   r   r   r   r   r%   r%   r%   r&   r     s.     		
	r   N)0rg   r   r   r   typingr   r   r   r   r   r	   Zzope.interfacer
   Zzope.interface.exceptionsr   Zzope.interface.verifyr   Ztwisted.python.failurer   Ztwisted.trial.unittestr   Z_flattenr   Z_formatr   Z_globalr   Z_interfacesr   r   Z_jsonr   r   r   r   r   r   Z_levelsr   Z_loggerr   Z	_observerr   r"   r'   r(   rh   r   r%   r%   r%   r&   <module>   s(     R