test_execute.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. import subprocess
  2. import pytest
  3. from flexmock import flexmock
  4. from borgmatic import execute as module
  5. @pytest.mark.parametrize(
  6. 'command,exit_code,borg_local_path,borg_exit_codes,expected_result',
  7. (
  8. (['grep'], 2, None, None, module.Exit_status.ERROR),
  9. (['grep'], 2, 'borg', None, module.Exit_status.ERROR),
  10. (['borg'], 2, 'borg', None, module.Exit_status.ERROR),
  11. (['borg1'], 2, 'borg1', None, module.Exit_status.ERROR),
  12. (['grep'], 1, None, None, module.Exit_status.ERROR),
  13. (['grep'], 1, 'borg', None, module.Exit_status.ERROR),
  14. (['borg'], 1, 'borg', None, module.Exit_status.WARNING),
  15. (['borg1'], 1, 'borg1', None, module.Exit_status.WARNING),
  16. (['grep'], 100, None, None, module.Exit_status.ERROR),
  17. (['grep'], 100, 'borg', None, module.Exit_status.ERROR),
  18. (['borg'], 100, 'borg', None, module.Exit_status.WARNING),
  19. (['borg1'], 100, 'borg1', None, module.Exit_status.WARNING),
  20. (['grep'], 0, None, None, module.Exit_status.SUCCESS),
  21. (['grep'], 0, 'borg', None, module.Exit_status.SUCCESS),
  22. (['borg'], 0, 'borg', None, module.Exit_status.SUCCESS),
  23. (['borg1'], 0, 'borg1', None, module.Exit_status.SUCCESS),
  24. # -9 exit code occurs when child process get SIGKILLed.
  25. (['grep'], -9, None, None, module.Exit_status.ERROR),
  26. (['grep'], -9, 'borg', None, module.Exit_status.ERROR),
  27. (['borg'], -9, 'borg', None, module.Exit_status.ERROR),
  28. (['borg1'], -9, 'borg1', None, module.Exit_status.ERROR),
  29. (['borg'], None, None, None, module.Exit_status.STILL_RUNNING),
  30. (['borg'], 1, 'borg', [], module.Exit_status.WARNING),
  31. (['borg'], 1, 'borg', [{}], module.Exit_status.WARNING),
  32. (['borg'], 1, 'borg', [{'code': 1}], module.Exit_status.WARNING),
  33. (['grep'], 1, 'borg', [{'code': 100, 'treat_as': 'error'}], module.Exit_status.ERROR),
  34. (['borg'], 1, 'borg', [{'code': 100, 'treat_as': 'error'}], module.Exit_status.WARNING),
  35. (['borg'], 1, 'borg', [{'code': 1, 'treat_as': 'error'}], module.Exit_status.ERROR),
  36. (['borg'], 2, 'borg', [{'code': 99, 'treat_as': 'warning'}], module.Exit_status.ERROR),
  37. (['borg'], 2, 'borg', [{'code': 2, 'treat_as': 'warning'}], module.Exit_status.WARNING),
  38. (['borg'], 100, 'borg', [{'code': 1, 'treat_as': 'error'}], module.Exit_status.WARNING),
  39. (['borg'], 100, 'borg', [{'code': 100, 'treat_as': 'error'}], module.Exit_status.ERROR),
  40. ),
  41. )
  42. def test_interpret_exit_code_respects_exit_code_and_borg_local_path(
  43. command, exit_code, borg_local_path, borg_exit_codes, expected_result
  44. ):
  45. assert (
  46. module.interpret_exit_code(command, exit_code, borg_local_path, borg_exit_codes)
  47. is expected_result
  48. )
  49. def test_command_for_process_converts_sequence_command_to_string():
  50. process = flexmock(args=['foo', 'bar', 'baz'])
  51. assert module.command_for_process(process) == 'foo bar baz'
  52. def test_command_for_process_passes_through_string_command():
  53. process = flexmock(args='foo bar baz')
  54. assert module.command_for_process(process) == 'foo bar baz'
  55. def test_output_buffer_for_process_returns_stderr_when_stdout_excluded():
  56. stdout = flexmock()
  57. stderr = flexmock()
  58. process = flexmock(stdout=stdout, stderr=stderr)
  59. assert module.output_buffer_for_process(process, exclude_stdouts=[flexmock(), stdout]) == stderr
  60. def test_output_buffer_for_process_returns_stdout_when_not_excluded():
  61. stdout = flexmock()
  62. process = flexmock(stdout=stdout)
  63. assert (
  64. module.output_buffer_for_process(process, exclude_stdouts=[flexmock(), flexmock()])
  65. == stdout
  66. )
  67. def test_append_last_lines_under_max_line_count_appends():
  68. last_lines = ['last']
  69. flexmock(module.logger).should_receive('log').once()
  70. module.append_last_lines(
  71. last_lines, captured_output=flexmock(), line='line', output_log_level=flexmock()
  72. )
  73. assert last_lines == ['last', 'line']
  74. def test_append_last_lines_over_max_line_count_trims_and_appends():
  75. original_last_lines = [str(number) for number in range(0, module.ERROR_OUTPUT_MAX_LINE_COUNT)]
  76. last_lines = list(original_last_lines)
  77. flexmock(module.logger).should_receive('log').once()
  78. module.append_last_lines(
  79. last_lines, captured_output=flexmock(), line='line', output_log_level=flexmock()
  80. )
  81. assert last_lines == original_last_lines[1:] + ['line']
  82. def test_append_last_lines_with_output_log_level_none_appends_captured_output():
  83. last_lines = ['last']
  84. captured_output = ['captured']
  85. flexmock(module.logger).should_receive('log').never()
  86. module.append_last_lines(
  87. last_lines, captured_output=captured_output, line='line', output_log_level=None
  88. )
  89. assert captured_output == ['captured', 'line']
  90. @pytest.mark.parametrize(
  91. 'full_command,input_file,output_file,environment,expected_result',
  92. (
  93. (('foo', 'bar'), None, None, None, 'foo bar'),
  94. (('foo', 'bar'), flexmock(name='input'), None, None, 'foo bar < input'),
  95. (('foo', 'bar'), None, flexmock(name='output'), None, 'foo bar > output'),
  96. (
  97. ('A',) * module.MAX_LOGGED_COMMAND_LENGTH,
  98. None,
  99. None,
  100. None,
  101. 'A ' * (module.MAX_LOGGED_COMMAND_LENGTH // 2 - 2) + '...',
  102. ),
  103. (
  104. ('foo', 'bar'),
  105. flexmock(name='input'),
  106. flexmock(name='output'),
  107. None,
  108. 'foo bar < input > output',
  109. ),
  110. (
  111. ('foo', 'bar'),
  112. None,
  113. None,
  114. {'DBPASS': 'secret', 'OTHER': 'thing'},
  115. 'DBPASS=*** OTHER=*** foo bar',
  116. ),
  117. ),
  118. )
  119. def test_log_command_logs_command_constructed_from_arguments(
  120. full_command, input_file, output_file, environment, expected_result
  121. ):
  122. flexmock(module.logger).should_receive('debug').with_args(expected_result).once()
  123. module.log_command(full_command, input_file, output_file, environment)
  124. def test_execute_command_calls_full_command():
  125. full_command = ['foo', 'bar']
  126. flexmock(module).should_receive('log_command')
  127. flexmock(module.os, environ={'a': 'b'})
  128. flexmock(module.subprocess).should_receive('Popen').with_args(
  129. full_command,
  130. stdin=None,
  131. stdout=module.subprocess.PIPE,
  132. stderr=module.subprocess.STDOUT,
  133. shell=False,
  134. env=None,
  135. cwd=None,
  136. ).and_return(flexmock(stdout=None)).once()
  137. flexmock(module).should_receive('log_outputs')
  138. output = module.execute_command(full_command)
  139. assert output is None
  140. def test_execute_command_calls_full_command_with_output_file():
  141. full_command = ['foo', 'bar']
  142. output_file = flexmock(name='test')
  143. flexmock(module).should_receive('log_command')
  144. flexmock(module.os, environ={'a': 'b'})
  145. flexmock(module.subprocess).should_receive('Popen').with_args(
  146. full_command,
  147. stdin=None,
  148. stdout=output_file,
  149. stderr=module.subprocess.PIPE,
  150. shell=False,
  151. env=None,
  152. cwd=None,
  153. ).and_return(flexmock(stderr=None)).once()
  154. flexmock(module).should_receive('log_outputs')
  155. output = module.execute_command(full_command, output_file=output_file)
  156. assert output is None
  157. def test_execute_command_calls_full_command_without_capturing_output():
  158. full_command = ['foo', 'bar']
  159. flexmock(module).should_receive('log_command')
  160. flexmock(module.os, environ={'a': 'b'})
  161. flexmock(module.subprocess).should_receive('Popen').with_args(
  162. full_command, stdin=None, stdout=None, stderr=None, shell=False, env=None, cwd=None
  163. ).and_return(flexmock(wait=lambda: 0)).once()
  164. flexmock(module).should_receive('interpret_exit_code').and_return(module.Exit_status.SUCCESS)
  165. flexmock(module).should_receive('log_outputs')
  166. output = module.execute_command(full_command, output_file=module.DO_NOT_CAPTURE)
  167. assert output is None
  168. def test_execute_command_calls_full_command_with_input_file():
  169. full_command = ['foo', 'bar']
  170. input_file = flexmock(name='test')
  171. flexmock(module).should_receive('log_command')
  172. flexmock(module.os, environ={'a': 'b'})
  173. flexmock(module.subprocess).should_receive('Popen').with_args(
  174. full_command,
  175. stdin=input_file,
  176. stdout=module.subprocess.PIPE,
  177. stderr=module.subprocess.STDOUT,
  178. shell=False,
  179. env=None,
  180. cwd=None,
  181. ).and_return(flexmock(stdout=None)).once()
  182. flexmock(module).should_receive('log_outputs')
  183. output = module.execute_command(full_command, input_file=input_file)
  184. assert output is None
  185. def test_execute_command_calls_full_command_with_shell():
  186. full_command = ['foo', 'bar']
  187. flexmock(module).should_receive('log_command')
  188. flexmock(module.os, environ={'a': 'b'})
  189. flexmock(module.subprocess).should_receive('Popen').with_args(
  190. ' '.join(full_command),
  191. stdin=None,
  192. stdout=module.subprocess.PIPE,
  193. stderr=module.subprocess.STDOUT,
  194. shell=True,
  195. env=None,
  196. cwd=None,
  197. ).and_return(flexmock(stdout=None)).once()
  198. flexmock(module).should_receive('log_outputs')
  199. output = module.execute_command(full_command, shell=True)
  200. assert output is None
  201. def test_execute_command_calls_full_command_with_extra_environment():
  202. full_command = ['foo', 'bar']
  203. flexmock(module).should_receive('log_command')
  204. flexmock(module.os, environ={'a': 'b'})
  205. flexmock(module.subprocess).should_receive('Popen').with_args(
  206. full_command,
  207. stdin=None,
  208. stdout=module.subprocess.PIPE,
  209. stderr=module.subprocess.STDOUT,
  210. shell=False,
  211. env={'a': 'b', 'c': 'd'},
  212. cwd=None,
  213. ).and_return(flexmock(stdout=None)).once()
  214. flexmock(module).should_receive('log_outputs')
  215. output = module.execute_command(full_command, extra_environment={'c': 'd'})
  216. assert output is None
  217. def test_execute_command_calls_full_command_with_working_directory():
  218. full_command = ['foo', 'bar']
  219. flexmock(module).should_receive('log_command')
  220. flexmock(module.os, environ={'a': 'b'})
  221. flexmock(module.subprocess).should_receive('Popen').with_args(
  222. full_command,
  223. stdin=None,
  224. stdout=module.subprocess.PIPE,
  225. stderr=module.subprocess.STDOUT,
  226. shell=False,
  227. env=None,
  228. cwd='/working',
  229. ).and_return(flexmock(stdout=None)).once()
  230. flexmock(module).should_receive('log_outputs')
  231. output = module.execute_command(full_command, working_directory='/working')
  232. assert output is None
  233. def test_execute_command_without_run_to_completion_returns_process():
  234. full_command = ['foo', 'bar']
  235. process = flexmock()
  236. flexmock(module).should_receive('log_command')
  237. flexmock(module.os, environ={'a': 'b'})
  238. flexmock(module.subprocess).should_receive('Popen').with_args(
  239. full_command,
  240. stdin=None,
  241. stdout=module.subprocess.PIPE,
  242. stderr=module.subprocess.STDOUT,
  243. shell=False,
  244. env=None,
  245. cwd=None,
  246. ).and_return(process).once()
  247. flexmock(module).should_receive('log_outputs')
  248. assert module.execute_command(full_command, run_to_completion=False) == process
  249. def test_execute_command_and_capture_output_returns_stdout():
  250. full_command = ['foo', 'bar']
  251. expected_output = '[]'
  252. flexmock(module).should_receive('log_command')
  253. flexmock(module.os, environ={'a': 'b'})
  254. flexmock(module.subprocess).should_receive('check_output').with_args(
  255. full_command, stderr=None, shell=False, env=None, cwd=None
  256. ).and_return(flexmock(decode=lambda: expected_output)).once()
  257. output = module.execute_command_and_capture_output(full_command)
  258. assert output == expected_output
  259. def test_execute_command_and_capture_output_with_capture_stderr_returns_stderr():
  260. full_command = ['foo', 'bar']
  261. expected_output = '[]'
  262. flexmock(module).should_receive('log_command')
  263. flexmock(module.os, environ={'a': 'b'})
  264. flexmock(module.subprocess).should_receive('check_output').with_args(
  265. full_command, stderr=module.subprocess.STDOUT, shell=False, env=None, cwd=None
  266. ).and_return(flexmock(decode=lambda: expected_output)).once()
  267. output = module.execute_command_and_capture_output(full_command, capture_stderr=True)
  268. assert output == expected_output
  269. def test_execute_command_and_capture_output_returns_output_when_process_error_is_not_considered_an_error():
  270. full_command = ['foo', 'bar']
  271. expected_output = '[]'
  272. err_output = b'[]'
  273. flexmock(module).should_receive('log_command')
  274. flexmock(module.os, environ={'a': 'b'})
  275. flexmock(module.subprocess).should_receive('check_output').with_args(
  276. full_command, stderr=None, shell=False, env=None, cwd=None
  277. ).and_raise(subprocess.CalledProcessError(1, full_command, err_output)).once()
  278. flexmock(module).should_receive('interpret_exit_code').and_return(
  279. module.Exit_status.SUCCESS
  280. ).once()
  281. output = module.execute_command_and_capture_output(full_command)
  282. assert output == expected_output
  283. def test_execute_command_and_capture_output_raises_when_command_errors():
  284. full_command = ['foo', 'bar']
  285. expected_output = '[]'
  286. flexmock(module).should_receive('log_command')
  287. flexmock(module.os, environ={'a': 'b'})
  288. flexmock(module.subprocess).should_receive('check_output').with_args(
  289. full_command, stderr=None, shell=False, env=None, cwd=None
  290. ).and_raise(subprocess.CalledProcessError(2, full_command, expected_output)).once()
  291. flexmock(module).should_receive('interpret_exit_code').and_return(
  292. module.Exit_status.ERROR
  293. ).once()
  294. with pytest.raises(subprocess.CalledProcessError):
  295. module.execute_command_and_capture_output(full_command)
  296. def test_execute_command_and_capture_output_returns_output_with_shell():
  297. full_command = ['foo', 'bar']
  298. expected_output = '[]'
  299. flexmock(module).should_receive('log_command')
  300. flexmock(module.os, environ={'a': 'b'})
  301. flexmock(module.subprocess).should_receive('check_output').with_args(
  302. 'foo bar', stderr=None, shell=True, env=None, cwd=None
  303. ).and_return(flexmock(decode=lambda: expected_output)).once()
  304. output = module.execute_command_and_capture_output(full_command, shell=True)
  305. assert output == expected_output
  306. def test_execute_command_and_capture_output_returns_output_with_extra_environment():
  307. full_command = ['foo', 'bar']
  308. expected_output = '[]'
  309. flexmock(module).should_receive('log_command')
  310. flexmock(module.os, environ={'a': 'b'})
  311. flexmock(module.subprocess).should_receive('check_output').with_args(
  312. full_command,
  313. stderr=None,
  314. shell=False,
  315. env={'a': 'b', 'c': 'd'},
  316. cwd=None,
  317. ).and_return(flexmock(decode=lambda: expected_output)).once()
  318. output = module.execute_command_and_capture_output(
  319. full_command, shell=False, extra_environment={'c': 'd'}
  320. )
  321. assert output == expected_output
  322. def test_execute_command_and_capture_output_returns_output_with_working_directory():
  323. full_command = ['foo', 'bar']
  324. expected_output = '[]'
  325. flexmock(module).should_receive('log_command')
  326. flexmock(module.os, environ={'a': 'b'})
  327. flexmock(module.subprocess).should_receive('check_output').with_args(
  328. full_command, stderr=None, shell=False, env=None, cwd='/working'
  329. ).and_return(flexmock(decode=lambda: expected_output)).once()
  330. output = module.execute_command_and_capture_output(
  331. full_command, shell=False, working_directory='/working'
  332. )
  333. assert output == expected_output
  334. def test_execute_command_with_processes_calls_full_command():
  335. full_command = ['foo', 'bar']
  336. processes = (flexmock(),)
  337. flexmock(module).should_receive('log_command')
  338. flexmock(module.os, environ={'a': 'b'})
  339. flexmock(module.subprocess).should_receive('Popen').with_args(
  340. full_command,
  341. stdin=None,
  342. stdout=module.subprocess.PIPE,
  343. stderr=module.subprocess.STDOUT,
  344. shell=False,
  345. env=None,
  346. cwd=None,
  347. ).and_return(flexmock(stdout=None)).once()
  348. flexmock(module).should_receive('log_outputs')
  349. output = module.execute_command_with_processes(full_command, processes)
  350. assert output is None
  351. def test_execute_command_with_processes_returns_output_with_output_log_level_none():
  352. full_command = ['foo', 'bar']
  353. processes = (flexmock(),)
  354. flexmock(module).should_receive('log_command')
  355. flexmock(module.os, environ={'a': 'b'})
  356. process = flexmock(stdout=None)
  357. flexmock(module.subprocess).should_receive('Popen').with_args(
  358. full_command,
  359. stdin=None,
  360. stdout=module.subprocess.PIPE,
  361. stderr=module.subprocess.STDOUT,
  362. shell=False,
  363. env=None,
  364. cwd=None,
  365. ).and_return(process).once()
  366. flexmock(module).should_receive('log_outputs').and_return({process: 'out'})
  367. output = module.execute_command_with_processes(full_command, processes, output_log_level=None)
  368. assert output == 'out'
  369. def test_execute_command_with_processes_calls_full_command_with_output_file():
  370. full_command = ['foo', 'bar']
  371. processes = (flexmock(),)
  372. output_file = flexmock(name='test')
  373. flexmock(module).should_receive('log_command')
  374. flexmock(module.os, environ={'a': 'b'})
  375. flexmock(module.subprocess).should_receive('Popen').with_args(
  376. full_command,
  377. stdin=None,
  378. stdout=output_file,
  379. stderr=module.subprocess.PIPE,
  380. shell=False,
  381. env=None,
  382. cwd=None,
  383. ).and_return(flexmock(stderr=None)).once()
  384. flexmock(module).should_receive('log_outputs')
  385. output = module.execute_command_with_processes(full_command, processes, output_file=output_file)
  386. assert output is None
  387. def test_execute_command_with_processes_calls_full_command_without_capturing_output():
  388. full_command = ['foo', 'bar']
  389. processes = (flexmock(),)
  390. flexmock(module).should_receive('log_command')
  391. flexmock(module.os, environ={'a': 'b'})
  392. flexmock(module.subprocess).should_receive('Popen').with_args(
  393. full_command, stdin=None, stdout=None, stderr=None, shell=False, env=None, cwd=None
  394. ).and_return(flexmock(wait=lambda: 0)).once()
  395. flexmock(module).should_receive('interpret_exit_code').and_return(module.Exit_status.SUCCESS)
  396. flexmock(module).should_receive('log_outputs')
  397. output = module.execute_command_with_processes(
  398. full_command, processes, output_file=module.DO_NOT_CAPTURE
  399. )
  400. assert output is None
  401. def test_execute_command_with_processes_calls_full_command_with_input_file():
  402. full_command = ['foo', 'bar']
  403. processes = (flexmock(),)
  404. input_file = flexmock(name='test')
  405. flexmock(module).should_receive('log_command')
  406. flexmock(module.os, environ={'a': 'b'})
  407. flexmock(module.subprocess).should_receive('Popen').with_args(
  408. full_command,
  409. stdin=input_file,
  410. stdout=module.subprocess.PIPE,
  411. stderr=module.subprocess.STDOUT,
  412. shell=False,
  413. env=None,
  414. cwd=None,
  415. ).and_return(flexmock(stdout=None)).once()
  416. flexmock(module).should_receive('log_outputs')
  417. output = module.execute_command_with_processes(full_command, processes, input_file=input_file)
  418. assert output is None
  419. def test_execute_command_with_processes_calls_full_command_with_shell():
  420. full_command = ['foo', 'bar']
  421. processes = (flexmock(),)
  422. flexmock(module).should_receive('log_command')
  423. flexmock(module.os, environ={'a': 'b'})
  424. flexmock(module.subprocess).should_receive('Popen').with_args(
  425. ' '.join(full_command),
  426. stdin=None,
  427. stdout=module.subprocess.PIPE,
  428. stderr=module.subprocess.STDOUT,
  429. shell=True,
  430. env=None,
  431. cwd=None,
  432. ).and_return(flexmock(stdout=None)).once()
  433. flexmock(module).should_receive('log_outputs')
  434. output = module.execute_command_with_processes(full_command, processes, shell=True)
  435. assert output is None
  436. def test_execute_command_with_processes_calls_full_command_with_extra_environment():
  437. full_command = ['foo', 'bar']
  438. processes = (flexmock(),)
  439. flexmock(module).should_receive('log_command')
  440. flexmock(module.os, environ={'a': 'b'})
  441. flexmock(module.subprocess).should_receive('Popen').with_args(
  442. full_command,
  443. stdin=None,
  444. stdout=module.subprocess.PIPE,
  445. stderr=module.subprocess.STDOUT,
  446. shell=False,
  447. env={'a': 'b', 'c': 'd'},
  448. cwd=None,
  449. ).and_return(flexmock(stdout=None)).once()
  450. flexmock(module).should_receive('log_outputs')
  451. output = module.execute_command_with_processes(
  452. full_command, processes, extra_environment={'c': 'd'}
  453. )
  454. assert output is None
  455. def test_execute_command_with_processes_calls_full_command_with_working_directory():
  456. full_command = ['foo', 'bar']
  457. processes = (flexmock(),)
  458. flexmock(module).should_receive('log_command')
  459. flexmock(module.os, environ={'a': 'b'})
  460. flexmock(module.subprocess).should_receive('Popen').with_args(
  461. full_command,
  462. stdin=None,
  463. stdout=module.subprocess.PIPE,
  464. stderr=module.subprocess.STDOUT,
  465. shell=False,
  466. env=None,
  467. cwd='/working',
  468. ).and_return(flexmock(stdout=None)).once()
  469. flexmock(module).should_receive('log_outputs')
  470. output = module.execute_command_with_processes(
  471. full_command, processes, working_directory='/working'
  472. )
  473. assert output is None
  474. def test_execute_command_with_processes_kills_processes_on_error():
  475. full_command = ['foo', 'bar']
  476. flexmock(module).should_receive('log_command')
  477. process = flexmock(stdout=flexmock(read=lambda count: None))
  478. process.should_receive('poll')
  479. process.should_receive('kill').once()
  480. processes = (process,)
  481. flexmock(module.os, environ={'a': 'b'})
  482. flexmock(module.subprocess).should_receive('Popen').with_args(
  483. full_command,
  484. stdin=None,
  485. stdout=module.subprocess.PIPE,
  486. stderr=module.subprocess.STDOUT,
  487. shell=False,
  488. env=None,
  489. cwd=None,
  490. ).and_raise(subprocess.CalledProcessError(1, full_command, 'error')).once()
  491. flexmock(module).should_receive('log_outputs').never()
  492. with pytest.raises(subprocess.CalledProcessError):
  493. module.execute_command_with_processes(full_command, processes)