B
    9dOP              	   @   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 ddlmZmZ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 ZdZi Z e!ede d< e!ede d< e!ede d< G dd deZ"G dd dZ#dd Z$dd Z%G dd de#Z&dd Z'dBddZ(d d! Z)d"d# Z*ej+d$d%Z,e,j-d&d'd(d) e,j-d*d+d,d- e,j-d.d/d0 e,j-d1d2d3dd4e.d5d6 e,j-d7d+d8d- e,j-d9d:d;d< d=d> Z/d?d@ Z0e1dAkre0  dS )CzNotebook Javascript Test Controller

This module runs one or more subprocesses which will actually run the Javascript
test suite.
    N)BytesIO)ThreadLockEvent)patch)jupyter_runtime_dir)bytes_to_strwhich)get_sys_info)TemporaryDirectory)TimeoutExpiredc             C   s
   |  |S )N)wait)ptimeout r   \/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/notebook/jstest.py
popen_wait   s    r   
   casperjs	phantomjsslimerjsc                   sN   e Zd ZdZdZd fdd	Zdd Zdd Zd	d
 Zdd Z	dd Z
  ZS )StreamCapturerTFc                sB   t    || _g | _t | _t \| _| _	t
 | _t | _d S )N)super__init__echostreamsr   bufferospipereadfdwritefdr   buffer_lockr   stop)selfr   )	__class__r   r   r   ,   s    
zStreamCapturer.__init__c          	   C   st   d| _ xP| j sVt| jd}| j | j| W d Q R X | j	rt
jt| qW t| j t| j d S )NTi   )startedr"   is_setr   readr   r!   r   writer   sysstdoutr   closer    )r#   chunkr   r   r   run5   s    zStreamCapturer.runc          	   C   s.   | j  | jd | jd W d Q R X d S )Nr   )r!   r   truncateseek)r#   r   r   r   reset_bufferC   s    zStreamCapturer.reset_bufferc          	   C   s   | j  | j S Q R X d S )N)r!   r   getvalue)r#   r   r   r   
get_bufferH   s    zStreamCapturer.get_bufferc             C   s   | j s|   d S )N)r%   start)r#   r   r   r   ensure_startedL   s    zStreamCapturer.ensure_startedc             C   s.   | j s
dS | j  t| jd |   dS )zSafely stop the thread.N    )r%   r"   setr   r(   r    join)r#   r   r   r   haltP   s
    
zStreamCapturer.halt)F)__name__
__module____qualname__daemonr%   r   r-   r0   r2   r4   r8   __classcell__r   r   )r$   r   r   )   s   	r   c               @   sf   e Zd ZdZdZdZdZdZdZdZ	dd Z
dd Zddd	Zd
d Zdd Zdd Zdd ZeZdS )TestControllerzRun tests in a subprocess
    Nc             C   s   g | _ i | _g | _d S )N)cmdenvdirs)r#   r   r   r   r   j   s    zTestController.__init__c             C   s   dS )zCreate temporary directories etc.

        This is only called when we know the test group will be run. Things
        created here may be cleaned up by self.cleanup().
        Nr   )r#   r   r   r   setupo   s    zTestController.setupFc             C   sn   t j }|| j |rd}t| d | _}|  |rB|jnd }|rPt	j
nd }t	j| j|||d| _d S )NT)r   )r*   stderrr@   )r   environcopyupdater@   r   stdout_capturerr3   r    
subprocessSTDOUTPopenr?   process)r#   buffer_outputcapture_outputr@   cr*   rC   r   r   r   launchw   s    

zTestController.launchc             C   s(   | j   | j  | j | _| j jS )N)rK   r   rG   r8   r2   r*   
returncode)r#   r   r   r   r      s    

zTestController.waitc             C   s   dS )aN  Print extra information about this test run.

        If we're running in parallel and showing the concise view, this is only
        called if the test group fails. Otherwise, it's called before the test
        group is started.

        The base implementation does nothing, but it can be overridden by
        subclasses.
        Nr   )r#   r   r   r   print_extra_info   s    
