o
    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* dede+de+f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%   ?/usr/lib/python3/dist-packages/twisted/logger/test/test_json.pysavedJSONInvariants!   s   r'   c                   @   s   e Zd ZdZdedefddZdddZdd	d
ZdddZ	dddZ
dddZdddZdddZdddZdddZ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.savedEventJSONNc                 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1r1   Nr,   r-   r%   r%   r&   test_saveLoadG   s   zSaveLoadTests.test_saveLoadc                 C   ,   |  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   r2   unpersistableTNr#   r   r+   objectr-   r%   r%   r&   test_saveUnPersistableS   s   z$SaveLoadTests.test_saveUnPersistablec                 C   r5   )zD
        Non-ASCII keys and values can be saved and loaded.
        u   䌡)u   ሴr1   r6   TNr7   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.
        hello   s   skipped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deddfddZdefddZdS )z@SaveLoadTests.test_saveUnPersistableThenFormat.<locals>.Reprablevaluer   Nc                 S   s
   || _ d S NrE   )r*   rE   r%   r%   r&   __init__~      
zISaveLoadTests.test_saveUnPersistableThenFormat.<locals>.Reprable.__init__c                 S   s   dS )Nreprabler%   r-   r%   r%   r&   __repr__   s   zISaveLoadTests.test_saveUnPersistableThenFormat.<locals>.Reprable.__repr__)__name__
__module____qualname__r8   rH   r"   rK   r%   r%   r%   r&   Reprable}   s    rO   z{object} {object.value}   
log_formatr8   z
reprable 7N)r   r+   r#   r   )r*   rO   rC   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ZdS )z8SaveLoadTests.test_extractingFieldsPostLoad.<locals>.Objr   Nc                 S   s
   d| _ d S )NY  rG   r-   r%   r%   r&   rH      rI   zASaveLoadTests.test_extractingFieldsPostLoad.<locals>.Obj.__init__r   N)rL   rM   rN   rH   r%   r%   r%   r&   Obj   s    rW   z{object.value}rQ   zobject.valuerU   r8   N)dictr   r+   r#   r   assertRaisesKeyError)r*   rW   rC   loadedEventr%   r%   r&   test_extractingFieldsPostLoad   s   z+SaveLoadTests.test_extractingFieldsPostLoadc                 C   s   g }t tt|jd}zdd  W n ty#   t }|d| Y nw | t|d t	| 
|d d }| |t | |t | | t dS )zl
        Round-tripping a failure through L{eventAsJSON} preserves its class and
        structure.
        observerr0   r   za message about failurelog_failureN)r   r	   r   appendZeroDivisionErrorr   failurer#   lenr   r+   r!   
assertTruecheckgetTracebackr"   )r*   eventsr   f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_levelrl   N)rX   r   warnr   r+   assertIs)r*   rC   r[   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"}}Nrk   )r   r#   rX   )r*   r[   r%   r%   r&   test_saveLoadUnknownLevel   s   z'SaveLoadTests.test_saveLoadUnknownLevelrV   )rL   rM   rN   __doc__r   r"   r+   r.   r4   r9   r:   rD   rT   r\   rj   ro   rp   r%   r%   r%   r&   r(   1   s    





	



	r(   c                   @   sL   e Zd ZdZdddZddeddfdd	Zdd
dZdddZdddZ	dS )FileLogObserverTestsz+
    Tests for L{jsonFileLogObserver}.
    r   Nc                 C   s   t  4}t|}ztt| W n ty& } z| | W Y d}~nd}~ww W d   dS W d   dS 1 s:w   Y  dS )zh
        A L{FileLogObserver} returned by L{jsonFileLogObserver} is an
        L{ILogObserver}.
        N)r   r   r   r   r   fail)r*   
fileHandler^   er%   r%   r&   test_interface   s   "z#FileLogObserverTests.test_interfacerecordSeparatorc                 C   s^   t  "}t||}tdd}|| | | | d W d   dS 1 s(w   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}
        r0   xz	{"x": 1}
N)r   r   rX   r#   getvalue)r*   rx   rt   r^   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r|   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{""}.
         rx   Nr}   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y1   |	d Y nw t |
 }tt|}dtt ddf 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.
        r]   r0   r   zfailed as expected	logEventsr   Nc                    s`     t| d | \} d| |d } |t | }  |jjj	dt
	d d S )Nr0   r_   co)r#   rc   assertInr!   r   getTracebackObjecttb_framef_codeco_filenamerstrip__file__)r   failureEventfailureObjecttracebackObjectr-   r%   r&   checkEvents  s   z@FileLogObserverTests.test_failureFormatting.<locals>.checkEvents)r   r   addObserverr	   r   r`   r   r   BaseExceptionrb   r{   listr   r   r   )r*   io	publisherloggedloggerreaderdeserializedr   r%   r-   r&   test_failureFormatting   s    
z+FileLogObserverTests.test_failureFormattingrV   )rw   )
rL   rM   rN   rq   rv   r"   r|   r~   r   r   r%   r%   r%   r&   rr      s    


