B
    u9aϟ                 @   s  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 Ze \ZZZedk redeeef e sedd	e krejd
kredejejejdZdZdd Ze Zdd Zed\ZZ esededej\Z Z!de!krHdZ"ee"e!#  dd Z$e$ Z%dZ&e'e
j(dG dd dej)Z*G dd de*Z+e'e dG d d! d!e*Z,G d"d# d#e*Z-G d$d% d%e*Z.G d&d' d'e*Z/G d(d) d)e*Z0d*d+ Z1e2d,kr e1  dS )-    N)support)run_unittestfindfilepython_is_optimizedc           	   C   s   y<t jdddgt jt jdd} |  |  d }W d Q R X W n tk
rZ   tdY nX td|}|d kr|t	d	| |t
|d
t
|dfS )Ngdbz-nxz	--versionT)stdoutstderrZuniversal_newlinesr   zCouldn't find gdb on the pathz^GNU gdb.*?\b(\d+)\.(\d+)zunable to parse GDB version: %r      )
subprocessPopenPIPEcommunicateOSErrorunittestSkipTestresearch	Exceptionintgroup)procversionmatch r   /usr/lib/python3.7/test_gdb.pyget_gdb_version   s    r      zFgdb versions before 7.0 didn't support python embedding. Saw %s.%s:
%sz3test_gdb only works on source builds at the moment.ZClangdarwinzDtest_gdb doesn't work correctly when python is built with LLVM clangzpython-gdb.pyZ123c              C   s4   t d} | sdS |  }d|ko2tdd |D S )NZCFLAGSFz-mcetc             s   s$   | ]}| d o|d V  qdS )z-fcf-protection)z=nonez=returnN)
startswithendswith).0flagr   r   r   	<genexpr>G   s   z!cet_protection.<locals>.<genexpr>)	sysconfigZget_config_varsplitany)Zcflagsflagsr   r   r   cet_protection?   s    
r(   c           	   O   s   |rt j }|| nd}d}ttfdkr>|ddt f7 }tj||  tj	tj	tj	|d}| |
 \}}W dQ R X |dd|ddfS )	zRuns gdb in --batch mode with the additional arguments given by *args.

    Returns its (stdout, stderr) decoded from utf-8 using the replace handler.
    N)r   z--batchz-nx)r      z-iexzadd-auto-load-safe-path )stdinr   r   envzutf-8replace)osenvironcopyupdategdb_major_versiongdb_minor_versioncheckout_hook_pathr   r   r   r   decode)argsZenv_varsr+   Zbase_cmdr   outerrr   r   r   run_gdbO   s    

r8   z9--eval-command=python import sys; print(sys.version_info)z*gdb not built with embedded python supportz--argszauto-loading has been declinedz3gdb security settings prevent use of custom hooks: c              C   s>   t d\} }td| }|s&td|dd}d|kS )Nz+--eval-command=python print(dir(gdb.Frame))z.*\[(.*)\].*z1Unable to parse output from gdb.Frame.select testr	   z, z'select')r8   r   r   r   r   r   r%   )r   _mZgdb_frame_dirr   r   r   gdb_has_frame_selectu   s    
r;   
builtin_idznot useful for PGOc               @   sF   e Zd ZdZddeddfddZdddZdd	 Zd
d Zdd Z	dS )DebuggerTestsz(Test that the debugger can debug Python.NFc             C   s  dd| ddg}t tfdkr&|dg7 }|rBtr8|dg7 }||7 }n
|dg7 }d	d
 |D }|dtjg7 }|t  |s|dg7 }|r|d|g7 }n|r||g7 }t|dt	i\}}	|	
 }
g }d| dddf}x8|
D ]0}|sqd|krtd||s|| qW | |g  |S )z
        Run 'python -c SOURCE' under gdb with a breakpoint.

        Support injecting commands after the breakpoint is reached

        Returns the stdout from gdb

        cmds_after_breakpoint: if provided, a list of strings: gdb commands
        zset breakpoint pending yeszbreak %szset print address offrun)r   r)   zset print entry-values nonext	backtracec             S   s   g | ]}d | qS )z--eval-command=%sr   )r!   cmdr   r   r   