zTestController.print_extra_infoc             C   s   | j }|dks| dk	rdS ytd|j  |  W n   Y n.X x*tdD ]}| dkrntd qRP qRW | dkrtd dS )z2Cleanup on exit by killing any leftover processes.NzCleaning up stale PID: r   g?z+... failed. Manual cleanup may be required.)rK   pollprintpidkillrangetimesleep)r#   Zsubpir   r   r   cleanup_process   s    zTestController.cleanup_processc             C   s$   |    x| jD ]}|  qW dS )zDKill process if it's still alive, and clean up temporary directoriesN)rZ   rA   cleanup)r#   tdr   r   r   r[      s    zTestController.cleanup)FF)r9   r:   r;   __doc__sectionr?   r@   rA   rK   r*   r   rB   rO   r   rQ   rZ   r[   __del__r   r   r   r   r>   Z   s   
r>   c              C   s$   dd l m}  tjtj| jdS )Nr    )Znotebook.teststestsr   pathr7   dirname__file__)tr   r   r   get_js_test_dir   s    rf   c                 s.   dd l } t  |   d } fdd|D S )Nr   z[!_]*/c                s   g | ]}t j| qS r   )r   rb   relpath).0x)test_dirr   r   
<listcomp>   s    z!all_js_groups.<locals>.<listcomp>)globrf   )rl   all_subdirsr   )rj   r   all_js_groups   s    rn   c                   s   e Zd ZdZdgZdddZdd	 Zd
d Z fddZ fddZ	dd Z
edd Zdd Zdd Zdd Zdd Zdd Z  ZS )JSControllerzRun CasperJS tests r   Tr   Nc             C   s~   t |  || _|| _|| _|| _d| _tjdtj	d| _
t }dtj|d }tj|| j}dd||d| j g| _d	S )
zCreate new test runner.z/a@b/z^FAIL.*)flagsz--includes=zutil.jsr   testz	--engine=N)r>   r   enginer^   xuniturlbase_urlrecompile	MULTILINEslimer_failurerf   r   rb   r7   r?   )r#   r^   rs   rr   rt   Zjs_test_dirZincludesZ
test_casesr   r   r   r      s    
zJSController.__init__c          	   C   sj  t  | _t  | _t  | _t  | _| jj| jj| jjd| _| j| j | j| j | j| j | j| j t	
t	j| jjt	jdd t	
t	j| jjt	jdd | jr|   | jr$yt| jjdk}W n   d}Y nX |r| jd| j  ntd	| j d
nBd| _|   | jrX| jd| jd| j  ntjddg| _d S )N)HOMEZJUPYTER_CONFIG_DIRZ
IPYTHONDIRu
   sub ∂ir1u   sub ∂ir 1au
   sub ∂ir2u   sub ∂ir 1b   Fz--url=zCould not reach "z".r   z--url=http://localhost:dz-czraise SystemExit(1))r   ZipydirZ
config_dirnbdirhomenamer@   rA   appendr   makedirsrb   r7   rs   	add_xunitrt   requestsgetstatus_coder?   	Exceptionserver_port_init_serverru   r)   
executable)r#   aliver   r   r   rB      s8    ""
zJSController.setupc             C   s0   t j| jddd }| jd|  d S )N/.z
.xunit.xmlz--xunit=)r   rb   abspathr^   replacer?   r   )r#   Z
xunit_filer   r   r   r      s    zJSController.add_xunitc                s.   | j dkr|st jddS t j|dS d S )Nr   T)rM   )rL   )rr   r   rO   )r#   rL   )r$   r   r   rO     s    zJSController.launchc                sF   t  j||}| jdkr>t| j}|dkr.|S t| j|S |S dS )z#Wait for the JSController to finishr   r   N)r   r   rr   r   r*   boolry   search)r#   Zpargskwargsretr*   )r$   r   r   r     s    

zJSController.waitc             C   s   t d| jj d S )Nz&Running tests with notebook directory )rS   r}   r   )r#   r   r   r   rQ     s    zJSController.print_extra_infoc             C   s    t dd | j| jg D }|S )Nc             s   s   | ]}t | V  qd S )N)have)rh   ar   r   r   	<genexpr>   s    z(JSController.will_run.<locals>.<genexpr>)allrequirementsrr   )r#   Z
should_runr   r   r   will_run  s    zJSController.will_runc          	   C   s   t jdddd| jjdd| j g | _}t jdr>|d t	  | _
}|  tj }|| j tj||jtj| jj|d	| _td
d| jji t }W dQ R X tj|d| jj d| _|   dS )z/Start the notebook server in a separate processz-mnotebookz--no-browserz--notebook-dirz--NotebookApp.token=z--NotebookApp.base_url=linuxz--KernelManager.transport=ipc)r*   rC   cwdr@   z
os.environrz   Nz	nbserver-z.json)r)   r   r}   r   ru   server_commandplatform
startswithr   r   stream_capturerr3   r   rD   rE   rF   r@   rH   rJ   r    rI   serverr   dictr~   r   rb   r7   rT   server_info_file_wait_for_server)r#   commandrN   r@   Zruntime_dirr   r   r   r   #  s.    