rr   c                	   @   s   e Zd ZdZd&ddZd&ddZ		d'd	ee d
ee	 de
ddfddZd&ddZd&ddZd&ddZd&ddZd&ddZd&ddZd&ddZd&ddZd&ddZd&d d!Zd&d"d#Zd&d$d%ZdS )(LogFileReaderTestsz-
    Tests for L{eventsFromJSONLogFile}.
    r   Nc                    s8   g  _ ttdtdd f fdd}| _t| d S )Nr)   r   c                    s.   | d t jkrd| v r j|  d S d S d S )Nlog_namespacerecord)jsonLog	namespaceerrorEventsr`   )r)   r-   r%   r&   r^     s   z*LogFileReaderTests.setUp.<locals>.observer)r   r
   r   r   logObserverr   r   )r*   r^   r%   r-   r&   setUp  s
   zLogFileReaderTests.setUpc                 C   s   t | j d S rF   )r   removeObserverr   r-   r%   r%   r&   tearDown&  s   zLogFileReaderTests.tearDown   inFilerx   
bufferSizec                 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}
        rz   r0   yr   N)iterr   r#   nextrY   StopIteration)r*   r   rx   r   rg   r%   r%   r&   _readEvents)  s   zLogFileReaderTests._readEventsc                 C   J   t d}| | | t| jd W d   dS 1 sw   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#   rc   r   r*   rt   r%   r%   r&   &test_readEventsAutoWithRecordSeparator>     

"z9LogFileReaderTests.test_readEventsAutoWithRecordSeparatorc                 C   r   )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  r   z:LogFileReaderTests.test_readEventsAutoEmptyRecordSeparatorc                 C   N   t d}| j|dd | t| jd W d   dS 1 s w   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}
r   r   Nr   r   r%   r%   r&   &test_readEventsExplicitRecordSeparatorP  s   
"z9LogFileReaderTests.test_readEventsExplicitRecordSeparatorc                 C   r   )zM
        L{eventsFromJSONLogFile} handles buffering a partial event.
        r   r0   r   r   Nr   r   r%   r%   r&   test_readEventsPartialBufferZ  s   
"z/LogFileReaderTests.test_readEventsPartialBufferc                 C      t d?}tt|}| t|ddi | tt| | t| jd | | jd d d | | jd d d	 W d
   d
S 1 sFw   Y  d
S )zF
        If the JSON text for a record is truncated, skip it.
        z{"x": 1{"y": 2}
r   r   r0   r   rR   z0Unable to read truncated JSON record: {record!r}r   s   {"x": 1N	r   r   r   r#   r   rY   r   rc   r   r*   rt   rg   r%   r%   r&   test_readTruncatedc     
"z%LogFileReaderTests.test_readTruncatedc                 C   n   t d)}tt|}| t|ddi | tt| | t| jd W d   dS 1 s0w   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   r   )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   rY   r   rc   r   r   r%   r%   r&   test_readUTF8Bytes  s   
"z%LogFileReaderTests.test_readUTF8Bytesc                 C   sr   t d+}tt|dd}| t|ddi | tt| | t| jd W d   dS 1 s2w   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   rz   r   r   Nr   r   r%   r%   r&   test_readTruncatedUTF8Bytes  s   
"z.LogFileReaderTests.test_readTruncatedUTF8Bytesc                 C   r   )zh
        If the JSON text for a record contains invalid UTF-8 text, ignore that
        record.
        s   {"x": ""}
{"y": 2}
r   r   r0   r   rR   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   r   )zD
        If the JSON text for a record is invalid, skip it.
        z{"x": }
{"y": 2}
r   r   r0   r   rR   &Unable to read JSON record: {record!r}r   s   {"x": }
Nr   r   r%   r%   r&   test_readInvalidJSON  r   z'LogFileReaderTests.test_readInvalidJSONc                 C   s   t d3}t|}| tt| | t| jd | | jd d d | | jd d d W d   dS 1 s:w   Y  dS )	zI
        Multiple events without a record separator are skipped.
        z{"x": 1}
{"y": 2}
r0   r   rR   r   r   s   {"x": 1}
{"y": 2}
N)r   r   rY   r   r   r#   rc   r   r   r%   r%   r&   test_readUnseparated  s   
"z'LogFileReaderTests.test_readUnseparatedc                 C   s|   t dd}t ,}t|}|| |d t|}| t||f | t| jd W d   dS 1 s7w   Y  dS )z
        Data written by a L{FileLogObserver} returned by L{jsonFileLogObserver}
        and read by L{eventsFromJSONLogFile} is reconstructed properly.
        r0   ry   r   N)	rX   r   r   seekr   r#   tuplerc   r   )r*   r)   rt   r^   rg   r%   r%   r&   test_roundTrip  s   

"z!LogFileReaderTests.test_roundTriprV   )Nr   )rL   rM   rN   rq   r   r   r   r   r   r"   intr   r   r   r   r   r   r   r   r   r   r   r   r   r%   r%   r%   r&   r     s6    




	
	


	





r   N)0rq   r   r   r   typingr   r   r   r   r   r	   zope.interfacer
   zope.interface.exceptionsr   zope.interface.verifyr   twisted.python.failurer   twisted.trial.unittestr   _flattenr   _formatr   _globalr   _interfacesr   r   _jsonr   r   r   r   r   r   _levelsr   _loggerr   	_observerr   r"   r'   r(   rr   r   r%   r%   r%   r&   <module>   s*     R