U
    luf©  ã                   @   s¤   d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddl
mZmZmZ ddlmZ dd„ Zejdd„ ƒZeG d	d
„ d
e	jƒƒZdS )ao  Test script to find circular references.

Circular references are not leaks per se, because they will eventually
be GC'd. However, on CPython, they prevent the reference-counting fast
path from being used and instead rely on the slower full GC. This
increases memory footprint and CPU overhead, so we try to eliminate
circular references created by normal operation.
é    N)ÚwebÚgenÚ
httpclient)ÚskipNotCPythonc                    sD   ‡ ‡‡‡‡‡fdd„‰g ‰ g ‰t ƒ ‰t tt| ƒƒ‰t ƒ ‰ˆ| ƒ ˆ S )a  Find circular references in a list of objects.

    The garbage list contains objects that participate in a cycle,
    but also the larger set of objects kept alive by that cycle.
    This function finds subsets of those objects that make up
    the cycle(s).
    c                    s˜   | D ]Ž}t |ƒ}|ˆkrq|ˆkr$q|ˆkrTˆˆ |¡d … }| |¡ ˆ  |¡ qˆ |¡ ˆ |¡ ˆt |¡ƒ ˆ ¡  ˆ |¡ ˆ |¡ qd S ©N)ÚidÚindexÚappendÚaddÚgcZget_referentsÚpopÚremove)ÚlevelÚitemZitem_idÚ	candidate©ÚfoundZgarbage_idsÚinnerÚstackZ	stack_idsZvisited_ids© ú@/tmp/pip-unpacked-wheel-bmg6zs32/tornado/test/circlerefs_test.pyr   "   s"    




z'find_circular_references.<locals>.inner)ÚsetÚmapr   )Úgarbager   r   r   Úfind_circular_references   s    	r   c               	   c   s*  t  ¡  t  ¡  t  t jt jB ¡ dV  zèt ¡ } t	j
}| t	_
zt  ¡  W 5 |t	_
X t jdd… }g t jdd…< t|ƒdkr„W ¢’dS t|ƒD ]r}|  d¡ |D ]}|  dt|ƒ› ¡ qž|D ]@}t|tjƒr¼|  d|j› ¡ |  dt|ƒ› ¡ t |¡ q¼qŒ~t|  ¡ ƒ‚W 5 t  d¡ t  ¡  X dS )zERaise AssertionError if the wrapped code creates garbage with cycles.Nr   z!
==========
 Circular 
==========z
    z	
Locals: z
Traceback: )r   ÚdisableZcollectZ	set_debugZDEBUG_STATSZDEBUG_SAVEALLÚenableÚioÚStringIOÚsysÚstderrr   Úlenr   ÚwriteÚreprÚ
isinstanceÚtypesÚ	FrameTypeÚf_localsÚ	tracebackÚprint_stackÚAssertionErrorÚgetvalue)ÚfZ
old_stderrr   Zcircularr   r   r   r   Úassert_no_cycle_garbage@   s8    

r-   c                   @   sD   e 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S )ÚCircleRefsTestc              
      s¼   G ‡ fdd„dt ƒ‰ |  t¡L}tƒ : ˆ dƒ}ˆ dƒ}ˆ dƒ}||_||_||_||_~~W 5 Q R X W 5 Q R X |  dt|j	ƒ¡ |  dt|j	ƒ¡ |  dt|j	ƒ¡ |  
d	t|j	ƒ¡ d S )
Nc                       s    e Zd Z‡ fdd„Zdd„ ZdS )z)CircleRefsTest.test_known_leak.<locals>.Cc                    s   || _ d | _d | _d | _d S r   )ÚnameÚaÚbÚc)Úselfr/   ©ÚCr   r   Ú__init__m   s    z2CircleRefsTest.test_known_leak.<locals>.C.__init__c                 S   s   d| j › S )Nzname=)r/   ©r3   r   r   r   Ú__repr__s   s    z2CircleRefsTest.test_known_leak.<locals>.C.__repr__N)Ú__name__Ú
__module__Ú__qualname__r6   r8   r   r4   r   r   r5   l   s   r5   r0   r1   r2   ZCircularz
    name=az
    name=bz
    name=c)ÚobjectÚassertRaisesr*   r-   r1   r2   r0   ZassertInÚstrÚ	exceptionZassertNotIn)r3   Úcmr0   r1   r2   r   r4   r   Útest_known_leakj   s    
