U
    W[H                     @   s   d Z ddl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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mZmZmZ ddlm Z  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}.
    )StringIOBytesIO)verifyObjectBrokenMethodImplementation)unicode)TestCase)Failure   )ILogObserverLogPublisher)formatEvent)LogLevel)extractField)globalLogPublisher)eventAsJSONeventFromJSONjsonFileLogObservereventsFromJSONLogFilelog)Loggerc                 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.
    @type testCase: L{TestCase}

    @param savedJSON: The result of L{eventAsJSON}.
    @type savedJSON: L{unicode} (we hope)

    @return: C{savedJSON}
    @rtype: L{unicode}

    @raise AssertionError: If any of the preconditions fail.
    
r   )assertIsInstancer   assertEqualcount)ZtestCaseZ	savedJSON r   ?/usr/lib/python3/dist-packages/twisted/logger/test/test_json.pysavedJSONInvariants   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d Zdd Zdd Zdd ZdS )SaveLoadTestsz2
    Tests for loading and saving log events.
    c                 C   s   t | t|S )z
        Serialize some an events, assert some things about it, and return the
        JSON.

        @param event: An event.
        @type event: L{dict}

        @return: JSON.
        )r   r   )selfeventr   r   r   savedEventJSON8   s    
zSaveLoadTests.savedEventJSONc                 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_simpleSaveLoadE   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{unicode} and any non-L{unicode}
        keys will be converted.
        r	   4)   31r&   Nr!   r"   r   r   r   test_saveLoadL   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	   r'   unpersistableTNr   r   r    objectr"   r   r   r   test_saveUnPersistableY   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   ሴr&   r*   TNr+   r"   r   r   r   test_saveNonASCIId   s    
zSaveLoadTests.test_saveNonASCIIc                 C   sZ   dd }d|t di}ttk	r.|ddi | t| |d|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.
        c                 S   s$   t tkrdtt| S t | S d S )N    )bytesstrjoinmapchrxr   r   r   asbytesu   s    z-SaveLoadTests.test_saveBytes.<locals>.asbytesZhello   s   skippedZokaycharmapN)ranger0   r1   updater   r   r    decode)r   r7   
inputEventr   r   r   test_saveBytesp   s    zSaveLoadTests.test_saveBytesc                 C   s@   G dd dt }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d Zdd ZdS )z@SaveLoadTests.test_saveUnPersistableThenFormat.<locals>.Reprablec                 S   s
   || _ d S Nvalue)r   rA   r   r   r   __init__   s    zISaveLoadTests.test_saveUnPersistableThenFormat.<locals>.Reprable.__init__c                 S   s   dS )NZreprabler   r"   r   r   r   __repr__   s    zISaveLoadTests.test_saveUnPersistableThenFormat.<locals>.Reprable.__repr__N)__name__
__module____qualname__rB   rC   r   r   r   r   Reprable   s   rG   z{object} {object.value}   
log_formatr,   z
reprable 7N)r,   r   r    r   r   )r   rG   r=   ZoutputEventr   r   r    test_saveUnPersistableThenFormat   s    z.SaveLoadTests.test_saveUnPersistableThenFormatc                 C   sb   G dd dt }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 ZdS )z8SaveLoadTests.test_extractingFieldsPostLoad.<locals>.Objc                 S   s
   d| _ d S )NY  r@   r"   r   r   r   rB      s    zASaveLoadTests.test_extractingFieldsPostLoad.<locals>.Obj.__init__N)rD   rE   rF   rB   r   r   r   r   Obj   s   rM   z{object.value}rI   zobject.valuerL   r,   N)r,   dictr   r    r   r   assertRaisesKeyError)r   rM   r=   loadedEventr   r   r   test_extractingFieldsPostLoad   s    z+SaveLoadTests.test_extractingFieldsPostLoadc                 C   s   g }t |jd}zdd  W n& tk
rB   t }|d| Y nX ddl}| d dk	rd|  | t	|d t
| |d d }| |t | |t | | t dS )zl
        Round-tripping a failure through L{eventAsJSON} preserves its class and
        structure.
        observerr%   r   za message about failureNlog_failure)r   appendZeroDivisionErrorr   failuresysexc_infoZ	exc_clearr   lenr   r    r   Z
