Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / cython / src / Cython / Debugger / Tests / TestLibCython.py
blob2f91096b4d0f7cc6206a8f95b12f785ad42f9c94
2 import os
3 import re
4 import sys
5 import shutil
6 import warnings
7 import textwrap
8 import unittest
9 import tempfile
10 import subprocess
11 #import distutils.core
12 #from distutils import sysconfig
13 from distutils import ccompiler
15 import runtests
16 import Cython.Distutils.extension
17 import Cython.Distutils.build_ext
18 from Cython.Debugger import Cygdb as cygdb
20 root = os.path.dirname(os.path.abspath(__file__))
21 codefile = os.path.join(root, 'codefile')
22 cfuncs_file = os.path.join(root, 'cfuncs.c')
24 f = open(codefile)
25 try:
26 source_to_lineno = dict([ (line.strip(), i + 1) for i, line in enumerate(f) ])
27 finally:
28 f.close()
30 # Cython.Distutils.__init__ imports build_ext from build_ext which means we
31 # can't access the module anymore. Get it from sys.modules instead.
32 build_ext = sys.modules['Cython.Distutils.build_ext']
35 have_gdb = None
36 def test_gdb():
37 global have_gdb
38 if have_gdb is not None:
39 return have_gdb
41 try:
42 p = subprocess.Popen(['gdb', '-v'], stdout=subprocess.PIPE)
43 have_gdb = True
44 except OSError:
45 # gdb was not installed
46 have_gdb = False
47 else:
48 gdb_version = p.stdout.read().decode('ascii', 'ignore')
49 p.wait()
50 p.stdout.close()
52 if have_gdb:
53 # Based on Lib/test/test_gdb.py
54 regex = "^GNU gdb [^\d]*(\d+)\.(\d+)"
55 gdb_version_number = list(map(int, re.search(regex, gdb_version).groups()))
57 if gdb_version_number >= [7, 2]:
58 python_version_script = tempfile.NamedTemporaryFile(mode='w+')
59 try:
60 python_version_script.write(
61 'python import sys; print("%s %s" % sys.version_info[:2])')
62 python_version_script.flush()
63 p = subprocess.Popen(['gdb', '-batch', '-x', python_version_script.name],
64 stdout=subprocess.PIPE)
65 try:
66 python_version = p.stdout.read().decode('ascii')
67 p.wait()
68 finally:
69 p.stdout.close()
70 try:
71 python_version_number = list(map(int, python_version.split()))
72 except ValueError:
73 have_gdb = False
74 finally:
75 python_version_script.close()
77 # Be Python 3 compatible
78 if (not have_gdb
79 or gdb_version_number < [7, 2]
80 or python_version_number < [2, 6]):
81 warnings.warn(
82 'Skipping gdb tests, need gdb >= 7.2 with Python >= 2.6')
83 have_gdb = False
85 return have_gdb
88 class DebuggerTestCase(unittest.TestCase):
90 def setUp(self):
91 """
92 Run gdb and have cygdb import the debug information from the code
93 defined in TestParseTreeTransforms's setUp method
94 """
95 if not test_gdb():
96 return
98 self.tempdir = tempfile.mkdtemp()
99 self.destfile = os.path.join(self.tempdir, 'codefile.pyx')
100 self.debug_dest = os.path.join(self.tempdir,
101 'cython_debug',
102 'cython_debug_info_codefile')
103 self.cfuncs_destfile = os.path.join(self.tempdir, 'cfuncs')
105 self.cwd = os.getcwd()
106 try:
107 os.chdir(self.tempdir)
109 shutil.copy(codefile, self.destfile)
110 shutil.copy(cfuncs_file, self.cfuncs_destfile + '.c')
112 compiler = ccompiler.new_compiler()
113 compiler.compile(['cfuncs.c'], debug=True, extra_postargs=['-fPIC'])
115 opts = dict(
116 test_directory=self.tempdir,
117 module='codefile',
120 optimization_disabler = build_ext.Optimization()
122 cython_compile_testcase = runtests.CythonCompileTestCase(
123 workdir=self.tempdir,
124 # we clean up everything (not only compiled files)
125 cleanup_workdir=False,
126 tags=runtests.parse_tags(codefile),
127 **opts
131 new_stderr = open(os.devnull, 'w')
133 stderr = sys.stderr
134 sys.stderr = new_stderr
136 optimization_disabler.disable_optimization()
137 try:
138 cython_compile_testcase.run_cython(
139 targetdir=self.tempdir,
140 incdir=None,
141 annotate=False,
142 extra_compile_options={
143 'gdb_debug':True,
144 'output_dir':self.tempdir,
146 **opts
149 cython_compile_testcase.run_distutils(
150 incdir=None,
151 workdir=self.tempdir,
152 extra_extension_args={'extra_objects':['cfuncs.o']},
153 **opts
155 finally:
156 optimization_disabler.restore_state()
157 sys.stderr = stderr
158 new_stderr.close()
160 # ext = Cython.Distutils.extension.Extension(
161 # 'codefile',
162 # ['codefile.pyx'],
163 # cython_gdb=True,
164 # extra_objects=['cfuncs.o'])
166 # distutils.core.setup(
167 # script_args=['build_ext', '--inplace'],
168 # ext_modules=[ext],
169 # cmdclass=dict(build_ext=Cython.Distutils.build_ext)
172 except:
173 os.chdir(self.cwd)
174 raise
176 def tearDown(self):
177 if not test_gdb():
178 return
179 os.chdir(self.cwd)
180 shutil.rmtree(self.tempdir)
183 class GdbDebuggerTestCase(DebuggerTestCase):
185 def setUp(self):
186 if not test_gdb():
187 return
189 super(GdbDebuggerTestCase, self).setUp()
191 prefix_code = textwrap.dedent('''\
192 python
194 import os
195 import sys
196 import traceback
198 def excepthook(type, value, tb):
199 traceback.print_exception(type, value, tb)
200 os._exit(1)
202 sys.excepthook = excepthook
204 # Have tracebacks end up on sys.stderr (gdb replaces sys.stderr
205 # with an object that calls gdb.write())
206 sys.stderr = sys.__stderr__
209 ''')
211 code = textwrap.dedent('''\
212 python
214 from Cython.Debugger.Tests import test_libcython_in_gdb
215 test_libcython_in_gdb.main(version=%r)
218 ''' % (sys.version_info[:2],))
220 self.gdb_command_file = cygdb.make_command_file(self.tempdir,
221 prefix_code)
223 f = open(self.gdb_command_file, 'a')
224 try:
225 f.write(code)
226 finally:
227 f.close()
229 args = ['gdb', '-batch', '-x', self.gdb_command_file, '-n', '--args',
230 sys.executable, '-c', 'import codefile']
232 paths = []
233 path = os.environ.get('PYTHONPATH')
234 if path:
235 paths.append(path)
236 paths.append(os.path.dirname(os.path.dirname(
237 os.path.abspath(Cython.__file__))))
238 env = dict(os.environ, PYTHONPATH=os.pathsep.join(paths))
240 self.p = subprocess.Popen(
241 args,
242 stdout=open(os.devnull, 'w'),
243 stderr=subprocess.PIPE,
244 env=env)
246 def tearDown(self):
247 if not test_gdb():
248 return
250 try:
251 super(GdbDebuggerTestCase, self).tearDown()
252 if self.p:
253 try: self.p.stdout.close()
254 except: pass
255 try: self.p.stderr.close()
256 except: pass
257 self.p.wait()
258 finally:
259 os.remove(self.gdb_command_file)
262 class TestAll(GdbDebuggerTestCase):
264 def test_all(self):
265 if not test_gdb():
266 return
268 out, err = self.p.communicate()
269 err = err.decode('UTF-8')
271 exit_status = self.p.returncode
273 if exit_status == 1:
274 sys.stderr.write(err)
275 elif exit_status >= 2:
276 border = u'*' * 30
277 start = u'%s v INSIDE GDB v %s' % (border, border)
278 end = u'%s ^ INSIDE GDB ^ %s' % (border, border)
279 errmsg = u'\n%s\n%s%s' % (start, err, end)
281 sys.stderr.write(errmsg)
284 if __name__ == '__main__':
285 unittest.main()