U
    PeaG                     @   s   d Z dZddlZddlZddlZddlZddlmZ ddlZddl	Z	ddl
mZ ddlmZ edZeZde krzejZejd	Zdae	 Zejd
dZdd ZdddZG dd deZG dd deZG dd deZdddZdS )a  
This is a extended unittest module for Kivy, to make unittests based on
graphics with an OpenGL context.

The idea is to render a Widget tree, and after 1, 2 or more frames, a
screenshot will be made and be compared to the original one.
If no screenshot exists for the current test, the very first one will be used.

The screenshots live in the 'kivy/tests/results' folder and are in PNG format,
320x240 pixels.
)GraphicUnitTestUnitTestTouchUTMotionEvent	async_runrequires_graphicsensure_web_server    N)partial)cgl_get_backend_name)MotionEventunittestmockZKIVY_UNITTEST_SCREENSHOTSZKIVY_EVENTLOOPasyncioc                 C   s    dt  krtjjdd| S | S )Nr   *Skipping because gl backend is set to mockreason)r	   pytestmarkskip)func r   5/tmp/pip-unpacked-wheel-xzebddm3/kivy/tests/common.pyr   )   s    
r   c                    s   t d k	rdS s(tjtjtddtjjdko>tjj	dkt
   fdd}tj|d}d|_|  t  t d krtdd S )	NTz..      c               	      s   ddl m}  ddlm} zz^r0t | }nt	| d}|d|ddadt_
dt_t  t  t  t  W n   dd l}|  Y nX W 5 d at  rt  X d S )	Nr   )SimpleHTTPRequestHandler)	TCPServer)	directory) i@  F)bind_and_activateT)Zhttp.serverr   socketserverr   http_serverhttp_server_readysetoschdirr   daemon_threadsallow_reuse_addressserver_bindserver_activateserve_forever	traceback	print_exc)r   r   handlerr)   Zcurr_dirZ
need_chdirrootr   r   _start_web_server9   s2    
  z,ensure_web_server.<locals>._start_web_server)targetzUnable to start webserver)r   r"   pathjoindirname__file__sysversion_infomajorminorgetcwd	threadingThreaddaemonstartr    wait	Exception)r-   r.   thr   r,   r   r   0   s    r   c                       sp   e Zd ZdZdd ZdddZ fddZd	d
 Zdd Zdd Z	d fdd	Z
dd Zdd Zdd Z  ZS )r   r   c                 G   s*   ddl m} |j}|r&|jr&|j  d S )Nr   	EventLoop)	kivy.baserA   windowcanvasZ
ask_update)selflargsrA   winr   r   r   _force_refreshb   s    
zGraphicUnitTest._force_refresh   c              	   C   sj   ddl m} ddlm} || _z|| jd || W 5 || j X | jdkrf| j	dd | 
  dS )ztCall rendering process using the `root` widget.
        The screenshot will be done in `framecount` frames.
        r   )runTouchApp)ClockrI   T)fakeN)rB   rJ   Z
kivy.clockrK   
framecountZ
unschedulerH   Zschedule_intervaltest_countertearDownsetUp)rE   r-   rM   rJ   rK   r   r   r   renderj   s    
zGraphicUnitTest.renderc                    sf   ddl m}m}m} ||td}trB||sBtd t	| d| _
|| _d| _tt| j||S )zExtend the run of unittest, to check if results directory have been
        found. If no results directory exists, the test will be ignored.
        r   )r1   r2   existsresultsz'No result directory found, cancel test.F)os.pathr1   r2   rR   r3   make_screenshotslogwarningr"   mkdirrN   results_dirtest_failedsuperr   run)rE   argskwargsr1   r2   rR   rY   	__class__r   r   r\   |   s    

zGraphicUnitTest.runc                 C   s   ddl m} d|d< ddlm} |ddd |dd	d
 |dD ]}|d|d  qFddlm} || _|j	| j
d |  |  d|_dd |_|   dS )zPrepare the graphic test, with:
            - Window size fixed to 320x240
            - Default kivy configuration
            - Without any kivy input
        r   environ1ZKIVY_USE_DEFAULTCONFIG)ConfigZgraphicswidthZ320heightZ240inputWindowZon_flipTc                  W   s   d S Nr   )sr   r   r   <lambda>       z'GraphicUnitTest.setUp.<locals>.<lambda>N)r"   rb   Zkivy.configrd   r!   itemsremove_optionkivy.core.windowri   bindon_window_flipZcreate_windowregisterZinitializedcloseclear_window_and_event_loop)rE   rb   rd   ro   ri   r   r   r   rP      s    
zGraphicUnitTest.setUpc                 C   s   ddl m} | j}|jd d  D ]}|| q |jj  |j  |jj  |j	  |j
D ].}t|dr||j	  qbt|drb|j  qbd S )Nr   r@   toucheslast_touches)rB   rA   ri   childrenZremove_widgetrD   beforeclearafterrw   Zpostproc_moduleshasattrrx   )rE   rA   rC   childZ	post_procr   r   r   rv      s    




