/Lib/test/test_subprocess.py

http://unladen-swallow.googlecode.com/ · Python · 741 lines · 566 code · 80 blank · 95 comment · 43 complexity · 032ea369e99ee1069077519ba3c67619 MD5 · raw file

  1. import unittest
  2. from test import test_support
  3. import subprocess
  4. import sys
  5. import signal
  6. import os
  7. import tempfile
  8. import time
  9. import re
  10. mswindows = (sys.platform == "win32")
  11. #
  12. # Depends on the following external programs: Python
  13. #
  14. if mswindows:
  15. SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), '
  16. 'os.O_BINARY);')
  17. else:
  18. SETBINARY = ''
  19. # In a debug build, stuff like "[6580 refs]" is printed to stderr at
  20. # shutdown time. That frustrates tests trying to check stderr produced
  21. # from a spawned Python process.
  22. def remove_stderr_debug_decorations(stderr):
  23. return re.sub(r"\[\d+ refs\]\r?\n?$", "", stderr)
  24. class ProcessTestCase(unittest.TestCase):
  25. def setUp(self):
  26. # Try to minimize the number of children we have so this test
  27. # doesn't crash on some buildbots (Alphas in particular).
  28. if hasattr(test_support, "reap_children"):
  29. test_support.reap_children()
  30. def tearDown(self):
  31. # Try to minimize the number of children we have so this test
  32. # doesn't crash on some buildbots (Alphas in particular).
  33. if hasattr(test_support, "reap_children"):
  34. test_support.reap_children()
  35. def mkstemp(self):
  36. """wrapper for mkstemp, calling mktemp if mkstemp is not available"""
  37. if hasattr(tempfile, "mkstemp"):
  38. return tempfile.mkstemp()
  39. else:
  40. fname = tempfile.mktemp()
  41. return os.open(fname, os.O_RDWR|os.O_CREAT), fname
  42. #
  43. # Generic tests
  44. #
  45. def test_call_seq(self):
  46. # call() function with sequence argument
  47. rc = subprocess.call([sys.executable, "-c",
  48. "import sys; sys.exit(47)"])
  49. self.assertEqual(rc, 47)
  50. def test_check_call_zero(self):
  51. # check_call() function with zero return code
  52. rc = subprocess.check_call([sys.executable, "-c",
  53. "import sys; sys.exit(0)"])
  54. self.assertEqual(rc, 0)
  55. def test_check_call_nonzero(self):
  56. # check_call() function with non-zero return code
  57. try:
  58. subprocess.check_call([sys.executable, "-c",
  59. "import sys; sys.exit(47)"])
  60. except subprocess.CalledProcessError, e:
  61. self.assertEqual(e.returncode, 47)
  62. else:
  63. self.fail("Expected CalledProcessError")
  64. def test_call_kwargs(self):
  65. # call() function with keyword args
  66. newenv = os.environ.copy()
  67. newenv["FRUIT"] = "banana"
  68. rc = subprocess.call([sys.executable, "-c",
  69. 'import sys, os;' \
  70. 'sys.exit(os.getenv("FRUIT")=="banana")'],
  71. env=newenv)
  72. self.assertEqual(rc, 1)
  73. def test_stdin_none(self):
  74. # .stdin is None when not redirected
  75. p = subprocess.Popen([sys.executable, "-c", 'print "banana"'],
  76. stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  77. p.wait()
  78. self.assertEqual(p.stdin, None)
  79. def test_stdout_none(self):
  80. # .stdout is None when not redirected
  81. p = subprocess.Popen([sys.executable, "-c",
  82. 'print " this bit of output is from a '
  83. 'test of stdout in a different '
  84. 'process ..."'],
  85. stdin=subprocess.PIPE, stderr=subprocess.PIPE)
  86. p.wait()
  87. self.assertEqual(p.stdout, None)
  88. def test_stderr_none(self):
  89. # .stderr is None when not redirected
  90. p = subprocess.Popen([sys.executable, "-c", 'print "banana"'],
  91. stdin=subprocess.PIPE, stdout=subprocess.PIPE)
  92. p.wait()
  93. self.assertEqual(p.stderr, None)
  94. def test_executable(self):
  95. p = subprocess.Popen(["somethingyoudonthave",
  96. "-c", "import sys; sys.exit(47)"],
  97. executable=sys.executable)
  98. p.wait()
  99. self.assertEqual(p.returncode, 47)
  100. def test_stdin_pipe(self):
  101. # stdin redirection
  102. p = subprocess.Popen([sys.executable, "-c",
  103. 'import sys; sys.exit(sys.stdin.read() == "pear")'],
  104. stdin=subprocess.PIPE)
  105. p.stdin.write("pear")
  106. p.stdin.close()
  107. p.wait()
  108. self.assertEqual(p.returncode, 1)
  109. def test_stdin_filedes(self):
  110. # stdin is set to open file descriptor
  111. tf = tempfile.TemporaryFile()
  112. d = tf.fileno()
  113. os.write(d, "pear")
  114. os.lseek(d, 0, 0)
  115. p = subprocess.Popen([sys.executable, "-c",
  116. 'import sys; sys.exit(sys.stdin.read() == "pear")'],
  117. stdin=d)
  118. p.wait()
  119. self.assertEqual(p.returncode, 1)
  120. def test_stdin_fileobj(self):
  121. # stdin is set to open file object
  122. tf = tempfile.TemporaryFile()
  123. tf.write("pear")
  124. tf.seek(0)
  125. p = subprocess.Popen([sys.executable, "-c",
  126. 'import sys; sys.exit(sys.stdin.read() == "pear")'],
  127. stdin=tf)
  128. p.wait()
  129. self.assertEqual(p.returncode, 1)
  130. def test_stdout_pipe(self):
  131. # stdout redirection
  132. p = subprocess.Popen([sys.executable, "-c",
  133. 'import sys; sys.stdout.write("orange")'],
  134. stdout=subprocess.PIPE)
  135. self.assertEqual(p.stdout.read(), "orange")
  136. def test_stdout_filedes(self):
  137. # stdout is set to open file descriptor
  138. tf = tempfile.TemporaryFile()
  139. d = tf.fileno()
  140. p = subprocess.Popen([sys.executable, "-c",
  141. 'import sys; sys.stdout.write("orange")'],
  142. stdout=d)
  143. p.wait()
  144. os.lseek(d, 0, 0)
  145. self.assertEqual(os.read(d, 1024), "orange")
  146. def test_stdout_fileobj(self):
  147. # stdout is set to open file object
  148. tf = tempfile.TemporaryFile()
  149. p = subprocess.Popen([sys.executable, "-c",
  150. 'import sys; sys.stdout.write("orange")'],
  151. stdout=tf)
  152. p.wait()
  153. tf.seek(0)
  154. self.assertEqual(tf.read(), "orange")
  155. def test_stderr_pipe(self):
  156. # stderr redirection
  157. p = subprocess.Popen([sys.executable, "-c",
  158. 'import sys; sys.stderr.write("strawberry")'],
  159. stderr=subprocess.PIPE)
  160. self.assertEqual(remove_stderr_debug_decorations(p.stderr.read()),
  161. "strawberry")
  162. def test_stderr_filedes(self):
  163. # stderr is set to open file descriptor
  164. tf = tempfile.TemporaryFile()
  165. d = tf.fileno()
  166. p = subprocess.Popen([sys.executable, "-c",
  167. 'import sys; sys.stderr.write("strawberry")'],
  168. stderr=d)
  169. p.wait()
  170. os.lseek(d, 0, 0)
  171. self.assertEqual(remove_stderr_debug_decorations(os.read(d, 1024)),
  172. "strawberry")
  173. def test_stderr_fileobj(self):
  174. # stderr is set to open file object
  175. tf = tempfile.TemporaryFile()
  176. p = subprocess.Popen([sys.executable, "-c",
  177. 'import sys; sys.stderr.write("strawberry")'],
  178. stderr=tf)
  179. p.wait()
  180. tf.seek(0)
  181. self.assertEqual(remove_stderr_debug_decorations(tf.read()),
  182. "strawberry")
  183. def test_stdout_stderr_pipe(self):
  184. # capture stdout and stderr to the same pipe
  185. p = subprocess.Popen([sys.executable, "-c",
  186. 'import sys;' \
  187. 'sys.stdout.write("apple");' \
  188. 'sys.stdout.flush();' \
  189. 'sys.stderr.write("orange")'],
  190. stdout=subprocess.PIPE,
  191. stderr=subprocess.STDOUT)
  192. output = p.stdout.read()
  193. stripped = remove_stderr_debug_decorations(output)
  194. self.assertEqual(stripped, "appleorange")
  195. def test_stdout_stderr_file(self):
  196. # capture stdout and stderr to the same open file
  197. tf = tempfile.TemporaryFile()
  198. p = subprocess.Popen([sys.executable, "-c",
  199. 'import sys;' \
  200. 'sys.stdout.write("apple");' \
  201. 'sys.stdout.flush();' \
  202. 'sys.stderr.write("orange")'],
  203. stdout=tf,
  204. stderr=tf)
  205. p.wait()
  206. tf.seek(0)
  207. output = tf.read()
  208. stripped = remove_stderr_debug_decorations(output)
  209. self.assertEqual(stripped, "appleorange")
  210. def test_stdout_filedes_of_stdout(self):
  211. # stdout is set to 1 (#1531862).
  212. cmd = r"import sys, os; sys.exit(os.write(sys.stdout.fileno(), '.\n'))"
  213. rc = subprocess.call([sys.executable, "-c", cmd], stdout=1)
  214. self.assertEquals(rc, 2)
  215. def test_cwd(self):
  216. tmpdir = tempfile.gettempdir()
  217. # We cannot use os.path.realpath to canonicalize the path,
  218. # since it doesn't expand Tru64 {memb} strings. See bug 1063571.
  219. cwd = os.getcwd()
  220. os.chdir(tmpdir)
  221. tmpdir = os.getcwd()
  222. os.chdir(cwd)
  223. p = subprocess.Popen([sys.executable, "-c",
  224. 'import sys,os;' \
  225. 'sys.stdout.write(os.getcwd())'],
  226. stdout=subprocess.PIPE,
  227. cwd=tmpdir)
  228. normcase = os.path.normcase
  229. self.assertEqual(normcase(p.stdout.read()), normcase(tmpdir))
  230. def test_env(self):
  231. newenv = os.environ.copy()
  232. newenv["FRUIT"] = "orange"
  233. p = subprocess.Popen([sys.executable, "-c",
  234. 'import sys,os;' \
  235. 'sys.stdout.write(os.getenv("FRUIT"))'],
  236. stdout=subprocess.PIPE,
  237. env=newenv)
  238. self.assertEqual(p.stdout.read(), "orange")
  239. def test_communicate_stdin(self):
  240. p = subprocess.Popen([sys.executable, "-c",
  241. 'import sys; sys.exit(sys.stdin.read() == "pear")'],
  242. stdin=subprocess.PIPE)
  243. p.communicate("pear")
  244. self.assertEqual(p.returncode, 1)
  245. def test_communicate_stdout(self):
  246. p = subprocess.Popen([sys.executable, "-c",
  247. 'import sys; sys.stdout.write("pineapple")'],
  248. stdout=subprocess.PIPE)
  249. (stdout, stderr) = p.communicate()
  250. self.assertEqual(stdout, "pineapple")
  251. self.assertEqual(stderr, None)
  252. def test_communicate_stderr(self):
  253. p = subprocess.Popen([sys.executable, "-c",
  254. 'import sys; sys.stderr.write("pineapple")'],
  255. stderr=subprocess.PIPE)
  256. (stdout, stderr) = p.communicate()
  257. self.assertEqual(stdout, None)
  258. self.assertEqual(remove_stderr_debug_decorations(stderr), "pineapple")
  259. def test_communicate(self):
  260. p = subprocess.Popen([sys.executable, "-c",
  261. 'import sys,os;'
  262. 'sys.stderr.write("pineapple");'
  263. 'sys.stdout.write(sys.stdin.read())'],
  264. stdin=subprocess.PIPE,
  265. stdout=subprocess.PIPE,
  266. stderr=subprocess.PIPE)
  267. (stdout, stderr) = p.communicate("banana")
  268. self.assertEqual(stdout, "banana")
  269. self.assertEqual(remove_stderr_debug_decorations(stderr),
  270. "pineapple")
  271. # This test is Linux specific for simplicity to at least have
  272. # some coverage. It is not a platform specific bug.
  273. if os.path.isdir('/proc/%d/fd' % os.getpid()):
  274. # Test for the fd leak reported in http://bugs.python.org/issue2791.
  275. def test_communicate_pipe_fd_leak(self):
  276. fd_directory = '/proc/%d/fd' % os.getpid()
  277. num_fds_before_popen = len(os.listdir(fd_directory))
  278. p = subprocess.Popen([sys.executable, '-c', 'print()'],
  279. stdout=subprocess.PIPE)
  280. p.communicate()
  281. num_fds_after_communicate = len(os.listdir(fd_directory))
  282. del p
  283. num_fds_after_destruction = len(os.listdir(fd_directory))
  284. self.assertEqual(num_fds_before_popen, num_fds_after_destruction)
  285. self.assertEqual(num_fds_before_popen, num_fds_after_communicate)
  286. def test_communicate_returns(self):
  287. # communicate() should return None if no redirection is active
  288. p = subprocess.Popen([sys.executable, "-c",
  289. "import sys; sys.exit(47)"])
  290. (stdout, stderr) = p.communicate()
  291. self.assertEqual(stdout, None)
  292. self.assertEqual(stderr, None)
  293. def test_communicate_pipe_buf(self):
  294. # communicate() with writes larger than pipe_buf
  295. # This test will probably deadlock rather than fail, if
  296. # communicate() does not work properly.
  297. x, y = os.pipe()
  298. if mswindows:
  299. pipe_buf = 512
  300. else:
  301. pipe_buf = os.fpathconf(x, "PC_PIPE_BUF")
  302. os.close(x)
  303. os.close(y)
  304. p = subprocess.Popen([sys.executable, "-c",
  305. 'import sys,os;'
  306. 'sys.stdout.write(sys.stdin.read(47));' \
  307. 'sys.stderr.write("xyz"*%d);' \
  308. 'sys.stdout.write(sys.stdin.read())' % pipe_buf],
  309. stdin=subprocess.PIPE,
  310. stdout=subprocess.PIPE,
  311. stderr=subprocess.PIPE)
  312. string_to_write = "abc"*pipe_buf
  313. (stdout, stderr) = p.communicate(string_to_write)
  314. self.assertEqual(stdout, string_to_write)
  315. def test_writes_before_communicate(self):
  316. # stdin.write before communicate()
  317. p = subprocess.Popen([sys.executable, "-c",
  318. 'import sys,os;' \
  319. 'sys.stdout.write(sys.stdin.read())'],
  320. stdin=subprocess.PIPE,
  321. stdout=subprocess.PIPE,
  322. stderr=subprocess.PIPE)
  323. p.stdin.write("banana")
  324. (stdout, stderr) = p.communicate("split")
  325. self.assertEqual(stdout, "bananasplit")
  326. self.assertEqual(remove_stderr_debug_decorations(stderr), "")
  327. def test_universal_newlines(self):
  328. p = subprocess.Popen([sys.executable, "-c",
  329. 'import sys,os;' + SETBINARY +
  330. 'sys.stdout.write("line1\\n");'
  331. 'sys.stdout.flush();'
  332. 'sys.stdout.write("line2\\r");'
  333. 'sys.stdout.flush();'
  334. 'sys.stdout.write("line3\\r\\n");'
  335. 'sys.stdout.flush();'
  336. 'sys.stdout.write("line4\\r");'
  337. 'sys.stdout.flush();'
  338. 'sys.stdout.write("\\nline5");'
  339. 'sys.stdout.flush();'
  340. 'sys.stdout.write("\\nline6");'],
  341. stdout=subprocess.PIPE,
  342. universal_newlines=1)
  343. stdout = p.stdout.read()
  344. if hasattr(file, 'newlines'):
  345. # Interpreter with universal newline support
  346. self.assertEqual(stdout,
  347. "line1\nline2\nline3\nline4\nline5\nline6")
  348. else:
  349. # Interpreter without universal newline support
  350. self.assertEqual(stdout,
  351. "line1\nline2\rline3\r\nline4\r\nline5\nline6")
  352. def test_universal_newlines_communicate(self):
  353. # universal newlines through communicate()
  354. p = subprocess.Popen([sys.executable, "-c",
  355. 'import sys,os;' + SETBINARY +
  356. 'sys.stdout.write("line1\\n");'
  357. 'sys.stdout.flush();'
  358. 'sys.stdout.write("line2\\r");'
  359. 'sys.stdout.flush();'
  360. 'sys.stdout.write("line3\\r\\n");'
  361. 'sys.stdout.flush();'
  362. 'sys.stdout.write("line4\\r");'
  363. 'sys.stdout.flush();'
  364. 'sys.stdout.write("\\nline5");'
  365. 'sys.stdout.flush();'
  366. 'sys.stdout.write("\\nline6");'],
  367. stdout=subprocess.PIPE, stderr=subprocess.PIPE,
  368. universal_newlines=1)
  369. (stdout, stderr) = p.communicate()
  370. if hasattr(file, 'newlines'):
  371. # Interpreter with universal newline support
  372. self.assertEqual(stdout,
  373. "line1\nline2\nline3\nline4\nline5\nline6")
  374. else:
  375. # Interpreter without universal newline support
  376. self.assertEqual(stdout, "line1\nline2\rline3\r\nline4\r\nline5\nline6")
  377. def test_no_leaking(self):
  378. # Make sure we leak no resources
  379. if not hasattr(test_support, "is_resource_enabled") \
  380. or test_support.is_resource_enabled("subprocess") and not mswindows:
  381. max_handles = 1026 # too much for most UNIX systems
  382. else:
  383. max_handles = 65
  384. for i in range(max_handles):
  385. p = subprocess.Popen([sys.executable, "-c",
  386. "import sys;sys.stdout.write(sys.stdin.read())"],
  387. stdin=subprocess.PIPE,
  388. stdout=subprocess.PIPE,
  389. stderr=subprocess.PIPE)
  390. data = p.communicate("lime")[0]
  391. self.assertEqual(data, "lime")
  392. def test_list2cmdline(self):
  393. self.assertEqual(subprocess.list2cmdline(['a b c', 'd', 'e']),
  394. '"a b c" d e')
  395. self.assertEqual(subprocess.list2cmdline(['ab"c', '\\', 'd']),
  396. 'ab\\"c \\ d')
  397. self.assertEqual(subprocess.list2cmdline(['ab"c', ' \\', 'd']),
  398. 'ab\\"c " \\\\" d')
  399. self.assertEqual(subprocess.list2cmdline(['a\\\\\\b', 'de fg', 'h']),
  400. 'a\\\\\\b "de fg" h')
  401. self.assertEqual(subprocess.list2cmdline(['a\\"b', 'c', 'd']),
  402. 'a\\\\\\"b c d')
  403. self.assertEqual(subprocess.list2cmdline(['a\\\\b c', 'd', 'e']),
  404. '"a\\\\b c" d e')
  405. self.assertEqual(subprocess.list2cmdline(['a\\\\b\\ c', 'd', 'e']),
  406. '"a\\\\b\\ c" d e')
  407. self.assertEqual(subprocess.list2cmdline(['ab', '']),
  408. 'ab ""')
  409. self.assertEqual(subprocess.list2cmdline(['echo', 'foo|bar']),
  410. 'echo "foo|bar"')
  411. def test_poll(self):
  412. p = subprocess.Popen([sys.executable,
  413. "-c", "import time; time.sleep(1)"])
  414. count = 0
  415. while p.poll() is None:
  416. time.sleep(0.1)
  417. count += 1
  418. # We expect that the poll loop probably went around about 10 times,
  419. # but, based on system scheduling we can't control, it's possible
  420. # poll() never returned None. It "should be" very rare that it
  421. # didn't go around at least twice.
  422. self.assert_(count >= 2)
  423. # Subsequent invocations should just return the returncode
  424. self.assertEqual(p.poll(), 0)
  425. def test_wait(self):
  426. p = subprocess.Popen([sys.executable,
  427. "-c", "import time; time.sleep(2)"])
  428. self.assertEqual(p.wait(), 0)
  429. # Subsequent invocations should just return the returncode
  430. self.assertEqual(p.wait(), 0)
  431. def test_invalid_bufsize(self):
  432. # an invalid type of the bufsize argument should raise
  433. # TypeError.
  434. try:
  435. subprocess.Popen([sys.executable, "-c", "pass"], "orange")
  436. except TypeError:
  437. pass
  438. else:
  439. self.fail("Expected TypeError")
  440. def test_leaking_fds_on_error(self):
  441. # see bug #5179: Popen leaks file descriptors to PIPEs if
  442. # the child fails to execute; this will eventually exhaust
  443. # the maximum number of open fds. 1024 seems a very common
  444. # value for that limit, but Windows has 2048, so we loop
  445. # 1024 times (each call leaked two fds).
  446. for i in range(1024):
  447. try:
  448. subprocess.Popen(['nonexisting_i_hope'],
  449. stdout=subprocess.PIPE,
  450. stderr=subprocess.PIPE)
  451. # Windows raises IOError
  452. except (IOError, OSError), err:
  453. if err.errno != 2: # ignore "no such file"
  454. raise
  455. #
  456. # POSIX tests
  457. #
  458. if not mswindows:
  459. def test_exceptions(self):
  460. # catched & re-raised exceptions
  461. try:
  462. p = subprocess.Popen([sys.executable, "-c", ""],
  463. cwd="/this/path/does/not/exist")
  464. except OSError, e:
  465. # The attribute child_traceback should contain "os.chdir"
  466. # somewhere.
  467. self.assertNotEqual(e.child_traceback.find("os.chdir"), -1)
  468. else:
  469. self.fail("Expected OSError")
  470. def _suppress_core_files(self):
  471. """Try to prevent core files from being created.
  472. Returns previous ulimit if successful, else None.
  473. """
  474. try:
  475. import resource
  476. old_limit = resource.getrlimit(resource.RLIMIT_CORE)
  477. resource.setrlimit(resource.RLIMIT_CORE, (0,0))
  478. return old_limit
  479. except (ImportError, ValueError, resource.error):
  480. return None
  481. def _unsuppress_core_files(self, old_limit):
  482. """Return core file behavior to default."""
  483. if old_limit is None:
  484. return
  485. try:
  486. import resource
  487. resource.setrlimit(resource.RLIMIT_CORE, old_limit)
  488. except (ImportError, ValueError, resource.error):
  489. return
  490. def test_run_abort(self):
  491. # returncode handles signal termination
  492. old_limit = self._suppress_core_files()
  493. try:
  494. p = subprocess.Popen([sys.executable,
  495. "-c", "import os; os.abort()"])
  496. finally:
  497. self._unsuppress_core_files(old_limit)
  498. p.wait()
  499. self.assertEqual(-p.returncode, signal.SIGABRT)
  500. def test_preexec(self):
  501. # preexec function
  502. p = subprocess.Popen([sys.executable, "-c",
  503. 'import sys,os;' \
  504. 'sys.stdout.write(os.getenv("FRUIT"))'],
  505. stdout=subprocess.PIPE,
  506. preexec_fn=lambda: os.putenv("FRUIT", "apple"))
  507. self.assertEqual(p.stdout.read(), "apple")
  508. def test_args_string(self):
  509. # args is a string
  510. f, fname = self.mkstemp()
  511. os.write(f, "#!/bin/sh\n")
  512. os.write(f, "exec '%s' -c 'import sys; sys.exit(47)'\n" %
  513. sys.executable)
  514. os.close(f)
  515. os.chmod(fname, 0700)
  516. p = subprocess.Popen(fname)
  517. p.wait()
  518. os.remove(fname)
  519. self.assertEqual(p.returncode, 47)
  520. def test_invalid_args(self):
  521. # invalid arguments should raise ValueError
  522. self.assertRaises(ValueError, subprocess.call,
  523. [sys.executable,
  524. "-c", "import sys; sys.exit(47)"],
  525. startupinfo=47)
  526. self.assertRaises(ValueError, subprocess.call,
  527. [sys.executable,
  528. "-c", "import sys; sys.exit(47)"],
  529. creationflags=47)
  530. def test_shell_sequence(self):
  531. # Run command through the shell (sequence)
  532. newenv = os.environ.copy()
  533. newenv["FRUIT"] = "apple"
  534. p = subprocess.Popen(["echo $FRUIT"], shell=1,
  535. stdout=subprocess.PIPE,
  536. env=newenv)
  537. self.assertEqual(p.stdout.read().strip(), "apple")
  538. def test_shell_string(self):
  539. # Run command through the shell (string)
  540. newenv = os.environ.copy()
  541. newenv["FRUIT"] = "apple"
  542. p = subprocess.Popen("echo $FRUIT", shell=1,
  543. stdout=subprocess.PIPE,
  544. env=newenv)
  545. self.assertEqual(p.stdout.read().strip(), "apple")
  546. def test_call_string(self):
  547. # call() function with string argument on UNIX
  548. f, fname = self.mkstemp()
  549. os.write(f, "#!/bin/sh\n")
  550. os.write(f, "exec '%s' -c 'import sys; sys.exit(47)'\n" %
  551. sys.executable)
  552. os.close(f)
  553. os.chmod(fname, 0700)
  554. rc = subprocess.call(fname)
  555. os.remove(fname)
  556. self.assertEqual(rc, 47)
  557. def DISABLED_test_send_signal(self):
  558. p = subprocess.Popen([sys.executable,
  559. "-c", "input()"])
  560. self.assert_(p.poll() is None, p.poll())
  561. p.send_signal(signal.SIGINT)
  562. self.assertNotEqual(p.wait(), 0)
  563. def DISABLED_test_kill(self):
  564. p = subprocess.Popen([sys.executable,
  565. "-c", "input()"])
  566. self.assert_(p.poll() is None, p.poll())
  567. p.kill()
  568. self.assertEqual(p.wait(), -signal.SIGKILL)
  569. def DISABLED_test_terminate(self):
  570. p = subprocess.Popen([sys.executable,
  571. "-c", "input()"])
  572. self.assert_(p.poll() is None, p.poll())
  573. p.terminate()
  574. self.assertEqual(p.wait(), -signal.SIGTERM)
  575. #
  576. # Windows tests
  577. #
  578. if mswindows:
  579. def test_startupinfo(self):
  580. # startupinfo argument
  581. # We uses hardcoded constants, because we do not want to
  582. # depend on win32all.
  583. STARTF_USESHOWWINDOW = 1
  584. SW_MAXIMIZE = 3
  585. startupinfo = subprocess.STARTUPINFO()
  586. startupinfo.dwFlags = STARTF_USESHOWWINDOW
  587. startupinfo.wShowWindow = SW_MAXIMIZE
  588. # Since Python is a console process, it won't be affected
  589. # by wShowWindow, but the argument should be silently
  590. # ignored
  591. subprocess.call([sys.executable, "-c", "import sys; sys.exit(0)"],
  592. startupinfo=startupinfo)
  593. def test_creationflags(self):
  594. # creationflags argument
  595. CREATE_NEW_CONSOLE = 16
  596. sys.stderr.write(" a DOS box should flash briefly ...\n")
  597. subprocess.call(sys.executable +
  598. ' -c "import time; time.sleep(0.25)"',
  599. creationflags=CREATE_NEW_CONSOLE)
  600. def test_invalid_args(self):
  601. # invalid arguments should raise ValueError
  602. self.assertRaises(ValueError, subprocess.call,
  603. [sys.executable,
  604. "-c", "import sys; sys.exit(47)"],
  605. preexec_fn=lambda: 1)
  606. self.assertRaises(ValueError, subprocess.call,
  607. [sys.executable,
  608. "-c", "import sys; sys.exit(47)"],
  609. stdout=subprocess.PIPE,
  610. close_fds=True)
  611. def test_close_fds(self):
  612. # close file descriptors
  613. rc = subprocess.call([sys.executable, "-c",
  614. "import sys; sys.exit(47)"],
  615. close_fds=True)
  616. self.assertEqual(rc, 47)
  617. def test_shell_sequence(self):
  618. # Run command through the shell (sequence)
  619. newenv = os.environ.copy()
  620. newenv["FRUIT"] = "physalis"
  621. p = subprocess.Popen(["set"], shell=1,
  622. stdout=subprocess.PIPE,
  623. env=newenv)
  624. self.assertNotEqual(p.stdout.read().find("physalis"), -1)
  625. def test_shell_string(self):
  626. # Run command through the shell (string)
  627. newenv = os.environ.copy()
  628. newenv["FRUIT"] = "physalis"
  629. p = subprocess.Popen("set", shell=1,
  630. stdout=subprocess.PIPE,
  631. env=newenv)
  632. self.assertNotEqual(p.stdout.read().find("physalis"), -1)
  633. def test_call_string(self):
  634. # call() function with string argument on Windows
  635. rc = subprocess.call(sys.executable +
  636. ' -c "import sys; sys.exit(47)"')
  637. self.assertEqual(rc, 47)
  638. def DISABLED_test_send_signal(self):
  639. p = subprocess.Popen([sys.executable,
  640. "-c", "input()"])
  641. self.assert_(p.poll() is None, p.poll())
  642. p.send_signal(signal.SIGTERM)
  643. self.assertNotEqual(p.wait(), 0)
  644. def DISABLED_test_kill(self):
  645. p = subprocess.Popen([sys.executable,
  646. "-c", "input()"])
  647. self.assert_(p.poll() is None, p.poll())
  648. p.kill()
  649. self.assertNotEqual(p.wait(), 0)
  650. def DISABLED_test_terminate(self):
  651. p = subprocess.Popen([sys.executable,
  652. "-c", "input()"])
  653. self.assert_(p.poll() is None, p.poll())
  654. p.terminate()
  655. self.assertNotEqual(p.wait(), 0)
  656. def test_main():
  657. test_support.run_unittest(ProcessTestCase)
  658. if hasattr(test_support, "reap_children"):
  659. test_support.reap_children()
  660. if __name__ == "__main__":
  661. test_main()