test_execute.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import logging
  2. import subprocess
  3. import pytest
  4. from flexmock import flexmock
  5. from borgmatic import execute as module
  6. def test_log_outputs_logs_each_line_separately():
  7. flexmock(module.logger).should_receive('log').with_args(logging.INFO, 'hi').once()
  8. flexmock(module.logger).should_receive('log').with_args(logging.INFO, 'there').once()
  9. flexmock(module).should_receive('exit_code_indicates_error').and_return(False)
  10. hi_process = subprocess.Popen(['echo', 'hi'], stdout=subprocess.PIPE)
  11. flexmock(module).should_receive('output_buffer_for_process').with_args(
  12. hi_process, ()
  13. ).and_return(hi_process.stdout)
  14. there_process = subprocess.Popen(['echo', 'there'], stdout=subprocess.PIPE)
  15. flexmock(module).should_receive('output_buffer_for_process').with_args(
  16. there_process, ()
  17. ).and_return(there_process.stdout)
  18. module.log_outputs(
  19. (hi_process, there_process),
  20. exclude_stdouts=(),
  21. output_log_level=logging.INFO,
  22. borg_local_path='borg',
  23. )
  24. def test_log_outputs_skips_logs_for_process_with_none_stdout():
  25. flexmock(module.logger).should_receive('log').with_args(logging.INFO, 'hi').never()
  26. flexmock(module.logger).should_receive('log').with_args(logging.INFO, 'there').once()
  27. flexmock(module).should_receive('exit_code_indicates_error').and_return(False)
  28. hi_process = subprocess.Popen(['echo', 'hi'], stdout=None)
  29. flexmock(module).should_receive('output_buffer_for_process').with_args(
  30. hi_process, ()
  31. ).and_return(hi_process.stdout)
  32. there_process = subprocess.Popen(['echo', 'there'], stdout=subprocess.PIPE)
  33. flexmock(module).should_receive('output_buffer_for_process').with_args(
  34. there_process, ()
  35. ).and_return(there_process.stdout)
  36. module.log_outputs(
  37. (hi_process, there_process),
  38. exclude_stdouts=(),
  39. output_log_level=logging.INFO,
  40. borg_local_path='borg',
  41. )
  42. def test_log_outputs_includes_error_output_in_exception():
  43. flexmock(module.logger).should_receive('log')
  44. flexmock(module).should_receive('exit_code_indicates_error').and_return(True)
  45. flexmock(module).should_receive('command_for_process').and_return('grep')
  46. process = subprocess.Popen(['grep'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  47. flexmock(module).should_receive('output_buffer_for_process').and_return(process.stdout)
  48. with pytest.raises(subprocess.CalledProcessError) as error:
  49. module.log_outputs(
  50. (process,), exclude_stdouts=(), output_log_level=logging.INFO, borg_local_path='borg'
  51. )
  52. assert error.value.returncode == 2
  53. assert error.value.output
  54. def test_log_outputs_skips_error_output_in_exception_for_process_with_none_stdout():
  55. flexmock(module.logger).should_receive('log')
  56. flexmock(module).should_receive('exit_code_indicates_error').and_return(True)
  57. flexmock(module).should_receive('command_for_process').and_return('grep')
  58. process = subprocess.Popen(['grep'], stdout=None)
  59. flexmock(module).should_receive('output_buffer_for_process').and_return(process.stdout)
  60. with pytest.raises(subprocess.CalledProcessError) as error:
  61. module.log_outputs(
  62. (process,), exclude_stdouts=(), output_log_level=logging.INFO, borg_local_path='borg'
  63. )
  64. assert error.value.returncode == 2
  65. assert not error.value.output
  66. def test_log_outputs_kills_other_processes_when_one_errors():
  67. flexmock(module.logger).should_receive('log')
  68. flexmock(module).should_receive('exit_code_indicates_error').and_return(True)
  69. flexmock(module).should_receive('command_for_process').and_return('grep')
  70. process = subprocess.Popen(['grep'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  71. other_process = subprocess.Popen(
  72. ['watch', 'true'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
  73. )
  74. flexmock(module).should_receive('output_buffer_for_process').with_args(process, ()).and_return(
  75. process.stdout
  76. )
  77. flexmock(module).should_receive('output_buffer_for_process').with_args(
  78. other_process, ()
  79. ).and_return(other_process.stdout)
  80. flexmock(other_process).should_receive('kill').once()
  81. with pytest.raises(subprocess.CalledProcessError) as error:
  82. module.log_outputs(
  83. (process, other_process),
  84. exclude_stdouts=(),
  85. output_log_level=logging.INFO,
  86. borg_local_path='borg',
  87. )
  88. assert error.value.returncode == 2
  89. assert error.value.output
  90. def test_log_outputs_truncates_long_error_output():
  91. flexmock(module).ERROR_OUTPUT_MAX_LINE_COUNT = 0
  92. flexmock(module.logger).should_receive('log')
  93. flexmock(module).should_receive('exit_code_indicates_error').and_return(True)
  94. flexmock(module).should_receive('command_for_process').and_return('grep')
  95. process = subprocess.Popen(['grep'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  96. flexmock(module).should_receive('output_buffer_for_process').and_return(process.stdout)
  97. with pytest.raises(subprocess.CalledProcessError) as error:
  98. module.log_outputs(
  99. (process,), exclude_stdouts=(), output_log_level=logging.INFO, borg_local_path='borg'
  100. )
  101. assert error.value.returncode == 2
  102. assert error.value.output.startswith('...')
  103. def test_log_outputs_with_no_output_logs_nothing():
  104. flexmock(module.logger).should_receive('log').never()
  105. flexmock(module).should_receive('exit_code_indicates_error').and_return(False)
  106. process = subprocess.Popen(['true'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  107. flexmock(module).should_receive('output_buffer_for_process').and_return(process.stdout)
  108. module.log_outputs(
  109. (process,), exclude_stdouts=(), output_log_level=logging.INFO, borg_local_path='borg'
  110. )