z+GraphicUnitTest.clear_window_and_event_loopc                  C   s  ddl m} ddlm} ddlm}m} ddlm}m	} ddl
m}m}	 t| ddd | _| jdkrhd	S tsx|  d	S d	}
d
}z&|ddd\}}|| || |  jd7  _dd|  ddd	 | jf }td|  ||}td|  || j|}
td|
  dd	l}|| d }||d \}}|d | }|| }d| ||< d|}d| ||< d|}||
std|  | |||  r|||
 |
}td d}n
td nddlm} ||dd}|jj d j!}||
dd}|jj d j!}||krxt"d |  | jf  | #|||
|  rpt"d! |||
 |
}d}nd| _$nd}dd"lm}m%}m}m&} dd#lm'} ||t(d$}||s|| |	|
||d%||
  ||
kr|	|||d&||
  t)||d'd(}|sd)nd*}|*d+|  |*d,|  | jf  |*d- |*d.||
  ||
krz|*d/||
  n
|*d0 |*d1|  |*d2 W 5 Q R X W 5 z|
|kr|| W n   Y nX |  X d	S )3a  Internal method to be called when the window have just displayed an
        image.
        When an image is showed, we decrement our framecount. If framecount is
        come to 0, we are taking the screenshot.

        The screenshot is done in a temporary place, and is compared to the
        original one -> test ok/ko.
        If no screenshot is available in the results directory, a new one will
        be created.
        r   r@   )mkstemp)r1   rR   )unlinkru   )movecopyrM   rI   NFz.pngz	kivyunit-)suffixprefixz	%s-%d.png_.zCapturing screenshot for %szCapture saved at %szCompare with %sr      z#<span style="color: red;">%s</span>r   z>>>>>>>>
%s<<<<<<<<
z$No image reference, move %s as ref ?zImage used as referenceTzImage discarded)Image)Z	keep_dataz)%s at render() #%d, images are different.zuser ask to use it as ref.)r1   r2   rR   basename)rX   buildzref_%sztest_%sz
index.htmlatz#ffddddz#ffffffz"<div style="background-color: %s">z<h2>%s #%d</h2>z:<table><tr><th>Reference</th><th>Test</th><th>Comment</th>z <tr><td><img src="ref_%s"/></td>z<td><img src="test_%s"/></td>z#<td>First time, no comparison.</td>z<td><pre>%s</pre></td>z</table></div>)+rB   rA   tempfiler   rT   r1   rR   r"   r   ru   shutilr   r   getattrrM   rU   stoprN   idsplitrV   infoZ
screenshotrY   inspectgetouterframescurrentframegetsourcelinesinteractive_ask_refZkivy.core.imager   image_datadatacriticalinteractive_ask_diffrZ   r2   r   rX   r3   openwrite) rE   rC   rA   r   r1   rR   r   ru   r   r   reffnmatchtmpfnfdZtest_uidr   frameZsourcecodetablineZcurrentlineZ
sourcecodeZsourcecodeaskZ	CoreImages1Zsd1s2Zsd2r2   r   rX   	build_dircolorr   r   r   rs      s    







   







