def test_env_var(self): # not tracing by default code = "import tracemalloc; print(tracemalloc.is_tracing())" ok, stdout, stderr = assert_python_ok("-c", code) stdout = stdout.rstrip() self.assertEqual(stdout, b"False") # PYTHON* environment variables must be ignored when -E option is # present code = "import tracemalloc; print(tracemalloc.is_tracing())" ok, stdout, stderr = assert_python_ok("-E", "-c", code, PYTHONTRACEMALLOC="1") stdout = stdout.rstrip() self.assertEqual(stdout, b"False") # tracing at startup code = "import tracemalloc; print(tracemalloc.is_tracing())" ok, stdout, stderr = assert_python_ok("-c", code, PYTHONTRACEMALLOC="1") stdout = stdout.rstrip() self.assertEqual(stdout, b"True") # start and set the number of frames code = "import tracemalloc; print(tracemalloc.get_traceback_limit())" ok, stdout, stderr = assert_python_ok("-c", code, PYTHONTRACEMALLOC="10") stdout = stdout.rstrip() self.assertEqual(stdout, b"10")
def test_env_var(self): # not tracing by default code = 'import tracemalloc; print(tracemalloc.is_tracing())' ok, stdout, stderr = assert_python_ok('-c', code) stdout = stdout.rstrip() self.assertEqual(stdout, b'False') # PYTHON* environment variables must be ignored when -E option is # present code = 'import tracemalloc; print(tracemalloc.is_tracing())' ok, stdout, stderr = assert_python_ok('-E', '-c', code, PYTHONTRACEMALLOC='1') stdout = stdout.rstrip() self.assertEqual(stdout, b'False') # tracing at startup code = 'import tracemalloc; print(tracemalloc.is_tracing())' ok, stdout, stderr = assert_python_ok('-c', code, PYTHONTRACEMALLOC='1') stdout = stdout.rstrip() self.assertEqual(stdout, b'True') # start and set the number of frames code = 'import tracemalloc; print(tracemalloc.get_traceback_limit())' ok, stdout, stderr = assert_python_ok('-c', code, PYTHONTRACEMALLOC='10') stdout = stdout.rstrip() self.assertEqual(stdout, b'10')
def check_wakeup(self, test_body): # use a subprocess to have only one thread and to not change signal # handling of the parent process code = """if 1: import fcntl import os import signal def handler(signum, frame): pass {} signal.signal(signal.SIGALRM, handler) read, write = os.pipe() flags = fcntl.fcntl(write, fcntl.F_GETFL, 0) flags = flags | os.O_NONBLOCK fcntl.fcntl(write, fcntl.F_SETFL, flags) signal.set_wakeup_fd(write) test() os.close(read) os.close(write) """.format(test_body) assert_python_ok('-c', code)
def test_socket(self): # use a subprocess to have only one thread code = """if 1: import signal import socket import struct import _testcapi signum = signal.SIGINT signals = (signum,) def handler(signum, frame): pass signal.signal(signum, handler) read, write = socket.socketpair() read.setblocking(False) write.setblocking(False) signal.set_wakeup_fd(write.fileno()) _testcapi.raise_signal(signum) data = read.recv(1) if not data: raise Exception("no signum written") raised = struct.unpack('B', data) if raised != signals: raise Exception("%r != %r" % (raised, signals)) read.close() write.close() """ assert_python_ok('-c', code)
def test_assert_python_ok_raises(self): # I didn't import the sys module so this child will fail. 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 was:', error_msg) self.assertIn('sys.exit(0)', error_msg, msg='unexpected command line')
def test_sigwait_thread(self): # Check that calling sigwait() from a thread doesn't suspend the whole # process. A new interpreter is spawned to avoid problems when mixing # threads and fork(): only async-safe functions are allowed between # fork() and exec(). assert_python_ok("-c", """if True: import os, threading, sys, time, signal # the default handler terminates the process signum = signal.SIGUSR1 def kill_later(): # wait until the main thread is waiting in sigwait() time.sleep(1) os.kill(os.getpid(), signum) # the signal must be blocked by all the threads signal.pthread_sigmask(signal.SIG_BLOCK, [signum]) killer = threading.Thread(target=kill_later) killer.start() received = signal.sigwait([signum]) if received != signum: print("sigwait() received %s, not %s" % (received, signum), file=sys.stderr) sys.exit(1) killer.join() # unblock the signal, which should have been cleared by sigwait() signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum]) """)
def test_sigpending(self): code = """if 1: import os import signal def handler(signum, frame): 1/0 signum = signal.SIGUSR1 signal.signal(signum, handler) signal.pthread_sigmask(signal.SIG_BLOCK, [signum]) os.kill(os.getpid(), signum) pending = signal.sigpending() for sig in pending: assert isinstance(sig, signal.Signals), repr(pending) if pending != {signum}: raise Exception('%s != {%s}' % (pending, signum)) try: signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum]) except ZeroDivisionError: pass else: raise Exception("ZeroDivisionError not raised") """ assert_python_ok('-c', code)
def test_hash_randomization(self): # Verify that -R enables hash randomization: self.verify_valid_flag('-R') hashes = [] if os.environ.get('PYTHONHASHSEED', 'random') != 'random': env = dict(os.environ) # copy # We need to test that it is enabled by default without # the environment variable enabling it for us. del env['PYTHONHASHSEED'] env['__cleanenv'] = '1' # consumed by assert_python_ok() else: env = {} for i in range(3): code = 'print(hash("spam"))' rc, out, err = assert_python_ok('-c', code, **env) self.assertEqual(rc, 0) hashes.append(out) hashes = sorted(set(hashes)) # uniq # Rare chance of failure due to 3 random seeds honestly being equal. self.assertGreater(len(hashes), 1, msg='3 runs produced an identical random hash ' ' for "spam": {}'.format(hashes)) # Verify that sys.flags contains hash_randomization code = 'import sys; print("random is", sys.flags.hash_randomization)' rc, out, err = assert_python_ok('-c', code) self.assertEqual(rc, 0) self.assertIn(b'random is 1', out)
def test_pthread_kill(self): code = """if 1: import signal import threading import sys signum = signal.SIGUSR1 def handler(signum, frame): 1/0 signal.signal(signum, handler) if sys.platform == 'freebsd6': # Issue #12392 and #12469: send a signal to the main thread # doesn't work before the creation of the first thread on # FreeBSD 6 def noop(): pass thread = threading.Thread(target=noop) thread.start() thread.join() tid = threading.get_ident() try: signal.pthread_kill(tid, signum) except ZeroDivisionError: pass else: raise Exception("ZeroDivisionError not raised") """ assert_python_ok('-c', code)
def test_doctest_main_issue4197(self): test_src = textwrap.dedent("""\ class Test: ">>> 'line 2'" pass import doctest doctest.testmod() """) pattern = 'File "%s", line 2, in %s' with temp_dir() as d: script_name = make_script(d, 'script', test_src) rc, out, err = assert_python_ok(script_name) expected = pattern % (script_name, "__main__.Test") if verbose: print ("Expected line", expected) print ("Got stdout:") print (ascii(out)) self.assertIn(expected.encode('utf-8'), out) zip_name, run_name = make_zip_script(d, "test_zip", script_name, '__main__.py') rc, out, err = assert_python_ok(zip_name) expected = pattern % (run_name, "__main__.Test") if verbose: print ("Expected line", expected) print ("Got stdout:") print (ascii(out)) self.assertIn(expected.encode('utf-8'), out)
def test_finalize_with_trace(self): # Issue1733757 # Avoid a deadlock when sys.settrace steps into threading._shutdown assert_python_ok( "-c", """if 1: import sys, threading # A deadlock-killer, to prevent the # testsuite to hang forever def killer(): import os, time time.sleep(2) print('program blocked; aborting') os._exit(2) t = threading.Thread(target=killer) t.daemon = True t.start() # This is the trace function def func(frame, event, arg): threading.current_thread() return func sys.settrace(func) """, )
def test_unencodable_filename(self): # Issue #11619: The Python parser and the import machinery must not # encode filenames, especially on Windows pyname = script_helper.make_script('', TESTFN_UNENCODABLE, 'pass') name = pyname[:-3] script_helper.assert_python_ok("-c", "mod = __import__(%a)" % name, __isolated=False)
def test_build_ext(self): support.copy_xxmodule_c(self.tmp_dir) xx_c = os.path.join(self.tmp_dir, 'xxmodule.c') xx_ext = Extension('xx', [xx_c]) dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]}) dist.package_dir = self.tmp_dir cmd = build_ext(dist) support.fixup_build_ext(cmd) cmd.build_lib = self.tmp_dir cmd.build_temp = self.tmp_dir cmd.ensure_finalized() cmd.run() code = textwrap.dedent("""\ import sys sys.path.insert(0, %r) import xx for attr in ('error', 'foo', 'new', 'roj'): assert hasattr(xx, attr) assert xx.foo(2, 5) == 7 assert xx.foo(13, 15) == 28 assert xx.new().demo() is None doc = 'This is a template module just for instruction.' assert xx.__doc__ == doc assert isinstance(xx.Null(), xx.Null) assert isinstance(xx.Str(), xx.Str) """) code = code % self.tmp_dir assert_python_ok('-c', code)
def test_verbose(self): # -v causes imports to write to stderr. If the write to # stderr itself causes an import to happen (for the output # codec), a recursion loop can occur. rc, out, err = assert_python_ok('-v') self.assertNotIn(b'stack overflow', err) rc, out, err = assert_python_ok('-vv') self.assertNotIn(b'stack overflow', err)
def test_xoptions(self): rc, out, err = assert_python_ok('-c', 'import sys; print(sys._xoptions)') opts = eval(out.splitlines()[0]) self.assertEqual(opts, {}) rc, out, err = assert_python_ok( '-Xa', '-Xb=c,d=e', '-c', 'import sys; print(sys._xoptions)') opts = eval(out.splitlines()[0]) self.assertEqual(opts, {'a': True, 'b': 'c,d=e'})
def test_run_code(self): # Test expected operation of the '-c' switch # Switch needs an argument assert_python_failure('-c') # Check we get an error for an uncaught exception assert_python_failure('-c', 'raise Exception') # All good if execution is successful assert_python_ok('-c', 'pass')
def test_non_ascii(self): # Test handling of non-ascii data if test.support.verbose: import locale print('locale encoding = %s, filesystem encoding = %s' % (locale.getpreferredencoding(), sys.getfilesystemencoding())) command = "assert(ord('\xe9') == 0xe9)" assert_python_ok('-c', command)
def test_del___main__(self): # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a # borrowed reference to the dict of __main__ module and later modify # the dict whereas the module was destroyed filename = test.support.TESTFN self.addCleanup(test.support.unlink, filename) with open(filename, "w") as script: print("import sys", file=script) print("del sys.modules['__main__']", file=script) assert_python_ok(filename)
def test_issue_8766(self): # "import encodings" emits a warning whereas the warnings is not loaded # or not completely loaded (warnings imports indirectly encodings by # importing linecache) yet with support.temp_cwd() as cwd, support.temp_cwd('encodings'): # encodings loaded by initfsencoding() assert_python_ok('-c', 'pass', PYTHONPATH=cwd) # Use -W to load warnings module at startup assert_python_ok('-c', 'pass', '-W', 'always', PYTHONPATH=cwd)
def f(self, ext=ext, switch=switch): script_helper.assert_python_ok(*(switch + ["-m", "compileall", "-q", self.pkgdir])) # Verify the __pycache__ directory contents. self.assertTrue(os.path.exists(self.pkgdir_cachedir)) expected = sorted( base.format(sys.implementation.cache_tag, ext) for base in ("__init__.{}.{}", "bar.{}.{}") ) self.assertEqual(sorted(os.listdir(self.pkgdir_cachedir)), expected) # Make sure there are no .pyc files in the source directory. self.assertFalse([fn for fn in os.listdir(self.pkgdir) if fn.endswith(ext)])
def test_import_in_del_does_not_crash(self): # Issue 4236 testfn = script_helper.make_script('', TESTFN, textwrap.dedent("""\ import sys class C: def __del__(self): import imp sys.argv.insert(0, C()) """)) script_helper.assert_python_ok(testfn)
def f(self, ext=ext, switch=switch): script_helper.assert_python_ok(*(switch + ['-m', 'compileall', '-q', self.pkgdir])) # Verify the __pycache__ directory contents. self.assertTrue(os.path.exists(self.pkgdir_cachedir)) expected = sorted(base.format(imp.get_tag(), ext) for base in ('__init__.{}.{}', 'bar.{}.{}')) self.assertEqual(sorted(os.listdir(self.pkgdir_cachedir)), expected) # Make sure there are no .pyc files in the source directory. self.assertFalse([fn for fn in os.listdir(self.pkgdir) if fn.endswith(ext)])
def test_run_module(self): # Test expected operation of the '-m' switch # Switch needs an argument assert_python_failure('-m') # Check we get an error for a nonexistent module assert_python_failure('-m', 'fnord43520xyz') # Check the runpy module also gives an error for # a nonexistent module assert_python_failure('-m', 'runpy', 'fnord43520xyz'), # All good if module is located and run successfully assert_python_ok('-m', 'timeit', '-n', '1'),
def test_wakeup_write_error(self): # Issue #16105: write() errors in the C signal handler should not # pass silently. # Use a subprocess to have only one thread. code = """if 1: import _testcapi import errno import fcntl import os import signal import sys from test.support import captured_stderr def handler(signum, frame): 1/0 signal.signal(signal.SIGALRM, handler) r, w = os.pipe() flags = fcntl.fcntl(r, fcntl.F_GETFL, 0) fcntl.fcntl(r, fcntl.F_SETFL, flags | os.O_NONBLOCK) # Set wakeup_fd a read-only file descriptor to trigger the error signal.set_wakeup_fd(r) try: with captured_stderr() as err: _testcapi.raise_signal(signal.SIGALRM) except ZeroDivisionError: # An ignored exception should have been printed out on stderr err = err.getvalue() if ('Exception ignored when trying to write to the signal wakeup fd' not in err): raise AssertionError(err) if ('OSError: [Errno %d]' % errno.EBADF) not in err: raise AssertionError(err) else: raise AssertionError("ZeroDivisionError not raised") os.close(r) os.close(w) """ r, w = os.pipe() try: os.write(r, b'x') except OSError: pass else: self.skipTest("OS doesn't report write() error on the read end of a pipe") finally: os.close(r) os.close(w) assert_python_ok('-c', code)
def test_empty_PYTHONPATH_issue16309(self): # On Posix, it is documented that setting PATH to the # empty string is equivalent to not setting PATH at all, # which is an exception to the rule that in a string like # "/bin::/usr/bin" the empty string in the middle gets # interpreted as '.' code = """if 1: import sys path = ":".join(sys.path) path = path.encode("ascii", "backslashreplace") sys.stdout.buffer.write(path)""" rc1, out1, err1 = assert_python_ok('-c', code, PYTHONPATH="") rc2, out2, err2 = assert_python_ok('-c', code, __isolated=False) # regarding to Posix specification, outputs should be equal # for empty and unset PYTHONPATH self.assertEqual(out1, out2)
def test_debugmallocstats(self): # Test sys._debugmallocstats() from test.script_helper import assert_python_ok args = ["-c", "import sys; sys._debugmallocstats()"] ret, out, err = assert_python_ok(*args) self.assertIn(b"free PyDictObjects", err)
def test_dummy_thread_after_fork(self): # Issue #14308: a dummy thread in the active list doesn't mess up # the after-fork mechanism. code = """if 1: import _thread, threading, os, time def background_thread(evt): # Creates and registers the _DummyThread instance threading.current_thread() evt.set() time.sleep(10) evt = threading.Event() _thread.start_new_thread(background_thread, (evt,)) evt.wait() assert threading.active_count() == 2, threading.active_count() if os.fork() == 0: assert threading.active_count() == 1, threading.active_count() os._exit(0) else: os.wait() """ _, out, err = assert_python_ok("-c", code) self.assertEqual(out, b"") self.assertEqual(err, b"")
def test_hash_randomization(self): # Verify that -R enables hash randomization: self.verify_valid_flag('-R') hashes = [] for i in range(2): code = 'print(hash("spam"))' rc, out, err = assert_python_ok('-R', '-c', code) self.assertEqual(rc, 0) hashes.append(out) self.assertNotEqual(hashes[0], hashes[1]) # Verify that sys.flags contains hash_randomization code = 'import sys; print("random is", sys.flags.hash_randomization)' rc, out, err = assert_python_ok('-R', '-c', code) self.assertEqual(rc, 0) self.assertIn(b'random is 1', out)
def test_print_exception_stderr_is_none_1(self): script = r"""if 1: import sys import threading import time running = False def run(): global running running = True while running: time.sleep(0.01) 1.0/0.0 t = threading.Thread(target=run) t.start() while not running: time.sleep(0.01) sys.stderr = None running = False t.join() """ rc, out, err = assert_python_ok("-c", script) self.assertEqual(out, '') self.assertIn("Exception in thread", err) self.assertIn("Traceback (most recent call last):", err) self.assertIn("ZeroDivisionError", err) self.assertNotIn("Unhandled exception", err)
def test_unbuffered_output(self): # Test expected operation of the '-u' switch for stream in ('stdout', 'stderr'): # Binary is unbuffered code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)" % stream) rc, out, err = assert_python_ok('-u', '-c', code) data = err if stream == 'stderr' else out self.assertEqual(data, b'x', "binary %s not unbuffered" % stream) # Text is line-buffered code = ("import os, sys; sys.%s.write('x\\n'); os._exit(0)" % stream) rc, out, err = assert_python_ok('-u', '-c', code) data = err if stream == 'stderr' else out self.assertEqual(data.strip(), b'x', "text %s not line-buffered" % stream)
def assertRunOK(self, *args, **env_vars): rc, out, err = script_helper.assert_python_ok('-S', '-m', 'compileall', *args, **env_vars) self.assertEqual(b'', err) return out
def test_help(self): rc, out, err = assert_python_ok(self.script, '-h') self.assertEqual(out, b'') self.assertGreater(err, b'')
def verify_valid_flag(self, cmd_line): rc, out, err = assert_python_ok(*cmd_line) self.assertTrue(out == b'' or out.endswith(b'\n')) self.assertNotIn(b'Traceback', out) self.assertNotIn(b'Traceback', err)
def test_closed_stdout(self): # Issue #13444: if stdout has been explicitly closed, we should # not attempt to flush it at shutdown. code = "import sys; sys.stdout.close()" rc, out, err = assert_python_ok('-c', code) self.assertEqual(b'', err)
def test_usage(self): rc, out, err = assert_python_ok('-h') self.assertIn(b'usage', out)
def test_version(self): version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii") rc, out, err = assert_python_ok('-V') self.assertTrue(err.startswith(version))
def test_exit(self): # call with two arguments self.assertRaises(TypeError, sys.exit, 42, 42) # call without argument with self.assertRaises(SystemExit) as cm: sys.exit() self.assertIsNone(cm.exception.code) rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') self.assertEqual(rc, 0) self.assertEqual(out, b'') self.assertEqual(err, b'') # call with integer argument with self.assertRaises(SystemExit) as cm: sys.exit(42) self.assertEqual(cm.exception.code, 42) # call with tuple argument with one entry # entry will be unpacked with self.assertRaises(SystemExit) as cm: sys.exit((42, )) self.assertEqual(cm.exception.code, 42) # call with string argument with self.assertRaises(SystemExit) as cm: sys.exit("exit") self.assertEqual(cm.exception.code, "exit") # call with tuple argument with two entries with self.assertRaises(SystemExit) as cm: sys.exit((17, 23)) self.assertEqual(cm.exception.code, (17, 23)) # test that the exit machinery handles SystemExits properly rc, out, err = assert_python_failure('-c', 'raise SystemExit(47)') self.assertEqual(rc, 47) self.assertEqual(out, b'') self.assertEqual(err, b'') def check_exit_message(code, expected, **env_vars): rc, out, err = assert_python_failure('-c', code, **env_vars) self.assertEqual(rc, 1) self.assertEqual(out, b'') self.assertTrue( err.startswith(expected), "%s doesn't start with %s" % (ascii(err), ascii(expected))) # test that stderr buffer is flushed before the exit message is written # into stderr check_exit_message( r'import sys; sys.stderr.write("unflushed,"); sys.exit("message")', b"unflushed,message") # test that the exit message is written with backslashreplace error # handler to stderr check_exit_message(r'import sys; sys.exit("surrogates:\uDCFF")', b"surrogates:\\udcff") # test that the unicode message is encoded to the stderr encoding # instead of the default encoding (utf8) check_exit_message(r'import sys; sys.exit("h\xe9")', b"h\xe9", PYTHONIOENCODING='latin-1')
def _check_script(self, script_name, *cmd_line_switches): if not __debug__: cmd_line_switches += ('-' + 'O' * sys.flags.optimize,) run_args = cmd_line_switches + (script_name, self.start_method) rc, out, err = assert_python_ok(*run_args, __isolated=False) self._check_output(script_name, rc, out, err)
def test_improper_option(self): # Same as above, but check that the message is printed out when # the interpreter is executed. This also checks that options are # actually parsed at all. rc, out, err = assert_python_ok("-Wxxx", "-c", "pass") self.assertIn(b"Invalid -W option ignored: invalid action: 'xxx'", err)
def test_noargs(self): assert_python_ok(self.script)