test_override.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import pytest
  2. import ruamel.yaml
  3. from flexmock import flexmock
  4. from borgmatic.config import override as module
  5. def test_set_values_with_empty_keys_bails():
  6. config = {}
  7. module.set_values(config, keys=(), value='value')
  8. assert config == {}
  9. def test_set_values_with_one_key_sets_it_into_config():
  10. config = {}
  11. module.set_values(config, keys=('key',), value='value')
  12. assert config == {'key': 'value'}
  13. def test_set_values_with_one_key_overwrites_existing_key():
  14. config = {'key': 'old_value', 'other': 'other_value'}
  15. module.set_values(config, keys=('key',), value='value')
  16. assert config == {'key': 'value', 'other': 'other_value'}
  17. def test_set_values_with_multiple_keys_creates_hierarchy():
  18. config = {}
  19. module.set_values(config, ('option', 'suboption'), 'value')
  20. assert config == {'option': {'suboption': 'value'}}
  21. def test_set_values_with_multiple_keys_updates_hierarchy():
  22. config = {'option': {'other': 'other_value'}}
  23. module.set_values(config, ('option', 'key'), 'value')
  24. assert config == {'option': {'key': 'value', 'other': 'other_value'}}
  25. def test_set_values_with_key_when_list_index_expected_errors():
  26. config = {'option': ['foo', 'bar', 'baz']}
  27. with pytest.raises(ValueError):
  28. module.set_values(config, keys=('option', 'key'), value='value')
  29. @pytest.mark.parametrize(
  30. 'schema,option_keys,expected_type',
  31. (
  32. ({'properties': {'foo': {'type': 'array'}}}, ('foo',), 'array'),
  33. (
  34. {'properties': {'foo': {'properties': {'bar': {'type': 'array'}}}}},
  35. ('foo', 'bar'),
  36. 'array',
  37. ),
  38. ({'properties': {'foo': {'type': 'array'}}}, ('other',), None),
  39. ({'properties': {'foo': {'description': 'stuff'}}}, ('foo',), None),
  40. ({}, ('foo',), None),
  41. ),
  42. )
  43. def test_type_for_option_grabs_type_if_found_in_schema(schema, option_keys, expected_type):
  44. assert module.type_for_option(schema, option_keys) == expected_type
  45. @pytest.mark.parametrize(
  46. 'key,expected_key',
  47. (
  48. (('foo', 'bar'), ('foo', 'bar')),
  49. (('location', 'foo'), ('foo',)),
  50. (('storage', 'foo'), ('foo',)),
  51. (('retention', 'foo'), ('foo',)),
  52. (('consistency', 'foo'), ('foo',)),
  53. (('output', 'foo'), ('foo',)),
  54. (('hooks', 'foo', 'bar'), ('foo', 'bar')),
  55. (('foo', 'hooks'), ('foo', 'hooks')),
  56. ),
  57. )
  58. def test_strip_section_names_passes_through_key_without_section_name(key, expected_key):
  59. assert module.strip_section_names(key) == expected_key
  60. def test_parse_overrides_splits_keys_and_values():
  61. flexmock(module).should_receive('strip_section_names').replace_with(lambda value: value)
  62. flexmock(module).should_receive('type_for_option').and_return('string')
  63. flexmock(module).should_receive('convert_value_type').replace_with(
  64. lambda value, option_type: value
  65. )
  66. raw_overrides = ['option.my_option=value1', 'other_option=value2']
  67. expected_result = (
  68. (('option', 'my_option'), 'value1'),
  69. (('other_option'), 'value2'),
  70. )
  71. module.parse_overrides(raw_overrides, schema={}) == expected_result
  72. def test_parse_overrides_allows_value_with_equal_sign():
  73. flexmock(module).should_receive('strip_section_names').replace_with(lambda value: value)
  74. flexmock(module).should_receive('type_for_option').and_return('string')
  75. flexmock(module).should_receive('convert_value_type').replace_with(
  76. lambda value, option_type: value
  77. )
  78. raw_overrides = ['option=this===value']
  79. expected_result = ((('option',), 'this===value'),)
  80. module.parse_overrides(raw_overrides, schema={}) == expected_result
  81. def test_parse_overrides_raises_on_missing_equal_sign():
  82. flexmock(module).should_receive('strip_section_names').replace_with(lambda value: value)
  83. flexmock(module).should_receive('type_for_option').and_return('string')
  84. flexmock(module).should_receive('convert_value_type').replace_with(
  85. lambda value, option_type: value
  86. )
  87. raw_overrides = ['option']
  88. with pytest.raises(ValueError):
  89. module.parse_overrides(raw_overrides, schema={})
  90. def test_parse_overrides_raises_on_invalid_override_value():
  91. flexmock(module).should_receive('strip_section_names').replace_with(lambda value: value)
  92. flexmock(module).should_receive('type_for_option').and_return('string')
  93. flexmock(module).should_receive('convert_value_type').and_raise(ruamel.yaml.parser.ParserError)
  94. raw_overrides = ['option=[in valid]']
  95. with pytest.raises(ValueError):
  96. module.parse_overrides(raw_overrides, schema={})
  97. def test_parse_overrides_allows_value_with_single_key():
  98. flexmock(module).should_receive('strip_section_names').replace_with(lambda value: value)
  99. flexmock(module).should_receive('type_for_option').and_return('string')
  100. flexmock(module).should_receive('convert_value_type').replace_with(
  101. lambda value, option_type: value
  102. )
  103. raw_overrides = ['option=value']
  104. expected_result = ((('option',), 'value'),)
  105. module.parse_overrides(raw_overrides, schema={}) == expected_result
  106. def test_parse_overrides_handles_empty_overrides():
  107. module.parse_overrides(raw_overrides=None, schema={}) == ()