1"""Unittests for test.support.script_helper. Who tests the test helper?""" 2 3import subprocess 4import sys 5import os 6from test.support import script_helper, requires_subprocess 7import unittest 8from unittest import mock 9 10 11class TestScriptHelper(unittest.TestCase): 12 13 def test_assert_python_ok(self): 14 t = script_helper.assert_python_ok('-c', 'import sys; sys.exit(0)') 15 self.assertEqual(0, t[0], 'return code was not 0') 16 17 def test_assert_python_failure(self): 18 # I didn't import the sys module so this child will fail. 19 rc, out, err = script_helper.assert_python_failure('-c', 'sys.exit(0)') 20 self.assertNotEqual(0, rc, 'return code should not be 0') 21 22 def test_assert_python_ok_raises(self): 23 # I didn't import the sys module so this child will fail. 24 with self.assertRaises(AssertionError) as error_context: 25 script_helper.assert_python_ok('-c', 'sys.exit(0)') 26 error_msg = str(error_context.exception) 27 self.assertIn('command line:', error_msg) 28 self.assertIn('sys.exit(0)', error_msg, msg='unexpected command line') 29 30 def test_assert_python_failure_raises(self): 31 with self.assertRaises(AssertionError) as error_context: 32 script_helper.assert_python_failure('-c', 'import sys; sys.exit(0)') 33 error_msg = str(error_context.exception) 34 self.assertIn('Process return code is 0\n', error_msg) 35 self.assertIn('import sys; sys.exit(0)', error_msg, 36 msg='unexpected command line.') 37 38 @mock.patch('subprocess.Popen') 39 def test_assert_python_isolated_when_env_not_required(self, mock_popen): 40 with mock.patch.object(script_helper, 41 'interpreter_requires_environment', 42 return_value=False) as mock_ire_func: 43 mock_popen.side_effect = RuntimeError('bail out of unittest') 44 try: 45 script_helper._assert_python(True, '-c', 'None') 46 except RuntimeError as err: 47 self.assertEqual('bail out of unittest', err.args[0]) 48 self.assertEqual(1, mock_popen.call_count) 49 self.assertEqual(1, mock_ire_func.call_count) 50 popen_command = mock_popen.call_args[0][0] 51 self.assertEqual(sys.executable, popen_command[0]) 52 self.assertIn('None', popen_command) 53 self.assertIn('-I', popen_command) 54 self.assertNotIn('-E', popen_command) # -I overrides this 55 56 @mock.patch('subprocess.Popen') 57 def test_assert_python_not_isolated_when_env_is_required(self, mock_popen): 58 """Ensure that -I is not passed when the environment is required.""" 59 with mock.patch.object(script_helper, 60 'interpreter_requires_environment', 61 return_value=True) as mock_ire_func: 62 mock_popen.side_effect = RuntimeError('bail out of unittest') 63 try: 64 script_helper._assert_python(True, '-c', 'None') 65 except RuntimeError as err: 66 self.assertEqual('bail out of unittest', err.args[0]) 67 popen_command = mock_popen.call_args[0][0] 68 self.assertNotIn('-I', popen_command) 69 self.assertNotIn('-E', popen_command) 70 71 72@requires_subprocess() 73class TestScriptHelperEnvironment(unittest.TestCase): 74 """Code coverage for interpreter_requires_environment().""" 75 76 def setUp(self): 77 self.assertTrue( 78 hasattr(script_helper, '__cached_interp_requires_environment')) 79 # Reset the private cached state. 80 script_helper.__dict__['__cached_interp_requires_environment'] = None 81 82 def tearDown(self): 83 # Reset the private cached state. 84 script_helper.__dict__['__cached_interp_requires_environment'] = None 85 86 @mock.patch('subprocess.check_call') 87 def test_interpreter_requires_environment_true(self, mock_check_call): 88 with mock.patch.dict(os.environ): 89 os.environ.pop('PYTHONHOME', None) 90 mock_check_call.side_effect = subprocess.CalledProcessError('', '') 91 self.assertTrue(script_helper.interpreter_requires_environment()) 92 self.assertTrue(script_helper.interpreter_requires_environment()) 93 self.assertEqual(1, mock_check_call.call_count) 94 95 @mock.patch('subprocess.check_call') 96 def test_interpreter_requires_environment_false(self, mock_check_call): 97 with mock.patch.dict(os.environ): 98 os.environ.pop('PYTHONHOME', None) 99 # The mocked subprocess.check_call fakes a no-error process. 100 script_helper.interpreter_requires_environment() 101 self.assertFalse(script_helper.interpreter_requires_environment()) 102 self.assertEqual(1, mock_check_call.call_count) 103 104 @mock.patch('subprocess.check_call') 105 def test_interpreter_requires_environment_details(self, mock_check_call): 106 with mock.patch.dict(os.environ): 107 os.environ.pop('PYTHONHOME', None) 108 script_helper.interpreter_requires_environment() 109 self.assertFalse(script_helper.interpreter_requires_environment()) 110 self.assertFalse(script_helper.interpreter_requires_environment()) 111 self.assertEqual(1, mock_check_call.call_count) 112 check_call_command = mock_check_call.call_args[0][0] 113 self.assertEqual(sys.executable, check_call_command[0]) 114 self.assertIn('-E', check_call_command) 115 116 @mock.patch('subprocess.check_call') 117 def test_interpreter_requires_environment_with_pythonhome(self, mock_check_call): 118 with mock.patch.dict(os.environ): 119 os.environ['PYTHONHOME'] = 'MockedHome' 120 self.assertTrue(script_helper.interpreter_requires_environment()) 121 self.assertTrue(script_helper.interpreter_requires_environment()) 122 self.assertEqual(0, mock_check_call.call_count) 123 124 125if __name__ == '__main__': 126 unittest.main() 127