unittests for test support scripthelper who tests the test helper import subprocess import sys import os from test support import scripthelper requiressubprocess import unittest from unittest import mock class testscripthelperunittest testcase def testassertpythonokself t scripthelper assertpythonok c import sys sys exit0 self assertequal0 t0 return code was not 0 def testassertpythonfailureself i didn t import the sys module so this child will fail rc out err scripthelper assertpythonfailure c sys exit0 self assertnotequal0 rc return code should not be 0 def testassertpythonokraisesself i didn t import the sys module so this child will fail with self assertraisesassertionerror as errorcontext scripthelper assertpythonok c sys exit0 errormsg strerrorcontext exception self assertin command line errormsg self assertin sys exit0 errormsg msg unexpected command line def testassertpythonfailureraisesself with self assertraisesassertionerror as errorcontext scripthelper assertpythonfailure c import sys sys exit0 errormsg strerrorcontext exception self assertin process return code is 0n errormsg self assertin import sys sys exit0 errormsg msg unexpected command line mock patch subprocess popen def testassertpythonisolatedwhenenvnotrequiredself mockpopen with mock patch objectscripthelper interpreterrequiresenvironment returnvaluefalse as mockirefunc mockpopen sideeffect runtimeerror bail out of unittest try scripthelper assertpythontrue c none except runtimeerror as err self assertequal bail out of unittest err args0 self assertequal1 mockpopen callcount self assertequal1 mockirefunc callcount popencommand mockpopen callargs00 self assertequalsys executable popencommand0 self assertin none popencommand self assertin i popencommand self assertnotin e popencommand i overrides this mock patch subprocess popen def testassertpythonnotisolatedwhenenvisrequiredself mockpopen code coverage for interpreterrequiresenvironment def setupself self asserttrue hasattrscripthelper cachedinterprequiresenvironment reset the private cached state scripthelper dict cachedinterprequiresenvironment none def teardownself reset the private cached state scripthelper dict cachedinterprequiresenvironment none mock patch subprocess checkcall def testinterpreterrequiresenvironmenttrueself mockcheckcall with mock patch dictos environ os environ pop pythonhome none mockcheckcall sideeffect subprocess calledprocesserror self asserttruescripthelper interpreterrequiresenvironment self asserttruescripthelper interpreterrequiresenvironment self assertequal1 mockcheckcall callcount mock patch subprocess checkcall def testinterpreterrequiresenvironmentfalseself mockcheckcall with mock patch dictos environ os environ pop pythonhome none the mocked subprocess checkcall fakes a noerror process scripthelper interpreterrequiresenvironment self assertfalsescripthelper interpreterrequiresenvironment self assertequal1 mockcheckcall callcount mock patch subprocess checkcall def testinterpreterrequiresenvironmentdetailsself mockcheckcall with mock patch dictos environ os environ pop pythonhome none scripthelper interpreterrequiresenvironment self assertfalsescripthelper interpreterrequiresenvironment self assertfalsescripthelper interpreterrequiresenvironment self assertequal1 mockcheckcall callcount checkcallcommand mockcheckcall callargs00 self assertequalsys executable checkcallcommand0 self assertin e checkcallcommand mock patch subprocess checkcall def testinterpreterrequiresenvironmentwithpythonhomeself mockcheckcall with mock patch dictos environ os environ pythonhome mockedhome self asserttruescripthelper interpreterrequiresenvironment self asserttruescripthelper interpreterrequiresenvironment self assertequal0 mockcheckcall callcount if name main unittest main i didn t import the sys module so this child will fail i didn t import the sys module so this child will fail i overrides this ensure that i is not passed when the environment is required code coverage for interpreter_requires_environment reset the private cached state reset the private cached state the mocked subprocess check_call fakes a no error process
import subprocess
import sys
import os
from test.support import script_helper, requires_subprocess
import unittest
from unittest import mock