zCircleRefsTest.test_known_leakc              	   Ã   s‚   t  d|fg¡}tj ¡ \}}tj |¡}| |¡ t 	¡ }t
ƒ  | d|› d¡I d H  W 5 Q R X | ¡  | ¡  | ¡  d S )Nú/zhttp://127.0.0.1:)r   ÚApplicationÚtornadoZtestingZbind_unused_portZ
httpserverZ
HTTPServerZ
add_socketr   ZAsyncHTTPClientr-   ÚfetchÚcloseÚstop)r3   Zhandler_classZappÚsocketÚportÚserverÚclientr   r   r   Úrun_handlerŒ   s    ÿÿ
"zCircleRefsTest.run_handlerc                 C   s&   G dd„ dt jƒ}t |  |¡¡ d S )Nc                   @   s   e Zd Zdd„ ZdS )z1CircleRefsTest.test_sync_handler.<locals>.Handlerc                 S   s   |   d¡ d S ©Núok
)r"   r7   r   r   r   Úget¤   s    z5CircleRefsTest.test_sync_handler.<locals>.Handler.getN©r9   r:   r;   rO   r   r   r   r   ÚHandler£   s   rQ   ©r   ZRequestHandlerÚasyncioÚrunrL   ©r3   rQ   r   r   r   Útest_sync_handler¢   s    z CircleRefsTest.test_sync_handlerc                 C   s&   G dd„ dt jƒ}t |  |¡¡ d S )Nc                   @   s   e Zd Zdd„ ZdS )z=CircleRefsTest.test_finish_exception_handler.<locals>.Handlerc                 S   s   t  d¡‚d S rM   )r   ZFinishr7   r   r   r   rO   «   s    zACircleRefsTest.test_finish_exception_handler.<locals>.Handler.getNrP   r   r   r   r   rQ   ª   s   rQ   rR   rU   r   r   r   Útest_finish_exception_handler©   s    z,CircleRefsTest.test_finish_exception_handlerc                 C   s&   G dd„ dt jƒ}t |  |¡¡ d S )Nc                   @   s   e Zd Zejdd„ ƒZdS )z1CircleRefsTest.test_coro_handler.<locals>.Handlerc                 s   s   t  d¡V  |  d¡ d S ©Ng{®Gáz„?rN   ©rS   Úsleepr"   r7   r   r   r   rO   ²   s    z5CircleRefsTest.test_coro_handler.<locals>.Handler.getN)r9   r:   r;   r   Ú	coroutinerO   r   r   r   r   rQ   ±   s   rQ   rR   rU   r   r   r   Útest_coro_handler°   s    z CircleRefsTest.test_coro_handlerc                 C   s&   G dd„ dt jƒ}t |  |¡¡ d S )Nc                   @   s   e Zd Zdd„ ZdS )z2CircleRefsTest.test_async_handler.<locals>.Handlerc                 Ó   s   t  d¡I d H  |  d¡ d S rX   rY   r7   r   r   r   rO   »   s    z6CircleRefsTest.test_async_handler.<locals>.Handler.getNrP   r   r   r   r   rQ   º   s   rQ   rR   rU   r   r   r   Útest_async_handler¹   s    z!CircleRefsTest.test_async_handlerc              
      sh   dd l }|j d¡J‰G ‡fdd„dtƒ}|ƒ ‰ ‡ fdd„}tƒ  t |ƒ ¡ W 5 Q R X W 5 Q R X d S )Nr   é   c                       s    e Zd Z” Zejjdd„ ƒZdS )z4CircleRefsTest.test_run_on_executor.<locals>.Factoryc                 S   s   d S r   r   r7   r   r   r   rT   Í   s    z8CircleRefsTest.test_run_on_executor.<locals>.Factory.runN)r9   r:   r;   ÚexecutorrD   Ú
concurrentZrun_on_executorrT   r   )Úthread_poolr   r   ÚFactoryÊ   s   rb   c                  “   s    t dƒD ]} ˆ  ¡ I d H  qd S )Né   )ÚrangerT   )Úi)Úfactoryr   r   ÚmainÓ   s    z1CircleRefsTest.test_run_on_executor.<locals>.main)Úconcurrent.futuresZfuturesZThreadPoolExecutorr<   r-   rS   rT   )r3   r`   rb   rg   r   )rf   ra   r   Útest_run_on_executorÁ   s    z#CircleRefsTest.test_run_on_executorN)
r9   r:   r;   rA   rL   rV   rW   r\   r]   ri   r   r   r   r   r.   h   s   "	r.   )Ú__doc__rS   Ú
contextlibr   r   r   r(   r%   ÚtypingZunittestrD   r   r   r   Ztornado.test.utilr   r   Úcontextmanagerr-   ZTestCaser.   r   r   r   r   Ú<module>   s"   	'
'