this repo has no description
at trunk 425 lines 17 kB view raw
1#!/usr/bin/env python3 2# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 3import os 4import subprocess 5import sys 6import unittest 7import zipfile 8from tempfile import TemporaryDirectory 9 10 11def with_pty(command): 12 return [sys.executable, '-c', 'import pty, sys; pty.spawn(sys.argv[1:])'] + command 13 14 15class OptionsTest(unittest.TestCase): 16 def test_I_option_sets_isolated_no_user_site_ignore_environment_flags(self): 17 result = subprocess.run( 18 [sys.executable, "-I", "-c", "import sys;print(sys.flags)"], 19 check=True, 20 capture_output=True, 21 ) 22 self.assertIn(b"isolated=1", result.stdout) 23 self.assertIn(b"ignore_environment=1", result.stdout) 24 self.assertIn(b"no_user_site=1", result.stdout) 25 26 def test_O_option_increments_optimize_flag(self): 27 result = subprocess.run( 28 [sys.executable, "-OO", "-OOO", "-c", "import sys;print(sys.flags)"], 29 check=True, 30 capture_output=True, 31 ) 32 self.assertIn(b"optimize=5", result.stdout) 33 34 def test_B_option_sets_dont_write_bytecode_flag(self): 35 result = subprocess.run( 36 [sys.executable, "-B", "-c", "import sys;print(sys.flags)"], 37 check=True, 38 capture_output=True, 39 ) 40 self.assertIn(b"dont_write_bytecode=1", result.stdout) 41 42 def test_PYTHONHASHSEED_sets_fixed_seed(self): 43 env = dict(os.environ) 44 env["PYTHONHASHSEED"] = "0" 45 code = "print(hash('abcdefghijkl'));import sys;print(sys.flags)" 46 result0 = subprocess.run( 47 [sys.executable, "-c", code], check=True, capture_output=True, env=env 48 ) 49 result1 = subprocess.run( 50 [sys.executable, "-c", code], check=True, capture_output=True, env=env 51 ) 52 self.assertEqual(result0.stdout, result1.stdout) 53 self.assertIn(b"hash_randomization=0", result0.stdout) 54 55 def test_PYTHONHASHSEED_sets_random_seed(self): 56 env = dict(os.environ) 57 env["PYTHONHASHSEED"] = "random" 58 code = "print(hash('abcdefghijkl'));import sys;print(sys.flags)" 59 result0 = subprocess.run( 60 [sys.executable, "-c", code], check=True, capture_output=True, env=env 61 ) 62 result1 = subprocess.run( 63 [sys.executable, "-c", code], check=True, capture_output=True, env=env 64 ) 65 self.assertNotEqual(result0.stdout, result1.stdout) 66 self.assertIn(b"hash_randomization=1", result0.stdout) 67 68 def test_PYTHONHASHSEED_unset_sets_random_seed(self): 69 code = "print(hash('abcdefghijkl'));import sys;print(sys.flags)" 70 result0 = subprocess.run( 71 [sys.executable, "-c", code], check=True, capture_output=True 72 ) 73 result1 = subprocess.run( 74 [sys.executable, "-c", code], check=True, capture_output=True 75 ) 76 self.assertNotEqual(result0.stdout, result1.stdout) 77 self.assertIn(b"hash_randomization=1", result0.stdout) 78 79 def test_PYTHONPATH_sets_sys_path(self): 80 with TemporaryDirectory() as tempdir: 81 path0 = os.path.abspath(os.path.join(tempdir, "foo")) 82 path1 = os.path.abspath(os.path.join(tempdir, "bar")) 83 env = dict(os.environ) 84 env["PYTHONPATH"] = f"{path0}:{path1}" 85 code = "import sys;print('sys.path: ' + str(sys.path))" 86 result = subprocess.run( 87 [sys.executable, "-c", code], 88 check=True, 89 capture_output=True, 90 env=env, 91 encoding="utf-8", 92 ) 93 self.assertIn(f"sys.path: ['', '{path0}', '{path1}'", result.stdout) 94 95 def test_PYTHONPYCACHEPREFIX_sets_sys_pycache_prefix(self): 96 with TemporaryDirectory() as tempdir: 97 path = os.path.abspath(os.path.join(tempdir, "foo")) 98 env = dict(os.environ) 99 env["PYTHONPYCACHEPREFIX"] = path 100 code = "import sys;print(f'pycache_prefix: {sys.pycache_prefix}')" 101 result = subprocess.run( 102 [sys.executable, "-c", code], 103 check=True, 104 capture_output=True, 105 env=env, 106 encoding="utf-8", 107 ) 108 self.assertIn(f"pycache_prefix: {path}", result.stdout) 109 110 def test_PYTHONWARNINGS_adds_warnoptions(self): 111 env = dict(os.environ) 112 env["PYTHONWARNINGS"] = "foo,bar" 113 code = "import sys;print('warnoptions: ' + str(sys.warnoptions))" 114 result = subprocess.run( 115 [sys.executable, "-W", "baz", "-W", "bam", "-c", code], 116 check=True, 117 capture_output=True, 118 env=env, 119 ) 120 self.assertIn(b"warnoptions: ['foo', 'bar', 'baz', 'bam']", result.stdout) 121 122 def test_S_option_sets_no_site_flag(self): 123 result = subprocess.run( 124 [sys.executable, "-S", "-c", "import sys;print(sys.flags)"], 125 check=True, 126 capture_output=True, 127 ) 128 self.assertIn(b"no_site=1", result.stdout) 129 130 def test_E_option_sets_ignore_environment_flag(self): 131 result = subprocess.run( 132 [sys.executable, "-E", "-c", "import sys;print(sys.flags)"], 133 check=True, 134 capture_output=True, 135 ) 136 self.assertIn(b"ignore_environment=1", result.stdout) 137 138 def test_V_option_prints_version(self): 139 result = subprocess.run( 140 [sys.executable, "-V"], check=True, capture_output=True, encoding="utf-8" 141 ) 142 version = sys.version_info 143 self.assertIn( 144 f"Python {version.major}.{version.minor}.{version.micro}", result.stdout 145 ) 146 147 def test_W_option_adds_warnoptions(self): 148 env = dict(os.environ) 149 code = "import sys;print('warnoptions: ' + str(sys.warnoptions))" 150 result = subprocess.run( 151 [sys.executable, "-W", "foo", "-W", "ba,r", "-c", code], 152 check=True, 153 capture_output=True, 154 env=env, 155 ) 156 self.assertIn(b"warnoptions: ['foo', 'ba,r']", result.stdout) 157 158 def test_c_option_runs_python_code(self): 159 result = subprocess.run( 160 [sys.executable, "-c", "print('test_c_op' + 'tion ok')"], 161 check=True, 162 capture_output=True, 163 ) 164 self.assertIn(b"test_c_option ok", result.stdout) 165 self.assertNotIn(b">>>", result.stderr) 166 167 def test_c_option_flushes_stderr_on_finalize(self): 168 result = subprocess.run( 169 [sys.executable, "-c", "import sys; sys.stderr.write('1;2;3')"], 170 check=True, 171 capture_output=True, 172 ) 173 self.assertIn(b"1;2;3", result.stderr) 174 175 def test_c_option_flushes_stdout_on_finalize(self): 176 result = subprocess.run( 177 [sys.executable, "-c", "import sys; sys.stdout.write('1;2;3')"], 178 check=True, 179 capture_output=True, 180 ) 181 self.assertIn(b"1;2;3", result.stdout) 182 183 def test_c_option_flushes_stdout_afer_sys_exit_call_on_finalize(self): 184 result = subprocess.run( 185 [sys.executable, "-c", "import sys; sys.stdout.write('1;2;3'); sys.exit()"], 186 check=True, 187 capture_output=True, 188 ) 189 self.assertIn(b"1;2;3", result.stdout) 190 191 def test_t_option_noop(self): 192 result = subprocess.run( 193 [sys.executable, "-t", "-c", "0"], check=True, capture_output=True 194 ) 195 self.assertIn(b"", result.stdout) 196 197 def test_i_option_sets_inspect_interactive_flags(self): 198 result = subprocess.run( 199 [sys.executable, "-i", "-c", "import sys;print(sys.flags);sys.ps1='TTT:'"], 200 check=True, 201 capture_output=True, 202 stdin=subprocess.DEVNULL, 203 ) 204 self.assertIn(b"inspect=1", result.stdout) 205 self.assertIn(b"interactive=1", result.stdout) 206 self.assertIn(b"TTT:", result.stderr) 207 208 def test_m_option_imports_module(self): 209 result = subprocess.run( 210 [sys.executable, "-m", "this"], check=True, capture_output=True 211 ) 212 self.assertIn(b"The Zen of Python", result.stdout) 213 self.assertNotIn(b">>>", result.stderr) 214 215 def test_no_option_sets_default_flags(self): 216 result = subprocess.run( 217 [sys.executable, "-c", "import sys;print(sys.flags)"], 218 check=True, 219 capture_output=True, 220 ) 221 self.assertIn( 222 b"sys.flags(debug=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0, ignore_environment=0, verbose=0, bytes_warning=0, quiet=0, hash_randomization=1, isolated=0, dev_mode=False, utf8_mode", 223 result.stdout, 224 ) 225 226 def test_no_arguments_works(self): 227 result = subprocess.run([sys.executable], stdin=subprocess.DEVNULL) 228 self.assertEqual(result.returncode, 0) 229 230 def test_s_option_sets_no_user_site_flag(self): 231 result = subprocess.run( 232 [sys.executable, "-s", "-c", "import sys;print(sys.flags)"], 233 check=True, 234 capture_output=True, 235 ) 236 self.assertIn(b"no_user_site=1", result.stdout) 237 238 def test_v_option_increments_verbose_flag(self): 239 result = subprocess.run( 240 [sys.executable, "-vvv", "-v", "-c", "import sys;print(sys.flags)"], 241 check=True, 242 capture_output=True, 243 ) 244 self.assertIn(b"verbose=4", result.stdout) 245 246 def test_version_option_prints_version(self): 247 result = subprocess.run( 248 [sys.executable, "--version"], 249 check=True, 250 capture_output=True, 251 encoding="utf-8", 252 ) 253 version = sys.version_info 254 self.assertIn( 255 f"Python {version.major}.{version.minor}.{version.micro}", result.stdout 256 ) 257 258 def test_q_option_sets_quiet_flag(self): 259 result = subprocess.run( 260 [sys.executable, "-q", "-c", "import sys;print(sys.flags)"], 261 check=True, 262 capture_output=True, 263 ) 264 self.assertIn(b"quiet=1", result.stdout) 265 266 def test_no_u_option_in_pty_sets_buffered_stdio(self): 267 result = subprocess.run( 268 with_pty([sys.executable, "-c", "import sys;print(sys.stdout.line_buffering)"]), 269 check=True, 270 capture_output=True, 271 ) 272 self.assertIn(b"True", result.stdout) 273 274 def test_no_u_option_no_pty_sets_unbuffered_stdio(self): 275 result = subprocess.run( 276 [sys.executable, "-c", "import sys;print(sys.stdout.line_buffering)"], 277 check=True, 278 capture_output=True, 279 ) 280 self.assertIn(b"False", result.stdout) 281 282 def test_u_option_in_pty_sets_unbuffered_stdio(self): 283 result = subprocess.run( 284 with_pty([sys.executable, "-u", "-c", "import sys;print(sys.stdout.line_buffering)"]), 285 check=True, 286 capture_output=True, 287 ) 288 self.assertIn(b"False", result.stdout) 289 290 def test_u_option_no_pty_sets_unbuffered_stdio(self): 291 result = subprocess.run( 292 [sys.executable, "-u", "-c", "import sys;print(sys.stdout.line_buffering)"], 293 check=True, 294 capture_output=True, 295 ) 296 self.assertIn(b"False", result.stdout) 297 298 def test_u_option_in_pty_sets_unbuffered_stdin(self): 299 result = subprocess.run( 300 with_pty([sys.executable, "-u", "-c", "import sys;print(sys.stdin.line_buffering)"]), 301 check=True, 302 capture_output=True, 303 ) 304 self.assertIn(b"False", result.stdout) 305 306 def test_u_option_sets_unbuffered_stdin(self): 307 result = subprocess.run( 308 [sys.executable, "-u", "-c", "import sys;print(sys.stdin.line_buffering)"], 309 check=True, 310 capture_output=True, 311 ) 312 self.assertIn(b"False", result.stdout) 313 314 315class RunTest(unittest.TestCase): 316 def test_builtins_of_dunder_main_is_module(self): 317 from types import ModuleType 318 319 main = sys.modules["__main__"] 320 self.assertIsInstance(main.__builtins__, ModuleType) 321 322 def test_with_directory_executes_code(self): 323 with TemporaryDirectory() as tempdir: 324 tempfile = os.path.join(tempdir, "__main__.py") 325 tempfile = os.path.abspath(tempfile) 326 with open(tempfile, "w") as fp: 327 fp.write("print('test directory executed')\n") 328 result = subprocess.run( 329 [sys.executable, tempdir], 330 check=True, 331 capture_output=True, 332 encoding="utf-8", 333 ) 334 self.assertEqual(result.returncode, 0) 335 self.assertIn("test directory executed", result.stdout) 336 337 def test_with_directory_reports_cant_find_dunder_main(self): 338 with TemporaryDirectory() as tempdir: 339 tempfile = os.path.join(tempdir, "sample.py") 340 tempfile = os.path.abspath(tempfile) 341 with open(tempfile, "w") as fp: 342 fp.write("print('test file executed')\n") 343 result = subprocess.run([sys.executable, tempdir], capture_output=True) 344 self.assertIn(b"can't find '__main__' module in ", result.stderr) 345 self.assertEqual(1, result.returncode) 346 347 def test_with_fifo_executes_code(self): 348 with TemporaryDirectory() as tempdir: 349 fifoname = f"{tempdir}/fifo" 350 os.mkfifo(fifoname) 351 proc = subprocess.Popen( 352 [sys.executable, fifoname], 353 stdout=subprocess.PIPE, 354 stderr=subprocess.PIPE, 355 ) 356 with open(fifoname, "w") as fp: 357 fp.write(f"# l{'o' * 10000}ng comment\n") 358 fp.write("print('testing 1,2,3')\n") 359 stdout, stderr = proc.communicate() 360 self.assertEqual(proc.returncode, 0) 361 self.assertEqual(stderr, b"") 362 self.assertEqual(stdout, b"testing 1,2,3\n") 363 364 def test_with_file_executes_code(self): 365 with TemporaryDirectory() as tempdir: 366 tempfile = os.path.join(tempdir, "foo.py") 367 tempfile = os.path.abspath(tempfile) 368 with open(tempfile, "w") as fp: 369 fp.write("print('test fi' + 'le executed')\n") 370 fp.write("import sys\n") 371 fp.write("print('argv: ' + str(sys.argv))\n") 372 result = subprocess.run( 373 [sys.executable, tempfile, "arg0", "arg1 with spaces"], 374 check=True, 375 capture_output=True, 376 encoding="utf-8", 377 ) 378 self.assertEqual(result.returncode, 0) 379 self.assertIn("test file executed", result.stdout) 380 self.assertIn( 381 f"argv: ['{tempfile}', 'arg0', 'arg1 with spaces']", result.stdout 382 ) 383 384 def test_with_file_invalid_utf8_raises_syntax_error(self): 385 with TemporaryDirectory() as tempdir: 386 tempfile = os.path.join(tempdir, "bad_utf8.py") 387 with open(tempfile, "wb") as fp: 388 fp.write(b"print('Bad UTF8: \xf8\xa1\xa1\xa1\xa1'\n") 389 result = subprocess.run( 390 [sys.executable, tempfile], 391 capture_output=True, 392 encoding="utf-8", 393 ) 394 self.assertIn("SyntaxError:", result.stderr) 395 self.assertEqual(result.returncode, 1) 396 397 def test_with_zipfile_executes_code(self): 398 with TemporaryDirectory() as tempdir: 399 tempzipfile = os.path.join(tempdir, "test.zip") 400 tempzipfile = os.path.abspath(tempzipfile) 401 with zipfile.ZipFile(tempzipfile, "w") as myzip: 402 myzip.writestr("__main__.py", "print('test zip file executed')\n") 403 result = subprocess.run( 404 [sys.executable, tempzipfile], 405 check=True, 406 capture_output=True, 407 encoding="utf-8", 408 ) 409 self.assertIn("test zip file executed", result.stdout) 410 411 def test_with_zipfile_reports_cant_find_dunder_main(self): 412 with TemporaryDirectory() as tempdir: 413 tempzipfile = os.path.join(tempdir, "test.zip") 414 tempzipfile = os.path.abspath(tempzipfile) 415 with zipfile.ZipFile(tempzipfile, "w") as myzip: 416 myzip.writestr("test.py", "print('test zip file executed')\n") 417 result = subprocess.run( 418 [sys.executable, tempzipfile], capture_output=True, encoding="utf-8" 419 ) 420 self.assertIn("can't find '__main__' module in", result.stderr) 421 self.assertEqual(1, result.returncode) 422 423 424if __name__ == "__main__": 425 unittest.main()