<listcomp>   s    z1DebuggerTests.get_stack_trace.<locals>.<listcomp>z--argsz-Sz-cPYTHONHASHSEEDzFunction "%s" not defined.z5Do you need "set solib-search-path" or "set sysroot"?zBFD: z	warning: zPC not savedzKgdb cannot walk the frame object because the Program Counter is not present)r1   r2   CET_PROTECTIONsys
executableextendr   Z_args_from_interpreter_flagsr8   rC   
splitlinesr   r   r   appendassertEqual)selfsourcescript
breakpointcmds_after_breakpointimport_siteZcommandsr5   r6   r7   ZerrlinesZunexpected_errlinesZignore_patternsliner   r   r   get_stack_trace   sJ    










zDebuggerTests.get_stack_tracec             C   sP   |pdg}| j |t||d}td|tj}|sB| d||f  |d|fS )Nzbacktrace 1)rN   rO   rP   zO.*#0\s+builtin_id\s+\(self\=.*,\s+v=\s*(.*?)\)\s+at\s+\S*Python/bltinmodule.c.*zUnexpected gdb output: %r
%sr	   )rR   BREAKPOINT_FNr   r   DOTALLfailr   )rK   rL   rO   rP   
gdb_outputr:   r   r   r   get_gdb_repr   s    

zDebuggerTests.get_gdb_reprc             C   s    | j ||d||f d dS )z9Ensure that the given "actual" string ends with "exp_end"z%r did not end with %r)msgN)
assertTruer    )rK   actualZexp_endr   r   r   assertEndsWith  s    zDebuggerTests.assertEndsWithc             C   s,   t ||t j}|s(| jd||f d d S )Nz%r did not match %r)rX   )r   r   rT   rU   )rK   rZ   patternr:   r   r   r   assertMultilineMatches  s    z$DebuggerTests.assertMultilineMatchesc             C   s   t dS )Nzgdb_sample.py)r   )rK   r   r   r   get_sample_script$  s    zDebuggerTests.get_sample_script)NF)
__name__
__module____qualname____doc__rS   rR   rW   r[   r]   r^   r   r   r   r   r=      s   t 
r=   c               @   s   e Zd Zdd Zd<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 d!Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; ZdS )>PrettyPrintTestsc             C   s   |  d}| t|k d S )Nzid(42))rR   rY   rS   )rK   rV   r   r   r   test_getting_backtrace(  s    
z'PrettyPrintTests.test_getting_backtraceNc             C   sB   |  dt| d \}}|s&t|}| ||d|||f  d S )Nzid()z1%r did not equal expected %r; full output was:
%s)rW   asciireprrJ   )rK   valZexp_reprgdb_reprrV   r   r   r   assertGdbRepr,  s    zPrettyPrintTests.assertGdbReprc             C   s6   |  d |  d |  d |  d |  d dS )z0Verify the pretty-printing of various int values*   r   il    J)l  I5 N)rj   )rK   r   r   r   test_int6  s
    



zPrettyPrintTests.test_intc             C   s"   |  d |  d |  d dS )z2Verify the pretty-printing of True, False and NoneTFN)rj   )rK   r   r   r   test_singletons>  s    

z PrettyPrintTests.test_singletonsc             C   s0   |  i  |  ddid |  dddd dS )z*Verify the pretty-printing of dictionariesfoobarz{'foo': 'bar'}rk   )rn   Zdouglasz{'foo': 'bar', 'douglas': 42}N)rj   )rK   r   r   r   
test_dictsD  s    
zPrettyPrintTests.test_dictsc             C   s    |  g  |  ttd dS )z#Verify the pretty-printing of lists   N)rj   listrange)rK   r   r   r   
test_listsK  s    
zPrettyPrintTests.test_listsc             C   sR   |  d |  d |  d |  d |  d |  tdd tdD  d	S )
z#Verify the pretty-printing of bytes    s(   And now for something hopefully the sames7   string with embedded NUL here   and then some more texts7   this is a tab:	 this is a slash-N:
 this is a slash-R:s!   this is byte 255: and byte 128:c             S   s   g | ]}|qS r   r   )r!   br   r   r   rB   \  s    z/PrettyPrintTests.test_bytes.<locals>.<listcomp>   N)rj   bytesrs   )rK   r   r   r   
