blob: 4fe005dfa130e33e6f88185adde4cd7281257334 [file] [log] [blame]
Nick Coghlan39f0bb52017-11-28 08:11:51 +10001# Run the tests in Programs/_testembed.c (tests for the CPython embedding APIs)
2from test import support
3import unittest
4
5from collections import namedtuple
Victor Stinner7ddd56f2018-11-14 00:24:28 +01006import json
Nick Coghlan39f0bb52017-11-28 08:11:51 +10007import os
Michael Feltd2067312018-09-15 11:28:31 +02008import platform
Nick Coghlan39f0bb52017-11-28 08:11:51 +10009import re
10import subprocess
11import sys
Victor Stinnera6537fb2018-11-26 11:54:12 +010012import textwrap
Nick Coghlan39f0bb52017-11-28 08:11:51 +100013
14
Victor Stinner01de89c2018-11-14 17:39:45 +010015MS_WINDOWS = (os.name == 'nt')
Victor Stinnerb16b4e42019-05-17 15:20:52 +020016PYMEM_ALLOCATOR_NOT_SET = 0
17PYMEM_ALLOCATOR_DEBUG = 2
18PYMEM_ALLOCATOR_MALLOC = 3
Victor Stinner01de89c2018-11-14 17:39:45 +010019
Victor Stinner6d1c4672019-05-20 11:02:00 +020020CONFIG_INIT = 0
21CONFIG_INIT_PYTHON = 1
22CONFIG_INIT_ISOLATED = 2
23
Victor Stinner01de89c2018-11-14 17:39:45 +010024
Victor Stinner56b29b62018-07-26 18:57:56 +020025class EmbeddingTestsMixin:
Nick Coghlan39f0bb52017-11-28 08:11:51 +100026 def setUp(self):
27 here = os.path.abspath(__file__)
28 basepath = os.path.dirname(os.path.dirname(os.path.dirname(here)))
29 exename = "_testembed"
Victor Stinner01de89c2018-11-14 17:39:45 +010030 if MS_WINDOWS:
Nick Coghlan39f0bb52017-11-28 08:11:51 +100031 ext = ("_d" if "_d" in sys.executable else "") + ".exe"
32 exename += ext
33 exepath = os.path.dirname(sys.executable)
34 else:
35 exepath = os.path.join(basepath, "Programs")
36 self.test_exe = exe = os.path.join(exepath, exename)
37 if not os.path.exists(exe):
38 self.skipTest("%r doesn't exist" % exe)
39 # This is needed otherwise we get a fatal error:
40 # "Py_Initialize: Unable to get the locale encoding
41 # LookupError: no codec search functions registered: can't find encoding"
42 self.oldcwd = os.getcwd()
43 os.chdir(basepath)
44
45 def tearDown(self):
46 os.chdir(self.oldcwd)
47
48 def run_embedded_interpreter(self, *args, env=None):
49 """Runs a test in the embedded interpreter"""
50 cmd = [self.test_exe]
51 cmd.extend(args)
Victor Stinner01de89c2018-11-14 17:39:45 +010052 if env is not None and MS_WINDOWS:
Nick Coghlan39f0bb52017-11-28 08:11:51 +100053 # Windows requires at least the SYSTEMROOT environment variable to
54 # start Python.
55 env = env.copy()
56 env['SYSTEMROOT'] = os.environ['SYSTEMROOT']
57
58 p = subprocess.Popen(cmd,
59 stdout=subprocess.PIPE,
60 stderr=subprocess.PIPE,
61 universal_newlines=True,
62 env=env)
Victor Stinner2f549082019-03-29 15:13:46 +010063 try:
64 (out, err) = p.communicate()
65 except:
66 p.terminate()
67 p.wait()
68 raise
Nick Coghlan39f0bb52017-11-28 08:11:51 +100069 if p.returncode != 0 and support.verbose:
70 print(f"--- {cmd} failed ---")
71 print(f"stdout:\n{out}")
Nick Coghlanbc77eff2018-03-25 20:44:30 +100072 print(f"stderr:\n{err}")
Nick Coghlan39f0bb52017-11-28 08:11:51 +100073 print(f"------")
74
75 self.assertEqual(p.returncode, 0,
76 "bad returncode %d, stderr is %r" %
77 (p.returncode, err))
78 return out, err
79
80 def run_repeated_init_and_subinterpreters(self):
81 out, err = self.run_embedded_interpreter("repeated_init_and_subinterpreters")
82 self.assertEqual(err, "")
83
84 # The output from _testembed looks like this:
85 # --- Pass 0 ---
86 # interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728
87 # interp 1 <0x1d4f690>, thread state <0x1d35350>: id(modules) = 139650431165784
88 # interp 2 <0x1d5a690>, thread state <0x1d99ed0>: id(modules) = 139650413140368
89 # interp 3 <0x1d4f690>, thread state <0x1dc3340>: id(modules) = 139650412862200
90 # interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728
91 # --- Pass 1 ---
92 # ...
93
94 interp_pat = (r"^interp (\d+) <(0x[\dA-F]+)>, "
95 r"thread state <(0x[\dA-F]+)>: "
96 r"id\(modules\) = ([\d]+)$")
97 Interp = namedtuple("Interp", "id interp tstate modules")
98
99 numloops = 0
100 current_run = []
101 for line in out.splitlines():
102 if line == "--- Pass {} ---".format(numloops):
103 self.assertEqual(len(current_run), 0)
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000104 if support.verbose > 1:
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000105 print(line)
106 numloops += 1
107 continue
108
109 self.assertLess(len(current_run), 5)
110 match = re.match(interp_pat, line)
111 if match is None:
112 self.assertRegex(line, interp_pat)
113
114 # Parse the line from the loop. The first line is the main
115 # interpreter and the 3 afterward are subinterpreters.
116 interp = Interp(*match.groups())
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000117 if support.verbose > 1:
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000118 print(interp)
119 self.assertTrue(interp.interp)
120 self.assertTrue(interp.tstate)
121 self.assertTrue(interp.modules)
122 current_run.append(interp)
123
124 # The last line in the loop should be the same as the first.
125 if len(current_run) == 5:
126 main = current_run[0]
127 self.assertEqual(interp, main)
128 yield current_run
129 current_run = []
130
Victor Stinner56b29b62018-07-26 18:57:56 +0200131
132class EmbeddingTests(EmbeddingTestsMixin, unittest.TestCase):
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000133 def test_subinterps_main(self):
134 for run in self.run_repeated_init_and_subinterpreters():
135 main = run[0]
136
137 self.assertEqual(main.id, '0')
138
139 def test_subinterps_different_ids(self):
140 for run in self.run_repeated_init_and_subinterpreters():
141 main, *subs, _ = run
142
143 mainid = int(main.id)
144 for i, sub in enumerate(subs):
145 self.assertEqual(sub.id, str(mainid + i + 1))
146
147 def test_subinterps_distinct_state(self):
148 for run in self.run_repeated_init_and_subinterpreters():
149 main, *subs, _ = run
150
151 if '0x0' in main:
152 # XXX Fix on Windows (and other platforms): something
153 # is going on with the pointers in Programs/_testembed.c.
154 # interp.interp is 0x0 and interp.modules is the same
155 # between interpreters.
156 raise unittest.SkipTest('platform prints pointers as 0x0')
157
158 for sub in subs:
159 # A new subinterpreter may have the same
160 # PyInterpreterState pointer as a previous one if
161 # the earlier one has already been destroyed. So
162 # we compare with the main interpreter. The same
163 # applies to tstate.
164 self.assertNotEqual(sub.interp, main.interp)
165 self.assertNotEqual(sub.tstate, main.tstate)
166 self.assertNotEqual(sub.modules, main.modules)
167
168 def test_forced_io_encoding(self):
169 # Checks forced configuration of embedded interpreter IO streams
170 env = dict(os.environ, PYTHONIOENCODING="utf-8:surrogateescape")
171 out, err = self.run_embedded_interpreter("forced_io_encoding", env=env)
172 if support.verbose > 1:
173 print()
174 print(out)
175 print(err)
176 expected_stream_encoding = "utf-8"
177 expected_errors = "surrogateescape"
178 expected_output = '\n'.join([
179 "--- Use defaults ---",
180 "Expected encoding: default",
181 "Expected errors: default",
182 "stdin: {in_encoding}:{errors}",
183 "stdout: {out_encoding}:{errors}",
184 "stderr: {out_encoding}:backslashreplace",
185 "--- Set errors only ---",
186 "Expected encoding: default",
187 "Expected errors: ignore",
188 "stdin: {in_encoding}:ignore",
189 "stdout: {out_encoding}:ignore",
190 "stderr: {out_encoding}:backslashreplace",
191 "--- Set encoding only ---",
Victor Stinner9e4994d2018-08-28 23:26:33 +0200192 "Expected encoding: iso8859-1",
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000193 "Expected errors: default",
Victor Stinner9e4994d2018-08-28 23:26:33 +0200194 "stdin: iso8859-1:{errors}",
195 "stdout: iso8859-1:{errors}",
196 "stderr: iso8859-1:backslashreplace",
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000197 "--- Set encoding and errors ---",
Victor Stinner9e4994d2018-08-28 23:26:33 +0200198 "Expected encoding: iso8859-1",
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000199 "Expected errors: replace",
Victor Stinner9e4994d2018-08-28 23:26:33 +0200200 "stdin: iso8859-1:replace",
201 "stdout: iso8859-1:replace",
202 "stderr: iso8859-1:backslashreplace"])
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000203 expected_output = expected_output.format(
204 in_encoding=expected_stream_encoding,
205 out_encoding=expected_stream_encoding,
206 errors=expected_errors)
207 # This is useful if we ever trip over odd platform behaviour
208 self.maxDiff = None
209 self.assertEqual(out.strip(), expected_output)
210
211 def test_pre_initialization_api(self):
212 """
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000213 Checks some key parts of the C-API that need to work before the runtine
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000214 is initialized (via Py_Initialize()).
215 """
216 env = dict(os.environ, PYTHONPATH=os.pathsep.join(sys.path))
217 out, err = self.run_embedded_interpreter("pre_initialization_api", env=env)
Victor Stinner01de89c2018-11-14 17:39:45 +0100218 if MS_WINDOWS:
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000219 expected_path = self.test_exe
220 else:
221 expected_path = os.path.join(os.getcwd(), "spam")
222 expected_output = f"sys.executable: {expected_path}\n"
223 self.assertIn(expected_output, out)
224 self.assertEqual(err, '')
225
226 def test_pre_initialization_sys_options(self):
227 """
228 Checks that sys.warnoptions and sys._xoptions can be set before the
229 runtime is initialized (otherwise they won't be effective).
230 """
Pablo Galindo41148462018-04-27 13:23:13 +0100231 env = dict(os.environ, PYTHONPATH=os.pathsep.join(sys.path))
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000232 out, err = self.run_embedded_interpreter(
233 "pre_initialization_sys_options", env=env)
234 expected_output = (
235 "sys.warnoptions: ['once', 'module', 'default']\n"
236 "sys._xoptions: {'not_an_option': '1', 'also_not_an_option': '2'}\n"
237 "warnings.filters[:3]: ['default', 'module', 'once']\n"
238 )
239 self.assertIn(expected_output, out)
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000240 self.assertEqual(err, '')
241
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100242 def test_bpo20891(self):
243 """
244 bpo-20891: Calling PyGILState_Ensure in a non-Python thread before
245 calling PyEval_InitThreads() must not crash. PyGILState_Ensure() must
246 call PyEval_InitThreads() for us in this case.
247 """
248 out, err = self.run_embedded_interpreter("bpo20891")
249 self.assertEqual(out, '')
250 self.assertEqual(err, '')
251
Victor Stinner209abf72018-06-22 19:14:51 +0200252 def test_initialize_twice(self):
253 """
254 bpo-33932: Calling Py_Initialize() twice should do nothing (and not
255 crash!).
256 """
257 out, err = self.run_embedded_interpreter("initialize_twice")
258 self.assertEqual(out, '')
259 self.assertEqual(err, '')
260
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200261 def test_initialize_pymain(self):
262 """
263 bpo-34008: Calling Py_Main() after Py_Initialize() must not fail.
264 """
265 out, err = self.run_embedded_interpreter("initialize_pymain")
266 self.assertEqual(out.rstrip(), "Py_Main() after Py_Initialize: sys.argv=['-c', 'arg2']")
267 self.assertEqual(err, '')
268
Victor Stinner2f549082019-03-29 15:13:46 +0100269 def test_run_main(self):
270 out, err = self.run_embedded_interpreter("run_main")
271 self.assertEqual(out.rstrip(), "_Py_RunMain(): sys.argv=['-c', 'arg2']")
272 self.assertEqual(err, '')
273
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000274
Victor Stinner56b29b62018-07-26 18:57:56 +0200275class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
276 maxDiff = 4096
Victor Stinner01de89c2018-11-14 17:39:45 +0100277 UTF8_MODE_ERRORS = ('surrogatepass' if MS_WINDOWS else 'surrogateescape')
278
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200279 # Marker to read the default configuration: get_default_config()
Victor Stinnera6537fb2018-11-26 11:54:12 +0100280 GET_DEFAULT_CONFIG = object()
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200281
282 # Marker to ignore a configuration parameter
283 IGNORE_CONFIG = object()
284
Victor Stinner1075d162019-03-25 23:19:57 +0100285 DEFAULT_PRE_CONFIG = {
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200286 'allocator': PYMEM_ALLOCATOR_NOT_SET,
Victor Stinner6d1c4672019-05-20 11:02:00 +0200287 'parse_argv': 0,
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200288 'configure_locale': 1,
Victor Stinner1075d162019-03-25 23:19:57 +0100289 'coerce_c_locale': 0,
290 'coerce_c_locale_warn': 0,
Victor Stinner1075d162019-03-25 23:19:57 +0100291 'utf8_mode': 0,
292 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200293 if MS_WINDOWS:
294 DEFAULT_PRE_CONFIG.update({
295 'legacy_windows_fs_encoding': 0,
296 })
297 PYTHON_PRE_CONFIG = dict(DEFAULT_PRE_CONFIG,
298 parse_argv=1,
Victor Stinner425717f2019-05-20 16:38:48 +0200299 coerce_c_locale=GET_DEFAULT_CONFIG,
300 utf8_mode=GET_DEFAULT_CONFIG,
Victor Stinner6d1c4672019-05-20 11:02:00 +0200301 )
Victor Stinnerbab0db62019-05-18 03:21:27 +0200302 ISOLATED_PRE_CONFIG = dict(DEFAULT_PRE_CONFIG,
303 configure_locale=0,
304 isolated=1,
305 use_environment=0,
306 utf8_mode=0,
307 dev_mode=0,
Victor Stinner425717f2019-05-20 16:38:48 +0200308 coerce_c_locale=0,
Victor Stinnerbab0db62019-05-18 03:21:27 +0200309 )
Victor Stinnerbab0db62019-05-18 03:21:27 +0200310
Victor Stinner20004952019-03-26 02:31:11 +0100311 COPY_PRE_CONFIG = [
312 'dev_mode',
313 'isolated',
314 'use_environment',
315 ]
316
Victor Stinner00b137c2018-11-13 19:59:26 +0100317 DEFAULT_CORE_CONFIG = {
Victor Stinner6d1c4672019-05-20 11:02:00 +0200318 '_config_init': CONFIG_INIT,
Victor Stinner20004952019-03-26 02:31:11 +0100319 'isolated': 0,
320 'use_environment': 1,
321 'dev_mode': 0,
322
Victor Stinner56b29b62018-07-26 18:57:56 +0200323 'install_signal_handlers': 1,
Victor Stinner56b29b62018-07-26 18:57:56 +0200324 'use_hash_seed': 0,
325 'hash_seed': 0,
Victor Stinner56b29b62018-07-26 18:57:56 +0200326 'faulthandler': 0,
327 'tracemalloc': 0,
328 'import_time': 0,
329 'show_ref_count': 0,
330 'show_alloc_count': 0,
331 'dump_refs': 0,
332 'malloc_stats': 0,
Victor Stinner56b29b62018-07-26 18:57:56 +0200333
Victor Stinnera6537fb2018-11-26 11:54:12 +0100334 'filesystem_encoding': GET_DEFAULT_CONFIG,
335 'filesystem_errors': GET_DEFAULT_CONFIG,
Victor Stinnerc5989cd2018-08-29 19:32:47 +0200336
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100337 'pycache_prefix': None,
Victor Stinner91c99872019-05-14 22:01:51 +0200338 'program_name': GET_DEFAULT_CONFIG,
Victor Stinnercab5d072019-05-17 19:01:14 +0200339 'parse_argv': 0,
Victor Stinner62599762019-03-15 16:03:23 +0100340 'argv': [""],
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100341
342 'xoptions': [],
343 'warnoptions': [],
Victor Stinner56b29b62018-07-26 18:57:56 +0200344
Victor Stinner01de89c2018-11-14 17:39:45 +0100345 'module_search_path_env': None,
346 'home': None,
Victor Stinner91c99872019-05-14 22:01:51 +0200347 'executable': GET_DEFAULT_CONFIG,
Victor Stinnera6537fb2018-11-26 11:54:12 +0100348
349 'prefix': GET_DEFAULT_CONFIG,
350 'base_prefix': GET_DEFAULT_CONFIG,
351 'exec_prefix': GET_DEFAULT_CONFIG,
352 'base_exec_prefix': GET_DEFAULT_CONFIG,
Victor Stinner5eb8b072019-05-15 02:12:48 +0200353 'module_search_paths': GET_DEFAULT_CONFIG,
Victor Stinner01de89c2018-11-14 17:39:45 +0100354
Victor Stinner56b29b62018-07-26 18:57:56 +0200355 'site_import': 1,
356 'bytes_warning': 0,
357 'inspect': 0,
358 'interactive': 0,
359 'optimization_level': 0,
Victor Stinner98512272018-08-01 03:07:00 +0200360 'parser_debug': 0,
Victor Stinner56b29b62018-07-26 18:57:56 +0200361 'write_bytecode': 1,
362 'verbose': 0,
363 'quiet': 0,
364 'user_site_directory': 1,
Victor Stinnercab5d072019-05-17 19:01:14 +0200365 'configure_c_stdio': 0,
Victor Stinner98512272018-08-01 03:07:00 +0200366 'buffered_stdio': 1,
Victor Stinnerc5989cd2018-08-29 19:32:47 +0200367
Victor Stinnera6537fb2018-11-26 11:54:12 +0100368 'stdio_encoding': GET_DEFAULT_CONFIG,
369 'stdio_errors': GET_DEFAULT_CONFIG,
Victor Stinner56b29b62018-07-26 18:57:56 +0200370
Victor Stinner62be7632019-03-01 13:10:14 +0100371 'skip_source_first_line': 0,
372 'run_command': None,
373 'run_module': None,
374 'run_filename': None,
375
Victor Stinner56b29b62018-07-26 18:57:56 +0200376 '_install_importlib': 1,
Victor Stinnercb9fbd32019-05-01 23:51:56 -0400377 'check_hash_pycs_mode': 'default',
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200378 'pathconfig_warnings': 1,
379 '_init_main': 1,
Victor Stinner56b29b62018-07-26 18:57:56 +0200380 }
Victor Stinner01de89c2018-11-14 17:39:45 +0100381 if MS_WINDOWS:
Victor Stinner1075d162019-03-25 23:19:57 +0100382 DEFAULT_CORE_CONFIG.update({
Victor Stinner01de89c2018-11-14 17:39:45 +0100383 'legacy_windows_stdio': 0,
384 })
385
Victor Stinnerbab0db62019-05-18 03:21:27 +0200386 PYTHON_CORE_CONFIG = dict(DEFAULT_CORE_CONFIG,
387 configure_c_stdio=1,
388 parse_argv=1,
389 )
390 ISOLATED_CORE_CONFIG = dict(DEFAULT_CORE_CONFIG,
391 isolated=1,
392 use_environment=0,
393 user_site_directory=0,
394 dev_mode=0,
395 install_signal_handlers=0,
396 use_hash_seed=0,
397 faulthandler=0,
398 tracemalloc=0,
399 pathconfig_warnings=0,
400 )
401 if MS_WINDOWS:
402 ISOLATED_CORE_CONFIG['legacy_windows_stdio'] = 0
403
Victor Stinner01de89c2018-11-14 17:39:45 +0100404 # global config
405 DEFAULT_GLOBAL_CONFIG = {
406 'Py_HasFileSystemDefaultEncoding': 0,
407 'Py_HashRandomizationFlag': 1,
408 '_Py_HasFileSystemDefaultEncodeErrors': 0,
409 }
Victor Stinner1075d162019-03-25 23:19:57 +0100410 COPY_GLOBAL_PRE_CONFIG = [
Victor Stinner1075d162019-03-25 23:19:57 +0100411 ('Py_UTF8Mode', 'utf8_mode'),
412 ]
Victor Stinner01de89c2018-11-14 17:39:45 +0100413 COPY_GLOBAL_CONFIG = [
414 # Copy core config to global config for expected values
415 # True means that the core config value is inverted (0 => 1 and 1 => 0)
416 ('Py_BytesWarningFlag', 'bytes_warning'),
417 ('Py_DebugFlag', 'parser_debug'),
418 ('Py_DontWriteBytecodeFlag', 'write_bytecode', True),
419 ('Py_FileSystemDefaultEncodeErrors', 'filesystem_errors'),
420 ('Py_FileSystemDefaultEncoding', 'filesystem_encoding'),
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200421 ('Py_FrozenFlag', 'pathconfig_warnings', True),
Victor Stinner20004952019-03-26 02:31:11 +0100422 ('Py_IgnoreEnvironmentFlag', 'use_environment', True),
Victor Stinner01de89c2018-11-14 17:39:45 +0100423 ('Py_InspectFlag', 'inspect'),
424 ('Py_InteractiveFlag', 'interactive'),
Victor Stinner20004952019-03-26 02:31:11 +0100425 ('Py_IsolatedFlag', 'isolated'),
Victor Stinner01de89c2018-11-14 17:39:45 +0100426 ('Py_NoSiteFlag', 'site_import', True),
427 ('Py_NoUserSiteDirectory', 'user_site_directory', True),
428 ('Py_OptimizeFlag', 'optimization_level'),
429 ('Py_QuietFlag', 'quiet'),
Victor Stinner01de89c2018-11-14 17:39:45 +0100430 ('Py_UnbufferedStdioFlag', 'buffered_stdio', True),
431 ('Py_VerboseFlag', 'verbose'),
432 ]
433 if MS_WINDOWS:
Victor Stinner1075d162019-03-25 23:19:57 +0100434 COPY_GLOBAL_PRE_CONFIG.extend((
Victor Stinner01de89c2018-11-14 17:39:45 +0100435 ('Py_LegacyWindowsFSEncodingFlag', 'legacy_windows_fs_encoding'),
Victor Stinner1075d162019-03-25 23:19:57 +0100436 ))
437 COPY_GLOBAL_CONFIG.extend((
Victor Stinner01de89c2018-11-14 17:39:45 +0100438 ('Py_LegacyWindowsStdioFlag', 'legacy_windows_stdio'),
439 ))
Victor Stinner56b29b62018-07-26 18:57:56 +0200440
Victor Stinner425717f2019-05-20 16:38:48 +0200441 EXPECTED_CONFIG = None
442
Victor Stinner01de89c2018-11-14 17:39:45 +0100443 def main_xoptions(self, xoptions_list):
444 xoptions = {}
445 for opt in xoptions_list:
446 if '=' in opt:
447 key, value = opt.split('=', 1)
448 xoptions[key] = value
449 else:
450 xoptions[opt] = True
451 return xoptions
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200452
Victor Stinner425717f2019-05-20 16:38:48 +0200453 def _get_expected_config(self, env):
Victor Stinnera6537fb2018-11-26 11:54:12 +0100454 code = textwrap.dedent('''
455 import json
Victor Stinnera6537fb2018-11-26 11:54:12 +0100456 import sys
Victor Stinner5eb8b072019-05-15 02:12:48 +0200457 import _testinternalcapi
Victor Stinnera6537fb2018-11-26 11:54:12 +0100458
Victor Stinner5eb8b072019-05-15 02:12:48 +0200459 configs = _testinternalcapi.get_configs()
Victor Stinnera6537fb2018-11-26 11:54:12 +0100460
Victor Stinner425717f2019-05-20 16:38:48 +0200461 data = json.dumps(configs)
Victor Stinnera6537fb2018-11-26 11:54:12 +0100462 data = data.encode('utf-8')
463 sys.stdout.buffer.write(data)
464 sys.stdout.buffer.flush()
465 ''')
466
467 # Use -S to not import the site module: get the proper configuration
468 # when test_embed is run from a venv (bpo-35313)
Victor Stinner5eb8b072019-05-15 02:12:48 +0200469 args = [sys.executable, '-S', '-c', code]
Victor Stinnera6537fb2018-11-26 11:54:12 +0100470 proc = subprocess.run(args, env=env,
471 stdout=subprocess.PIPE,
472 stderr=subprocess.STDOUT)
473 if proc.returncode:
474 raise Exception(f"failed to get the default config: "
475 f"stdout={proc.stdout!r} stderr={proc.stderr!r}")
476 stdout = proc.stdout.decode('utf-8')
Victor Stinner4631da12019-05-02 15:30:21 -0400477 try:
Victor Stinner425717f2019-05-20 16:38:48 +0200478 return json.loads(stdout)
Victor Stinner4631da12019-05-02 15:30:21 -0400479 except json.JSONDecodeError:
480 self.fail(f"fail to decode stdout: {stdout!r}")
Victor Stinnera6537fb2018-11-26 11:54:12 +0100481
Victor Stinner425717f2019-05-20 16:38:48 +0200482 def get_expected_config(self, expected_preconfig, expected, env, api,
483 add_path=None):
484 cls = self.__class__
485 if cls.EXPECTED_CONFIG is None:
486 cls.EXPECTED_CONFIG = self._get_expected_config(env)
487 configs = {key: dict(value)
488 for key, value in self.EXPECTED_CONFIG.items()}
489
490 pre_config = configs['pre_config']
491 for key, value in expected_preconfig.items():
492 if value is self.GET_DEFAULT_CONFIG:
493 expected_preconfig[key] = pre_config[key]
494
495 if not expected_preconfig['configure_locale'] or api == CONFIG_INIT:
496 # there is no easy way to get the locale encoding before
497 # setlocale(LC_CTYPE, "") is called: don't test encodings
498 for key in ('filesystem_encoding', 'filesystem_errors',
499 'stdio_encoding', 'stdio_errors'):
500 expected[key] = self.IGNORE_CONFIG
501
502 if not expected_preconfig['configure_locale']:
503 # UTF-8 Mode depends on the locale. There is no easy way
504 # to guess if UTF-8 Mode will be enabled or not if the locale
505 # is not configured.
506 expected_preconfig['utf8_mode'] = self.IGNORE_CONFIG
507
508 if expected_preconfig['utf8_mode'] == 1:
509 if expected['filesystem_encoding'] is self.GET_DEFAULT_CONFIG:
510 expected['filesystem_encoding'] = 'utf-8'
511 if expected['filesystem_errors'] is self.GET_DEFAULT_CONFIG:
512 expected['filesystem_errors'] = self.UTF8_MODE_ERRORS
513 if expected['stdio_encoding'] is self.GET_DEFAULT_CONFIG:
514 expected['stdio_encoding'] = 'utf-8'
515 if expected['stdio_errors'] is self.GET_DEFAULT_CONFIG:
516 expected['stdio_errors'] = 'surrogateescape'
517
Victor Stinner91c99872019-05-14 22:01:51 +0200518 if expected['executable'] is self.GET_DEFAULT_CONFIG:
519 if sys.platform == 'win32':
520 expected['executable'] = self.test_exe
521 else:
522 if expected['program_name'] is not self.GET_DEFAULT_CONFIG:
523 expected['executable'] = os.path.abspath(expected['program_name'])
524 else:
525 expected['executable'] = os.path.join(os.getcwd(), '_testembed')
526 if expected['program_name'] is self.GET_DEFAULT_CONFIG:
527 expected['program_name'] = './_testembed'
528
Victor Stinner425717f2019-05-20 16:38:48 +0200529 core_config = configs['core_config']
Victor Stinnera6537fb2018-11-26 11:54:12 +0100530 for key, value in expected.items():
531 if value is self.GET_DEFAULT_CONFIG:
Victor Stinner425717f2019-05-20 16:38:48 +0200532 expected[key] = core_config[key]
Victor Stinner5eb8b072019-05-15 02:12:48 +0200533
Victor Stinner425717f2019-05-20 16:38:48 +0200534 prepend_path = expected['module_search_path_env']
535 if prepend_path is not None:
536 expected['module_search_paths'] = [prepend_path, *expected['module_search_paths']]
Victor Stinner5eb8b072019-05-15 02:12:48 +0200537 if add_path is not None:
Victor Stinner425717f2019-05-20 16:38:48 +0200538 expected['module_search_paths'] = [*expected['module_search_paths'], add_path]
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200539
Victor Stinner425717f2019-05-20 16:38:48 +0200540 for key in self.COPY_PRE_CONFIG:
541 if key not in expected_preconfig:
542 expected_preconfig[key] = expected[key]
Victor Stinner01de89c2018-11-14 17:39:45 +0100543
Victor Stinner1075d162019-03-25 23:19:57 +0100544 def check_pre_config(self, config, expected):
Victor Stinner425717f2019-05-20 16:38:48 +0200545 pre_config = dict(config['pre_config'])
546 for key, value in list(expected.items()):
547 if value is self.IGNORE_CONFIG:
548 del pre_config[key]
549 del expected[key]
550 self.assertEqual(pre_config, expected)
Victor Stinner1075d162019-03-25 23:19:57 +0100551
Victor Stinner5eb8b072019-05-15 02:12:48 +0200552 def check_core_config(self, config, expected):
Victor Stinner01de89c2018-11-14 17:39:45 +0100553 core_config = dict(config['core_config'])
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200554 for key, value in list(expected.items()):
555 if value is self.IGNORE_CONFIG:
556 del core_config[key]
557 del expected[key]
Victor Stinner01de89c2018-11-14 17:39:45 +0100558 self.assertEqual(core_config, expected)
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200559
Victor Stinner01de89c2018-11-14 17:39:45 +0100560 def check_global_config(self, config):
Victor Stinner1075d162019-03-25 23:19:57 +0100561 pre_config = config['pre_config']
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100562 core_config = config['core_config']
Victor Stinner00b137c2018-11-13 19:59:26 +0100563
Victor Stinnera6537fb2018-11-26 11:54:12 +0100564 expected = dict(self.DEFAULT_GLOBAL_CONFIG)
Victor Stinner01de89c2018-11-14 17:39:45 +0100565 for item in self.COPY_GLOBAL_CONFIG:
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100566 if len(item) == 3:
567 global_key, core_key, opposite = item
Victor Stinnera6537fb2018-11-26 11:54:12 +0100568 expected[global_key] = 0 if core_config[core_key] else 1
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100569 else:
570 global_key, core_key = item
Victor Stinnera6537fb2018-11-26 11:54:12 +0100571 expected[global_key] = core_config[core_key]
Victor Stinner1075d162019-03-25 23:19:57 +0100572 for item in self.COPY_GLOBAL_PRE_CONFIG:
573 if len(item) == 3:
574 global_key, core_key, opposite = item
575 expected[global_key] = 0 if pre_config[core_key] else 1
576 else:
577 global_key, core_key = item
578 expected[global_key] = pre_config[core_key]
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100579
Victor Stinnera6537fb2018-11-26 11:54:12 +0100580 self.assertEqual(config['global_config'], expected)
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100581
Victor Stinnerbab0db62019-05-18 03:21:27 +0200582 def check_config(self, testname, expected_config=None, expected_preconfig=None,
Victor Stinner6d1c4672019-05-20 11:02:00 +0200583 add_path=None, stderr=None, api=CONFIG_INIT):
Victor Stinner01de89c2018-11-14 17:39:45 +0100584 env = dict(os.environ)
585 # Remove PYTHON* environment variables to get deterministic environment
586 for key in list(env):
587 if key.startswith('PYTHON'):
588 del env[key]
Victor Stinner01de89c2018-11-14 17:39:45 +0100589
Victor Stinner6d1c4672019-05-20 11:02:00 +0200590 if api == CONFIG_INIT_ISOLATED:
Victor Stinnerbab0db62019-05-18 03:21:27 +0200591 default_preconfig = self.ISOLATED_PRE_CONFIG
Victor Stinner6d1c4672019-05-20 11:02:00 +0200592 elif api == CONFIG_INIT_PYTHON:
593 default_preconfig = self.PYTHON_PRE_CONFIG
Victor Stinnerbab0db62019-05-18 03:21:27 +0200594 else:
595 default_preconfig = self.DEFAULT_PRE_CONFIG
596 if expected_preconfig is None:
597 expected_preconfig = {}
598 expected_preconfig = dict(default_preconfig, **expected_preconfig)
599 if expected_config is None:
600 expected_config = {}
Victor Stinner425717f2019-05-20 16:38:48 +0200601
602 if api == CONFIG_INIT_PYTHON:
603 default_config = self.PYTHON_CORE_CONFIG
604 elif api == CONFIG_INIT_ISOLATED:
605 default_config = self.ISOLATED_CORE_CONFIG
606 else:
607 default_config = self.DEFAULT_CORE_CONFIG
608 expected_config = dict(default_config, **expected_config)
609 expected_config['_config_init'] = api
610
611 self.get_expected_config(expected_preconfig,
612 expected_config, env,
613 api, add_path)
Victor Stinner1075d162019-03-25 23:19:57 +0100614
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200615 out, err = self.run_embedded_interpreter(testname, env=env)
616 if stderr is None and not expected_config['verbose']:
617 stderr = ""
618 if stderr is not None:
619 self.assertEqual(err.rstrip(), stderr)
620 try:
621 config = json.loads(out)
622 except json.JSONDecodeError:
623 self.fail(f"fail to decode stdout: {out!r}")
624
Victor Stinner1075d162019-03-25 23:19:57 +0100625 self.check_pre_config(config, expected_preconfig)
Victor Stinner5eb8b072019-05-15 02:12:48 +0200626 self.check_core_config(config, expected_config)
Victor Stinner01de89c2018-11-14 17:39:45 +0100627 self.check_global_config(config)
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100628
Victor Stinner56b29b62018-07-26 18:57:56 +0200629 def test_init_default_config(self):
Victor Stinner1075d162019-03-25 23:19:57 +0100630 self.check_config("init_default_config", {}, {})
Victor Stinner56b29b62018-07-26 18:57:56 +0200631
632 def test_init_global_config(self):
Victor Stinner1075d162019-03-25 23:19:57 +0100633 preconfig = {
634 'utf8_mode': 1,
635 }
Victor Stinner56b29b62018-07-26 18:57:56 +0200636 config = {
637 'program_name': './globalvar',
638 'site_import': 0,
639 'bytes_warning': 1,
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100640 'warnoptions': ['default::BytesWarning'],
Victor Stinner56b29b62018-07-26 18:57:56 +0200641 'inspect': 1,
642 'interactive': 1,
643 'optimization_level': 2,
644 'write_bytecode': 0,
645 'verbose': 1,
646 'quiet': 1,
Victor Stinner98512272018-08-01 03:07:00 +0200647 'buffered_stdio': 0,
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200648
Victor Stinner56b29b62018-07-26 18:57:56 +0200649 'user_site_directory': 0,
Victor Stinner54b43bb2019-05-16 18:30:15 +0200650 'pathconfig_warnings': 0,
Victor Stinner56b29b62018-07-26 18:57:56 +0200651 }
Victor Stinner1075d162019-03-25 23:19:57 +0100652 self.check_config("init_global_config", config, preconfig)
Victor Stinner56b29b62018-07-26 18:57:56 +0200653
654 def test_init_from_config(self):
Victor Stinner1075d162019-03-25 23:19:57 +0100655 preconfig = {
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200656 'allocator': PYMEM_ALLOCATOR_MALLOC,
Victor Stinner1075d162019-03-25 23:19:57 +0100657 'utf8_mode': 1,
658 }
Victor Stinner56b29b62018-07-26 18:57:56 +0200659 config = {
660 'install_signal_handlers': 0,
661 'use_hash_seed': 1,
662 'hash_seed': 123,
Victor Stinner56b29b62018-07-26 18:57:56 +0200663 'tracemalloc': 2,
664 'import_time': 1,
665 'show_ref_count': 1,
666 'show_alloc_count': 1,
667 'malloc_stats': 1,
668
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200669 'stdio_encoding': 'iso8859-1',
670 'stdio_errors': 'replace',
Victor Stinner56b29b62018-07-26 18:57:56 +0200671
672 'pycache_prefix': 'conf_pycache_prefix',
673 'program_name': './conf_program_name',
Victor Stinner2f549082019-03-29 15:13:46 +0100674 'argv': ['-c', 'arg2'],
Victor Stinnercab5d072019-05-17 19:01:14 +0200675 'parse_argv': 1,
Victor Stinner01de89c2018-11-14 17:39:45 +0100676 'xoptions': ['core_xoption1=3', 'core_xoption2=', 'core_xoption3'],
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100677 'warnoptions': ['error::ResourceWarning', 'default::BytesWarning'],
Victor Stinner2f549082019-03-29 15:13:46 +0100678 'run_command': 'pass\n',
Victor Stinner56b29b62018-07-26 18:57:56 +0200679
680 'site_import': 0,
681 'bytes_warning': 1,
682 'inspect': 1,
683 'interactive': 1,
684 'optimization_level': 2,
685 'write_bytecode': 0,
686 'verbose': 1,
687 'quiet': 1,
Victor Stinnercab5d072019-05-17 19:01:14 +0200688 'configure_c_stdio': 1,
Victor Stinner98512272018-08-01 03:07:00 +0200689 'buffered_stdio': 0,
Victor Stinner56b29b62018-07-26 18:57:56 +0200690 'user_site_directory': 0,
691 'faulthandler': 1,
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200692
Victor Stinnercb9fbd32019-05-01 23:51:56 -0400693 'check_hash_pycs_mode': 'always',
Victor Stinner54b43bb2019-05-16 18:30:15 +0200694 'pathconfig_warnings': 0,
Victor Stinner56b29b62018-07-26 18:57:56 +0200695 }
Victor Stinner1075d162019-03-25 23:19:57 +0100696 self.check_config("init_from_config", config, preconfig)
Victor Stinner56b29b62018-07-26 18:57:56 +0200697
698 def test_init_env(self):
Victor Stinner425717f2019-05-20 16:38:48 +0200699 preconfig = {
700 'allocator': PYMEM_ALLOCATOR_MALLOC,
701 }
702 config = {
703 'use_hash_seed': 1,
704 'hash_seed': 42,
705 'tracemalloc': 2,
706 'import_time': 1,
707 'malloc_stats': 1,
708 'inspect': 1,
709 'optimization_level': 2,
710 'module_search_path_env': '/my/path',
711 'pycache_prefix': 'env_pycache_prefix',
712 'write_bytecode': 0,
713 'verbose': 1,
714 'buffered_stdio': 0,
715 'stdio_encoding': 'iso8859-1',
716 'stdio_errors': 'replace',
717 'user_site_directory': 0,
718 'faulthandler': 1,
719 'warnoptions': ['EnvVar'],
720 }
721 self.check_config("init_env", config, preconfig)
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100722
723 def test_init_env_dev_mode(self):
Victor Stinner425717f2019-05-20 16:38:48 +0200724 preconfig = dict(allocator=PYMEM_ALLOCATOR_DEBUG)
725 config = dict(dev_mode=1,
726 faulthandler=1,
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100727 warnoptions=['default'])
Victor Stinner1075d162019-03-25 23:19:57 +0100728 self.check_config("init_env_dev_mode", config, preconfig)
Victor Stinner56b29b62018-07-26 18:57:56 +0200729
Victor Stinner20004952019-03-26 02:31:11 +0100730 def test_init_env_dev_mode_alloc(self):
Victor Stinner425717f2019-05-20 16:38:48 +0200731 preconfig = dict(allocator=PYMEM_ALLOCATOR_MALLOC)
732 config = dict(dev_mode=1,
733 faulthandler=1,
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100734 warnoptions=['default'])
Victor Stinner1075d162019-03-25 23:19:57 +0100735 self.check_config("init_env_dev_mode_alloc", config, preconfig)
Victor Stinner25d13f32019-03-06 12:51:53 +0100736
Victor Stinner56b29b62018-07-26 18:57:56 +0200737 def test_init_dev_mode(self):
Victor Stinner1075d162019-03-25 23:19:57 +0100738 preconfig = {
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200739 'allocator': PYMEM_ALLOCATOR_DEBUG,
Victor Stinner56b29b62018-07-26 18:57:56 +0200740 }
Victor Stinner1075d162019-03-25 23:19:57 +0100741 config = {
742 'faulthandler': 1,
Victor Stinner20004952019-03-26 02:31:11 +0100743 'dev_mode': 1,
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100744 'warnoptions': ['default'],
Victor Stinner1075d162019-03-25 23:19:57 +0100745 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200746 self.check_config("init_dev_mode", config, preconfig,
747 api=CONFIG_INIT_PYTHON)
748
749 def test_preinit_parse_argv(self):
750 # Pre-initialize implicitly using argv: make sure that -X dev
751 # is used to configure the allocation in preinitialization
752 preconfig = {
753 'allocator': PYMEM_ALLOCATOR_DEBUG,
754 }
755 config = {
756 'argv': ['script.py'],
757 'run_filename': 'script.py',
758 'dev_mode': 1,
759 'faulthandler': 1,
760 'warnoptions': ['default'],
761 'xoptions': ['dev'],
762 }
763 self.check_config("preinit_parse_argv", config, preconfig,
764 api=CONFIG_INIT_PYTHON)
765
766 def test_preinit_dont_parse_argv(self):
767 # -X dev must be ignored by isolated preconfiguration
768 preconfig = {
769 'isolated': 0,
770 }
771 config = {
772 'argv': ["python3", "-E", "-I",
773 "-X", "dev", "-X", "utf8", "script.py"],
774 'isolated': 0,
775 }
776 self.check_config("preinit_dont_parse_argv", config, preconfig,
777 api=CONFIG_INIT_ISOLATED)
Victor Stinner56b29b62018-07-26 18:57:56 +0200778
Victor Stinnercab5d072019-05-17 19:01:14 +0200779 def test_init_isolated_flag(self):
Victor Stinner1075d162019-03-25 23:19:57 +0100780 config = {
Victor Stinner20004952019-03-26 02:31:11 +0100781 'isolated': 1,
782 'use_environment': 0,
Victor Stinner56b29b62018-07-26 18:57:56 +0200783 'user_site_directory': 0,
784 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200785 self.check_config("init_isolated_flag", config, api=CONFIG_INIT_PYTHON)
Victor Stinner56b29b62018-07-26 18:57:56 +0200786
Victor Stinner6da20a42019-03-27 00:26:18 +0100787 def test_preinit_isolated1(self):
788 # _PyPreConfig.isolated=1, _PyCoreConfig.isolated not set
Victor Stinner6da20a42019-03-27 00:26:18 +0100789 config = {
790 'isolated': 1,
791 'use_environment': 0,
792 'user_site_directory': 0,
793 }
Victor Stinnerbab0db62019-05-18 03:21:27 +0200794 self.check_config("preinit_isolated1", config)
Victor Stinner6da20a42019-03-27 00:26:18 +0100795
796 def test_preinit_isolated2(self):
797 # _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1
Victor Stinner6da20a42019-03-27 00:26:18 +0100798 config = {
799 'isolated': 1,
800 'use_environment': 0,
801 'user_site_directory': 0,
802 }
Victor Stinnerbab0db62019-05-18 03:21:27 +0200803 self.check_config("preinit_isolated2", config)
Victor Stinner6da20a42019-03-27 00:26:18 +0100804
Victor Stinner6d1c4672019-05-20 11:02:00 +0200805 def test_preinit_isolated_config(self):
806 self.check_config("preinit_isolated_config", api=CONFIG_INIT_ISOLATED)
807
Victor Stinnercab5d072019-05-17 19:01:14 +0200808 def test_init_isolated_config(self):
Victor Stinner6d1c4672019-05-20 11:02:00 +0200809 self.check_config("init_isolated_config", api=CONFIG_INIT_ISOLATED)
Victor Stinnercab5d072019-05-17 19:01:14 +0200810
811 def test_init_python_config(self):
Victor Stinner6d1c4672019-05-20 11:02:00 +0200812 self.check_config("init_python_config", api=CONFIG_INIT_PYTHON)
Victor Stinnercab5d072019-05-17 19:01:14 +0200813
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200814 def test_init_dont_configure_locale(self):
815 # _PyPreConfig.configure_locale=0
816 preconfig = {
817 'configure_locale': 0,
Victor Stinner425717f2019-05-20 16:38:48 +0200818 'coerce_c_locale': 0,
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200819 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200820 self.check_config("init_dont_configure_locale", {}, preconfig,
821 api=CONFIG_INIT_PYTHON)
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200822
Victor Stinner91c99872019-05-14 22:01:51 +0200823 def test_init_read_set(self):
Victor Stinner91c99872019-05-14 22:01:51 +0200824 core_config = {
825 'program_name': './init_read_set',
826 'executable': 'my_executable',
827 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200828 self.check_config("init_read_set", core_config,
829 api=CONFIG_INIT_PYTHON,
Victor Stinner91c99872019-05-14 22:01:51 +0200830 add_path="init_read_set_path")
831
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200832 def test_init_run_main(self):
Victor Stinner5eb8b072019-05-15 02:12:48 +0200833 code = ('import _testinternalcapi, json; '
834 'print(json.dumps(_testinternalcapi.get_configs()))')
835 core_config = {
836 'argv': ['-c', 'arg2'],
Victor Stinner5eb8b072019-05-15 02:12:48 +0200837 'program_name': './python3',
838 'run_command': code + '\n',
Victor Stinnercab5d072019-05-17 19:01:14 +0200839 'parse_argv': 1,
Victor Stinner5eb8b072019-05-15 02:12:48 +0200840 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200841 self.check_config("init_run_main", core_config,
842 api=CONFIG_INIT_PYTHON)
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200843
844 def test_init_main(self):
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200845 code = ('import _testinternalcapi, json; '
846 'print(json.dumps(_testinternalcapi.get_configs()))')
847 core_config = {
848 'argv': ['-c', 'arg2'],
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200849 'program_name': './python3',
850 'run_command': code + '\n',
Victor Stinnercab5d072019-05-17 19:01:14 +0200851 'parse_argv': 1,
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200852 '_init_main': 0,
853 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200854 self.check_config("init_main", core_config,
855 api=CONFIG_INIT_PYTHON,
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200856 stderr="Run Python code before _Py_InitializeMain")
Victor Stinner5eb8b072019-05-15 02:12:48 +0200857
Victor Stinnercab5d072019-05-17 19:01:14 +0200858 def test_init_parse_argv(self):
859 core_config = {
Victor Stinnerbab0db62019-05-18 03:21:27 +0200860 'parse_argv': 1,
Victor Stinnercab5d072019-05-17 19:01:14 +0200861 'argv': ['-c', 'arg1', '-v', 'arg3'],
862 'program_name': './argv0',
Victor Stinnercab5d072019-05-17 19:01:14 +0200863 'run_command': 'pass\n',
864 'use_environment': 0,
865 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200866 self.check_config("init_parse_argv", core_config,
867 api=CONFIG_INIT_PYTHON)
Victor Stinnercab5d072019-05-17 19:01:14 +0200868
Victor Stinnerae239f62019-05-16 17:02:56 +0200869 def test_init_dont_parse_argv(self):
Victor Stinner6d1c4672019-05-20 11:02:00 +0200870 pre_config = {
871 'parse_argv': 0,
872 }
Victor Stinnerae239f62019-05-16 17:02:56 +0200873 core_config = {
Victor Stinnerbab0db62019-05-18 03:21:27 +0200874 'parse_argv': 0,
Victor Stinnercab5d072019-05-17 19:01:14 +0200875 'argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'],
876 'program_name': './argv0',
Victor Stinnerae239f62019-05-16 17:02:56 +0200877 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200878 self.check_config("init_dont_parse_argv", core_config, pre_config,
879 api=CONFIG_INIT_PYTHON)
Victor Stinnerae239f62019-05-16 17:02:56 +0200880
Victor Stinner56b29b62018-07-26 18:57:56 +0200881
Nick Coghlan39f0bb52017-11-28 08:11:51 +1000882if __name__ == "__main__":
883 unittest.main()