class TestScriptHelper(unittest.TestCase):

    def test_assert_python_ok(self):
        t = script_helper.assert_python_ok('-c', 'import sys; sys.exit(0)')
        self.assertEqual(0, t[0], 'return code was not 0')

    def test_assert_python_failure(self):
        
        rc, out, err = script_helper.assert_python_failure('-c', 'sys.exit(0)')
        self.assertNotEqual(0, rc, 'return code should not be 0')

    def test_assert_python_ok_raises(self):
        
        with self.assertRaises(AssertionError) as error_context:
            script_helper.assert_python_ok('-c', 'sys.exit(0)')
        error_msg = str(error_context.exception)
        self.assertIn('command line:', error_msg)
        self.assertIn('sys.exit(0)', error_msg, msg='unexpected command line')

    def test_assert_python_failure_raises(self):
        with self.assertRaises(AssertionError) as error_context:
            script_helper.assert_python_failure('-c', 'import sys; sys.exit(0)')
        error_msg = str(error_context.exception)
        self.assertIn('Process return code is 0\n', error_msg)
        self.assertIn('import sys; sys.exit(0)', error_msg,
                      msg='unexpected command line.')

    @mock.patch('subprocess.Popen')
    def test_assert_python_isolated_when_env_not_required(self, mock_popen):
        with mock.patch.object(script_helper,
                               'interpreter_requires_environment',
                               return_value=False) as mock_ire_func:
            mock_popen.side_effect = RuntimeError('bail out of unittest')
            try:
                script_helper._assert_python(True, '-c', 'None')
            except RuntimeError as err:
                self.assertEqual('bail out of unittest', err.args[0])
            self.assertEqual(1, mock_popen.call_count)
            self.assertEqual(1, mock_ire_func.call_count)
            popen_command = mock_popen.call_args[0][0]
            self.assertEqual(sys.executable, popen_command[0])
            self.assertIn('None', popen_command)
            self.assertIn('-I', popen_command)
            self.assertNotIn('-E', popen_command)  

    @mock.patch('subprocess.Popen')
    def test_assert_python_not_isolated_when_env_is_required(self, mock_popen):
        
        with mock.patch.object(script_helper,
                               'interpreter_requires_environment',
                               return_value=True) as mock_ire_func:
            mock_popen.side_effect = RuntimeError('bail out of unittest')
            try:
                script_helper._assert_python(True, '-c', 'None')
            except RuntimeError as err:
                self.assertEqual('bail out of unittest', err.args[0])
            popen_command = mock_popen.call_args[0][0]
            self.assertNotIn('-I', popen_command)
            self.assertNotIn('-E', popen_command)


@requires_subprocess()
class TestScriptHelperEnvironment(unittest.TestCase):
    

    def setUp(self):
        self.assertTrue(
            hasattr(script_helper, '__cached_interp_requires_environment'))
        
        script_helper.__dict__['__cached_interp_requires_environment'] = None

    def tearDown(self):
        
        script_helper.__dict__['__cached_interp_requires_environment'] = None

    @mock.patch('subprocess.check_call')
    def test_interpreter_requires_environment_true(self, mock_check_call):
        with mock.patch.dict(os.environ):
            os.environ.pop('PYTHONHOME', None)
            mock_check_call.side_effect = subprocess.CalledProcessError('', '')
            self.assertTrue(script_helper.interpreter_requires_environment())
            self.assertTrue(script_helper.interpreter_requires_environment())
            self.assertEqual(1, mock_check_call.call_count)

    @mock.patch('subprocess.check_call')
    def test_interpreter_requires_environment_false(self, mock_check_call):
        with mock.patch.dict(os.environ):
            os.environ.pop('PYTHONHOME', None)
            
            script_helper.interpreter_requires_environment()
            self.assertFalse(script_helper.interpreter_requires_environment())
            self.assertEqual(1, mock_check_call.call_count)

    @mock.patch('subprocess.check_call')
    def test_interpreter_requires_environment_details(self, mock_check_call):
        with mock.patch.dict(os.environ):
            os.environ.pop('PYTHONHOME', None)
            script_helper.interpreter_requires_environment()
            self.assertFalse(script_helper.interpreter_requires_environment())
            self.assertFalse(script_helper.interpreter_requires_environment())
            self.assertEqual(1, mock_check_call.call_count)
            check_call_command = mock_check_call.call_args[0][0]
            self.assertEqual(sys.executable, check_call_command[0])
            self.assertIn('-E', check_call_command)

    @mock.patch('subprocess.check_call')
    def test_interpreter_requires_environment_with_pythonhome(self, mock_check_call):
        with mock.patch.dict(os.environ):
            os.environ['PYTHONHOME'] = 'MockedHome'
            self.assertTrue(script_helper.interpreter_requires_environment())
            self.assertTrue(script_helper.interpreter_requires_environment())
            self.assertEqual(0, mock_check_call.call_count)


if __name__ == '__main__':
    unittest.main()