test_bytesP  s    




zPrettyPrintTests.test_bytesc                sx   t dd\}}|  |s s,td|  fdd}d d d |d	 |d
 |td dS )z-Verify the pretty-printing of unicode stringsz--eval-commandz:python import locale; print(locale.getpreferredencoding())zFunable to determine the preferred encoding of embedded Python in GDB: c                sF   y|    d}W n$ tk
r6   | t|  Y nX |  d S )NT)encodeUnicodeEncodeErrorrj   rf   )textZ	printable)encodingrK   r   r   
check_reprn  s    
z1PrettyPrintTests.test_strings.<locals>.check_repr z(And now for something hopefully the samez7string with embedded NUL here   and then some more textu   ☠u   文字化けi! N)r8   rstripRuntimeErrorrj   chr)rK   r6   r7   r~   r   )r}   rK   r   test_strings^  s    
	


zPrettyPrintTests.test_stringsc             C   s(   |  t d |  dd |  d dS )z$Verify the pretty-printing of tuplesz())r	   z(1,))rn   ro   ZbazN)rj   tuple)rK   r   r   r   test_tuples  s    zPrettyPrintTests.test_tuplesc             C   s   t tfdk r| d | t d | tdgd tjjsh| tddgd | tdd	d
gd | d\}}| 	|d dS )z"Verify the pretty-printing of sets)r      z.pretty-printing of sets needs gdb 7.3 or laterzset()az{'a'}rv   z
{'a', 'b'}r)   rq      z	{4, 5, 6}z&s = set(['a','b'])
s.remove('a')
id(s)z{'b'}N)
r1   r2   skipTestrj   setrE   r'   ignore_environmentrW   rJ   )rK   ri   rV   r   r   r   	test_sets  s    

zPrettyPrintTests.test_setsc             C   sl   t tfdk r| d | t d | tdgd tjjsh| tddgd | tdd	d
gd dS )z(Verify the pretty-printing of frozensets)r   r   z4pretty-printing of frozensets needs gdb 7.3 or laterzfrozenset()r   zfrozenset({'a'})rv   zfrozenset({'a', 'b'})r)   rq   r   zfrozenset({4, 5, 6})N)r1   r2   r   rj   	frozensetrE   r'   r   )rK   r   r   r   test_frozensets  s    
z PrettyPrintTests.test_frozensetsc             C   s8   |  d\}}| |d |  d\}}| |d d S )NzR
try:
    raise RuntimeError("I am an error")
except RuntimeError as e:
    id(e)
zRuntimeError('I am an error',)z=
try:
    a = 1 / 0
except ZeroDivisionError as e:
    id(e)
z&ZeroDivisionError('division by zero',))rW   rJ   )rK   ri   rV   r   r   r   test_exceptions  s    

z PrettyPrintTests.test_exceptionsc             C   s0   |  d\}}td|}| j|d| d dS )z7Verify the pretty-printing of new-style class instancesz8
class Foo:
    pass
foo = Foo()
foo.an_int = 42
id(foo)z*<Foo\(an_int=42\) at remote 0x-?[0-9a-f]+>z'Unexpected new-style class rendering %r)rX   N)rW   r   r   rY   )rK   ri   rV   r:   r   r   r   test_modern_class  s
    
z"PrettyPrintTests.test_modern_classc             C   s0   |  d\}}td|}| j|d| d dS )z<Verify the pretty-printing of an instance of a list subclasszO
class Foo(list):
    pass
foo = Foo()
foo += [1, 2, 3]
foo.an_int = 42
id(foo)z*<Foo\(an_int=42\) at remote 0x-?[0-9a-f]+>z'Unexpected new-style class rendering %r)rX   N)rW   r   r   rY   )rK   ri   rV   r:   r   r   r   test_subclassing_list  s
    
z&PrettyPrintTests.test_subclassing_listc             C   s0   |  d\}}td|}| j|d| d dS )z=Verify the pretty-printing of an instance of a tuple subclasszH
class Foo(tuple):
    pass