assertTrueZcheckZgetTracebackr1   )r   eventsr   frY   Z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_levelr`   N)rN   r   warnr   r    ZassertIs)r   r=   rQ   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"}}Nr_   )r   r   rN   )r   rQ   r   r   r   test_saveLoadUnknownLevel   s    z'SaveLoadTests.test_saveLoadUnknownLevelN)rD   rE   rF   __doc__r    r#   r)   r-   r.   r>   rK   rR   r^   rb   rc   r   r   r   r   r   3   s   
r   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )FileLogObserverTestsz+
    Tests for L{jsonFileLogObserver}.
    c                 C   sZ   t  J}t|}ztt| W n, tk
rJ } z| | W 5 d}~X Y nX W 5 Q R X dS )zh
        A L{FileLogObserver} returned by L{jsonFileLogObserver} is an
        L{ILogObserver}.
        N)r   r   r   r
   r   Zfail)r   
fileHandlerT   er   r   r   test_interface   s    z#FileLogObserverTests.test_interfacec              	   K   sV   | dd}t :}t|f|}tdd}|| | | d| W 5 Q R X 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: A record separator.
        @type recordSeparator: L{unicode}

        @param kwargs: Keyword arguments to pass to L{jsonFileLogObserver}.
        @type kwargs: L{dict}
        recordSeparatorr%   r5   z{0}{{"x": 1}}
N)getr   r   rN   r   getvalueformat)r   kwargsri   rf   rT   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{u"\x1e"}.
        Nro   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{u""}.
         ri   Nrp   r"   r   r   r   &test_observeWritesEmptyRecordSeparator  s    z;FileLogObserverTests.test_observeWritesEmptyRecordSeparatorc                    s   t  }t }g }||j |t| t|d}zdd  W n   |d Y nX t | }tt	|} 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.
        rS   r%   r   zfailed as expectedc                    s`     t| d | \} d| |d } |t | }  |jjj	dt
	d d S )Nr%   rU   co)r   r[   ZassertInr   r   ZgetTracebackObjecttb_framef_codeco_filenamerstrip__file__)Z	logEventsZfailureEventZfailureObjectZtracebackObjectr"   r   r   checkEvents,  s    z@FileLogObserverTests.test_failureFormatting.<locals>.checkEventsN)
r   r   addObserverrV   r   r   rX   rl   listr   )r   ioZ	publisherZloggedZloggerreaderZdeserializedr{   r   r"   r   test_failureFormatting  s    
z+FileLogObserverTests.test_failureFormattingN)	rD   rE   rF   rd   rh   ro   rq   rt   r   r   r   r   r   re      s   		re   c                   @   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 S )!LogFileReaderTestsz-
    Tests for L{eventsFromJSONLogFile}.
    c                    s&   g  _  fdd}| _t| d S )Nc                    s&   | d t jkr"d| kr" j|  d S )NZlog_namespacerecord)jsonLog	namespaceerrorEventsrV   )r   r"   r   r   rT   D  s
    z*LogFileReaderTests.setUp.<locals>.observer)r   logObserverr   r|   )r   rT   r   r"   r   setUpA  s    zLogFileReaderTests.setUpc                 C   s   t | j d S r?   )r   ZremoveObserverr   r"   r   r   r   tearDownP  s    zLogFileReaderTests.tearDownc                 K   sF   t |f|}| 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{{u"x": 1}} and C{{u"y": 2}}.

        @param fileHandle: The file to read from.

        @param kwargs: Keyword arguments to pass to L{eventsFromJSONLogFile}.
        r6   r%   yr	   N)r   r   nextrO   StopIteration)r   rf   rn   r\   r   r   r   _readEventsT  s    	zLogFileReaderTests._readEventsc              	   C   s4   t d"}| | | t| jd W 5 Q R X dS )z
        L{eventsFromJSONLogFile} reads events from a file and automatically
        detects use of C{u"\x1e"} as the record separator.
        {"x": 1}
{"y": 2}
r   Nr   r   r   r[   r   r   rf   r   r   r   &test_readEventsAutoWithRecordSeparatord  s    
z9LogFileReaderTests.test_readEventsAutoWithRecordSeparatorc              	   C   s4   t d"}| | | t| jd W 5 Q R X dS )z
        L{eventsFromJSONLogFile} reads events from a file and automatically
        detects use of C{u""} as the record separator.
        z{"x": 1}
{"y": 2}
r   Nr   r   r   r   r   'test_readEventsAutoEmptyRecordSeparatorq  s    
z:LogFileReaderTests.test_readEventsAutoEmptyRecordSeparatorc              	   C   s8   t d&}| j|dd | t| jd W 5 Q R X dS )z{
        L{eventsFromJSONLogFile} reads events from a file and is told to use
        a specific record separator.
        z{"x": 1}
{"y": 2}
rs   r   Nr   r   r   r   r   &test_readEventsExplicitRecordSeparator~  s    z9LogFileReaderTests.test_readEventsExplicitRecordSeparatorc              	   C   s8   t d&}| j|dd | t| jd W 5 Q R X dS )zM
        L{eventsFromJSONLogFile} handles buffering a partial event.
        r   r%   Z
