U
    n5{ibG  ã                   @   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%   úA/tmp/pip-unpacked-wheel-mnhg7r0q/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   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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©rE   )r+   rE   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   rH   r"   rI   r%   r%   r%   r&   ÚReprable}   s   rM   z{object} {object.value}é   ©Ú
log_formatr9   z
reprable 7N)r   r,   r#   r   )r+   rM   rC   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 )NéY  rG   r/   r%   r%   r&   rH   �   s    zASaveLoadTests.test_extractingFieldsPostLoad.<locals>.Obj.__init__)rJ   rK   rL   rH   r%   r%   r%   r&   ÚObjŽ   s   rS   z{object.value}rO   zobject.valuerR   r9   N)Údictr   r,   r#   r   ÚassertRaisesÚKeyError)r+   rS   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k
rH   tƒ }| d|¡ Y nX |  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!   Ú
assertTrueÚ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_levelrf   N)rT   r   Úwarnr   r,   ZassertIs)r+   rC   rW   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"}}Nre   )r   r#   rT   )r+   rW   r%   r%   r&   Útest_saveLoadUnknownLevel·   s    ÿz'SaveLoadTests.test_saveLoadUnknownLevel)rJ   rK   rL   Ú__doc__r   r"   r,   r0   r6   r:   r;   rD   rQ   rX   rd   rh   ri   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   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+   Ú
fileHandlerZ   Úer%   r%   r&   Útest_interfaceÈ   s    z#FileLogObserverTests.test_interfaceú)ÚrecordSeparatorr   c              	   C   sH   t ƒ �8}t||ƒ}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: C{recordSeparator} argument to
            L{jsonFileLogObserver}
        r2   ©Úxz	{"x": 1}
N)r   r   rT   r#   Úgetvalue)r+   rp   rl   rZ   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©rt   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{""}.
        Ú ©rp   Nru   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k
rd   | 	d¡ Y nX 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.
        rY   r2   r   zfailed as expectedN)Ú	logEventsr   c                    s`   ˆ   t| ƒd¡ | \}ˆ  d|¡ |d }ˆ  |t¡ | ¡ }ˆ   |jjj 	d¡t
 	d¡¡ d S )Nr2   r[   Úco)r#   r_   ZassertInr!   r   ZgetTracebackObjectÚtb_frameÚf_codeÚco_filenameÚrstripÚ__file__)rz   ZfailureEventZfailureObjectZtracebackObjectr/   r%   r&   ÚcheckEvents  s    þz@FileLogObserverTests.test_failureFormatting.<locals>.checkEvents)r   r   ÚaddObserverr	   r   r\   r   r   ÚBaseExceptionr^   rs   Úlistr   r   r   )r+   ÚioZ	publisherZloggedÚloggerÚreaderZdeserializedr�   r%   r/   r&   Útest_failureFormattingó   s    
z+FileLogObserverTests.test_failureFormatting)ro   )
rJ   rK   rL   rj   rn   r"   rt   rv   ry   rˆ   r%   r%   r%   r&   rk   Ã   s   rk   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| kr"ˆ j | ¡ d S )NZlog_namespaceÚrecord)ÚjsonLogÚ	namespaceÚerrorEventsr\   )r*   r/   r%   r&   rZ     s    z*LogFileReaderTests.setUp.<locals>.observer)r�   r
   r   r   ÚlogObserverr   r‚   )r+   rZ   r%   r/   r&   ÚsetUp  s
    zLogFileReaderTests.setUpc                 C   s   t  | j¡ d S rF   )r   ZremoveObserverrŽ   r/   r%   r%   r&   ÚtearDown&  s    zLogFileReaderTests.tearDowné   )ÚinFilerp   Ú
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}
        rr   r2   Úyr   N)Úiterr   r#   ÚnextrU   ÚStopIteration)r+   r’   rp   r“   rb   r%   r%   r&   Ú_readEvents)  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{"\x1e"} as the record separator.
        ú{"x": 1}
{"y": 2}
r   N©r   r˜   r#   r_   r�   ©r+   rl   r%   r%   r&   Ú&test_readEventsAutoWithRecordSeparator>  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{""} as the record separator.
        z{"x": 1}
{"y": 2}
r   Nrš   r›   r%   r%   r&   Ú'test_readEventsAutoEmptyRecordSeparatorG  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}
úrx   r   Nrš   r›   r%   r%   r&   Ú&test_readEventsExplicitRecordSeparatorP  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™   r2   ©r“   r   Nrš   r›   r%   r%   r&   Útest_readEventsPartialBufferZ  s    
z/LogFileReaderTests.test_readEventsPartialBufferc              	   C   s„   t dƒ�r}t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   r2   r   rP   z0Unable to read truncated JSON record: {record!r}rŠ   s   {"x": 1N©	r   r•   r   r#   r–   rU   r—   r_   r�   ©r+   rl   rb   r%   r%   r&   Útest_readTruncatedc  s    
þz%LogFileReaderTests.test_readTruncatedc              	   C   sX   t dƒ�F}tt|ƒƒ}|  t|ƒddi¡ |  tt|¡ |  t| jƒd¡ W 5 Q R X 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   sX   t dƒ�F}t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#   r–   rU   r—   r_   r�   r£   r%   r%   r&   Útest_readUTF8Bytes‚  s
    
z%LogFileReaderTests.test_readUTF8Bytesc              	   C   s\   t dƒ�J}t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    rr   r¦   r   Nr¨   r£   r%   r%   r&   Útest_readTruncatedUTF8Bytes�  s
    
z.LogFileReaderTests.test_readTruncatedUTF8Bytesc              	   C   s„   t dƒ�r}t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   r2   r   rP   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ƒ�r}t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   r2   r   rP   ú&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}
r2   r   rP   r­   rŠ   s   {"x": 1}
{"y": 2}
N)r   r   rU   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.
        r2   rq   r   N)	rT   r   r   Úseekr   r#   Útupler_   r�   )r+   r*   rl   rZ   rb   r%   r%   r&   Útest_roundTripÖ  s    

z!LogFileReaderTests.test_roundTrip)Nr‘   )rJ   rK   rL   rj   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)0rj   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   Ú_flattenr   Ú_formatr   Z_globalr   Z_interfacesr   r   Ú_jsonr   r   r   r   r   r‹   Z_levelsr   Z_loggerr   Z	_observerr   r"   r'   r(   rk   r‰   r%   r%   r%   r&   Ú<module>   s(     R