foo = Foo((1, 2, 3))
foo.an_int = 42
id(foo)z*<Foo\(an_int=42\) at remote 0x-?[0-9a-f]+>z'Unexpected new-style class rendering %r)rX   N)rW   r   r   rY   )rK   ri   rV   r:   r   r   r   test_subclassing_tuple  s
    
z'PrettyPrintTests.test_subclassing_tuplec       	      C   s`   |r|dg}ndg}| j ||d\}}|r6||kr6dS d}t||}|s\| d||f  dS )zRun Python under gdb, corrupting variables in the inferior process
        immediately before taking a backtrace.

        Verify that the variable's representation is the expected failsafe
        representationr@   )rO   Nz<.* at remote 0x-?[0-9a-f]+>z$Unexpected gdb representation: %r
%s)rW   r   r   rU   )	rK   rL   Z
corruptionexpreprrO   ri   rV   r\   r:   r   r   r   
assertSane  s    
zPrettyPrintTests.assertSanec             C   s&   | j dddgd\}}| |d dS )z2Ensure that a NULL PyObject* is handled gracefullyzid(42)zset variable v=0r@   )rO   Z0x0N)rW   rJ   )rK   ri   rV   r   r   r   test_NULL_ptr
  s    zPrettyPrintTests.test_NULL_ptrc             C   s   |  dd dS )z?Ensure that a PyObject* with NULL ob_type is handled gracefullyzid(42)zset v->ob_type=0N)r   )rK   r   r   r   test_NULL_ob_type  s    z"PrettyPrintTests.test_NULL_ob_typec             C   s   | j dddd dS )zDEnsure that a PyObject* with a corrupt ob_type is handled gracefullyzid(42)zset v->ob_type=0xDEADBEEF42)r   N)r   )rK   r   r   r   test_corrupt_ob_type  s    z%PrettyPrintTests.test_corrupt_ob_typec             C   s   | j dddd dS )zDEnsure that a PyObject* with a type with corrupt tp_flags is handledzid(42)zset v->ob_type->tp_flags=0x0r   )r   N)r   )rK   r   r   r   test_corrupt_tp_flags  s    z&PrettyPrintTests.test_corrupt_tp_flagsc             C   s   | j dddd dS )zCEnsure that a PyObject* with a type with corrupt tp_name is handledzid(42)z"set v->ob_type->tp_name=0xDEADBEEFr   )r   N)r   )rK   r   r   r   test_corrupt_tp_name%  s    z%PrettyPrintTests.test_corrupt_tp_namec             C   sF   t jjr| d | jddd\}}td|}| j|d| d dS )	zAEnsure that the new-style class _Helper in site.py can be handledz(need site module, but -S option was usedzid(__builtins__.help)T)rP   z!<_Helper at remote 0x-?[0-9a-f]+>zUnexpected rendering %r)rX   N)rE   r'   no_siter   rW   r   r   rY   )rK   ri   rV   r:   r   r   r   test_builtins_help+  s    
z#PrettyPrintTests.test_builtins_helpc             C   s8   |  d\}}| |d |  d\}}| |d dS )zbEnsure that a reference loop involving a list doesn't lead proxyval
        into an infinite loop:z#a = [3, 4, 5] ; a.append(a) ; id(a)z[3, 4, 5, [...]]z-a = [3, 4, 5] ; b = [a] ; a.append(b) ; id(a)z[3, 4, 5, [[...]]]N)rW   rJ   )rK   ri   rV   r   r   r   test_selfreferential_list9  s    z*PrettyPrintTests.test_selfreferential_listc             C   s   |  d\}}| |d dS )zbEnsure that a reference loop involving a dict doesn't lead proxyval
        into an infinite loop:z-a = {} ; b = {'bar':a} ; a['foo'] = b ; id(a)z{'foo': {'bar': {...}}}N)rW   rJ   )rK   ri   rV   r   r   r   test_selfreferential_dictD  s    z*PrettyPrintTests.test_selfreferential_dictc             C   s.   |  d\}}| td|d||f  d S )Nz:
class Foo:
    pass
foo = Foo()
foo.an_attr = foo
id(foo)z1<Foo\(an_attr=<\.\.\.>\) at remote 0x-?[0-9a-f]+>z$Unexpected gdb representation: %r
%s)rW   rY   r   r   )rK   ri   rV   r   r   r   'test_selfreferential_old_style_instanceL  s    

