Skip to content

Commit 7d7846e

Browse files
committed
gh-152132: Add embed tests for -m and message SystemExit paths
Add test_run_main_system_exit_module and test_run_main_system_exit_command_message to _testembed.c and test_embed.py, covering the remaining sys.exit() paths mentioned in the review feedback (-m module and string message variants).
1 parent 18b7910 commit 7d7846e

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

Lib/test/test_embed.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,25 @@ def test_run_main_system_exit_file(self):
439439
finally:
440440
os.unlink(filename)
441441

442+
def test_run_main_system_exit_module(self):
443+
# gh-152132: same as above, but for the run_module code path.
444+
with tempfile.TemporaryDirectory() as tmpdir:
445+
mod = os.path.join(tmpdir, "exit_mod.py")
446+
with open(mod, "w", encoding="utf-8") as f:
447+
f.write("import sys; sys.exit(42)\n")
448+
env = dict(os.environ, PYTHONPATH=tmpdir)
449+
out, err = self.run_embedded_interpreter(
450+
"test_run_main_system_exit_module", env=env)
451+
self.assertEqual(out, '')
452+
self.assertEqual(err, '')
453+
454+
def test_run_main_system_exit_command_message(self):
455+
# gh-152132: same as above, but with a string exit message.
456+
out, err = self.run_embedded_interpreter(
457+
"test_run_main_system_exit_command_message")
458+
self.assertEqual(out, '')
459+
self.assertIn('error message', err)
460+
442461
def test_finalize_structseq(self):
443462
# bpo-46417: Py_Finalize() clears structseq static types. Check that
444463
# sys attributes using struct types still work when

Programs/_testembed.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,50 @@ static int test_run_main_system_exit_file(void)
21122112
}
21132113

21142114

2115+
static int test_run_main_system_exit_module(void)
2116+
{
2117+
// gh-152132: Py_RunMain() must return the SystemExit code instead of
2118+
// calling exit() directly. The module under -m is resolved from PYTHONPATH
2119+
// set by the test harness.
2120+
PyConfig config;
2121+
PyConfig_InitPythonConfig(&config);
2122+
2123+
wchar_t *argv[] = {L"python3", L"-m", L"exit_mod"};
2124+
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
2125+
config_set_string(&config, &config.program_name, L"./python3");
2126+
init_from_config_clear(&config);
2127+
2128+
int exitcode = Py_RunMain();
2129+
if (exitcode != 42) {
2130+
fprintf(stderr, "expected exit code 42, got %d\n", exitcode);
2131+
return 1;
2132+
}
2133+
return 0;
2134+
}
2135+
2136+
2137+
static int test_run_main_system_exit_command_message(void)
2138+
{
2139+
// gh-152132: Py_RunMain() must return the SystemExit code instead of
2140+
// calling exit() directly.
2141+
PyConfig config;
2142+
PyConfig_InitPythonConfig(&config);
2143+
2144+
wchar_t *argv[] = {L"python3", L"-c",
2145+
L"import sys; sys.exit('error message')"};
2146+
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
2147+
config_set_string(&config, &config.program_name, L"./python3");
2148+
init_from_config_clear(&config);
2149+
2150+
int exitcode = Py_RunMain();
2151+
if (exitcode != 1) {
2152+
fprintf(stderr, "expected exit code 1, got %d\n", exitcode);
2153+
return 1;
2154+
}
2155+
return 0;
2156+
}
2157+
2158+
21152159
static int test_get_argc_argv(void)
21162160
{
21172161
PyConfig config;
@@ -3008,6 +3052,8 @@ static struct TestCase TestCases[] = {
30083052
{"test_run_main_loop", test_run_main_loop},
30093053
{"test_run_main_system_exit_command", test_run_main_system_exit_command},
30103054
{"test_run_main_system_exit_file", test_run_main_system_exit_file},
3055+
{"test_run_main_system_exit_module", test_run_main_system_exit_module},
3056+
{"test_run_main_system_exit_command_message", test_run_main_system_exit_command_message},
30113057
{"test_get_argc_argv", test_get_argc_argv},
30123058
{"test_init_use_frozen_modules", test_init_use_frozen_modules},
30133059
{"test_init_main_interpreter_settings", test_init_main_interpreter_settings},

0 commit comments

Comments
 (0)