Move tests to the root of the repository, in keeping with more common convention.
This commit is contained in:
0
tests/integration/__init__.py
Normal file
0
tests/integration/__init__.py
Normal file
0
tests/integration/commands/__init__.py
Normal file
0
tests/integration/commands/__init__.py
Normal file
103
tests/integration/commands/test_borgmatic.py
Normal file
103
tests/integration/commands/test_borgmatic.py
Normal file
@@ -0,0 +1,103 @@
|
||||
from flexmock import flexmock
|
||||
import pytest
|
||||
|
||||
from borgmatic.commands import borgmatic as module
|
||||
|
||||
|
||||
def test_parse_arguments_with_no_arguments_uses_defaults():
|
||||
config_paths = ['default']
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(config_paths)
|
||||
|
||||
parser = module.parse_arguments()
|
||||
|
||||
assert parser.config_paths == config_paths
|
||||
assert parser.excludes_filename is None
|
||||
assert parser.verbosity is 0
|
||||
assert parser.json is False
|
||||
|
||||
|
||||
def test_parse_arguments_with_path_arguments_overrides_defaults():
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||
|
||||
parser = module.parse_arguments('--config', 'myconfig', '--excludes', 'myexcludes')
|
||||
|
||||
assert parser.config_paths == ['myconfig']
|
||||
assert parser.excludes_filename == 'myexcludes'
|
||||
assert parser.verbosity is 0
|
||||
|
||||
|
||||
def test_parse_arguments_with_multiple_config_paths_parses_as_list():
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||
|
||||
parser = module.parse_arguments('--config', 'myconfig', 'otherconfig')
|
||||
|
||||
assert parser.config_paths == ['myconfig', 'otherconfig']
|
||||
assert parser.verbosity is 0
|
||||
|
||||
|
||||
def test_parse_arguments_with_verbosity_flag_overrides_default():
|
||||
config_paths = ['default']
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(config_paths)
|
||||
|
||||
parser = module.parse_arguments('--verbosity', '1')
|
||||
|
||||
assert parser.config_paths == config_paths
|
||||
assert parser.excludes_filename is None
|
||||
assert parser.verbosity == 1
|
||||
|
||||
|
||||
def test_parse_arguments_with_json_flag_overrides_default():
|
||||
parser = module.parse_arguments('--list', '--json')
|
||||
assert parser.json is True
|
||||
|
||||
|
||||
def test_parse_arguments_with_no_actions_defaults_to_all_actions_enabled():
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||
|
||||
parser = module.parse_arguments()
|
||||
|
||||
assert parser.prune is True
|
||||
assert parser.create is True
|
||||
assert parser.check is True
|
||||
|
||||
|
||||
def test_parse_arguments_with_prune_action_leaves_other_actions_disabled():
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||
|
||||
parser = module.parse_arguments('--prune')
|
||||
|
||||
assert parser.prune is True
|
||||
assert parser.create is False
|
||||
assert parser.check is False
|
||||
|
||||
|
||||
def test_parse_arguments_with_multiple_actions_leaves_other_action_disabled():
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||
|
||||
parser = module.parse_arguments('--create', '--check')
|
||||
|
||||
assert parser.prune is False
|
||||
assert parser.create is True
|
||||
assert parser.check is True
|
||||
|
||||
|
||||
def test_parse_arguments_with_invalid_arguments_exits():
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
module.parse_arguments('--posix-me-harder')
|
||||
|
||||
|
||||
def test_parse_arguments_with_json_flag_with_list_or_info_flag_does_not_raise_any_error():
|
||||
module.parse_arguments('--list', '--json')
|
||||
module.parse_arguments('--info', '--json')
|
||||
|
||||
|
||||
def test_parse_arguments_with_json_flag_but_no_list_or_info_flag_raises_value_error():
|
||||
with pytest.raises(ValueError):
|
||||
module.parse_arguments('--json')
|
||||
|
||||
|
||||
def test_parse_arguments_with_json_flag_and_both_list_and_info_flag_raises_value_error():
|
||||
with pytest.raises(ValueError):
|
||||
module.parse_arguments('--list', '--info', '--json')
|
||||
50
tests/integration/commands/test_convert_config.py
Normal file
50
tests/integration/commands/test_convert_config.py
Normal file
@@ -0,0 +1,50 @@
|
||||
import os
|
||||
|
||||
from flexmock import flexmock
|
||||
import pytest
|
||||
|
||||
from borgmatic.commands import convert_config as module
|
||||
|
||||
|
||||
def test_parse_arguments_with_no_arguments_uses_defaults():
|
||||
flexmock(os.path).should_receive('exists').and_return(True)
|
||||
|
||||
parser = module.parse_arguments()
|
||||
|
||||
assert parser.source_config_filename == module.DEFAULT_SOURCE_CONFIG_FILENAME
|
||||
assert parser.source_excludes_filename == module.DEFAULT_SOURCE_EXCLUDES_FILENAME
|
||||
assert parser.destination_config_filename == module.DEFAULT_DESTINATION_CONFIG_FILENAME
|
||||
|
||||
|
||||
def test_parse_arguments_with_filename_arguments_overrides_defaults():
|
||||
flexmock(os.path).should_receive('exists').and_return(True)
|
||||
|
||||
parser = module.parse_arguments(
|
||||
'--source-config',
|
||||
'config',
|
||||
'--source-excludes',
|
||||
'excludes',
|
||||
'--destination-config',
|
||||
'config.yaml',
|
||||
)
|
||||
|
||||
assert parser.source_config_filename == 'config'
|
||||
assert parser.source_excludes_filename == 'excludes'
|
||||
assert parser.destination_config_filename == 'config.yaml'
|
||||
|
||||
|
||||
def test_parse_arguments_with_missing_default_excludes_file_sets_filename_to_none():
|
||||
flexmock(os.path).should_receive('exists').and_return(False)
|
||||
|
||||
parser = module.parse_arguments()
|
||||
|
||||
assert parser.source_config_filename == module.DEFAULT_SOURCE_CONFIG_FILENAME
|
||||
assert parser.source_excludes_filename is None
|
||||
assert parser.destination_config_filename == module.DEFAULT_DESTINATION_CONFIG_FILENAME
|
||||
|
||||
|
||||
def test_parse_arguments_with_invalid_arguments_exits():
|
||||
flexmock(os.path).should_receive('exists').and_return(True)
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
module.parse_arguments('--posix-me-harder')
|
||||
13
tests/integration/commands/test_generate_config.py
Normal file
13
tests/integration/commands/test_generate_config.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from borgmatic.commands import generate_config as module
|
||||
|
||||
|
||||
def test_parse_arguments_with_no_arguments_uses_defaults():
|
||||
parser = module.parse_arguments()
|
||||
|
||||
assert parser.destination_filename == module.DEFAULT_DESTINATION_CONFIG_FILENAME
|
||||
|
||||
|
||||
def test_parse_arguments_with_filename_argument_overrides_defaults():
|
||||
parser = module.parse_arguments('--destination', 'config.yaml')
|
||||
|
||||
assert parser.destination_filename == 'config.yaml'
|
||||
0
tests/integration/config/__init__.py
Normal file
0
tests/integration/config/__init__.py
Normal file
125
tests/integration/config/test_generate.py
Normal file
125
tests/integration/config/test_generate.py
Normal file
@@ -0,0 +1,125 @@
|
||||
from io import StringIO
|
||||
import os
|
||||
import sys
|
||||
|
||||
from flexmock import flexmock
|
||||
import pytest
|
||||
|
||||
from borgmatic.config import generate as module
|
||||
|
||||
|
||||
def test_insert_newline_before_comment_does_not_raise():
|
||||
field_name = 'foo'
|
||||
config = module.yaml.comments.CommentedMap([(field_name, 33)])
|
||||
config.yaml_set_comment_before_after_key(key=field_name, before='Comment')
|
||||
|
||||
module._insert_newline_before_comment(config, field_name)
|
||||
|
||||
|
||||
def test_comment_out_line_skips_blank_line():
|
||||
line = ' \n'
|
||||
|
||||
assert module._comment_out_line(line) == line
|
||||
|
||||
|
||||
def test_comment_out_line_skips_already_commented_out_line():
|
||||
line = ' # foo'
|
||||
|
||||
assert module._comment_out_line(line) == line
|
||||
|
||||
|
||||
def test_comment_out_line_comments_section_name():
|
||||
line = 'figgy-pudding:'
|
||||
|
||||
assert module._comment_out_line(line) == '#' + line
|
||||
|
||||
|
||||
def test_comment_out_line_comments_indented_option():
|
||||
line = ' enabled: true'
|
||||
|
||||
assert module._comment_out_line(line) == ' #enabled: true'
|
||||
|
||||
|
||||
def test_comment_out_optional_configuration_comments_optional_config_only():
|
||||
flexmock(module)._comment_out_line = lambda line: '#' + line
|
||||
config = '''
|
||||
foo:
|
||||
bar:
|
||||
- baz
|
||||
- quux
|
||||
|
||||
location:
|
||||
repositories:
|
||||
- one
|
||||
- two
|
||||
|
||||
other: thing
|
||||
'''
|
||||
|
||||
expected_config = '''
|
||||
#foo:
|
||||
# bar:
|
||||
# - baz
|
||||
# - quux
|
||||
#
|
||||
location:
|
||||
repositories:
|
||||
- one
|
||||
- two
|
||||
#
|
||||
# other: thing
|
||||
'''
|
||||
|
||||
assert module._comment_out_optional_configuration(config.strip()) == expected_config.strip()
|
||||
|
||||
|
||||
def test_render_configuration_does_not_raise():
|
||||
flexmock(module.yaml).should_receive('round_trip_dump')
|
||||
|
||||
module._render_configuration({})
|
||||
|
||||
|
||||
def test_write_configuration_does_not_raise():
|
||||
flexmock(os.path).should_receive('exists').and_return(False)
|
||||
flexmock(os).should_receive('makedirs')
|
||||
builtins = flexmock(sys.modules['builtins'])
|
||||
builtins.should_receive('open').and_return(StringIO())
|
||||
flexmock(os).should_receive('chmod')
|
||||
|
||||
module.write_configuration('config.yaml', 'config: yaml')
|
||||
|
||||
|
||||
def test_write_configuration_with_already_existing_file_raises():
|
||||
flexmock(os.path).should_receive('exists').and_return(True)
|
||||
|
||||
with pytest.raises(FileExistsError):
|
||||
module.write_configuration('config.yaml', 'config: yaml')
|
||||
|
||||
|
||||
def test_write_configuration_with_already_existing_directory_does_not_raise():
|
||||
flexmock(os.path).should_receive('exists').and_return(False)
|
||||
flexmock(os).should_receive('makedirs').and_raise(FileExistsError)
|
||||
builtins = flexmock(sys.modules['builtins'])
|
||||
builtins.should_receive('open').and_return(StringIO())
|
||||
flexmock(os).should_receive('chmod')
|
||||
|
||||
module.write_configuration('config.yaml', 'config: yaml')
|
||||
|
||||
|
||||
def test_add_comments_to_configuration_does_not_raise():
|
||||
# Ensure that it can deal with fields both in the schema and missing from the schema.
|
||||
config = module.yaml.comments.CommentedMap([('foo', 33), ('bar', 44), ('baz', 55)])
|
||||
schema = {'map': {'foo': {'desc': 'Foo'}, 'bar': {'desc': 'Bar'}}}
|
||||
|
||||
module.add_comments_to_configuration(config, schema)
|
||||
|
||||
|
||||
def test_generate_sample_configuration_does_not_raise():
|
||||
builtins = flexmock(sys.modules['builtins'])
|
||||
builtins.should_receive('open').with_args('schema.yaml').and_return('')
|
||||
flexmock(module).should_receive('_schema_to_sample_configuration')
|
||||
flexmock(module).should_receive('_render_configuration')
|
||||
flexmock(module).should_receive('_comment_out_optional_configuration')
|
||||
flexmock(module).should_receive('write_configuration')
|
||||
|
||||
module.generate_sample_configuration('config.yaml', 'schema.yaml')
|
||||
19
tests/integration/config/test_legacy.py
Normal file
19
tests/integration/config/test_legacy.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from io import StringIO
|
||||
|
||||
from collections import OrderedDict
|
||||
import string
|
||||
|
||||
from borgmatic.config import legacy as module
|
||||
|
||||
|
||||
def test_parse_section_options_with_punctuation_should_return_section_options():
|
||||
parser = module.RawConfigParser()
|
||||
parser.read_file(StringIO('[section]\nfoo: {}\n'.format(string.punctuation)))
|
||||
|
||||
section_format = module.Section_format(
|
||||
'section', (module.Config_option('foo', str, required=True),)
|
||||
)
|
||||
|
||||
config = module.parse_section_options(parser, section_format)
|
||||
|
||||
assert config == OrderedDict((('foo', string.punctuation),))
|
||||
153
tests/integration/config/test_validate.py
Normal file
153
tests/integration/config/test_validate.py
Normal file
@@ -0,0 +1,153 @@
|
||||
import io
|
||||
import string
|
||||
import sys
|
||||
|
||||
from flexmock import flexmock
|
||||
import pytest
|
||||
|
||||
from borgmatic.config import validate as module
|
||||
|
||||
|
||||
def test_schema_filename_returns_plausable_path():
|
||||
schema_path = module.schema_filename()
|
||||
|
||||
assert schema_path.endswith('/schema.yaml')
|
||||
|
||||
|
||||
def mock_config_and_schema(config_yaml, schema_yaml=None):
|
||||
'''
|
||||
Set up mocks for the given config config YAML string and the schema YAML string, or the default
|
||||
schema if no schema is provided. The idea is that that the code under test consumes these mocks
|
||||
when parsing the configuration.
|
||||
'''
|
||||
config_stream = io.StringIO(config_yaml)
|
||||
if schema_yaml is None:
|
||||
schema_stream = open(module.schema_filename())
|
||||
else:
|
||||
schema_stream = io.StringIO(schema_yaml)
|
||||
|
||||
builtins = flexmock(sys.modules['builtins'])
|
||||
builtins.should_receive('open').with_args('config.yaml').and_return(config_stream)
|
||||
builtins.should_receive('open').with_args('schema.yaml').and_return(schema_stream)
|
||||
|
||||
|
||||
def test_parse_configuration_transforms_file_into_mapping():
|
||||
mock_config_and_schema(
|
||||
'''
|
||||
location:
|
||||
source_directories:
|
||||
- /home
|
||||
- /etc
|
||||
|
||||
repositories:
|
||||
- hostname.borg
|
||||
|
||||
retention:
|
||||
keep_minutely: 60
|
||||
keep_hourly: 24
|
||||
keep_daily: 7
|
||||
|
||||
consistency:
|
||||
checks:
|
||||
- repository
|
||||
- archives
|
||||
'''
|
||||
)
|
||||
|
||||
result = module.parse_configuration('config.yaml', 'schema.yaml')
|
||||
|
||||
assert result == {
|
||||
'location': {'source_directories': ['/home', '/etc'], 'repositories': ['hostname.borg']},
|
||||
'retention': {'keep_daily': 7, 'keep_hourly': 24, 'keep_minutely': 60},
|
||||
'consistency': {'checks': ['repository', 'archives']},
|
||||
}
|
||||
|
||||
|
||||
def test_parse_configuration_passes_through_quoted_punctuation():
|
||||
escaped_punctuation = string.punctuation.replace('\\', r'\\').replace('"', r'\"')
|
||||
|
||||
mock_config_and_schema(
|
||||
'''
|
||||
location:
|
||||
source_directories:
|
||||
- /home
|
||||
|
||||
repositories:
|
||||
- "{}.borg"
|
||||
'''.format(
|
||||
escaped_punctuation
|
||||
)
|
||||
)
|
||||
|
||||
result = module.parse_configuration('config.yaml', 'schema.yaml')
|
||||
|
||||
assert result == {
|
||||
'location': {
|
||||
'source_directories': ['/home'],
|
||||
'repositories': ['{}.borg'.format(string.punctuation)],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def test_parse_configuration_with_schema_lacking_examples_does_not_raise():
|
||||
mock_config_and_schema(
|
||||
'''
|
||||
location:
|
||||
source_directories:
|
||||
- /home
|
||||
|
||||
repositories:
|
||||
- hostname.borg
|
||||
''',
|
||||
'''
|
||||
map:
|
||||
location:
|
||||
required: true
|
||||
map:
|
||||
source_directories:
|
||||
required: true
|
||||
seq:
|
||||
- type: scalar
|
||||
repositories:
|
||||
required: true
|
||||
seq:
|
||||
- type: scalar
|
||||
''',
|
||||
)
|
||||
|
||||
module.parse_configuration('config.yaml', 'schema.yaml')
|
||||
|
||||
|
||||
def test_parse_configuration_raises_for_missing_config_file():
|
||||
with pytest.raises(FileNotFoundError):
|
||||
module.parse_configuration('config.yaml', 'schema.yaml')
|
||||
|
||||
|
||||
def test_parse_configuration_raises_for_missing_schema_file():
|
||||
mock_config_and_schema('')
|
||||
builtins = flexmock(sys.modules['builtins'])
|
||||
builtins.should_receive('open').with_args('schema.yaml').and_raise(FileNotFoundError)
|
||||
|
||||
with pytest.raises(FileNotFoundError):
|
||||
module.parse_configuration('config.yaml', 'schema.yaml')
|
||||
|
||||
|
||||
def test_parse_configuration_raises_for_syntax_error():
|
||||
mock_config_and_schema('foo:\nbar')
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.parse_configuration('config.yaml', 'schema.yaml')
|
||||
|
||||
|
||||
def test_parse_configuration_raises_for_validation_error():
|
||||
mock_config_and_schema(
|
||||
'''
|
||||
location:
|
||||
source_directories: yes
|
||||
repositories:
|
||||
- hostname.borg
|
||||
'''
|
||||
)
|
||||
|
||||
with pytest.raises(module.Validation_error):
|
||||
module.parse_configuration('config.yaml', 'schema.yaml')
|
||||
8
tests/integration/test_version.py
Normal file
8
tests/integration/test_version.py
Normal file
@@ -0,0 +1,8 @@
|
||||
import subprocess
|
||||
|
||||
|
||||
def test_setup_version_matches_news_version():
|
||||
setup_version = subprocess.check_output(('python', 'setup.py', '--version')).decode('ascii')
|
||||
news_version = open('NEWS').readline()
|
||||
|
||||
assert setup_version == news_version
|
||||
Reference in New Issue
Block a user