z8PrettyPrintTests.test_selfreferential_old_style_instancec             C   sX   |  d\}}| td|d||f  |  d\}}| td|d||f  d S )NzB
class Foo(object):
    pass
foo = Foo()
foo.an_attr = foo
id(foo)z1<Foo\(an_attr=<\.\.\.>\) at remote 0x-?[0-9a-f]+>z$Unexpected gdb representation: %r
%szR
class Foo(object):
    pass
a = Foo()
b = Foo()
a.an_attr = b
b.an_attr = a
id(a)zZ<Foo\(an_attr=<Foo\(an_attr=<\.\.\.>\) at remote 0x-?[0-9a-f]+>\) at remote 0x-?[0-9a-f]+>)rW   rY   r   r   )rK   ri   rV   r   r   r   'test_selfreferential_new_style_instanceY  s    



z8PrettyPrintTests.test_selfreferential_new_style_instancec             C   s6   |  d\}}| |d | t|dtd  dS )z)Verify that very long output is truncatedzid(list(range(1000)))a  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226...(truncated)i   z...(truncated)N)rW   rJ   len)rK   ri   rV   r   r   r   test_truncationt  s
    
z PrettyPrintTests.test_truncationc             C   s.   |  d\}}| td|d||f  d S )Nz$import sys; id(sys.stdout.readlines)zO<built-in method readlines of _io.TextIOWrapper object at remote 0x-?[0-9a-f]+>z$Unexpected gdb representation: %r
%s)rW   rY   r   r   )rK   ri   rV   r   r   r   test_builtin_method  s
    
z$PrettyPrintTests.test_builtin_methodc             C   s6   | j dddgd}| td|tjd||f  d S )Nz:
def foo(a, b, c):
    pass

foo(3, 4, 5)
id(foo.__code__)r<   z:print (PyFrameObject*)(((PyCodeObject*)v)->co_zombieframe))rN   rO   zM.*\s+\$1 =\s+Frame 0x-?[0-9a-f]+, for file <string>, line 3, in foo \(\)\s+.*z$Unexpected gdb representation: %r
%s)rR   rY   r   r   rT   )rK   rV   r   r   r   test_frames  s    

zPrettyPrintTests.test_frames)N)N) r_   r`   ra   rd   rj   rl   rm   rp   rt   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rc   '  s:   

-

rc   z&Python was compiled with optimizationsc               @   s,   e Zd Zdd Zdd Zdd Zdd Zd	S )
PyListTestsc             C   s   |  || d S )N)r[   )rK   ZexpectedrZ   r   r   r   assertListing  s    zPyListTests.assertListingc             C   s$   | j |  dgd}| d| dS )z'Verify that the "py-list" command workszpy-list)rM   rO   z   5    
   6    def bar(a, b, c):
   7        baz(a, b, c)
   8    
   9    def baz(*args):
 >10        id(42)
  11    
  12    foo(1, 2, 3)
N)rR   r^   r   )rK   btr   r   r   test_basic_command  s    

zPyListTests.test_basic_commandc             C   s$   | j |  dgd}| d| dS )z7Verify the "py-list" command with one absolute argumentz	py-list 9)rM   rO   zI   9    def baz(*args):
 >10        id(42)
  11    
  12    foo(1, 2, 3)
N)rR   r^   r   )rK   r   r   r   r   test_one_abs_arg  s    

zPyListTests.test_one_abs_argc             C   s$   | j |  dgd}| d| dS )z8Verify the "py-list" command with two absolute argumentszpy-list 1,3)rM   rO   zR   1    # Sample script for use by test_gdb.py
   2    
   3    def foo(a, b, c):
N)rR   r^   r   )rK   r   r   r   r   test_two_abs_args  s    

zPyListTests.test_two_abs_argsN)r_   r`   ra   r   r   r   r   r   r   r   r   r     s   r   c               @   sx   e Zd Zeedee ddd Zeeddd Z	eeddd Z
eedee dd	d
 ZdS )StackNavigationTestsz$test requires py-up/py-down commandsz&Python was compiled with optimizationsc             C   s&   | j |  ddgd}| |d dS )z%Verify that the "py-up" command workszpy-up)rM   rO   zp^.*
