test_validate.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import io
  2. import string
  3. import sys
  4. from flexmock import flexmock
  5. import pytest
  6. from borgmatic.config import validate as module
  7. def test_schema_filename_returns_plausable_path():
  8. schema_path = module.schema_filename()
  9. assert schema_path.endswith('/schema.yaml')
  10. def mock_config_and_schema(config_yaml, schema_yaml=None):
  11. '''
  12. Set up mocks for the given config config YAML string and the schema YAML string, or the default
  13. schema if no schema is provided. The idea is that that the code under test consumes these mocks
  14. when parsing the configuration.
  15. '''
  16. config_stream = io.StringIO(config_yaml)
  17. if schema_yaml is None:
  18. schema_stream = open(module.schema_filename())
  19. else:
  20. schema_stream = io.StringIO(schema_yaml)
  21. builtins = flexmock(sys.modules['builtins'])
  22. builtins.should_receive('open').with_args('config.yaml').and_return(config_stream)
  23. builtins.should_receive('open').with_args('schema.yaml').and_return(schema_stream)
  24. def test_parse_configuration_transforms_file_into_mapping():
  25. mock_config_and_schema(
  26. '''
  27. location:
  28. source_directories:
  29. - /home
  30. - /etc
  31. repositories:
  32. - hostname.borg
  33. retention:
  34. keep_minutely: 60
  35. keep_hourly: 24
  36. keep_daily: 7
  37. consistency:
  38. checks:
  39. - repository
  40. - archives
  41. '''
  42. )
  43. result = module.parse_configuration('config.yaml', 'schema.yaml')
  44. assert result == {
  45. 'location': {'source_directories': ['/home', '/etc'], 'repositories': ['hostname.borg']},
  46. 'retention': {'keep_daily': 7, 'keep_hourly': 24, 'keep_minutely': 60},
  47. 'consistency': {'checks': ['repository', 'archives']},
  48. }
  49. def test_parse_configuration_passes_through_quoted_punctuation():
  50. escaped_punctuation = string.punctuation.replace('\\', r'\\').replace('"', r'\"')
  51. mock_config_and_schema(
  52. '''
  53. location:
  54. source_directories:
  55. - /home
  56. repositories:
  57. - "{}.borg"
  58. '''.format(
  59. escaped_punctuation
  60. )
  61. )
  62. result = module.parse_configuration('config.yaml', 'schema.yaml')
  63. assert result == {
  64. 'location': {
  65. 'source_directories': ['/home'],
  66. 'repositories': ['{}.borg'.format(string.punctuation)],
  67. }
  68. }
  69. def test_parse_configuration_with_schema_lacking_examples_does_not_raise():
  70. mock_config_and_schema(
  71. '''
  72. location:
  73. source_directories:
  74. - /home
  75. repositories:
  76. - hostname.borg
  77. ''',
  78. '''
  79. map:
  80. location:
  81. required: true
  82. map:
  83. source_directories:
  84. required: true
  85. seq:
  86. - type: scalar
  87. repositories:
  88. required: true
  89. seq:
  90. - type: scalar
  91. ''',
  92. )
  93. module.parse_configuration('config.yaml', 'schema.yaml')
  94. def test_parse_configuration_raises_for_missing_config_file():
  95. with pytest.raises(FileNotFoundError):
  96. module.parse_configuration('config.yaml', 'schema.yaml')
  97. def test_parse_configuration_raises_for_missing_schema_file():
  98. mock_config_and_schema('')
  99. builtins = flexmock(sys.modules['builtins'])
  100. builtins.should_receive('open').with_args('schema.yaml').and_raise(FileNotFoundError)
  101. with pytest.raises(FileNotFoundError):
  102. module.parse_configuration('config.yaml', 'schema.yaml')
  103. def test_parse_configuration_raises_for_syntax_error():
  104. mock_config_and_schema('foo:\nbar')
  105. with pytest.raises(ValueError):
  106. module.parse_configuration('config.yaml', 'schema.yaml')
  107. def test_parse_configuration_raises_for_validation_error():
  108. mock_config_and_schema(
  109. '''
  110. location:
  111. source_directories: yes
  112. repositories:
  113. - hostname.borg
  114. '''
  115. )
  116. with pytest.raises(module.Validation_error):
  117. module.parse_configuration('config.yaml', 'schema.yaml')