test_dispatch.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. import sys
  2. import pytest
  3. from flexmock import flexmock
  4. from borgmatic.hooks import dispatch as module
  5. def hook_function(hook_config, config, log_prefix, thing, value):
  6. '''
  7. This test function gets mocked out below.
  8. '''
  9. pass
  10. def test_call_hook_invokes_module_function_with_arguments_and_returns_value():
  11. config = {'super_hook': flexmock(), 'other_hook': flexmock()}
  12. expected_return_value = flexmock()
  13. test_module = sys.modules[__name__]
  14. flexmock(module).should_receive('get_submodule_names').with_args(
  15. module.borgmatic.hooks.data_source
  16. ).and_return(['other_hook'])
  17. flexmock(module).should_receive('get_submodule_names').with_args(
  18. module.borgmatic.hooks.monitoring
  19. ).and_return(['super_hook', 'third_hook'])
  20. flexmock(module.importlib).should_receive('import_module').with_args(
  21. 'borgmatic.hooks.monitoring.super_hook'
  22. ).and_return(test_module)
  23. flexmock(test_module).should_receive('hook_function').with_args(
  24. config['super_hook'], config, 'prefix', 55, value=66
  25. ).and_return(expected_return_value).once()
  26. return_value = module.call_hook('hook_function', config, 'prefix', 'super_hook', 55, value=66)
  27. assert return_value == expected_return_value
  28. def test_call_hook_probes_config_with_databases_suffix():
  29. config = {'super_hook_databases': flexmock(), 'other_hook': flexmock()}
  30. expected_return_value = flexmock()
  31. test_module = sys.modules[__name__]
  32. flexmock(module).should_receive('get_submodule_names').with_args(
  33. module.borgmatic.hooks.data_source
  34. ).and_return(['other_hook'])
  35. flexmock(module).should_receive('get_submodule_names').with_args(
  36. module.borgmatic.hooks.monitoring
  37. ).and_return(['super_hook', 'third_hook'])
  38. flexmock(module.importlib).should_receive('import_module').with_args(
  39. 'borgmatic.hooks.monitoring.super_hook'
  40. ).and_return(test_module)
  41. flexmock(test_module).should_receive('hook_function').with_args(
  42. config['super_hook_databases'], config, 'prefix', 55, value=66
  43. ).and_return(expected_return_value).once()
  44. return_value = module.call_hook('hook_function', config, 'prefix', 'super_hook', 55, value=66)
  45. assert return_value == expected_return_value
  46. def test_call_hook_strips_databases_suffix_from_hook_name():
  47. config = {'super_hook_databases': flexmock(), 'other_hook_databases': flexmock()}
  48. expected_return_value = flexmock()
  49. test_module = sys.modules[__name__]
  50. flexmock(module).should_receive('get_submodule_names').with_args(
  51. module.borgmatic.hooks.data_source
  52. ).and_return(['other_hook'])
  53. flexmock(module).should_receive('get_submodule_names').with_args(
  54. module.borgmatic.hooks.monitoring
  55. ).and_return(['super_hook', 'third_hook'])
  56. flexmock(module.importlib).should_receive('import_module').with_args(
  57. 'borgmatic.hooks.monitoring.super_hook'
  58. ).and_return(test_module)
  59. flexmock(test_module).should_receive('hook_function').with_args(
  60. config['super_hook_databases'], config, 'prefix', 55, value=66
  61. ).and_return(expected_return_value).once()
  62. return_value = module.call_hook(
  63. 'hook_function', config, 'prefix', 'super_hook_databases', 55, value=66
  64. )
  65. assert return_value == expected_return_value
  66. def test_call_hook_without_hook_config_invokes_module_function_with_arguments_and_returns_value():
  67. config = {'other_hook': flexmock()}
  68. expected_return_value = flexmock()
  69. test_module = sys.modules[__name__]
  70. flexmock(module).should_receive('get_submodule_names').with_args(
  71. module.borgmatic.hooks.data_source
  72. ).and_return(['other_hook'])
  73. flexmock(module).should_receive('get_submodule_names').with_args(
  74. module.borgmatic.hooks.monitoring
  75. ).and_return(['super_hook', 'third_hook'])
  76. flexmock(module.importlib).should_receive('import_module').with_args(
  77. 'borgmatic.hooks.monitoring.super_hook'
  78. ).and_return(test_module)
  79. flexmock(test_module).should_receive('hook_function').with_args(
  80. None, config, 'prefix', 55, value=66
  81. ).and_return(expected_return_value).once()
  82. return_value = module.call_hook('hook_function', config, 'prefix', 'super_hook', 55, value=66)
  83. assert return_value == expected_return_value
  84. def test_call_hook_without_corresponding_module_raises():
  85. config = {'super_hook': flexmock(), 'other_hook': flexmock()}
  86. test_module = sys.modules[__name__]
  87. flexmock(module).should_receive('get_submodule_names').with_args(
  88. module.borgmatic.hooks.data_source
  89. ).and_return(['other_hook'])
  90. flexmock(module).should_receive('get_submodule_names').with_args(
  91. module.borgmatic.hooks.monitoring
  92. ).and_return(['some_hook'])
  93. flexmock(module.importlib).should_receive('import_module').with_args(
  94. 'borgmatic.hooks.monitoring.super_hook'
  95. ).and_return(test_module)
  96. flexmock(test_module).should_receive('hook_function').never()
  97. with pytest.raises(ValueError):
  98. module.call_hook('hook_function', config, 'prefix', 'super_hook', 55, value=66)
  99. def test_call_hook_skips_non_hook_modules():
  100. config = {'not_a_hook': flexmock(), 'other_hook': flexmock()}
  101. flexmock(module).should_receive('get_submodule_names').with_args(
  102. module.borgmatic.hooks.data_source
  103. ).and_return(['other_hook'])
  104. flexmock(module).should_receive('get_submodule_names').with_args(
  105. module.borgmatic.hooks.monitoring
  106. ).and_return(['not_a_hook', 'third_hook'])
  107. not_a_hook_module = flexmock(IS_A_HOOK=False)
  108. flexmock(module.importlib).should_receive('import_module').with_args(
  109. 'borgmatic.hooks.monitoring.not_a_hook'
  110. ).and_return(not_a_hook_module)
  111. return_value = module.call_hook('hook_function', config, 'prefix', 'not_a_hook', 55, value=66)
  112. assert return_value is None
  113. def test_call_hooks_calls_each_hook_and_collects_return_values():
  114. config = {'super_hook': flexmock(), 'other_hook': flexmock()}
  115. expected_return_values = {'super_hook': flexmock(), 'other_hook': flexmock()}
  116. flexmock(module.importlib).should_receive('import_module').with_args(
  117. 'borgmatic.hooks.monitoring'
  118. ).and_return(module.borgmatic.hooks.monitoring)
  119. flexmock(module).should_receive('get_submodule_names').with_args(
  120. module.borgmatic.hooks.monitoring
  121. ).and_return(['super_hook', 'other_hook'])
  122. flexmock(module).should_receive('call_hook').and_return(
  123. expected_return_values['super_hook']
  124. ).and_return(expected_return_values['other_hook'])
  125. return_values = module.call_hooks('do_stuff', config, 'prefix', module.Hook_type.MONITORING, 55)
  126. assert return_values == expected_return_values
  127. def test_call_hooks_calls_skips_return_values_for_unconfigured_hooks():
  128. config = {'super_hook': flexmock()}
  129. expected_return_values = {'super_hook': flexmock()}
  130. flexmock(module.importlib).should_receive('import_module').with_args(
  131. 'borgmatic.hooks.monitoring'
  132. ).and_return(module.borgmatic.hooks.monitoring)
  133. flexmock(module).should_receive('get_submodule_names').with_args(
  134. module.borgmatic.hooks.monitoring
  135. ).and_return(['super_hook', 'other_hook'])
  136. flexmock(module).should_receive('call_hook').and_return(expected_return_values['super_hook'])
  137. return_values = module.call_hooks('do_stuff', config, 'prefix', module.Hook_type.MONITORING, 55)
  138. assert return_values == expected_return_values
  139. def test_call_hooks_calls_treats_null_hook_as_optionless():
  140. config = {'super_hook': flexmock(), 'other_hook': None}
  141. expected_return_values = {'super_hook': flexmock(), 'other_hook': flexmock()}
  142. flexmock(module.importlib).should_receive('import_module').with_args(
  143. 'borgmatic.hooks.monitoring'
  144. ).and_return(module.borgmatic.hooks.monitoring)
  145. flexmock(module).should_receive('get_submodule_names').with_args(
  146. module.borgmatic.hooks.monitoring
  147. ).and_return(['super_hook', 'other_hook'])
  148. flexmock(module).should_receive('call_hook').and_return(
  149. expected_return_values['super_hook']
  150. ).and_return(expected_return_values['other_hook'])
  151. return_values = module.call_hooks('do_stuff', config, 'prefix', module.Hook_type.MONITORING, 55)
  152. assert return_values == expected_return_values
  153. def test_call_hooks_calls_looks_up_databases_suffix_in_config():
  154. config = {'super_hook_databases': flexmock(), 'other_hook': flexmock()}
  155. expected_return_values = {'super_hook': flexmock(), 'other_hook': flexmock()}
  156. flexmock(module.importlib).should_receive('import_module').with_args(
  157. 'borgmatic.hooks.monitoring'
  158. ).and_return(module.borgmatic.hooks.monitoring)
  159. flexmock(module).should_receive('get_submodule_names').with_args(
  160. module.borgmatic.hooks.monitoring
  161. ).and_return(['super_hook', 'other_hook'])
  162. flexmock(module).should_receive('call_hook').and_return(
  163. expected_return_values['super_hook']
  164. ).and_return(expected_return_values['other_hook'])
  165. return_values = module.call_hooks('do_stuff', config, 'prefix', module.Hook_type.MONITORING, 55)
  166. assert return_values == expected_return_values
  167. def test_call_hooks_even_if_unconfigured_calls_each_hook_and_collects_return_values():
  168. config = {'super_hook': flexmock(), 'other_hook': flexmock()}
  169. expected_return_values = {'super_hook': flexmock(), 'other_hook': flexmock()}
  170. flexmock(module.importlib).should_receive('import_module').with_args(
  171. 'borgmatic.hooks.monitoring'
  172. ).and_return(module.borgmatic.hooks.monitoring)
  173. flexmock(module).should_receive('get_submodule_names').with_args(
  174. module.borgmatic.hooks.monitoring
  175. ).and_return(['super_hook', 'other_hook'])
  176. flexmock(module).should_receive('call_hook').and_return(
  177. expected_return_values['super_hook']
  178. ).and_return(expected_return_values['other_hook'])
  179. return_values = module.call_hooks_even_if_unconfigured(
  180. 'do_stuff', config, 'prefix', module.Hook_type.MONITORING, 55
  181. )
  182. assert return_values == expected_return_values
  183. def test_call_hooks_even_if_unconfigured_calls_each_hook_configured_or_not_and_collects_return_values():
  184. config = {'other_hook': flexmock()}
  185. expected_return_values = {'super_hook': flexmock(), 'other_hook': flexmock()}
  186. flexmock(module.importlib).should_receive('import_module').with_args(
  187. 'borgmatic.hooks.monitoring'
  188. ).and_return(module.borgmatic.hooks.monitoring)
  189. flexmock(module).should_receive('get_submodule_names').with_args(
  190. module.borgmatic.hooks.monitoring
  191. ).and_return(['super_hook', 'other_hook'])
  192. flexmock(module).should_receive('call_hook').and_return(
  193. expected_return_values['super_hook']
  194. ).and_return(expected_return_values['other_hook'])
  195. return_values = module.call_hooks_even_if_unconfigured(
  196. 'do_stuff', config, 'prefix', module.Hook_type.MONITORING, 55
  197. )
  198. assert return_values == expected_return_values