#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\)
    baz\(a, b, c\)
$N)rR   r^   r]   )rK   r   r   r   r   test_pyup_command  s    
z&StackNavigationTests.test_pyup_commandc             C   s$   | j |  dgd}| |d dS )z7Verify handling of "py-down" at the bottom of the stackzpy-down)rM   rO   z$Unable to find a newer python frame
N)rR   r^   r[   )rK   r   r   r   r   test_down_at_bottom  s    

z(StackNavigationTests.test_down_at_bottomc             C   s(   | j |  dgd d}| |d dS )z2Verify handling of "py-up" at the top of the stackzpy-uprq   )rM   rO   z%Unable to find an older python frame
N)rR   r^   r[   )rK   r   r   r   r   test_up_at_top  s    
z#StackNavigationTests.test_up_at_topc             C   s(   | j |  dddgd}| |d dS )z$Verify "py-up" followed by "py-down"zpy-upzpy-down)rM   rO   z^.*
#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\)
    baz\(a, b, c\)
#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 10, in baz \(args=\(1, 2, 3\)\)
    id\(42\)
$N)rR   r^   r]   )rK   r   r   r   r   test_up_then_down  s    
z&StackNavigationTests.test_up_then_downN)r_   r`   ra   r   
skipUnlessHAS_PYUP_PYDOWNskipIfr   r   r   r   r   r   r   r   r   r     s   

r   c               @   s   e Zd Zee ddd Zee ddd Zdd Zee ddd	 Z	ee dd
d Z
ee ddd ZdS )	PyBtTestsz&Python was compiled with optimizationsc             C   s$   | j |  dgd}| |d dS )z%Verify that the "py-bt" command workszpy-bt)rM   rO   aF  ^.*
Traceback \(most recent call first\):
  <built-in method id of module object .*>
  File ".*gdb_sample.py", line 10, in baz
    id\(42\)
  File ".*gdb_sample.py", line 7, in bar
    baz\(a, b, c\)
  File ".*gdb_sample.py", line 4, in foo
    bar\(a, b, c\)
  File ".*gdb_sample.py", line 12, in <module>
    foo\(1, 2, 3\)
N)rR   r^   r]   )rK   r   r   r   r   test_bt  s    

zPyBtTests.test_btc             C   s$   | j |  dgd}| |d dS )z*Verify that the "py-bt-full" command worksz
py-bt-full)rM   rO   a>  ^.*
#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\)
    baz\(a, b, c\)
#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 4, in foo \(a=1, b=2, c=3\)
    bar\(a, b, c\)
#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 12, in <module> \(\)
    foo\(1, 2, 3\)
N)rR   r^   r]   )rK   r   r   r   r   test_bt_full  s    

zPyBtTests.test_bt_fullc             C   s@   d}| j |dgd}| d| | j |dgd}| d| dS )zBVerify that "py-bt" indicates threads that are waiting for the GILaN  
from threading import Thread

class TestThread(Thread):
    # These threads would run forever, but we'll interrupt things with the
    # debugger
    def run(self):
        i = 0
        while 1:
             i += 1

t = {}
for i in range(4):
   t[i] = TestThread()
   t[i].start()

# Trigger a breakpoint on the main thread
id(42)

zthread apply all py-bt)rO   zWaiting for the GILzthread apply all py-bt-fullN)rR   assertIn)rK   rA   rV   r   r   r   test_threads"  s    

zPyBtTests.test_threadsc             C   sH   d}| j |dddgd}| d| | j |dddgd}| d| dS )	z?Verify that "py-bt" indicates if a thread is garbage-collectingzRfrom gc import collect
id(42)
def foo():
    collect()
def bar():
    foo()
bar()
zbreak update_refscontinuezpy-bt)rO   zGarbage-collectingz
py-bt-fullN)rR   r   )rK   rA   rV   r   r   r   test_gcB  s    zPyBtTests.test_gcc             C   sF   d}| j |dddgd}| d| | j |ddgd}| d| d	S )
zAVerify that "py-bt" displays invocations of PyCFunction instanceszLfrom time import gmtime
def foo():
    gmtime(1)
def bar():
    foo()
bar()
Ztime_gmtimer   zpy-bt)rN   rO   z<built-in method gmtimez
py-bt-fullz#2 <built-in method gmtimeN)rR   r   )rK   rA   rV   r   r   r   test_pycfunction\  s    	
zPyBtTests.test_pycfunctionc             C   sH   t d}ddg}tr |d |d | j||d}| |d d S )Nz
            class MyList(list):
                def __init__(self):
                    super().__init__()   # wrapper_call()

            id("first break point")
            l = MyList()
        zbreak wrapper_callr   r?   zpy-bt)rO   z1<method-wrapper u?'__init__' of MyList object at )textwrapdedentrD   rI   rR   ZassertRegex)rK   rA   rO   rV   r   r   r   test_wrapper_cally  s    

zPyBtTests.test_wrapper_callN)r_   r`   ra   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s    r   c               @   sp   e Zd Zee ddd Zee deeddd Z	ee ddd Z
ee dd	d
 ZdS )PyPrintTestsz&Python was compiled with optimizationsc             C   s&   | j |  ddgd}| |d dS )z(Verify that the "py-print" command workszpy-upzpy-print args)rM   rO   z".*\nlocal 'args' = \(1, 2, 3\)\n.*N)rR   r^   r]   )rK   r   r   r   r   r     s    