zGraphicUnitTest.on_window_flipFc                    s`   ddl m} ddlm} |j| jd |   d| _|  |sN| jrN| d t	t
|   dS )zgWhen the test is finished, stop the application, and unbind our
        current flip callback.
        r   )stopTouchApprh   rj   NF)rB   r   rq   ri   Zunbindrs   rv   rZ   
assertTruer[   r   rO   )rE   rL   r   ri   r_   r   r   rO   7  s    

zGraphicUnitTest.tearDownc                    s
  ddl m} d|krdS ddlm}m}m}m}m}	m}
 ddl	m
}m} d_| fdd	  fd
d}||}||}|d| d  |dd  |||dj|d ||dj|d |
d|dj|	d |
d dj|	d   jS )Nr   ra   UNITTEST_INTERACTIVETTkLabelLEFTRIGHTBOTTOMButtonr   ImageTkFc                      s       d S rk   destroyr   r-   r   r   do_closeQ  s    z5GraphicUnitTest.interactive_ask_ref.<locals>.do_closec                      s   d_    d S NTretvalr   r   rE   r   r   do_yesT  s    z3GraphicUnitTest.interactive_ask_ref.<locals>.do_yeszThe test %s
have no reference.textzUse this image as a reference ?r   ZjustifyZsider   zUse as referencer   commandZDiscard)r"   rb   tkinterr   r   r   r   r   r   PILr   r   r   r   
PhotoImagepackmainloop)rE   codeZimagefntestidrb   r   r   r   r   r   r   r   r   r   r   Zphotor   r   r-   rE   r   r   E  s&     

z#GraphicUnitTest.interactive_ask_refc                    s*  ddl m} d|krdS ddlm}m}m}m}	m}
m} ddl	m
}m} d_| fdd  fd	d
}|||}|||}|d| d  |dd  |||dj|	d ||dj|	d ||dj|d |d|dj|
d |d dj|
d   jS )Nr   ra   r   Fr   r   c                      s       d S rk   r   r   r   r   r   r   p  s    z6GraphicUnitTest.interactive_ask_diff.<locals>.do_closec                      s   d_    d S r   r   r   r   r   r   r   s  s    z4GraphicUnitTest.interactive_ask_diff.<locals>.do_yeszCThe test %s
have generated an differentimage as the reference one..r   zWhich one is good ?r   r   r   zUse the new image -->r   z<-- Use the reference)r"   rb   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rE   r   r   r   r   rb   r   r   r   r   r   r   r   r   r   ZphototmpZphotorefr   r   r   r   d  s<     z$GraphicUnitTest.interactive_ask_diffc                 C   s&   ddl m} t|D ]}|  qdS )zRender the new frames and:

        * tick the Clock
        * dispatch input from all registered providers
        * flush all the canvas operations
        * redraw Window canvas if necessary
        r   r@   N)rB   rA   rangeZidle)rE   countrA   ir   r   r   advance_frames  s    zGraphicUnitTest.advance_frames)rI   )F)__name__
__module____qualname__rM   rH   rQ   r\   rP   rv   rs   rO   r   r   r   __classcell__r   r   r_   r   r   _   s   
 #r   c                       sD   e Zd ZdZ fddZdd Zdd Zdd	 Z fd
dZ  Z	S )r   a  Custom MotionEvent representing a single touch. Similar to `on_touch_*`
    methods from the Widget class, this one introduces:

    * touch_down
    * touch_move
    * touch_up

    Create a new touch with::

        touch = UnitTestTouch(x, y)

    then you press it on the default position with::

        touch.touch_down()

    or move it or even release with these simple calls::

        touch.touch_move(new_x, new_y)
        touch.touch_up()
    c                    s\   ddl m} || _|j}tt| j| jjd||j	d  ||j
d  dddd d	g| _d
S )z`Create a MotionEvent instance with X and Y of the first
        position a touch is at.
        r   r@   c         ?xyTtouch)is_touchtype_idposN)rB   rA   	eventlooprC   r[   r   __init__r`   r   re   rf   profile)rE   r   r   rA   rG   r_   r   r   r     s    
 
zUnitTestTouch.__init__c                 G   s   | j d|  d S )Nbeginr   post_dispatch_inputrE   r]   r   r   r   
touch_down  s    zUnitTestTouch.touch_downc                 C   s>   | j j}| ||jd  ||jd  d | j d|  d S )Nr   r   update)r   rC   r   re   rf   r   )rE   r   r   rG   r   r   r   
touch_move  s    zUnitTestTouch.touch_movec                 G   s   | j d|  d S )Nendr   r   r   r   r   touch_up  s    zUnitTestTouch.touch_upc                    s$   |d | _ |d | _t | d S Nr   r   ZsxZsyr[   depackr   r_   r   r   r     s    

zUnitTestTouch.depack)
r   r   r   __doc__r   r   r   r   r   r   r   r   r_   r   r     s   r   c                       s(   e Zd Z fddZ fddZ  ZS )r   c                    s2   | dd | dd t j|| dg| _d S )Nr   Tr   r   r   )
setdefaultr[   r   r   )rE   r]   r^   r_   r   r   r     s    zUTMotionEvent.__init__c                    s$   |d | _ |d | _t | d S r   r   r   r_   r   r   r     s    

zUTMotionEvent.depack)r   r   r   r   r   r   r   r   r_   r   r     s   r   c                    s     fdd}| d kr|S || S )Nc                    s&  dt  krtjjdd| S tjd dk s8tjd dkrJtjjdd| S  d k	rltjjd	 ggd
d| } tdkrzdd l}tj	|
| W S  tk
r   tjjdd|  Y S X nhtdkrz dd l}ddlm} d
| _| W S  tk
r   tjjdd|  Y S X ntjjdd| S d S )Nr   r   r   r   r   rI      zJSkipping because graphics tests are not supported on py3.5, only on py3.6+Zkivy_appT)Zindirectr   zAKIVY_EVENTLOOP == "asyncio" but "pytest-asyncio" is not installedtrio)trio_fixturez;KIVY_EVENTLOOP == "trio" but "pytest-trio" is not installedzNKIVY_EVENTLOOP must be set to either of "asyncio" or "trio" to run async tests)r	   r   r   r   r4   r5   Zparametrizekivy_eventlooppytest_asyncior   ZfixtureImportErrorr   Zpytest_trior   Z_force_trio_fixture)r   r   r   r   app_cls_funcr   r   
inner_func  s^    
  
zasync_run.<locals>.inner_funcr   )r   r   r   r   r   r   r     s    %r   )N)NN) r   __all__r   loggingr   r4   	functoolsr   r"   r9   Zkivy.graphics.cglr	   Zkivy.input.motioneventr
   	getLoggerrV   object_baseZTestCaserb   getrU   r   Eventr    r   r   r   r   r   r   r   r   r   r   r   <module>   s4   


/  7A