diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:15 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:15 +0300 |
commit | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch) | |
tree | da2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /contrib/tools/cython/Cython/Debugger/Tests | |
parent | 778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff) | |
download | ydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/cython/Cython/Debugger/Tests')
6 files changed, 899 insertions, 899 deletions
diff --git a/contrib/tools/cython/Cython/Debugger/Tests/TestLibCython.py b/contrib/tools/cython/Cython/Debugger/Tests/TestLibCython.py index 13560646ff..6a769cc2fc 100644 --- a/contrib/tools/cython/Cython/Debugger/Tests/TestLibCython.py +++ b/contrib/tools/cython/Cython/Debugger/Tests/TestLibCython.py @@ -1,274 +1,274 @@ - -import os -import re -import sys -import shutil -import warnings -import textwrap -import unittest -import tempfile -import subprocess -#import distutils.core -#from distutils import sysconfig -from distutils import ccompiler - -import runtests -import Cython.Distutils.extension + +import os +import re +import sys +import shutil +import warnings +import textwrap +import unittest +import tempfile +import subprocess +#import distutils.core +#from distutils import sysconfig +from distutils import ccompiler + +import runtests +import Cython.Distutils.extension import Cython.Distutils.old_build_ext as build_ext -from Cython.Debugger import Cygdb as cygdb - -root = os.path.dirname(os.path.abspath(__file__)) -codefile = os.path.join(root, 'codefile') -cfuncs_file = os.path.join(root, 'cfuncs.c') - -with open(codefile) as f: - source_to_lineno = dict((line.strip(), i + 1) for i, line in enumerate(f)) - - -have_gdb = None -def test_gdb(): - global have_gdb - if have_gdb is not None: - return have_gdb - +from Cython.Debugger import Cygdb as cygdb + +root = os.path.dirname(os.path.abspath(__file__)) +codefile = os.path.join(root, 'codefile') +cfuncs_file = os.path.join(root, 'cfuncs.c') + +with open(codefile) as f: + source_to_lineno = dict((line.strip(), i + 1) for i, line in enumerate(f)) + + +have_gdb = None +def test_gdb(): + global have_gdb + if have_gdb is not None: + return have_gdb + have_gdb = False - try: + try: p = subprocess.Popen(['gdb', '-nx', '--version'], stdout=subprocess.PIPE) - except OSError: + except OSError: # gdb not found gdb_version = None - else: + else: stdout, _ = p.communicate() - # Based on Lib/test/test_gdb.py + # Based on Lib/test/test_gdb.py regex = r"GNU gdb [^\d]*(\d+)\.(\d+)" gdb_version = re.match(regex, stdout.decode('ascii', 'ignore')) - + if gdb_version: gdb_version_number = list(map(int, gdb_version.groups())) - if gdb_version_number >= [7, 2]: + if gdb_version_number >= [7, 2]: have_gdb = True with tempfile.NamedTemporaryFile(mode='w+') as python_version_script: - python_version_script.write( - 'python import sys; print("%s %s" % sys.version_info[:2])') - python_version_script.flush() - p = subprocess.Popen(['gdb', '-batch', '-x', python_version_script.name], - stdout=subprocess.PIPE) + python_version_script.write( + 'python import sys; print("%s %s" % sys.version_info[:2])') + python_version_script.flush() + p = subprocess.Popen(['gdb', '-batch', '-x', python_version_script.name], + stdout=subprocess.PIPE) stdout, _ = p.communicate() - try: + try: internal_python_version = list(map(int, stdout.decode('ascii', 'ignore').split())) if internal_python_version < [2, 6]: have_gdb = False - except ValueError: - have_gdb = False - + except ValueError: + have_gdb = False + if not have_gdb: warnings.warn('Skipping gdb tests, need gdb >= 7.2 with Python >= 2.6') - - return have_gdb - - -class DebuggerTestCase(unittest.TestCase): - - def setUp(self): - """ - Run gdb and have cygdb import the debug information from the code - defined in TestParseTreeTransforms's setUp method - """ - if not test_gdb(): - return - - self.tempdir = tempfile.mkdtemp() - self.destfile = os.path.join(self.tempdir, 'codefile.pyx') - self.debug_dest = os.path.join(self.tempdir, - 'cython_debug', - 'cython_debug_info_codefile') - self.cfuncs_destfile = os.path.join(self.tempdir, 'cfuncs') - - self.cwd = os.getcwd() - try: - os.chdir(self.tempdir) - - shutil.copy(codefile, self.destfile) - shutil.copy(cfuncs_file, self.cfuncs_destfile + '.c') + + return have_gdb + + +class DebuggerTestCase(unittest.TestCase): + + def setUp(self): + """ + Run gdb and have cygdb import the debug information from the code + defined in TestParseTreeTransforms's setUp method + """ + if not test_gdb(): + return + + self.tempdir = tempfile.mkdtemp() + self.destfile = os.path.join(self.tempdir, 'codefile.pyx') + self.debug_dest = os.path.join(self.tempdir, + 'cython_debug', + 'cython_debug_info_codefile') + self.cfuncs_destfile = os.path.join(self.tempdir, 'cfuncs') + + self.cwd = os.getcwd() + try: + os.chdir(self.tempdir) + + shutil.copy(codefile, self.destfile) + shutil.copy(cfuncs_file, self.cfuncs_destfile + '.c') shutil.copy(cfuncs_file.replace('.c', '.h'), self.cfuncs_destfile + '.h') - - compiler = ccompiler.new_compiler() - compiler.compile(['cfuncs.c'], debug=True, extra_postargs=['-fPIC']) - - opts = dict( - test_directory=self.tempdir, - module='codefile', - ) - - optimization_disabler = build_ext.Optimization() - - cython_compile_testcase = runtests.CythonCompileTestCase( - workdir=self.tempdir, - # we clean up everything (not only compiled files) - cleanup_workdir=False, - tags=runtests.parse_tags(codefile), - **opts - ) - - - new_stderr = open(os.devnull, 'w') - - stderr = sys.stderr - sys.stderr = new_stderr - - optimization_disabler.disable_optimization() - try: - cython_compile_testcase.run_cython( - targetdir=self.tempdir, - incdir=None, - annotate=False, - extra_compile_options={ - 'gdb_debug':True, - 'output_dir':self.tempdir, - }, - **opts - ) - - cython_compile_testcase.run_distutils( - incdir=None, - workdir=self.tempdir, - extra_extension_args={'extra_objects':['cfuncs.o']}, - **opts - ) - finally: - optimization_disabler.restore_state() - sys.stderr = stderr - new_stderr.close() - - # ext = Cython.Distutils.extension.Extension( - # 'codefile', - # ['codefile.pyx'], - # cython_gdb=True, - # extra_objects=['cfuncs.o']) - # - # distutils.core.setup( - # script_args=['build_ext', '--inplace'], - # ext_modules=[ext], - # cmdclass=dict(build_ext=Cython.Distutils.build_ext) - # ) - - except: - os.chdir(self.cwd) - raise - - def tearDown(self): - if not test_gdb(): - return - os.chdir(self.cwd) - shutil.rmtree(self.tempdir) - - -class GdbDebuggerTestCase(DebuggerTestCase): - - def setUp(self): - if not test_gdb(): - return - - super(GdbDebuggerTestCase, self).setUp() - - prefix_code = textwrap.dedent('''\ - python - - import os - import sys - import traceback - - def excepthook(type, value, tb): - traceback.print_exception(type, value, tb) - sys.stderr.flush() - sys.stdout.flush() - os._exit(1) - - sys.excepthook = excepthook - - # Have tracebacks end up on sys.stderr (gdb replaces sys.stderr - # with an object that calls gdb.write()) - sys.stderr = sys.__stderr__ - - end - ''') - - code = textwrap.dedent('''\ - python - - from Cython.Debugger.Tests import test_libcython_in_gdb - test_libcython_in_gdb.main(version=%r) - - end - ''' % (sys.version_info[:2],)) - - self.gdb_command_file = cygdb.make_command_file(self.tempdir, - prefix_code) - - with open(self.gdb_command_file, 'a') as f: - f.write(code) - - args = ['gdb', '-batch', '-x', self.gdb_command_file, '-n', '--args', - sys.executable, '-c', 'import codefile'] - - paths = [] - path = os.environ.get('PYTHONPATH') - if path: - paths.append(path) - paths.append(os.path.dirname(os.path.dirname( - os.path.abspath(Cython.__file__)))) - env = dict(os.environ, PYTHONPATH=os.pathsep.join(paths)) - - self.p = subprocess.Popen( - args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=env) - - def tearDown(self): - if not test_gdb(): - return - - try: - super(GdbDebuggerTestCase, self).tearDown() - if self.p: - try: self.p.stdout.close() - except: pass - try: self.p.stderr.close() - except: pass - self.p.wait() - finally: - os.remove(self.gdb_command_file) - - -class TestAll(GdbDebuggerTestCase): - - def test_all(self): - if not test_gdb(): - return - - out, err = self.p.communicate() - out = out.decode('UTF-8') - err = err.decode('UTF-8') - - exit_status = self.p.returncode - - if exit_status == 1: - sys.stderr.write(out) - sys.stderr.write(err) - elif exit_status >= 2: - border = u'*' * 30 - start = u'%s v INSIDE GDB v %s' % (border, border) - stderr = u'%s v STDERR v %s' % (border, border) - end = u'%s ^ INSIDE GDB ^ %s' % (border, border) - errmsg = u'\n%s\n%s%s\n%s%s' % (start, out, stderr, err, end) - - sys.stderr.write(errmsg) - - # FIXME: re-enable this to make the test fail on internal failures - #self.assertEqual(exit_status, 0) - - -if __name__ == '__main__': - unittest.main() + + compiler = ccompiler.new_compiler() + compiler.compile(['cfuncs.c'], debug=True, extra_postargs=['-fPIC']) + + opts = dict( + test_directory=self.tempdir, + module='codefile', + ) + + optimization_disabler = build_ext.Optimization() + + cython_compile_testcase = runtests.CythonCompileTestCase( + workdir=self.tempdir, + # we clean up everything (not only compiled files) + cleanup_workdir=False, + tags=runtests.parse_tags(codefile), + **opts + ) + + + new_stderr = open(os.devnull, 'w') + + stderr = sys.stderr + sys.stderr = new_stderr + + optimization_disabler.disable_optimization() + try: + cython_compile_testcase.run_cython( + targetdir=self.tempdir, + incdir=None, + annotate=False, + extra_compile_options={ + 'gdb_debug':True, + 'output_dir':self.tempdir, + }, + **opts + ) + + cython_compile_testcase.run_distutils( + incdir=None, + workdir=self.tempdir, + extra_extension_args={'extra_objects':['cfuncs.o']}, + **opts + ) + finally: + optimization_disabler.restore_state() + sys.stderr = stderr + new_stderr.close() + + # ext = Cython.Distutils.extension.Extension( + # 'codefile', + # ['codefile.pyx'], + # cython_gdb=True, + # extra_objects=['cfuncs.o']) + # + # distutils.core.setup( + # script_args=['build_ext', '--inplace'], + # ext_modules=[ext], + # cmdclass=dict(build_ext=Cython.Distutils.build_ext) + # ) + + except: + os.chdir(self.cwd) + raise + + def tearDown(self): + if not test_gdb(): + return + os.chdir(self.cwd) + shutil.rmtree(self.tempdir) + + +class GdbDebuggerTestCase(DebuggerTestCase): + + def setUp(self): + if not test_gdb(): + return + + super(GdbDebuggerTestCase, self).setUp() + + prefix_code = textwrap.dedent('''\ + python + + import os + import sys + import traceback + + def excepthook(type, value, tb): + traceback.print_exception(type, value, tb) + sys.stderr.flush() + sys.stdout.flush() + os._exit(1) + + sys.excepthook = excepthook + + # Have tracebacks end up on sys.stderr (gdb replaces sys.stderr + # with an object that calls gdb.write()) + sys.stderr = sys.__stderr__ + + end + ''') + + code = textwrap.dedent('''\ + python + + from Cython.Debugger.Tests import test_libcython_in_gdb + test_libcython_in_gdb.main(version=%r) + + end + ''' % (sys.version_info[:2],)) + + self.gdb_command_file = cygdb.make_command_file(self.tempdir, + prefix_code) + + with open(self.gdb_command_file, 'a') as f: + f.write(code) + + args = ['gdb', '-batch', '-x', self.gdb_command_file, '-n', '--args', + sys.executable, '-c', 'import codefile'] + + paths = [] + path = os.environ.get('PYTHONPATH') + if path: + paths.append(path) + paths.append(os.path.dirname(os.path.dirname( + os.path.abspath(Cython.__file__)))) + env = dict(os.environ, PYTHONPATH=os.pathsep.join(paths)) + + self.p = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env) + + def tearDown(self): + if not test_gdb(): + return + + try: + super(GdbDebuggerTestCase, self).tearDown() + if self.p: + try: self.p.stdout.close() + except: pass + try: self.p.stderr.close() + except: pass + self.p.wait() + finally: + os.remove(self.gdb_command_file) + + +class TestAll(GdbDebuggerTestCase): + + def test_all(self): + if not test_gdb(): + return + + out, err = self.p.communicate() + out = out.decode('UTF-8') + err = err.decode('UTF-8') + + exit_status = self.p.returncode + + if exit_status == 1: + sys.stderr.write(out) + sys.stderr.write(err) + elif exit_status >= 2: + border = u'*' * 30 + start = u'%s v INSIDE GDB v %s' % (border, border) + stderr = u'%s v STDERR v %s' % (border, border) + end = u'%s ^ INSIDE GDB ^ %s' % (border, border) + errmsg = u'\n%s\n%s%s\n%s%s' % (start, out, stderr, err, end) + + sys.stderr.write(errmsg) + + # FIXME: re-enable this to make the test fail on internal failures + #self.assertEqual(exit_status, 0) + + +if __name__ == '__main__': + unittest.main() diff --git a/contrib/tools/cython/Cython/Debugger/Tests/__init__.py b/contrib/tools/cython/Cython/Debugger/Tests/__init__.py index fa81adaff6..4a2889e8e1 100644 --- a/contrib/tools/cython/Cython/Debugger/Tests/__init__.py +++ b/contrib/tools/cython/Cython/Debugger/Tests/__init__.py @@ -1 +1 @@ -# empty file +# empty file diff --git a/contrib/tools/cython/Cython/Debugger/Tests/cfuncs.c b/contrib/tools/cython/Cython/Debugger/Tests/cfuncs.c index ccb42050bf..263589e77f 100644 --- a/contrib/tools/cython/Cython/Debugger/Tests/cfuncs.c +++ b/contrib/tools/cython/Cython/Debugger/Tests/cfuncs.c @@ -1,8 +1,8 @@ -void -some_c_function(void) -{ - int a, b, c; - - a = 1; - b = 2; -} +void +some_c_function(void) +{ + int a, b, c; + + a = 1; + b = 2; +} diff --git a/contrib/tools/cython/Cython/Debugger/Tests/codefile b/contrib/tools/cython/Cython/Debugger/Tests/codefile index 6b4c6b6add..5c2b0c2957 100644 --- a/contrib/tools/cython/Cython/Debugger/Tests/codefile +++ b/contrib/tools/cython/Cython/Debugger/Tests/codefile @@ -1,50 +1,50 @@ -cdef extern from "stdio.h": - int puts(char *s) - +cdef extern from "stdio.h": + int puts(char *s) + cdef extern from "cfuncs.h": - void some_c_function() - -import os - -cdef int c_var = 12 -python_var = 13 - -def spam(a=0): - cdef: - int b, c - - b = c = d = 0 - - b = 1 - c = 2 - int(10) - puts("spam") - os.path.join("foo", "bar") - some_c_function() - -cpdef eggs(): + void some_c_function() + +import os + +cdef int c_var = 12 +python_var = 13 + +def spam(a=0): + cdef: + int b, c + + b = c = d = 0 + + b = 1 + c = 2 + int(10) + puts("spam") + os.path.join("foo", "bar") + some_c_function() + +cpdef eggs(): pass -cdef ham(): - pass - -cdef class SomeClass(object): - def spam(self): - pass - -def outer(): - cdef object a = "an object" - def inner(): - b = 2 - # access closed over variables - print a, b - return inner - - -outer()() - -spam() -print "bye!" - -def use_ham(): - ham() +cdef ham(): + pass + +cdef class SomeClass(object): + def spam(self): + pass + +def outer(): + cdef object a = "an object" + def inner(): + b = 2 + # access closed over variables + print a, b + return inner + + +outer()() + +spam() +print "bye!" + +def use_ham(): + ham() diff --git a/contrib/tools/cython/Cython/Debugger/Tests/test_libcython_in_gdb.py b/contrib/tools/cython/Cython/Debugger/Tests/test_libcython_in_gdb.py index bd7608d607..c4d4ace7c0 100644 --- a/contrib/tools/cython/Cython/Debugger/Tests/test_libcython_in_gdb.py +++ b/contrib/tools/cython/Cython/Debugger/Tests/test_libcython_in_gdb.py @@ -1,496 +1,496 @@ -""" -Tests that run inside GDB. - -Note: debug information is already imported by the file generated by -Cython.Debugger.Cygdb.make_command_file() -""" - +""" +Tests that run inside GDB. + +Note: debug information is already imported by the file generated by +Cython.Debugger.Cygdb.make_command_file() +""" + from __future__ import absolute_import -import os -import re -import sys -import trace -import inspect -import warnings -import unittest -import textwrap -import tempfile -import functools -import traceback -import itertools +import os +import re +import sys +import trace +import inspect +import warnings +import unittest +import textwrap +import tempfile +import functools +import traceback +import itertools #from test import test_support - -import gdb - + +import gdb + from .. import libcython from .. import libpython from . import TestLibCython as test_libcython from ...Utils import add_metaclass - -# for some reason sys.argv is missing in gdb -sys.argv = ['gdb'] - - -def print_on_call_decorator(func): - @functools.wraps(func) - def wrapper(self, *args, **kwargs): - _debug(type(self).__name__, func.__name__) - - try: - return func(self, *args, **kwargs) + +# for some reason sys.argv is missing in gdb +sys.argv = ['gdb'] + + +def print_on_call_decorator(func): + @functools.wraps(func) + def wrapper(self, *args, **kwargs): + _debug(type(self).__name__, func.__name__) + + try: + return func(self, *args, **kwargs) except Exception: _debug("An exception occurred:", traceback.format_exc()) - raise - - return wrapper - -class TraceMethodCallMeta(type): - - def __init__(self, name, bases, dict): + raise + + return wrapper + +class TraceMethodCallMeta(type): + + def __init__(self, name, bases, dict): for func_name, func in dict.items(): - if inspect.isfunction(func): - setattr(self, func_name, print_on_call_decorator(func)) - - + if inspect.isfunction(func): + setattr(self, func_name, print_on_call_decorator(func)) + + @add_metaclass(TraceMethodCallMeta) -class DebugTestCase(unittest.TestCase): - """ - Base class for test cases. On teardown it kills the inferior and unsets - all breakpoints. - """ - - def __init__(self, name): - super(DebugTestCase, self).__init__(name) - self.cy = libcython.cy - self.module = libcython.cy.cython_namespace['codefile'] - self.spam_func, self.spam_meth = libcython.cy.functions_by_name['spam'] - self.ham_func = libcython.cy.functions_by_qualified_name[ - 'codefile.ham'] - self.eggs_func = libcython.cy.functions_by_qualified_name[ - 'codefile.eggs'] - - def read_var(self, varname, cast_to=None): - result = gdb.parse_and_eval('$cy_cvalue("%s")' % varname) - if cast_to: - result = cast_to(result) - - return result - - def local_info(self): - return gdb.execute('info locals', to_string=True) - - def lineno_equals(self, source_line=None, lineno=None): - if source_line is not None: - lineno = test_libcython.source_to_lineno[source_line] - frame = gdb.selected_frame() - self.assertEqual(libcython.cython_info.lineno(frame), lineno) - - def break_and_run(self, source_line): - break_lineno = test_libcython.source_to_lineno[source_line] - gdb.execute('cy break codefile:%d' % break_lineno, to_string=True) - gdb.execute('run', to_string=True) - - def tearDown(self): - gdb.execute('delete breakpoints', to_string=True) - try: - gdb.execute('kill inferior 1', to_string=True) - except RuntimeError: - pass - - gdb.execute('set args -c "import codefile"') - - -class TestDebugInformationClasses(DebugTestCase): - - def test_CythonModule(self): - "test that debug information was parsed properly into data structures" - self.assertEqual(self.module.name, 'codefile') - global_vars = ('c_var', 'python_var', '__name__', - '__builtins__', '__doc__', '__file__') - assert set(global_vars).issubset(self.module.globals) - - def test_CythonVariable(self): - module_globals = self.module.globals - c_var = module_globals['c_var'] - python_var = module_globals['python_var'] - self.assertEqual(c_var.type, libcython.CObject) - self.assertEqual(python_var.type, libcython.PythonObject) - self.assertEqual(c_var.qualified_name, 'codefile.c_var') - - def test_CythonFunction(self): - self.assertEqual(self.spam_func.qualified_name, 'codefile.spam') - self.assertEqual(self.spam_meth.qualified_name, - 'codefile.SomeClass.spam') - self.assertEqual(self.spam_func.module, self.module) - - assert self.eggs_func.pf_cname, (self.eggs_func, self.eggs_func.pf_cname) - assert not self.ham_func.pf_cname - assert not self.spam_func.pf_cname - assert not self.spam_meth.pf_cname - - self.assertEqual(self.spam_func.type, libcython.CObject) - self.assertEqual(self.ham_func.type, libcython.CObject) - - self.assertEqual(self.spam_func.arguments, ['a']) - self.assertEqual(self.spam_func.step_into_functions, - set(['puts', 'some_c_function'])) - - expected_lineno = test_libcython.source_to_lineno['def spam(a=0):'] - self.assertEqual(self.spam_func.lineno, expected_lineno) - self.assertEqual(sorted(self.spam_func.locals), list('abcd')) - - -class TestParameters(unittest.TestCase): - - def test_parameters(self): - gdb.execute('set cy_colorize_code on') - assert libcython.parameters.colorize_code - gdb.execute('set cy_colorize_code off') - assert not libcython.parameters.colorize_code - - -class TestBreak(DebugTestCase): - - def test_break(self): - breakpoint_amount = len(gdb.breakpoints() or ()) - gdb.execute('cy break codefile.spam') - - self.assertEqual(len(gdb.breakpoints()), breakpoint_amount + 1) - bp = gdb.breakpoints()[-1] - self.assertEqual(bp.type, gdb.BP_BREAKPOINT) - assert self.spam_func.cname in bp.location - assert bp.enabled - - def test_python_break(self): - gdb.execute('cy break -p join') - assert 'def join(' in gdb.execute('cy run', to_string=True) - - def test_break_lineno(self): - beginline = 'import os' - nextline = 'cdef int c_var = 12' - - self.break_and_run(beginline) - self.lineno_equals(beginline) - step_result = gdb.execute('cy step', to_string=True) - self.lineno_equals(nextline) - assert step_result.rstrip().endswith(nextline) - - -class TestKilled(DebugTestCase): - - def test_abort(self): - gdb.execute("set args -c 'import os; os.abort()'") - output = gdb.execute('cy run', to_string=True) - assert 'abort' in output.lower() - - -class DebugStepperTestCase(DebugTestCase): - - def step(self, varnames_and_values, source_line=None, lineno=None): - gdb.execute(self.command) - for varname, value in varnames_and_values: - self.assertEqual(self.read_var(varname), value, self.local_info()) - - self.lineno_equals(source_line, lineno) - - -class TestStep(DebugStepperTestCase): - """ - Test stepping. Stepping happens in the code found in - Cython/Debugger/Tests/codefile. - """ - - def test_cython_step(self): - gdb.execute('cy break codefile.spam') - - gdb.execute('run', to_string=True) - self.lineno_equals('def spam(a=0):') - - gdb.execute('cy step', to_string=True) - self.lineno_equals('b = c = d = 0') - - self.command = 'cy step' - self.step([('b', 0)], source_line='b = 1') - self.step([('b', 1), ('c', 0)], source_line='c = 2') - self.step([('c', 2)], source_line='int(10)') - self.step([], source_line='puts("spam")') - - gdb.execute('cont', to_string=True) - self.assertEqual(len(gdb.inferiors()), 1) - self.assertEqual(gdb.inferiors()[0].pid, 0) - - def test_c_step(self): - self.break_and_run('some_c_function()') - gdb.execute('cy step', to_string=True) - self.assertEqual(gdb.selected_frame().name(), 'some_c_function') - - def test_python_step(self): - self.break_and_run('os.path.join("foo", "bar")') - - result = gdb.execute('cy step', to_string=True) - - curframe = gdb.selected_frame() - self.assertEqual(curframe.name(), 'PyEval_EvalFrameEx') - - pyframe = libpython.Frame(curframe).get_pyop() - # With Python 3 inferiors, pyframe.co_name will return a PyUnicodePtr, - # be compatible - frame_name = pyframe.co_name.proxyval(set()) - self.assertEqual(frame_name, 'join') - assert re.match(r'\d+ def join\(', result), result - - -class TestNext(DebugStepperTestCase): - - def test_cython_next(self): - self.break_and_run('c = 2') - - lines = ( - 'int(10)', - 'puts("spam")', - 'os.path.join("foo", "bar")', - 'some_c_function()', - ) - - for line in lines: - gdb.execute('cy next') - self.lineno_equals(line) - - -class TestLocalsGlobals(DebugTestCase): - - def test_locals(self): - self.break_and_run('int(10)') - - result = gdb.execute('cy locals', to_string=True) - assert 'a = 0', repr(result) - assert 'b = (int) 1', result - assert 'c = (int) 2' in result, repr(result) - - def test_globals(self): - self.break_and_run('int(10)') - - result = gdb.execute('cy globals', to_string=True) - assert '__name__ ' in result, repr(result) - assert '__doc__ ' in result, repr(result) - assert 'os ' in result, repr(result) - assert 'c_var ' in result, repr(result) - assert 'python_var ' in result, repr(result) - - -class TestBacktrace(DebugTestCase): - - def test_backtrace(self): - libcython.parameters.colorize_code.value = False - - self.break_and_run('os.path.join("foo", "bar")') - - def match_backtrace_output(result): - assert re.search(r'\#\d+ *0x.* in spam\(\) at .*codefile\.pyx:22', - result), result - assert 'os.path.join("foo", "bar")' in result, result - - result = gdb.execute('cy bt', to_string=True) - match_backtrace_output(result) - - result = gdb.execute('cy bt -a', to_string=True) - match_backtrace_output(result) - - # Apparently not everyone has main() - # assert re.search(r'\#0 *0x.* in main\(\)', result), result - - -class TestFunctions(DebugTestCase): - - def test_functions(self): - self.break_and_run('c = 2') - result = gdb.execute('print $cy_cname("b")', to_string=True) - assert re.search('__pyx_.*b', result), result - - result = gdb.execute('print $cy_lineno()', to_string=True) - supposed_lineno = test_libcython.source_to_lineno['c = 2'] - assert str(supposed_lineno) in result, (supposed_lineno, result) - - result = gdb.execute('print $cy_cvalue("b")', to_string=True) - assert '= 1' in result - - -class TestPrint(DebugTestCase): - - def test_print(self): - self.break_and_run('c = 2') - result = gdb.execute('cy print b', to_string=True) - self.assertEqual('b = (int) 1\n', result) - - -class TestUpDown(DebugTestCase): - - def test_updown(self): - self.break_and_run('os.path.join("foo", "bar")') - gdb.execute('cy step') - self.assertRaises(RuntimeError, gdb.execute, 'cy down') - - result = gdb.execute('cy up', to_string=True) - assert 'spam()' in result - assert 'os.path.join("foo", "bar")' in result - - -class TestExec(DebugTestCase): - - def setUp(self): - super(TestExec, self).setUp() - self.fd, self.tmpfilename = tempfile.mkstemp() - self.tmpfile = os.fdopen(self.fd, 'r+') - - def tearDown(self): - super(TestExec, self).tearDown() - - try: - self.tmpfile.close() - finally: - os.remove(self.tmpfilename) - - def eval_command(self, command): - gdb.execute('cy exec open(%r, "w").write(str(%s))' % - (self.tmpfilename, command)) - return self.tmpfile.read().strip() - - def test_cython_exec(self): - self.break_and_run('os.path.join("foo", "bar")') - - # test normal behaviour - self.assertEqual("[0]", self.eval_command('[a]')) - - # test multiline code - result = gdb.execute(textwrap.dedent('''\ - cy exec - pass - - "nothing" - end - ''')) - result = self.tmpfile.read().rstrip() - self.assertEqual('', result) - - def test_python_exec(self): - self.break_and_run('os.path.join("foo", "bar")') - gdb.execute('cy step') - - gdb.execute('cy exec some_random_var = 14') - self.assertEqual('14', self.eval_command('some_random_var')) - - -class CySet(DebugTestCase): - - def test_cyset(self): - self.break_and_run('os.path.join("foo", "bar")') - - gdb.execute('cy set a = $cy_eval("{None: []}")') - stringvalue = self.read_var("a", cast_to=str) - self.assertEqual(stringvalue, "{None: []}") - - -class TestCyEval(DebugTestCase): - "Test the $cy_eval() gdb function." - - def test_cy_eval(self): - # This function leaks a few objects in the GDB python process. This - # is no biggie - self.break_and_run('os.path.join("foo", "bar")') - - result = gdb.execute('print $cy_eval("None")', to_string=True) - assert re.match(r'\$\d+ = None\n', result), result - - result = gdb.execute('print $cy_eval("[a]")', to_string=True) - assert re.match(r'\$\d+ = \[0\]', result), result - - -class TestClosure(DebugTestCase): - - def break_and_run_func(self, funcname): - gdb.execute('cy break ' + funcname) - gdb.execute('cy run') - - def test_inner(self): - self.break_and_run_func('inner') - self.assertEqual('', gdb.execute('cy locals', to_string=True)) - - # Allow the Cython-generated code to initialize the scope variable - gdb.execute('cy step') - - self.assertEqual(str(self.read_var('a')), "'an object'") - print_result = gdb.execute('cy print a', to_string=True).strip() - self.assertEqual(print_result, "a = 'an object'") - - def test_outer(self): - self.break_and_run_func('outer') - self.assertEqual('', gdb.execute('cy locals', to_string=True)) - - # Initialize scope with 'a' uninitialized - gdb.execute('cy step') - self.assertEqual('', gdb.execute('cy locals', to_string=True)) - - # Initialize 'a' to 1 - gdb.execute('cy step') - print_result = gdb.execute('cy print a', to_string=True).strip() - self.assertEqual(print_result, "a = 'an object'") - - -_do_debug = os.environ.get('GDB_DEBUG') -if _do_debug: - _debug_file = open('/dev/tty', 'w') - -def _debug(*messages): - if _do_debug: - messages = itertools.chain([sys._getframe(1).f_code.co_name, ':'], - messages) - _debug_file.write(' '.join(str(msg) for msg in messages) + '\n') - - -def run_unittest_in_module(modulename): - try: - gdb.lookup_type('PyModuleObject') - except RuntimeError: - msg = ("Unable to run tests, Python was not compiled with " - "debugging information. Either compile python with " - "-g or get a debug build (configure with --with-pydebug).") - warnings.warn(msg) - os._exit(1) - else: - m = __import__(modulename, fromlist=['']) - tests = inspect.getmembers(m, inspect.isclass) - - # test_support.run_unittest(tests) - - test_loader = unittest.TestLoader() - suite = unittest.TestSuite( - [test_loader.loadTestsFromTestCase(cls) for name, cls in tests]) - - result = unittest.TextTestRunner(verbosity=1).run(suite) - return result.wasSuccessful() - -def runtests(): - """ - Run the libcython and libpython tests. Ensure that an appropriate status is - returned to the parent test process. - """ - from Cython.Debugger.Tests import test_libpython_in_gdb - - success_libcython = run_unittest_in_module(__name__) - success_libpython = run_unittest_in_module(test_libpython_in_gdb.__name__) - - if not success_libcython or not success_libpython: - sys.exit(2) - -def main(version, trace_code=False): - global inferior_python_version - - inferior_python_version = version - - if trace_code: - tracer = trace.Trace(count=False, trace=True, outfile=sys.stderr, - ignoredirs=[sys.prefix, sys.exec_prefix]) - tracer.runfunc(runtests) - else: - runtests() +class DebugTestCase(unittest.TestCase): + """ + Base class for test cases. On teardown it kills the inferior and unsets + all breakpoints. + """ + + def __init__(self, name): + super(DebugTestCase, self).__init__(name) + self.cy = libcython.cy + self.module = libcython.cy.cython_namespace['codefile'] + self.spam_func, self.spam_meth = libcython.cy.functions_by_name['spam'] + self.ham_func = libcython.cy.functions_by_qualified_name[ + 'codefile.ham'] + self.eggs_func = libcython.cy.functions_by_qualified_name[ + 'codefile.eggs'] + + def read_var(self, varname, cast_to=None): + result = gdb.parse_and_eval('$cy_cvalue("%s")' % varname) + if cast_to: + result = cast_to(result) + + return result + + def local_info(self): + return gdb.execute('info locals', to_string=True) + + def lineno_equals(self, source_line=None, lineno=None): + if source_line is not None: + lineno = test_libcython.source_to_lineno[source_line] + frame = gdb.selected_frame() + self.assertEqual(libcython.cython_info.lineno(frame), lineno) + + def break_and_run(self, source_line): + break_lineno = test_libcython.source_to_lineno[source_line] + gdb.execute('cy break codefile:%d' % break_lineno, to_string=True) + gdb.execute('run', to_string=True) + + def tearDown(self): + gdb.execute('delete breakpoints', to_string=True) + try: + gdb.execute('kill inferior 1', to_string=True) + except RuntimeError: + pass + + gdb.execute('set args -c "import codefile"') + + +class TestDebugInformationClasses(DebugTestCase): + + def test_CythonModule(self): + "test that debug information was parsed properly into data structures" + self.assertEqual(self.module.name, 'codefile') + global_vars = ('c_var', 'python_var', '__name__', + '__builtins__', '__doc__', '__file__') + assert set(global_vars).issubset(self.module.globals) + + def test_CythonVariable(self): + module_globals = self.module.globals + c_var = module_globals['c_var'] + python_var = module_globals['python_var'] + self.assertEqual(c_var.type, libcython.CObject) + self.assertEqual(python_var.type, libcython.PythonObject) + self.assertEqual(c_var.qualified_name, 'codefile.c_var') + + def test_CythonFunction(self): + self.assertEqual(self.spam_func.qualified_name, 'codefile.spam') + self.assertEqual(self.spam_meth.qualified_name, + 'codefile.SomeClass.spam') + self.assertEqual(self.spam_func.module, self.module) + + assert self.eggs_func.pf_cname, (self.eggs_func, self.eggs_func.pf_cname) + assert not self.ham_func.pf_cname + assert not self.spam_func.pf_cname + assert not self.spam_meth.pf_cname + + self.assertEqual(self.spam_func.type, libcython.CObject) + self.assertEqual(self.ham_func.type, libcython.CObject) + + self.assertEqual(self.spam_func.arguments, ['a']) + self.assertEqual(self.spam_func.step_into_functions, + set(['puts', 'some_c_function'])) + + expected_lineno = test_libcython.source_to_lineno['def spam(a=0):'] + self.assertEqual(self.spam_func.lineno, expected_lineno) + self.assertEqual(sorted(self.spam_func.locals), list('abcd')) + + +class TestParameters(unittest.TestCase): + + def test_parameters(self): + gdb.execute('set cy_colorize_code on') + assert libcython.parameters.colorize_code + gdb.execute('set cy_colorize_code off') + assert not libcython.parameters.colorize_code + + +class TestBreak(DebugTestCase): + + def test_break(self): + breakpoint_amount = len(gdb.breakpoints() or ()) + gdb.execute('cy break codefile.spam') + + self.assertEqual(len(gdb.breakpoints()), breakpoint_amount + 1) + bp = gdb.breakpoints()[-1] + self.assertEqual(bp.type, gdb.BP_BREAKPOINT) + assert self.spam_func.cname in bp.location + assert bp.enabled + + def test_python_break(self): + gdb.execute('cy break -p join') + assert 'def join(' in gdb.execute('cy run', to_string=True) + + def test_break_lineno(self): + beginline = 'import os' + nextline = 'cdef int c_var = 12' + + self.break_and_run(beginline) + self.lineno_equals(beginline) + step_result = gdb.execute('cy step', to_string=True) + self.lineno_equals(nextline) + assert step_result.rstrip().endswith(nextline) + + +class TestKilled(DebugTestCase): + + def test_abort(self): + gdb.execute("set args -c 'import os; os.abort()'") + output = gdb.execute('cy run', to_string=True) + assert 'abort' in output.lower() + + +class DebugStepperTestCase(DebugTestCase): + + def step(self, varnames_and_values, source_line=None, lineno=None): + gdb.execute(self.command) + for varname, value in varnames_and_values: + self.assertEqual(self.read_var(varname), value, self.local_info()) + + self.lineno_equals(source_line, lineno) + + +class TestStep(DebugStepperTestCase): + """ + Test stepping. Stepping happens in the code found in + Cython/Debugger/Tests/codefile. + """ + + def test_cython_step(self): + gdb.execute('cy break codefile.spam') + + gdb.execute('run', to_string=True) + self.lineno_equals('def spam(a=0):') + + gdb.execute('cy step', to_string=True) + self.lineno_equals('b = c = d = 0') + + self.command = 'cy step' + self.step([('b', 0)], source_line='b = 1') + self.step([('b', 1), ('c', 0)], source_line='c = 2') + self.step([('c', 2)], source_line='int(10)') + self.step([], source_line='puts("spam")') + + gdb.execute('cont', to_string=True) + self.assertEqual(len(gdb.inferiors()), 1) + self.assertEqual(gdb.inferiors()[0].pid, 0) + + def test_c_step(self): + self.break_and_run('some_c_function()') + gdb.execute('cy step', to_string=True) + self.assertEqual(gdb.selected_frame().name(), 'some_c_function') + + def test_python_step(self): + self.break_and_run('os.path.join("foo", "bar")') + + result = gdb.execute('cy step', to_string=True) + + curframe = gdb.selected_frame() + self.assertEqual(curframe.name(), 'PyEval_EvalFrameEx') + + pyframe = libpython.Frame(curframe).get_pyop() + # With Python 3 inferiors, pyframe.co_name will return a PyUnicodePtr, + # be compatible + frame_name = pyframe.co_name.proxyval(set()) + self.assertEqual(frame_name, 'join') + assert re.match(r'\d+ def join\(', result), result + + +class TestNext(DebugStepperTestCase): + + def test_cython_next(self): + self.break_and_run('c = 2') + + lines = ( + 'int(10)', + 'puts("spam")', + 'os.path.join("foo", "bar")', + 'some_c_function()', + ) + + for line in lines: + gdb.execute('cy next') + self.lineno_equals(line) + + +class TestLocalsGlobals(DebugTestCase): + + def test_locals(self): + self.break_and_run('int(10)') + + result = gdb.execute('cy locals', to_string=True) + assert 'a = 0', repr(result) + assert 'b = (int) 1', result + assert 'c = (int) 2' in result, repr(result) + + def test_globals(self): + self.break_and_run('int(10)') + + result = gdb.execute('cy globals', to_string=True) + assert '__name__ ' in result, repr(result) + assert '__doc__ ' in result, repr(result) + assert 'os ' in result, repr(result) + assert 'c_var ' in result, repr(result) + assert 'python_var ' in result, repr(result) + + +class TestBacktrace(DebugTestCase): + + def test_backtrace(self): + libcython.parameters.colorize_code.value = False + + self.break_and_run('os.path.join("foo", "bar")') + + def match_backtrace_output(result): + assert re.search(r'\#\d+ *0x.* in spam\(\) at .*codefile\.pyx:22', + result), result + assert 'os.path.join("foo", "bar")' in result, result + + result = gdb.execute('cy bt', to_string=True) + match_backtrace_output(result) + + result = gdb.execute('cy bt -a', to_string=True) + match_backtrace_output(result) + + # Apparently not everyone has main() + # assert re.search(r'\#0 *0x.* in main\(\)', result), result + + +class TestFunctions(DebugTestCase): + + def test_functions(self): + self.break_and_run('c = 2') + result = gdb.execute('print $cy_cname("b")', to_string=True) + assert re.search('__pyx_.*b', result), result + + result = gdb.execute('print $cy_lineno()', to_string=True) + supposed_lineno = test_libcython.source_to_lineno['c = 2'] + assert str(supposed_lineno) in result, (supposed_lineno, result) + + result = gdb.execute('print $cy_cvalue("b")', to_string=True) + assert '= 1' in result + + +class TestPrint(DebugTestCase): + + def test_print(self): + self.break_and_run('c = 2') + result = gdb.execute('cy print b', to_string=True) + self.assertEqual('b = (int) 1\n', result) + + +class TestUpDown(DebugTestCase): + + def test_updown(self): + self.break_and_run('os.path.join("foo", "bar")') + gdb.execute('cy step') + self.assertRaises(RuntimeError, gdb.execute, 'cy down') + + result = gdb.execute('cy up', to_string=True) + assert 'spam()' in result + assert 'os.path.join("foo", "bar")' in result + + +class TestExec(DebugTestCase): + + def setUp(self): + super(TestExec, self).setUp() + self.fd, self.tmpfilename = tempfile.mkstemp() + self.tmpfile = os.fdopen(self.fd, 'r+') + + def tearDown(self): + super(TestExec, self).tearDown() + + try: + self.tmpfile.close() + finally: + os.remove(self.tmpfilename) + + def eval_command(self, command): + gdb.execute('cy exec open(%r, "w").write(str(%s))' % + (self.tmpfilename, command)) + return self.tmpfile.read().strip() + + def test_cython_exec(self): + self.break_and_run('os.path.join("foo", "bar")') + + # test normal behaviour + self.assertEqual("[0]", self.eval_command('[a]')) + + # test multiline code + result = gdb.execute(textwrap.dedent('''\ + cy exec + pass + + "nothing" + end + ''')) + result = self.tmpfile.read().rstrip() + self.assertEqual('', result) + + def test_python_exec(self): + self.break_and_run('os.path.join("foo", "bar")') + gdb.execute('cy step') + + gdb.execute('cy exec some_random_var = 14') + self.assertEqual('14', self.eval_command('some_random_var')) + + +class CySet(DebugTestCase): + + def test_cyset(self): + self.break_and_run('os.path.join("foo", "bar")') + + gdb.execute('cy set a = $cy_eval("{None: []}")') + stringvalue = self.read_var("a", cast_to=str) + self.assertEqual(stringvalue, "{None: []}") + + +class TestCyEval(DebugTestCase): + "Test the $cy_eval() gdb function." + + def test_cy_eval(self): + # This function leaks a few objects in the GDB python process. This + # is no biggie + self.break_and_run('os.path.join("foo", "bar")') + + result = gdb.execute('print $cy_eval("None")', to_string=True) + assert re.match(r'\$\d+ = None\n', result), result + + result = gdb.execute('print $cy_eval("[a]")', to_string=True) + assert re.match(r'\$\d+ = \[0\]', result), result + + +class TestClosure(DebugTestCase): + + def break_and_run_func(self, funcname): + gdb.execute('cy break ' + funcname) + gdb.execute('cy run') + + def test_inner(self): + self.break_and_run_func('inner') + self.assertEqual('', gdb.execute('cy locals', to_string=True)) + + # Allow the Cython-generated code to initialize the scope variable + gdb.execute('cy step') + + self.assertEqual(str(self.read_var('a')), "'an object'") + print_result = gdb.execute('cy print a', to_string=True).strip() + self.assertEqual(print_result, "a = 'an object'") + + def test_outer(self): + self.break_and_run_func('outer') + self.assertEqual('', gdb.execute('cy locals', to_string=True)) + + # Initialize scope with 'a' uninitialized + gdb.execute('cy step') + self.assertEqual('', gdb.execute('cy locals', to_string=True)) + + # Initialize 'a' to 1 + gdb.execute('cy step') + print_result = gdb.execute('cy print a', to_string=True).strip() + self.assertEqual(print_result, "a = 'an object'") + + +_do_debug = os.environ.get('GDB_DEBUG') +if _do_debug: + _debug_file = open('/dev/tty', 'w') + +def _debug(*messages): + if _do_debug: + messages = itertools.chain([sys._getframe(1).f_code.co_name, ':'], + messages) + _debug_file.write(' '.join(str(msg) for msg in messages) + '\n') + + +def run_unittest_in_module(modulename): + try: + gdb.lookup_type('PyModuleObject') + except RuntimeError: + msg = ("Unable to run tests, Python was not compiled with " + "debugging information. Either compile python with " + "-g or get a debug build (configure with --with-pydebug).") + warnings.warn(msg) + os._exit(1) + else: + m = __import__(modulename, fromlist=['']) + tests = inspect.getmembers(m, inspect.isclass) + + # test_support.run_unittest(tests) + + test_loader = unittest.TestLoader() + suite = unittest.TestSuite( + [test_loader.loadTestsFromTestCase(cls) for name, cls in tests]) + + result = unittest.TextTestRunner(verbosity=1).run(suite) + return result.wasSuccessful() + +def runtests(): + """ + Run the libcython and libpython tests. Ensure that an appropriate status is + returned to the parent test process. + """ + from Cython.Debugger.Tests import test_libpython_in_gdb + + success_libcython = run_unittest_in_module(__name__) + success_libpython = run_unittest_in_module(test_libpython_in_gdb.__name__) + + if not success_libcython or not success_libpython: + sys.exit(2) + +def main(version, trace_code=False): + global inferior_python_version + + inferior_python_version = version + + if trace_code: + tracer = trace.Trace(count=False, trace=True, outfile=sys.stderr, + ignoredirs=[sys.prefix, sys.exec_prefix]) + tracer.runfunc(runtests) + else: + runtests() diff --git a/contrib/tools/cython/Cython/Debugger/Tests/test_libpython_in_gdb.py b/contrib/tools/cython/Cython/Debugger/Tests/test_libpython_in_gdb.py index 6f34cee47b..8a2b83419b 100644 --- a/contrib/tools/cython/Cython/Debugger/Tests/test_libpython_in_gdb.py +++ b/contrib/tools/cython/Cython/Debugger/Tests/test_libpython_in_gdb.py @@ -1,115 +1,115 @@ -# -*- coding: UTF-8 -*- - -""" -Test libpython.py. This is already partly tested by test_libcython_in_gdb and -Lib/test/test_gdb.py in the Python source. These tests are run in gdb and -called from test_libcython_in_gdb.main() -""" - -import os -import sys - -import gdb - -from Cython.Debugger import libcython -from Cython.Debugger import libpython - +# -*- coding: UTF-8 -*- + +""" +Test libpython.py. This is already partly tested by test_libcython_in_gdb and +Lib/test/test_gdb.py in the Python source. These tests are run in gdb and +called from test_libcython_in_gdb.main() +""" + +import os +import sys + +import gdb + +from Cython.Debugger import libcython +from Cython.Debugger import libpython + from . import test_libcython_in_gdb from .test_libcython_in_gdb import _debug, inferior_python_version - - -class TestPrettyPrinters(test_libcython_in_gdb.DebugTestCase): - """ - Test whether types of Python objects are correctly inferred and that - the right libpython.PySomeTypeObjectPtr classes are instantiated. - - Also test whether values are appropriately formatted (don't be too - laborious as Lib/test/test_gdb.py already covers this extensively). - - Don't take care of decreffing newly allocated objects as a new - interpreter is started for every test anyway. - """ - - def setUp(self): - super(TestPrettyPrinters, self).setUp() - self.break_and_run('b = c = d = 0') - - def get_pyobject(self, code): - value = gdb.parse_and_eval(code) - assert libpython.pointervalue(value) != 0 - return value - - def pyobject_fromcode(self, code, gdbvar=None): - if gdbvar is not None: - d = {'varname':gdbvar, 'code':code} - gdb.execute('set $%(varname)s = %(code)s' % d) - code = '$' + gdbvar - - return libpython.PyObjectPtr.from_pyobject_ptr(self.get_pyobject(code)) - - def get_repr(self, pyobject): - return pyobject.get_truncated_repr(libpython.MAX_OUTPUT_LEN) - - def alloc_bytestring(self, string, gdbvar=None): - if inferior_python_version < (3, 0): - funcname = 'PyString_FromStringAndSize' - else: - funcname = 'PyBytes_FromStringAndSize' - + + +class TestPrettyPrinters(test_libcython_in_gdb.DebugTestCase): + """ + Test whether types of Python objects are correctly inferred and that + the right libpython.PySomeTypeObjectPtr classes are instantiated. + + Also test whether values are appropriately formatted (don't be too + laborious as Lib/test/test_gdb.py already covers this extensively). + + Don't take care of decreffing newly allocated objects as a new + interpreter is started for every test anyway. + """ + + def setUp(self): + super(TestPrettyPrinters, self).setUp() + self.break_and_run('b = c = d = 0') + + def get_pyobject(self, code): + value = gdb.parse_and_eval(code) + assert libpython.pointervalue(value) != 0 + return value + + def pyobject_fromcode(self, code, gdbvar=None): + if gdbvar is not None: + d = {'varname':gdbvar, 'code':code} + gdb.execute('set $%(varname)s = %(code)s' % d) + code = '$' + gdbvar + + return libpython.PyObjectPtr.from_pyobject_ptr(self.get_pyobject(code)) + + def get_repr(self, pyobject): + return pyobject.get_truncated_repr(libpython.MAX_OUTPUT_LEN) + + def alloc_bytestring(self, string, gdbvar=None): + if inferior_python_version < (3, 0): + funcname = 'PyString_FromStringAndSize' + else: + funcname = 'PyBytes_FromStringAndSize' + assert b'"' not in string - - # ensure double quotes + + # ensure double quotes code = '(PyObject *) %s("%s", %d)' % (funcname, string.decode('iso8859-1'), len(string)) - return self.pyobject_fromcode(code, gdbvar=gdbvar) - - def alloc_unicodestring(self, string, gdbvar=None): - postfix = libpython.get_inferior_unicode_postfix() + return self.pyobject_fromcode(code, gdbvar=gdbvar) + + def alloc_unicodestring(self, string, gdbvar=None): + postfix = libpython.get_inferior_unicode_postfix() funcname = 'PyUnicode%s_DecodeUnicodeEscape' % (postfix,) - + data = string.encode("unicode_escape").decode('iso8859-1') - return self.pyobject_fromcode( + return self.pyobject_fromcode( '(PyObject *) %s("%s", %d, "strict")' % ( funcname, data.replace('"', r'\"').replace('\\', r'\\'), len(data)), - gdbvar=gdbvar) - - def test_bytestring(self): + gdbvar=gdbvar) + + def test_bytestring(self): bytestring = self.alloc_bytestring(b"spam") - - if inferior_python_version < (3, 0): - bytestring_class = libpython.PyStringObjectPtr + + if inferior_python_version < (3, 0): + bytestring_class = libpython.PyStringObjectPtr expected = repr(b"spam") - else: - bytestring_class = libpython.PyBytesObjectPtr - expected = "b'spam'" - - self.assertEqual(type(bytestring), bytestring_class) - self.assertEqual(self.get_repr(bytestring), expected) - - def test_unicode(self): - unicode_string = self.alloc_unicodestring(u"spam ἄλφα") - + else: + bytestring_class = libpython.PyBytesObjectPtr + expected = "b'spam'" + + self.assertEqual(type(bytestring), bytestring_class) + self.assertEqual(self.get_repr(bytestring), expected) + + def test_unicode(self): + unicode_string = self.alloc_unicodestring(u"spam ἄλφα") + expected = u"'spam ἄλφα'" - if inferior_python_version < (3, 0): - expected = 'u' + expected - - self.assertEqual(type(unicode_string), libpython.PyUnicodeObjectPtr) - self.assertEqual(self.get_repr(unicode_string), expected) - - def test_int(self): - if inferior_python_version < (3, 0): - intval = self.pyobject_fromcode('PyInt_FromLong(100)') - self.assertEqual(type(intval), libpython.PyIntObjectPtr) - self.assertEqual(self.get_repr(intval), '100') - - def test_long(self): - longval = self.pyobject_fromcode('PyLong_FromLong(200)', - gdbvar='longval') - assert gdb.parse_and_eval('$longval->ob_type == &PyLong_Type') - - self.assertEqual(type(longval), libpython.PyLongObjectPtr) - self.assertEqual(self.get_repr(longval), '200') - - def test_frame_type(self): - frame = self.pyobject_fromcode('PyEval_GetFrame()') - - self.assertEqual(type(frame), libpython.PyFrameObjectPtr) + if inferior_python_version < (3, 0): + expected = 'u' + expected + + self.assertEqual(type(unicode_string), libpython.PyUnicodeObjectPtr) + self.assertEqual(self.get_repr(unicode_string), expected) + + def test_int(self): + if inferior_python_version < (3, 0): + intval = self.pyobject_fromcode('PyInt_FromLong(100)') + self.assertEqual(type(intval), libpython.PyIntObjectPtr) + self.assertEqual(self.get_repr(intval), '100') + + def test_long(self): + longval = self.pyobject_fromcode('PyLong_FromLong(200)', + gdbvar='longval') + assert gdb.parse_and_eval('$longval->ob_type == &PyLong_Type') + + self.assertEqual(type(longval), libpython.PyLongObjectPtr) + self.assertEqual(self.get_repr(longval), '200') + + def test_frame_type(self): + frame = self.pyobject_fromcode('PyEval_GetFrame()') + + self.assertEqual(type(frame), libpython.PyFrameObjectPtr) |