zPyPrintTests.test_basic_commandz$test requires py-up/py-down commandsc             C   s,   | j |  dddddgd}| |d d S )Nzpy-upz
py-print cz
py-print bz
py-print a)rM   rO   z3.*\nlocal 'c' = 3\nlocal 'b' = 2\nlocal 'a' = 1\n.*)rR   r^   r]   )rK   r   r   r   r   test_print_after_up  s    
z PyPrintTests.test_print_after_upc             C   s&   | j |  ddgd}| |d d S )Nzpy-upzpy-print __name__)rM   rO   z&.*\nglobal '__name__' = '__main__'\n.*)rR   r^   r]   )rK   r   r   r   r   test_printing_global  s    
z!PyPrintTests.test_printing_globalc             C   s&   | j |  ddgd}| |d d S )Nzpy-upzpy-print len)rM   rO   zV.*\nbuiltin 'len' = <built-in method len of module object at remote 0x-?[0-9a-f]+>\n.*)rR   r^   r]   )rK   r   r   r   r   test_printing_builtin  s    
z"PyPrintTests.test_printing_builtinN)r_   r`   ra   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s   r   c               @   sD   e Zd Zee ddd Zeedee ddd Z	dS )PyLocalsTestsz&Python was compiled with optimizationsc             C   s&   | j |  ddgd}| |d d S )Nzpy-upz	py-locals)rM   rO   z.*\nargs = \(1, 2, 3\)\n.*)rR   r^   r]   )rK   r   r   r   r   r     s    
z PyLocalsTests.test_basic_commandz$test requires py-up/py-down commandsc             C   s(   | j |  dddgd}| |d d S )Nzpy-upz	py-locals)rM   rO   z.*\na = 1\nb = 2\nc = 3\n.*)rR   r^   r]   )rK   r   r   r   r   test_locals_after_up  s    
z"PyLocalsTests.test_locals_after_upN)
r_   r`   ra   r   r   r   r   r   r   r   r   r   r   r   r     s
   
r   c              C   sJ   t jr4tdttf  xt D ]} td|   q W ttt	t
ttt d S )NzGDB version %s.%s:z    )r   verboseprintr1   r2   gdb_versionrH   r   rc   r   r   r   r   r   )rQ   r   r   r   	test_main  s    r   __main__)3localer-   platformr   r   rE   r$   r   r   Ztestr   Ztest.supportr   r   r   r   r   r1   r2   r   Zis_python_buildZpython_compilerpathjoindirnamerF   r3   rC   r(   rD   r8   Zgdbpy_versionr9   Zgdbpy_errorsrX   r   r;   r   rS   r   ZPGOZTestCaser=   rc   r   r   r   r   r   r   r_   r   r   r   r   <module>   sl   




	
 %   (- #