zJSController._init_serverc          	   C   s   xdt dD ]X}| j dk	r$|  S tj| jrXy|   W n t	k
rR   Y nX dS t
d q
W td| j tjd dS )z0Wait 30 seconds for the notebook server to starti,  Ng?z)Notebook server-info file never arrived: )file)rV   r   rR   _failed_to_startr   rb   existsr   _load_server_info
ValueErrorrW   rX   rS   r)   rC   )r#   rY   r   r   r   r   B  s    
zJSController._wait_for_serverc             C   s<   | j  dd}tdtjd t| j t|tjd dS )z"Notebook server exited prematurelyzutf-8r   zNotebook failed to start: )r   N)r   r2   decoderS   r)   rC   r   )r#   Zcapturedr   r   r   r   V  s    
zJSController._failed_to_startc          	   C   s.   t | j}t|}W dQ R X |d | _dS )z7Notebook server started, load connection info from JSONNport)openr   jsonloadr   )r#   finfor   r   r   r   ]  s    zJSController._load_server_infoc             C   s   t | dry| j  W n tk
r,   Y nX yt| jt W nF tk
r   ytdtj	d | j
  W n tk
r~   Y nX Y nX yt| jt W n, tk
r   td| j dtj	d Y nX | j  t|  d S )Nr   z0Failed to terminate notebook server, killing it.)r   zNotebook server still running ())hasattrr   	terminateOSErrorr   NOTEBOOK_SHUTDOWN_TIMEOUTr   rS   r)   rC   rU   r   r   r8   r>   r[   )r#   r   r   r   r[   c  s,    


zJSController.cleanup)Tr   N)r9   r:   r;   r]   r   r   rB   r   rO   r   rQ   propertyr   r   r   r   r   r[   r=   r   r   )r$   r   ro      s   
)	ro   c                sZ   j }|st }jrdnd  fdd|D }|}dd |D }dd |D }||fS )zVReturns two lists of TestController instances, those to run, and those
    not to run.r   r   c                s    g | ]}t |j jd qS ))rs   rr   rt   )ro   rs   rt   )rh   r   )rr   optionsr   r   rk     s    z'prepare_controllers.<locals>.<listcomp>c             S   s   g | ]}|j r|qS r   )r   )rh   rN   r   r   r   rk     s    c             S   s   g | ]}|j s|qS r   )r   )rh   rN   r   r   r   rk     s    )
testgroupsrn   r   )r   r   Zc_jsZcontrollersto_runnot_runr   )rr   r   r   prepare_controllers  s    r   Tc             C   s   zy^y$|    |s|   | j|d W n( tk
rP   ddl}|  | dfS X |  }| |fS  tk
r|   | tj	 fS X W d| 
  X dS )a  Setup and run a test controller.

    If buffer_output is True, no output is displayed, to avoid it appearing
    interleaved. In this case, the caller is responsible for displaying test
    output on failure.

    Returns
    -------
    controller : TestController
      The same controller as passed in, as a convenience for using map() type
      APIs.
    exitcode : int
      The exit code of the test subprocess. Non-zero indicates failure.
    )rL   r   N   )rB   rQ   rO   r   	traceback	print_excr   KeyboardInterruptsignalSIGINTr[   )
controllerrL   r   exitcoder   r   r   do_run  s    
r   c                 s  t  } g   fdd}|d| d dd |d| d  |d	| d
  tdd  D fdd D  g }g }x.t D ]"\}}|r|| q~|| q~W |r҈ d |   dd| d  |r d |   dd| d  d S )z@Return a string with a summary report of test-related variables.c                s     | |f d S )N)r   )r   value)outr   r   _add  s    zreport.<locals>._addzPython versionsys_version