bufferSizer   Nr   r   r   r   r   test_readEventsPartialBuffer  s    z/LogFileReaderTests.test_readEventsPartialBufferc              	   C   s   t dn}t|}| t|ddi | tt| | t| jd | | jd d d | | jd d d	 W 5 Q R X d
S )zF
        If the JSON text for a record is truncated, skip it.
        z{"x": 1{"y": 2}
r   r	   r%   r   rJ   z0Unable to read truncated JSON record: {record!r}r   s   {"x": 1Nr   r   r   r   rO   r   r[   r   r   rf   r\   r   r   r   test_readTruncated  s    z%LogFileReaderTests.test_readTruncatedc              	   C   sT   t dB}t|}| t|ddi | tt| | t| jd W 5 Q R X dS )zg
        If the file being read from vends L{unicode}, strings decode from JSON
        as-is.
        u   {"currency": "€"}
currency   €r   Nr   r   r   r   r   test_readUnicode  s
    
z#LogFileReaderTests.test_readUnicodec              	   C   sT   t dB}t|}| t|ddi | tt| | t| jd W 5 Q R X 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   rO   r   r[   r   r   r   r   r   test_readUTF8Bytes  s
    
z%LogFileReaderTests.test_readUTF8Bytesc              	   C   sX   t dF}t|dd}| t|ddi | tt| | t| jd W 5 Q R X 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   r6   r   r   Nr   r   r   r   r   test_readTruncatedUTF8Bytes  s
    
z.LogFileReaderTests.test_readTruncatedUTF8Bytesc              	   C   s   t dn}t|}| t|ddi | tt| | t| jd | | jd d d | | jd d d	 W 5 Q R X d
S )zh
        If the JSON text for a record contains invalid UTF-8 text, ignore that
        record.
        s   {"x": ""}
{"y": 2}
r   r	   r%   r   rJ   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n}t|}| t|ddi | tt| | t| jd | | jd d d | | jd d d	 W 5 Q R X d
S )zD
        If the JSON text for a record is invalid, skip it.
        z{"x": }
{"y": 2}
r   r	   r%   r   rJ   &Unable to read JSON record: {record!r}r   s   {"x": }
Nr   r   r   r   r   test_readInvalidJSON  s    z'LogFileReaderTests.test_readInvalidJSONc              	   C   sl   t dZ}t|}| tt| | t| jd | | jd d d | | jd d d W 5 Q R X dS )	zI
        Multiple events without a record separator are skipped.
        z{"x": 1}
{"y": 2}
r%   r   rJ   r   r   s   {"x": 1}
{"y": 2}
N)r   r   rO   r   r   r   r[   r   r   r   r   r   test_readUnseparated  s    z'LogFileReaderTests.test_readUnseparatedc              	   C   sf   t dd}t L}t|}|| |d t|}| t||f | t| jd W 5 Q R X dS )z
        Data written by a L{FileLogObserver} returned by L{jsonFileLogObserver}
        and read by L{eventsFromJSONLogFile} is reconstructed properly.
        r%   r5   r   N)	rN   r   r   seekr   r   tupler[   r   )r   r   rf   rT   r\   r   r   r   test_roundTrip%  s    

z!LogFileReaderTests.test_roundTripN)rD   rE   rF   rd   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <  s    r   N)%rd   r~   r   r   Zzope.interface.verifyr   r   Ztwisted.python.compatr   Ztwisted.trial.unittestr   Ztwisted.python.failurer   Z	_observerr
   r   Z_formatr   Z_levelsr   Z_flattenr   Z_globalr   Z_jsonr   r   r   r   r   r   Z_loggerr   r   r   re   r   r   r   r   r   <module>   s"    -]