r`   zsys.executableZsys_executablePlatformr   c             s   s   | ]\}}t |V  qd S )N)len)rh   nvr   r   r   r     s    zreport.<locals>.<genexpr>c                s(   g | ] \}}|d   d| dqS )<z: r   r   )rh   r   r   )widthr   r   rk     s    zreport.<locals>.<listcomp>z-
Tools and libraries available at test time:
z    z1
Tools and libraries NOT available at test time:
)r
   r   maxr   itemsr   sortr7   )infr   ZavailZ	not_availkZis_availr   )r   r   r   report  s.    

r   c          	   C   s,  t | \}}d#dd}g }t }t  | jdkrx\|D ]T}td|j tj  t|dd\}}|r|	| |t
j krtd	 P t  q8W nytj| j}xv|t|D ]f\}}|d
krdnd}	t|d|j |	 |r|  tt|j |	| |t
j krtd	 P qW W n tk
r2   dS X x"|D ]}t|d|j d q:W t }
|
| }t|}t|}td td tt  d|dd}tddd |std| d| nRdd |D }td| d| dd| d | t  td! td$|  t  |r(td dS )%a  Run the entire Javascript test suite.

    This function constructs TestControllers and runs them in subprocesses.

    Parameters
    ----------

    All parameters are passed as attributes of the options object.

    testgroups : list of str
      Run only these sections of the test suite. If empty, run all the available
      sections.

    fast : int or None
      Run the test suite in parallel, using n simultaneous processes. If None
      is passed, one process is used per CPU core. Default 1 (i.e. sequential)

    inc_slow : bool
      Include slow tests. By default, these tests aren't run.

    slimerjs : bool
      Use slimerjs if it's installed instead of phantomjs for casperjs tests.

    url : unicode
      Address:port to use when running the JS tests.

    xunit : bool
      Produce Xunit XML output. This is written to multiple foo.xunit.xml files.

    extra_args : list
      Extra arguments to pass to the test subprocesses, e.g. '-v'
    F   -c             S   s(   | d7 } d|  |t|  |}| | S )Nr   )rjustr   )ZltextZrtextr   fillr   r   r   justify  s    zrun_jstestall.<locals>.justifyr   zTest group:F)rL   ZInterruptedr   OKZFAILEDzTest group: NzNOT RUNZF______________________________________________________________________z?Test suite completed for system with the following information:zTook z.3fzs.zStatus: r`   )endzOK (z test groups).c             S   s   g | ]
}|j qS r   )r^   )rh   rN   r   r   r   rk   5  s    z!run_jstestall.<locals>.<listcomp>zERROR - z out of z test groups failed (z, z).z"You may wish to rerun these, with:  python -m notebook.jstest)r   r   )r   )r   rW   rS   fastr^   r)   r*   flushr   r   r   r   multiprocessingpoolZ
ThreadPoolZimap_unorderedrQ   r   r   r   r   r7   exit)r   r   r   r   failedZt_startr   resr   Z
res_stringZt_endZt_testsZnrunnersZnfailZtookZfailed_sectionsr   r   r   run_jstestall  sf    !








$r   z%Run Jupyter Notebook Javascript tests)descriptionr   *z9Run specified groups of tests. If omitted, run all tests.)nargshelpz
--slimerjs
store_truezGUse slimerjs if it's installed instead of phantomjs for casperjs tests.)actionr   z--urlzURL to use for the JS tests.)r   z-jz--fast?r   zlRun test sections in parallel. This starts as many processes as you have cores, or you can specify a number.)r   constdefaulttyper   z--xunitzProduce Xunit XML resultsz--subproc-streamscapturezkWhat to do with stdout/stderr from subprocesses. 'capture' (default), 'show' and 'discard' are the options.)r   r   c              C   s   t g } g | _| S )zgGet an argparse Namespace object with the default arguments, to pass to
    :func:`run_iptestall`.
    )	argparser
parse_args
extra_args)r   r   r   r   default_optionsP  s    
r   c              C   st   yt jd} W n& tk
r6   t jdd  }g }Y n"X t jd|  }t j| d d  }t|}||_t| d S )Nz--r   )r)   argvindexr   r   r   r   r   )ZixZto_parser   r   r   r   r   mainX  s    

r   __main__)T)2r]   argparser   Zmultiprocessing.poolr   r   rv   r   r   r)   rH   rW   ior   	threadingr   r   r   Zunittest.mockr   Zjupyter_core.pathsr   Zipython_genutils.py3compatr   r	   Znotebook._sysinfor
   Zipython_genutils.tempdirr   r   r   r   r   r   r   r>   rf   rn   ro   r   r   r   r   ArgumentParserr   add_argumentintr   r   r9   r   r   r   r   <module>   sd   1^ C
"#h
