From 5a24bf203756cbd5d82de0aa46d911602d24077b Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Fri, 22 Nov 2024 20:16:18 -0800 Subject: [PATCH] Get tests passing (#261). --- borgmatic/actions/check.py | 6 +- borgmatic/actions/create.py | 4 +- borgmatic/borg/create.py | 27 +- borgmatic/config/generate.py | 4 +- borgmatic/hooks/mongodb.py | 1 + borgmatic/hooks/zfs.py | 3 +- tests/unit/actions/test_check.py | 40 +- tests/unit/actions/test_create.py | 269 ++++++++++--- tests/unit/borg/test_create.py | 560 +++------------------------- tests/unit/config/test_generate.py | 20 + tests/unit/hooks/test_dispatch.py | 8 +- tests/unit/hooks/test_mariadb.py | 42 ++- tests/unit/hooks/test_mongodb.py | 49 ++- tests/unit/hooks/test_mysql.py | 42 ++- tests/unit/hooks/test_postgresql.py | 84 ++++- tests/unit/hooks/test_sqlite.py | 42 ++- 16 files changed, 568 insertions(+), 633 deletions(-) diff --git a/borgmatic/actions/check.py b/borgmatic/actions/check.py index 581e9721..beeaa747 100644 --- a/borgmatic/actions/check.py +++ b/borgmatic/actions/check.py @@ -373,12 +373,10 @@ def collect_spot_check_source_paths( dry_run=True, repository_path=repository['path'], config=config, - config_paths=(), - source_directories=borgmatic.actions.create.process_source_directories( - config, (), borgmatic_runtime_directory - ), + source_directories=borgmatic.actions.create.process_source_directories(config, ()), local_borg_version=local_borg_version, global_arguments=global_arguments, + borgmatic_runtime_directory=borgmatic_runtime_directory, local_path=local_path, remote_path=remote_path, list_files=True, diff --git a/borgmatic/actions/create.py b/borgmatic/actions/create.py index 880dc359..99e8f42c 100644 --- a/borgmatic/actions/create.py +++ b/borgmatic/actions/create.py @@ -129,6 +129,9 @@ def deduplicate_directories(directory_devices, additional_directory_devices): return sorted(deduplicated) +ROOT_PATTERN_PREFIX = 'R ' + + def pattern_root_directories(patterns=None): ''' Given a sequence of patterns, parse out and return just the root directories. @@ -239,7 +242,6 @@ def run_create( global_arguments.dry_run, repository['path'], config, - config_paths, source_directories, local_borg_version, global_arguments, diff --git a/borgmatic/borg/create.py b/borgmatic/borg/create.py index ae24d094..49f0ea89 100644 --- a/borgmatic/borg/create.py +++ b/borgmatic/borg/create.py @@ -134,9 +134,6 @@ def make_list_filter_flags(local_borg_version, dry_run): return f'{base_flags}-' -ROOT_PATTERN_PREFIX = 'R ' - - def special_file(path): ''' Return whether the given path is a special file (character device, block device, or named pipe @@ -197,21 +194,15 @@ def collect_special_file_paths( ) -def check_all_source_directories_exist(source_directories, working_directory=None): +def check_all_source_directories_exist(source_directories): ''' - Given a sequence of source directories and an optional working directory to serve as a prefix - for each (if it's a relative directory), check that the source directories all exist. If any do + Given a sequence of source directories, check that the source directories all exist. If any do not, raise an exception. ''' missing_directories = [ source_directory for source_directory in source_directories - if not all( - [ - os.path.exists(os.path.join(working_directory or '', directory)) - for directory in expand_directory(source_directory, working_directory) - ] - ) + if not os.path.exists(source_directory) ] if missing_directories: raise ValueError(f"Source directories do not exist: {', '.join(missing_directories)}") @@ -224,10 +215,10 @@ def make_base_create_command( dry_run, repository_path, config, - config_paths, source_directories, local_borg_version, global_arguments, + borgmatic_runtime_directory, local_path='borg', remote_path=None, progress=False, @@ -242,12 +233,8 @@ def make_base_create_command( (base Borg create command flags, Borg create command positional arguments, open pattern file handle, open exclude file handle). ''' - working_directory = borgmatic.config.paths.get_working_directory(config) - if config.get('source_directories_must_exist', False): - check_all_source_directories_exist( - config.get('source_directories'), working_directory=working_directory - ) + check_all_source_directories_exist(source_directories) ensure_files_readable(config.get('patterns_from'), config.get('exclude_from')) @@ -339,6 +326,7 @@ def make_base_create_command( f'{repository_path}: Ignoring configured "read_special" value of false, as true is needed for database hooks.' ) borg_environment = environment.make_environment(config) + working_directory = borgmatic.config.paths.get_working_directory(config) logger.debug(f'{repository_path}: Collecting special file paths') special_file_paths = collect_special_file_paths( @@ -376,7 +364,6 @@ def create_archive( dry_run, repository_path, config, - config_paths, source_directories, local_borg_version, global_arguments, @@ -406,10 +393,10 @@ def create_archive( dry_run, repository_path, config, - config_paths, source_directories, local_borg_version, global_arguments, + borgmatic_runtime_directory, local_path, remote_path, progress, diff --git a/borgmatic/config/generate.py b/borgmatic/config/generate.py index c9f5aa81..f42c1690 100644 --- a/borgmatic/config/generate.py +++ b/borgmatic/config/generate.py @@ -44,12 +44,12 @@ def schema_to_sample_configuration(schema, level=0, parent_is_sequence=False): if example is not None: return example - if schema_type == 'array' or 'array' in schema_type: + if schema_type == 'array' or (isinstance(schema_type, list) and 'array' in schema_type): config = ruamel.yaml.comments.CommentedSeq( [schema_to_sample_configuration(schema['items'], level, parent_is_sequence=True)] ) add_comments_to_configuration_sequence(config, schema, indent=(level * INDENT)) - elif schema_type == 'object' or 'object' in schema_type: + elif schema_type == 'object' or (isinstance(schema_type, list) and 'object' in schema_type): config = ruamel.yaml.comments.CommentedMap( [ (field_name, schema_to_sample_configuration(sub_schema, level + 1)) diff --git a/borgmatic/hooks/mongodb.py b/borgmatic/hooks/mongodb.py index e1bdc2a4..853711bd 100644 --- a/borgmatic/hooks/mongodb.py +++ b/borgmatic/hooks/mongodb.py @@ -1,4 +1,5 @@ import logging +import os import shlex import borgmatic.config.paths diff --git a/borgmatic/hooks/zfs.py b/borgmatic/hooks/zfs.py index 34e6c4a5..dfb13eb6 100644 --- a/borgmatic/hooks/zfs.py +++ b/borgmatic/hooks/zfs.py @@ -1,7 +1,6 @@ import glob import logging import os -import shlex import shutil import subprocess @@ -66,7 +65,7 @@ def get_all_datasets(zfs_command): '-t', 'filesystem', '-o', - f'name,mountpoint', + 'name,mountpoint', ) ) diff --git a/tests/unit/actions/test_check.py b/tests/unit/actions/test_check.py index e7299522..d41237c1 100644 --- a/tests/unit/actions/test_check.py +++ b/tests/unit/actions/test_check.py @@ -557,14 +557,17 @@ def test_collect_spot_check_source_paths_parses_borg_output(): flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return( {'hook1': False, 'hook2': True} ) + flexmock(module.borgmatic.actions.create).should_receive( + 'process_source_directories' + ).and_return(['foo', 'bar']) flexmock(module.borgmatic.borg.create).should_receive('make_base_create_command').with_args( dry_run=True, repository_path='repo', config=object, - config_paths=(), + source_directories=['foo', 'bar'], local_borg_version=object, global_arguments=object, - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', local_path=object, remote_path=object, list_files=True, @@ -588,6 +591,7 @@ def test_collect_spot_check_source_paths_parses_borg_output(): global_arguments=flexmock(), local_path=flexmock(), remote_path=flexmock(), + borgmatic_runtime_directory='/run/borgmatic', ) == ('/etc/path', '/etc/other') @@ -595,14 +599,17 @@ def test_collect_spot_check_source_paths_passes_through_stream_processes_false() flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return( {'hook1': False, 'hook2': False} ) + flexmock(module.borgmatic.actions.create).should_receive( + 'process_source_directories' + ).and_return(['foo', 'bar']) flexmock(module.borgmatic.borg.create).should_receive('make_base_create_command').with_args( dry_run=True, repository_path='repo', config=object, - config_paths=(), + source_directories=['foo', 'bar'], local_borg_version=object, global_arguments=object, - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', local_path=object, remote_path=object, list_files=True, @@ -626,6 +633,7 @@ def test_collect_spot_check_source_paths_passes_through_stream_processes_false() global_arguments=flexmock(), local_path=flexmock(), remote_path=flexmock(), + borgmatic_runtime_directory='/run/borgmatic', ) == ('/etc/path', '/etc/other') @@ -633,14 +641,17 @@ def test_collect_spot_check_source_paths_without_working_directory_parses_borg_o flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return( {'hook1': False, 'hook2': True} ) + flexmock(module.borgmatic.actions.create).should_receive( + 'process_source_directories' + ).and_return(['foo', 'bar']) flexmock(module.borgmatic.borg.create).should_receive('make_base_create_command').with_args( dry_run=True, repository_path='repo', config=object, - config_paths=(), + source_directories=['foo', 'bar'], local_borg_version=object, global_arguments=object, - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', local_path=object, remote_path=object, list_files=True, @@ -664,6 +675,7 @@ def test_collect_spot_check_source_paths_without_working_directory_parses_borg_o global_arguments=flexmock(), local_path=flexmock(), remote_path=flexmock(), + borgmatic_runtime_directory='/run/borgmatic', ) == ('/etc/path', '/etc/other') @@ -671,14 +683,17 @@ def test_collect_spot_check_source_paths_skips_directories(): flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return( {'hook1': False, 'hook2': True} ) + flexmock(module.borgmatic.actions.create).should_receive( + 'process_source_directories' + ).and_return(['foo', 'bar']) flexmock(module.borgmatic.borg.create).should_receive('make_base_create_command').with_args( dry_run=True, repository_path='repo', config=object, - config_paths=(), + source_directories=['foo', 'bar'], local_borg_version=object, global_arguments=object, - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', local_path=object, remote_path=object, list_files=True, @@ -704,6 +719,7 @@ def test_collect_spot_check_source_paths_skips_directories(): global_arguments=flexmock(), local_path=flexmock(), remote_path=flexmock(), + borgmatic_runtime_directory='/run/borgmatic', ) == () ) @@ -806,14 +822,17 @@ def test_collect_spot_check_source_paths_uses_working_directory(): flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return( {'hook1': False, 'hook2': True} ) + flexmock(module.borgmatic.actions.create).should_receive( + 'process_source_directories' + ).and_return(['foo', 'bar']) flexmock(module.borgmatic.borg.create).should_receive('make_base_create_command').with_args( dry_run=True, repository_path='repo', config=object, - config_paths=(), + source_directories=['foo', 'bar'], local_borg_version=object, global_arguments=object, - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', local_path=object, remote_path=object, list_files=True, @@ -840,6 +859,7 @@ def test_collect_spot_check_source_paths_uses_working_directory(): global_arguments=flexmock(), local_path=flexmock(), remote_path=flexmock(), + borgmatic_runtime_directory='/run/borgmatic', ) == ('foo', 'bar') diff --git a/tests/unit/actions/test_create.py b/tests/unit/actions/test_create.py index c8450897..5849b682 100644 --- a/tests/unit/actions/test_create.py +++ b/tests/unit/actions/test_create.py @@ -1,10 +1,221 @@ import sys +import pytest from flexmock import flexmock from borgmatic.actions import create as module +def test_create_borgmatic_manifest_creates_manifest_file(): + flexmock(module.os.path).should_receive('join').with_args( + '/run/borgmatic', 'bootstrap', 'manifest.json' + ).and_return('/run/borgmatic/bootstrap/manifest.json') + flexmock(module.os.path).should_receive('exists').and_return(False) + flexmock(module.os).should_receive('makedirs').and_return(True) + + flexmock(module.importlib.metadata).should_receive('version').and_return('1.0.0') + flexmock(sys.modules['builtins']).should_receive('open').with_args( + '/run/borgmatic/bootstrap/manifest.json', 'w' + ).and_return( + flexmock( + __enter__=lambda *args: flexmock(write=lambda *args: None, close=lambda *args: None), + __exit__=lambda *args: None, + ) + ) + flexmock(module.json).should_receive('dump').and_return(True).once() + + module.create_borgmatic_manifest({}, 'test.yaml', '/run/borgmatic', False) + + +def test_create_borgmatic_manifest_creates_manifest_file_with_custom_borgmatic_runtime_directory(): + flexmock(module.os.path).should_receive('join').with_args( + '/run/borgmatic', 'bootstrap', 'manifest.json' + ).and_return('/run/borgmatic/bootstrap/manifest.json') + flexmock(module.os.path).should_receive('exists').and_return(False) + flexmock(module.os).should_receive('makedirs').and_return(True) + + flexmock(module.importlib.metadata).should_receive('version').and_return('1.0.0') + flexmock(sys.modules['builtins']).should_receive('open').with_args( + '/run/borgmatic/bootstrap/manifest.json', 'w' + ).and_return( + flexmock( + __enter__=lambda *args: flexmock(write=lambda *args: None, close=lambda *args: None), + __exit__=lambda *args: None, + ) + ) + flexmock(module.json).should_receive('dump').and_return(True).once() + + module.create_borgmatic_manifest( + {'borgmatic_runtime_directory': '/borgmatic'}, 'test.yaml', '/run/borgmatic', False + ) + + +def test_create_borgmatic_manifest_does_not_create_manifest_file_on_dry_run(): + flexmock(module.json).should_receive('dump').never() + + module.create_borgmatic_manifest({}, 'test.yaml', '/run/borgmatic', True) + + +def test_expand_directory_with_basic_path_passes_it_through(): + flexmock(module.os.path).should_receive('expanduser').and_return('foo') + flexmock(module.glob).should_receive('glob').and_return([]) + + paths = module.expand_directory('foo', None) + + assert paths == ['foo'] + + +def test_expand_directory_with_glob_expands(): + flexmock(module.os.path).should_receive('expanduser').and_return('foo*') + flexmock(module.glob).should_receive('glob').and_return(['foo', 'food']) + + paths = module.expand_directory('foo*', None) + + assert paths == ['foo', 'food'] + + +def test_expand_directory_with_working_directory_passes_it_through(): + flexmock(module.os.path).should_receive('expanduser').and_return('foo') + flexmock(module.glob).should_receive('glob').with_args('/working/dir/foo').and_return([]).once() + + paths = module.expand_directory('foo', working_directory='/working/dir') + + assert paths == ['/working/dir/foo'] + + +def test_expand_directory_with_glob_passes_through_working_directory(): + flexmock(module.os.path).should_receive('expanduser').and_return('foo*') + flexmock(module.glob).should_receive('glob').with_args('/working/dir/foo*').and_return( + ['/working/dir/foo', '/working/dir/food'] + ).once() + + paths = module.expand_directory('foo*', working_directory='/working/dir') + + assert paths == ['/working/dir/foo', '/working/dir/food'] + + +def test_expand_directories_flattens_expanded_directories(): + flexmock(module).should_receive('expand_directory').with_args('~/foo', None).and_return( + ['/root/foo'] + ) + flexmock(module).should_receive('expand_directory').with_args('bar*', None).and_return( + ['bar', 'barf'] + ) + + paths = module.expand_directories(('~/foo', 'bar*')) + + assert paths == ('/root/foo', 'bar', 'barf') + + +def test_expand_directories_with_working_directory_passes_it_through(): + flexmock(module).should_receive('expand_directory').with_args('foo', '/working/dir').and_return( + ['/working/dir/foo'] + ) + + paths = module.expand_directories(('foo',), working_directory='/working/dir') + + assert paths == ('/working/dir/foo',) + + +def test_expand_directories_considers_none_as_no_directories(): + paths = module.expand_directories(None, None) + + assert paths == () + + +def test_map_directories_to_devices_gives_device_id_per_path(): + flexmock(module.os.path).should_receive('exists').and_return(True) + flexmock(module.os).should_receive('stat').with_args('/foo').and_return(flexmock(st_dev=55)) + flexmock(module.os).should_receive('stat').with_args('/bar').and_return(flexmock(st_dev=66)) + + device_map = module.map_directories_to_devices(('/foo', '/bar')) + + assert device_map == { + '/foo': 55, + '/bar': 66, + } + + +def test_map_directories_to_devices_with_missing_path_does_not_error(): + flexmock(module.os.path).should_receive('exists').and_return(True).and_return(False) + flexmock(module.os).should_receive('stat').with_args('/foo').and_return(flexmock(st_dev=55)) + flexmock(module.os).should_receive('stat').with_args('/bar').never() + + device_map = module.map_directories_to_devices(('/foo', '/bar')) + + assert device_map == { + '/foo': 55, + '/bar': None, + } + + +def test_map_directories_to_devices_uses_working_directory_to_construct_path(): + flexmock(module.os.path).should_receive('exists').and_return(True) + flexmock(module.os).should_receive('stat').with_args('/foo').and_return(flexmock(st_dev=55)) + flexmock(module.os).should_receive('stat').with_args('/working/dir/bar').and_return( + flexmock(st_dev=66) + ) + + device_map = module.map_directories_to_devices( + ('/foo', 'bar'), working_directory='/working/dir' + ) + + assert device_map == { + '/foo': 55, + 'bar': 66, + } + + +@pytest.mark.parametrize( + 'directories,additional_directories,expected_directories', + ( + ({'/': 1, '/root': 1}, {}, ['/']), + ({'/': 1, '/root/': 1}, {}, ['/']), + ({'/': 1, '/root': 2}, {}, ['/', '/root']), + ({'/root': 1, '/': 1}, {}, ['/']), + ({'/root': 1, '/root/foo': 1}, {}, ['/root']), + ({'/root/': 1, '/root/foo': 1}, {}, ['/root/']), + ({'/root': 1, '/root/foo/': 1}, {}, ['/root']), + ({'/root': 1, '/root/foo': 2}, {}, ['/root', '/root/foo']), + ({'/root/foo': 1, '/root': 1}, {}, ['/root']), + ({'/root': None, '/root/foo': None}, {}, ['/root', '/root/foo']), + ({'/root': 1, '/etc': 1, '/root/foo/bar': 1}, {}, ['/etc', '/root']), + ({'/root': 1, '/root/foo': 1, '/root/foo/bar': 1}, {}, ['/root']), + ({'/dup': 1, '/dup': 1}, {}, ['/dup']), + ({'/foo': 1, '/bar': 1}, {}, ['/bar', '/foo']), + ({'/foo': 1, '/bar': 2}, {}, ['/bar', '/foo']), + ({'/root/foo': 1}, {'/root': 1}, []), + ({'/root/foo': 1}, {'/root': 2}, ['/root/foo']), + ({'/root/foo': 1}, {}, ['/root/foo']), + ), +) +def test_deduplicate_directories_removes_child_paths_on_the_same_filesystem( + directories, additional_directories, expected_directories +): + assert ( + module.deduplicate_directories(directories, additional_directories) == expected_directories + ) + + +def test_pattern_root_directories_deals_with_none_patterns(): + assert module.pattern_root_directories(patterns=None) == [] + + +def test_pattern_root_directories_parses_roots_and_ignores_others(): + assert module.pattern_root_directories( + ['R /root', '+ /root/foo', '- /root/foo/bar', 'R /baz'] + ) == ['/root', '/baz'] + + +# TODO +# def test_process_source_directories_... +# flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) +# flexmock(module).should_receive('map_directories_to_devices').and_return({}) +# flexmock(module).should_receive('expand_directories').and_return(()) +# flexmock(module).should_receive('pattern_root_directories').and_return([]) +# ... + + def test_run_create_executes_and_calls_hooks_for_configured_repository(): flexmock(module.logger).answer = lambda message: None flexmock(module.borgmatic.config.validate).should_receive('repositories_match').never() @@ -18,6 +229,8 @@ def test_run_create_executes_and_calls_hooks_for_configured_repository(): flexmock(module.borgmatic.hooks.dispatch).should_receive( 'call_hooks_even_if_unconfigured' ).and_return({}) + flexmock(module).should_receive('process_source_directories').and_return([]) + flexmock(module.os.path).should_receive('join').and_return('/run/borgmatic/bootstrap') create_arguments = flexmock( repository=None, progress=flexmock(), @@ -57,6 +270,8 @@ def test_run_create_with_store_config_files_false_does_not_create_borgmatic_mani flexmock(module.borgmatic.hooks.dispatch).should_receive( 'call_hooks_even_if_unconfigured' ).and_return({}) + flexmock(module).should_receive('process_source_directories').and_return([]) + flexmock(module.os.path).should_receive('join').and_return('/run/borgmatic/bootstrap') create_arguments = flexmock( repository=None, progress=flexmock(), @@ -98,6 +313,8 @@ def test_run_create_runs_with_selected_repository(): flexmock(module.borgmatic.hooks.dispatch).should_receive( 'call_hooks_even_if_unconfigured' ).and_return({}) + flexmock(module).should_receive('process_source_directories').and_return([]) + flexmock(module.os.path).should_receive('join').and_return('/run/borgmatic/bootstrap') create_arguments = flexmock( repository=flexmock(), progress=flexmock(), @@ -177,6 +394,8 @@ def test_run_create_produces_json(): flexmock(module.borgmatic.hooks.dispatch).should_receive( 'call_hooks_even_if_unconfigured' ).and_return({}) + flexmock(module).should_receive('process_source_directories').and_return([]) + flexmock(module.os.path).should_receive('join').and_return('/run/borgmatic/bootstrap') create_arguments = flexmock( repository=flexmock(), progress=flexmock(), @@ -201,53 +420,3 @@ def test_run_create_produces_json(): remote_path=None, ) ) == [parsed_json] - - -def test_create_borgmatic_manifest_creates_manifest_file(): - flexmock(module.os.path).should_receive('join').with_args( - '/run/borgmatic', 'bootstrap', 'manifest.json' - ).and_return('/run/borgmatic/bootstrap/manifest.json') - flexmock(module.os.path).should_receive('exists').and_return(False) - flexmock(module.os).should_receive('makedirs').and_return(True) - - flexmock(module.importlib.metadata).should_receive('version').and_return('1.0.0') - flexmock(sys.modules['builtins']).should_receive('open').with_args( - '/run/borgmatic/bootstrap/manifest.json', 'w' - ).and_return( - flexmock( - __enter__=lambda *args: flexmock(write=lambda *args: None, close=lambda *args: None), - __exit__=lambda *args: None, - ) - ) - flexmock(module.json).should_receive('dump').and_return(True).once() - - module.create_borgmatic_manifest({}, 'test.yaml', '/run/borgmatic', False) - - -def test_create_borgmatic_manifest_creates_manifest_file_with_custom_borgmatic_runtime_directory(): - flexmock(module.os.path).should_receive('join').with_args( - '/run/borgmatic', 'bootstrap', 'manifest.json' - ).and_return('/run/borgmatic/bootstrap/manifest.json') - flexmock(module.os.path).should_receive('exists').and_return(False) - flexmock(module.os).should_receive('makedirs').and_return(True) - - flexmock(module.importlib.metadata).should_receive('version').and_return('1.0.0') - flexmock(sys.modules['builtins']).should_receive('open').with_args( - '/run/borgmatic/bootstrap/manifest.json', 'w' - ).and_return( - flexmock( - __enter__=lambda *args: flexmock(write=lambda *args: None, close=lambda *args: None), - __exit__=lambda *args: None, - ) - ) - flexmock(module.json).should_receive('dump').and_return(True).once() - - module.create_borgmatic_manifest( - {'borgmatic_runtime_directory': '/borgmatic'}, 'test.yaml', '/run/borgmatic', False - ) - - -def test_create_borgmatic_manifest_does_not_create_manifest_file_on_dry_run(): - flexmock(module.json).should_receive('dump').never() - - module.create_borgmatic_manifest({}, 'test.yaml', '/run/borgmatic', True) diff --git a/tests/unit/borg/test_create.py b/tests/unit/borg/test_create.py index b1f8b509..bc91986d 100644 --- a/tests/unit/borg/test_create.py +++ b/tests/unit/borg/test_create.py @@ -9,73 +9,6 @@ from borgmatic.borg import create as module from ..test_verbosity import insert_logging_mock -def test_expand_directory_with_basic_path_passes_it_through(): - flexmock(module.os.path).should_receive('expanduser').and_return('foo') - flexmock(module.glob).should_receive('glob').and_return([]) - - paths = module.expand_directory('foo', None) - - assert paths == ['foo'] - - -def test_expand_directory_with_glob_expands(): - flexmock(module.os.path).should_receive('expanduser').and_return('foo*') - flexmock(module.glob).should_receive('glob').and_return(['foo', 'food']) - - paths = module.expand_directory('foo*', None) - - assert paths == ['foo', 'food'] - - -def test_expand_directory_with_working_directory_passes_it_through(): - flexmock(module.os.path).should_receive('expanduser').and_return('foo') - flexmock(module.glob).should_receive('glob').with_args('/working/dir/foo').and_return([]).once() - - paths = module.expand_directory('foo', working_directory='/working/dir') - - assert paths == ['/working/dir/foo'] - - -def test_expand_directory_with_glob_passes_through_working_directory(): - flexmock(module.os.path).should_receive('expanduser').and_return('foo*') - flexmock(module.glob).should_receive('glob').with_args('/working/dir/foo*').and_return( - ['/working/dir/foo', '/working/dir/food'] - ).once() - - paths = module.expand_directory('foo*', working_directory='/working/dir') - - assert paths == ['/working/dir/foo', '/working/dir/food'] - - -def test_expand_directories_flattens_expanded_directories(): - flexmock(module).should_receive('expand_directory').with_args('~/foo', None).and_return( - ['/root/foo'] - ) - flexmock(module).should_receive('expand_directory').with_args('bar*', None).and_return( - ['bar', 'barf'] - ) - - paths = module.expand_directories(('~/foo', 'bar*')) - - assert paths == ('/root/foo', 'bar', 'barf') - - -def test_expand_directories_with_working_directory_passes_it_through(): - flexmock(module).should_receive('expand_directory').with_args('foo', '/working/dir').and_return( - ['/working/dir/foo'] - ) - - paths = module.expand_directories(('foo',), working_directory='/working/dir') - - assert paths == ('/working/dir/foo',) - - -def test_expand_directories_considers_none_as_no_directories(): - paths = module.expand_directories(None, None) - - assert paths == () - - def test_expand_home_directories_expands_tildes(): flexmock(module.os.path).should_receive('expanduser').with_args('~/bar').and_return('/foo/bar') flexmock(module.os.path).should_receive('expanduser').with_args('baz').and_return('baz') @@ -91,80 +24,6 @@ def test_expand_home_directories_considers_none_as_no_directories(): assert paths == () -def test_map_directories_to_devices_gives_device_id_per_path(): - flexmock(module.os.path).should_receive('exists').and_return(True) - flexmock(module.os).should_receive('stat').with_args('/foo').and_return(flexmock(st_dev=55)) - flexmock(module.os).should_receive('stat').with_args('/bar').and_return(flexmock(st_dev=66)) - - device_map = module.map_directories_to_devices(('/foo', '/bar')) - - assert device_map == { - '/foo': 55, - '/bar': 66, - } - - -def test_map_directories_to_devices_with_missing_path_does_not_error(): - flexmock(module.os.path).should_receive('exists').and_return(True).and_return(False) - flexmock(module.os).should_receive('stat').with_args('/foo').and_return(flexmock(st_dev=55)) - flexmock(module.os).should_receive('stat').with_args('/bar').never() - - device_map = module.map_directories_to_devices(('/foo', '/bar')) - - assert device_map == { - '/foo': 55, - '/bar': None, - } - - -def test_map_directories_to_devices_uses_working_directory_to_construct_path(): - flexmock(module.os.path).should_receive('exists').and_return(True) - flexmock(module.os).should_receive('stat').with_args('/foo').and_return(flexmock(st_dev=55)) - flexmock(module.os).should_receive('stat').with_args('/working/dir/bar').and_return( - flexmock(st_dev=66) - ) - - device_map = module.map_directories_to_devices( - ('/foo', 'bar'), working_directory='/working/dir' - ) - - assert device_map == { - '/foo': 55, - 'bar': 66, - } - - -@pytest.mark.parametrize( - 'directories,additional_directories,expected_directories', - ( - ({'/': 1, '/root': 1}, {}, ('/',)), - ({'/': 1, '/root/': 1}, {}, ('/',)), - ({'/': 1, '/root': 2}, {}, ('/', '/root')), - ({'/root': 1, '/': 1}, {}, ('/',)), - ({'/root': 1, '/root/foo': 1}, {}, ('/root',)), - ({'/root/': 1, '/root/foo': 1}, {}, ('/root/',)), - ({'/root': 1, '/root/foo/': 1}, {}, ('/root',)), - ({'/root': 1, '/root/foo': 2}, {}, ('/root', '/root/foo')), - ({'/root/foo': 1, '/root': 1}, {}, ('/root',)), - ({'/root': None, '/root/foo': None}, {}, ('/root', '/root/foo')), - ({'/root': 1, '/etc': 1, '/root/foo/bar': 1}, {}, ('/etc', '/root')), - ({'/root': 1, '/root/foo': 1, '/root/foo/bar': 1}, {}, ('/root',)), - ({'/dup': 1, '/dup': 1}, {}, ('/dup',)), - ({'/foo': 1, '/bar': 1}, {}, ('/bar', '/foo')), - ({'/foo': 1, '/bar': 2}, {}, ('/bar', '/foo')), - ({'/root/foo': 1}, {'/root': 1}, ()), - ({'/root/foo': 1}, {'/root': 2}, ('/root/foo',)), - ({'/root/foo': 1}, {}, ('/root/foo',)), - ), -) -def test_deduplicate_directories_removes_child_paths_on_the_same_filesystem( - directories, additional_directories, expected_directories -): - assert ( - module.deduplicate_directories(directories, additional_directories) == expected_directories - ) - - def test_write_pattern_file_writes_pattern_lines(): temporary_file = flexmock(name='filename', flush=lambda: None) temporary_file.should_receive('write').with_args('R /foo\n+ /foo/bar') @@ -372,28 +231,6 @@ def test_make_list_filter_flags_with_info_and_feature_not_available_omits_x(): assert module.make_list_filter_flags(local_borg_version=flexmock(), dry_run=False) == 'AME-' -def test_collect_borgmatic_runtime_directories_set_when_directory_exists(): - flexmock(module.os.path).should_receive('exists').and_return(True) - - assert module.collect_borgmatic_runtime_directories('/tmp') == ['/tmp'] - - -def test_collect_borgmatic_runtime_directories_empty_when_directory_does_not_exist(): - flexmock(module.os.path).should_receive('exists').and_return(False) - - assert module.collect_borgmatic_runtime_directories('/tmp') == [] - - -def test_pattern_root_directories_deals_with_none_patterns(): - assert module.pattern_root_directories(patterns=None) == [] - - -def test_pattern_root_directories_parses_roots_and_ignores_others(): - assert module.pattern_root_directories( - ['R /root', '+ /root/foo', '- /root/foo/bar', 'R /baz'] - ) == ['/root', '/baz'] - - @pytest.mark.parametrize( 'character_device,block_device,fifo,expected_result', ( @@ -516,11 +353,6 @@ REPO_ARCHIVE_WITH_PATHS = (f'repo::{DEFAULT_ARCHIVE_NAME}', 'foo', 'bar') def test_make_base_create_produces_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('ensure_files_readable') flexmock(module).should_receive('write_pattern_file').and_return(None) @@ -540,10 +372,10 @@ def test_make_base_create_produces_borg_command(): 'source_directories': ['foo', 'bar'], 'repositories': ['repo'], }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -555,11 +387,6 @@ def test_make_base_create_produces_borg_command(): def test_make_base_create_command_includes_patterns_file_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) mock_pattern_file = flexmock(name='/tmp/patterns') flexmock(module).should_receive('write_pattern_file').and_return(mock_pattern_file).and_return( @@ -587,10 +414,10 @@ def test_make_base_create_command_includes_patterns_file_in_borg_command(): 'repositories': ['repo'], 'patterns': ['pattern'], }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -600,66 +427,8 @@ def test_make_base_create_command_includes_patterns_file_in_borg_command(): assert not exclude_file -def test_make_base_create_command_includes_sources_and_config_paths_in_borg_command(): - flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return( - ('foo', 'bar', '/tmp/test.yaml') - ) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').with_args([], None).and_return(()) - flexmock(module).should_receive('expand_directories').with_args( - ('foo', 'bar', '/tmp/test.yaml'), - None, - ).and_return(('foo', 'bar', '/tmp/test.yaml')) - flexmock(module).should_receive('expand_directories').with_args([], None).and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) - flexmock(module).should_receive('expand_home_directories').and_return(()) - flexmock(module).should_receive('write_pattern_file').and_return(None) - flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') - flexmock(module.flags).should_receive('get_default_archive_name_format').and_return( - '{hostname}' - ) - flexmock(module.feature).should_receive('available').and_return(True) - flexmock(module).should_receive('ensure_files_readable') - flexmock(module).should_receive('make_pattern_flags').and_return(()) - flexmock(module).should_receive('make_exclude_flags').and_return(()) - flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( - (f'repo::{DEFAULT_ARCHIVE_NAME}',) - ) - - (create_flags, create_positional_arguments, pattern_file, exclude_file) = ( - module.make_base_create_command( - dry_run=False, - repository_path='repo', - config={ - 'source_directories': ['foo', 'bar'], - 'repositories': ['repo'], - }, - config_paths=['/tmp/test.yaml'], - local_borg_version='1.2.3', - global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), - ) - ) - - assert create_flags == ('borg', 'create') - assert create_positional_arguments == REPO_ARCHIVE_WITH_PATHS + ('/tmp/test.yaml',) - assert not pattern_file - assert not exclude_file - - def test_make_base_create_command_with_store_config_false_omits_config_files(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').with_args([], None).and_return(()) - flexmock(module).should_receive('expand_directories').with_args( - ('foo', 'bar'), None - ).and_return(('foo', 'bar')) - flexmock(module).should_receive('expand_directories').with_args([], None).and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -683,10 +452,10 @@ def test_make_base_create_command_with_store_config_false_omits_config_files(): 'repositories': ['repo'], 'store_config_files': False, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -698,11 +467,6 @@ def test_make_base_create_command_with_store_config_false_omits_config_files(): def test_make_base_create_command_includes_exclude_patterns_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(('exclude',)) mock_exclude_file = flexmock(name='/tmp/excludes') flexmock(module).should_receive('write_pattern_file').and_return(mock_exclude_file) @@ -728,10 +492,10 @@ def test_make_base_create_command_includes_exclude_patterns_in_borg_command(): 'repositories': ['repo'], 'exclude_patterns': ['exclude'], }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -776,11 +540,6 @@ def test_make_base_create_command_includes_configuration_option_as_command_flag( option_name, option_value, feature_available, option_flags ): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -804,10 +563,10 @@ def test_make_base_create_command_includes_configuration_option_as_command_flag( 'repositories': ['repo'], option_name: option_value, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -819,11 +578,6 @@ def test_make_base_create_command_includes_configuration_option_as_command_flag( def test_make_base_create_command_includes_dry_run_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -847,10 +601,10 @@ def test_make_base_create_command_includes_dry_run_in_borg_command(): 'repositories': ['repo'], 'exclude_patterns': ['exclude'], }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -862,11 +616,6 @@ def test_make_base_create_command_includes_dry_run_in_borg_command(): def test_make_base_create_command_includes_local_path_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -889,10 +638,10 @@ def test_make_base_create_command_includes_local_path_in_borg_command(): 'source_directories': ['foo', 'bar'], 'repositories': ['repo'], }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', local_path='borg1', ) ) @@ -905,11 +654,6 @@ def test_make_base_create_command_includes_local_path_in_borg_command(): def test_make_base_create_command_includes_remote_path_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -932,10 +676,10 @@ def test_make_base_create_command_includes_remote_path_in_borg_command(): 'source_directories': ['foo', 'bar'], 'repositories': ['repo'], }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', remote_path='borg1', ) ) @@ -948,11 +692,6 @@ def test_make_base_create_command_includes_remote_path_in_borg_command(): def test_make_base_create_command_includes_log_json_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -975,10 +714,10 @@ def test_make_base_create_command_includes_log_json_in_borg_command(): 'source_directories': ['foo', 'bar'], 'repositories': ['repo'], }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=True), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -990,11 +729,6 @@ def test_make_base_create_command_includes_log_json_in_borg_command(): def test_make_base_create_command_includes_list_flags_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -1017,10 +751,10 @@ def test_make_base_create_command_includes_list_flags_in_borg_command(): 'source_directories': ['foo', 'bar'], 'repositories': ['repo'], }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', list_files=True, ) ) @@ -1033,11 +767,6 @@ def test_make_base_create_command_includes_list_flags_in_borg_command(): def test_make_base_create_command_with_stream_processes_ignores_read_special_false_and_excludes_special_files(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -1067,10 +796,10 @@ def test_make_base_create_command_with_stream_processes_ignores_read_special_fal 'repositories': ['repo'], 'read_special': False, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', stream_processes=flexmock(), ) ) @@ -1083,11 +812,6 @@ def test_make_base_create_command_with_stream_processes_ignores_read_special_fal def test_make_base_create_command_with_stream_processes_and_read_special_true_skip_special_files_excludes(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -1113,10 +837,10 @@ def test_make_base_create_command_with_stream_processes_and_read_special_true_sk 'repositories': ['repo'], 'read_special': True, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', stream_processes=flexmock(), ) ) @@ -1127,100 +851,8 @@ def test_make_base_create_command_with_stream_processes_and_read_special_true_sk assert not exclude_file -def test_make_base_create_command_with_non_matching_source_directories_glob_passes_through(): - flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo*',)) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) - flexmock(module).should_receive('expand_home_directories').and_return(()) - flexmock(module).should_receive('write_pattern_file').and_return(None) - flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') - flexmock(module.flags).should_receive('get_default_archive_name_format').and_return( - '{hostname}' - ) - flexmock(module.feature).should_receive('available').and_return(True) - flexmock(module).should_receive('ensure_files_readable') - flexmock(module).should_receive('make_pattern_flags').and_return(()) - flexmock(module).should_receive('make_exclude_flags').and_return(()) - flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( - (f'repo::{DEFAULT_ARCHIVE_NAME}',) - ) - - (create_flags, create_positional_arguments, pattern_file, exclude_file) = ( - module.make_base_create_command( - dry_run=False, - repository_path='repo', - config={ - 'source_directories': ['foo*'], - 'repositories': ['repo'], - }, - config_paths=['/tmp/test.yaml'], - local_borg_version='1.2.3', - global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), - ) - ) - - assert create_flags == ('borg', 'create') - assert create_positional_arguments == (f'repo::{DEFAULT_ARCHIVE_NAME}', 'foo*') - assert not pattern_file - assert not exclude_file - - -def test_make_base_create_command_expands_glob_in_source_directories(): - flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'food')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) - flexmock(module).should_receive('expand_home_directories').and_return(()) - flexmock(module).should_receive('write_pattern_file').and_return(None) - flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') - flexmock(module.flags).should_receive('get_default_archive_name_format').and_return( - '{hostname}' - ) - flexmock(module.feature).should_receive('available').and_return(True) - flexmock(module).should_receive('ensure_files_readable') - flexmock(module).should_receive('make_pattern_flags').and_return(()) - flexmock(module).should_receive('make_exclude_flags').and_return(()) - flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( - (f'repo::{DEFAULT_ARCHIVE_NAME}',) - ) - - (create_flags, create_positional_arguments, pattern_file, exclude_file) = ( - module.make_base_create_command( - dry_run=False, - repository_path='repo', - config={ - 'source_directories': ['foo*'], - 'repositories': ['repo'], - }, - config_paths=['/tmp/test.yaml'], - local_borg_version='1.2.3', - global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), - ) - ) - - assert create_flags == ('borg', 'create') - assert create_positional_arguments == (f'repo::{DEFAULT_ARCHIVE_NAME}', 'foo', 'food') - assert not pattern_file - assert not exclude_file - - def test_make_base_create_command_includes_archive_name_format_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -1244,10 +876,10 @@ def test_make_base_create_command_includes_archive_name_format_in_borg_command() 'repositories': ['repo'], 'archive_name_format': 'ARCHIVE_NAME', }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -1259,12 +891,6 @@ def test_make_base_create_command_includes_archive_name_format_in_borg_command() def test_make_base_create_command_includes_default_archive_name_format_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -1287,10 +913,10 @@ def test_make_base_create_command_includes_default_archive_name_format_in_borg_c 'source_directories': ['foo', 'bar'], 'repositories': ['repo'], }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -1302,11 +928,6 @@ def test_make_base_create_command_includes_default_archive_name_format_in_borg_c def test_make_base_create_command_includes_archive_name_format_with_placeholders_in_borg_command(): repository_archive_pattern = 'repo::Documents_{hostname}-{now}' # noqa: FS003 - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -1330,10 +951,10 @@ def test_make_base_create_command_includes_archive_name_format_with_placeholders 'repositories': ['repo'], 'archive_name_format': 'Documents_{hostname}-{now}', # noqa: FS003 }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -1345,11 +966,6 @@ def test_make_base_create_command_includes_archive_name_format_with_placeholders def test_make_base_create_command_includes_repository_and_archive_name_format_with_placeholders_in_borg_command(): repository_archive_pattern = '{fqdn}::Documents_{hostname}-{now}' # noqa: FS003 - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -1373,10 +989,10 @@ def test_make_base_create_command_includes_repository_and_archive_name_format_wi 'repositories': ['{fqdn}'], # noqa: FS003 'archive_name_format': 'Documents_{hostname}-{now}', # noqa: FS003 }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -1388,11 +1004,6 @@ def test_make_base_create_command_includes_repository_and_archive_name_format_wi def test_make_base_create_command_includes_extra_borg_options_in_borg_command(): flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) - flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) - flexmock(module).should_receive('map_directories_to_devices').and_return({}) - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('pattern_root_directories').and_return([]) - flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) flexmock(module).should_receive('expand_home_directories').and_return(()) flexmock(module).should_receive('write_pattern_file').and_return(None) flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') @@ -1416,10 +1027,10 @@ def test_make_base_create_command_includes_extra_borg_options_in_borg_command(): 'repositories': ['repo'], 'extra_borg_options': {'create': '--extra --options'}, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) ) @@ -1442,18 +1053,16 @@ def test_make_base_create_command_with_non_existent_directory_and_source_directo 'repositories': ['repo'], 'source_directories_must_exist': True, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), - borgmatic_runtime_directories=(), + borgmatic_runtime_directory='/run/borgmatic', ) def test_create_archive_calls_borg_with_parameters(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1477,7 +1086,7 @@ def test_create_archive_calls_borg_with_parameters(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1487,8 +1096,6 @@ def test_create_archive_calls_borg_with_parameters(): def test_create_archive_calls_borg_with_environment(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1513,7 +1120,7 @@ def test_create_archive_calls_borg_with_environment(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1523,8 +1130,6 @@ def test_create_archive_calls_borg_with_environment(): def test_create_archive_with_log_info_calls_borg_with_info_parameter(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1549,7 +1154,7 @@ def test_create_archive_with_log_info_calls_borg_with_info_parameter(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1559,8 +1164,6 @@ def test_create_archive_with_log_info_calls_borg_with_info_parameter(): def test_create_archive_with_log_info_and_json_suppresses_most_borg_output(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1583,7 +1186,7 @@ def test_create_archive_with_log_info_and_json_suppresses_most_borg_output(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1594,8 +1197,6 @@ def test_create_archive_with_log_info_and_json_suppresses_most_borg_output(): def test_create_archive_with_log_debug_calls_borg_with_debug_parameter(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1620,7 +1221,7 @@ def test_create_archive_with_log_debug_calls_borg_with_debug_parameter(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1630,8 +1231,6 @@ def test_create_archive_with_log_debug_calls_borg_with_debug_parameter(): def test_create_archive_with_log_debug_and_json_suppresses_most_borg_output(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1654,7 +1253,7 @@ def test_create_archive_with_log_debug_and_json_suppresses_most_borg_output(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1667,8 +1266,6 @@ def test_create_archive_with_stats_and_dry_run_calls_borg_without_stats(): # https://borgbackup.readthedocs.io/en/stable/usage/create.html#description flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create', '--dry-run'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1693,7 +1290,7 @@ def test_create_archive_with_stats_and_dry_run_calls_borg_without_stats(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1704,8 +1301,6 @@ def test_create_archive_with_stats_and_dry_run_calls_borg_without_stats(): def test_create_archive_with_working_directory_calls_borg_with_working_directory(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1732,7 +1327,7 @@ def test_create_archive_with_working_directory_calls_borg_with_working_directory 'working_directory': '/working/dir', 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1742,8 +1337,6 @@ def test_create_archive_with_working_directory_calls_borg_with_working_directory def test_create_archive_with_exit_codes_calls_borg_using_them(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1769,7 +1362,7 @@ def test_create_archive_with_exit_codes_calls_borg_using_them(): 'exclude_patterns': None, 'borg_exit_codes': borg_exit_codes, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1779,8 +1372,6 @@ def test_create_archive_with_exit_codes_calls_borg_using_them(): def test_create_archive_with_stats_calls_borg_with_stats_parameter_and_answer_output_log_level(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1804,7 +1395,7 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter_and_answer_ou 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1815,8 +1406,6 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter_and_answer_ou def test_create_archive_with_files_calls_borg_with_answer_output_log_level(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( ( ('borg', 'create', '--list', '--filter', 'FOO'), @@ -1845,7 +1434,7 @@ def test_create_archive_with_files_calls_borg_with_answer_output_log_level(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1856,8 +1445,6 @@ def test_create_archive_with_files_calls_borg_with_answer_output_log_level(): def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_parameter_and_no_list(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1882,7 +1469,7 @@ def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_para 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1893,8 +1480,6 @@ def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_para def test_create_archive_with_progress_calls_borg_with_progress_parameter(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -1918,7 +1503,7 @@ def test_create_archive_with_progress_calls_borg_with_progress_parameter(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1930,8 +1515,6 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER processes = flexmock() - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( ( ('borg', 'create', '--read-special'), @@ -1977,7 +1560,7 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -1989,8 +1572,6 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr def test_create_archive_with_json_calls_borg_with_json_flag(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -2012,7 +1593,7 @@ def test_create_archive_with_json_calls_borg_with_json_flag(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -2025,8 +1606,6 @@ def test_create_archive_with_json_calls_borg_with_json_flag(): def test_create_archive_with_stats_and_json_calls_borg_without_stats_flag(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -2048,7 +1627,7 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_flag(): 'repositories': ['repo'], 'exclude_patterns': None, }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', @@ -2062,8 +1641,6 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_flag(): def test_create_archive_calls_borg_with_working_directory(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER - flexmock(module).should_receive('expand_directories').and_return(()) - flexmock(module).should_receive('collect_borgmatic_runtime_directories').and_return([]) flexmock(module).should_receive('make_base_create_command').and_return( (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock()) ) @@ -2090,46 +1667,21 @@ def test_create_archive_calls_borg_with_working_directory(): 'exclude_patterns': None, 'working_directory': '/working/dir', }, - config_paths=['/tmp/test.yaml'], + source_directories=['foo', 'bar'], local_borg_version='1.2.3', global_arguments=flexmock(log_json=False), borgmatic_runtime_directory='/borgmatic/run', ) -def test_check_all_source_directories_exist_with_glob_and_tilde_directories(): - flexmock(module).should_receive('expand_directory').with_args('foo*', None).and_return( - ('foo', 'food') - ) - flexmock(module).should_receive('expand_directory').with_args('~/bar', None).and_return( - ('/root/bar',) - ) - flexmock(module.os.path).should_receive('exists').and_return(False) - flexmock(module.os.path).should_receive('exists').with_args('foo').and_return(True) - flexmock(module.os.path).should_receive('exists').with_args('food').and_return(True) - flexmock(module.os.path).should_receive('exists').with_args('/root/bar').and_return(True) +def test_check_all_source_directories_exist_with_existent_directory_does_not_raise(): + flexmock(module.os.path).should_receive('exists').and_return(True) - module.check_all_source_directories_exist(['foo*', '~/bar']) + module.check_all_source_directories_exist(['foo']) def test_check_all_source_directories_exist_with_non_existent_directory_raises(): - flexmock(module).should_receive('expand_directory').with_args('foo', None).and_return(('foo',)) flexmock(module.os.path).should_receive('exists').and_return(False) with pytest.raises(ValueError): module.check_all_source_directories_exist(['foo']) - - -def test_check_all_source_directories_exist_with_working_directory_applies_to_relative_source_directories(): - flexmock(module).should_receive('expand_directory').with_args( - 'foo*', working_directory='/tmp' - ).and_return(('/tmp/foo', '/tmp/food')) - flexmock(module).should_receive('expand_directory').with_args( - '/root/bar', working_directory='/tmp' - ).and_return(('/root/bar',)) - flexmock(module.os.path).should_receive('exists').and_return(False) - flexmock(module.os.path).should_receive('exists').with_args('/tmp/foo').and_return(True) - flexmock(module.os.path).should_receive('exists').with_args('/tmp/food').and_return(True) - flexmock(module.os.path).should_receive('exists').with_args('/root/bar').and_return(True) - - module.check_all_source_directories_exist(['foo*', '/root/bar'], working_directory='/tmp') diff --git a/tests/unit/config/test_generate.py b/tests/unit/config/test_generate.py index 1ba1df3c..530d641c 100644 --- a/tests/unit/config/test_generate.py +++ b/tests/unit/config/test_generate.py @@ -103,6 +103,26 @@ def test_schema_to_sample_configuration_generates_config_sequence_of_maps_with_e assert config == [OrderedDict([('field1', 'Example 1'), ('field2', 'Example 2')])] +def test_schema_to_sample_configuration_generates_config_sequence_of_maps_with_multiple_types(): + schema = { + 'type': 'array', + 'items': { + 'type': ['object', 'null'], + 'properties': OrderedDict( + [('field1', {'example': 'Example 1'}), ('field2', {'example': 'Example 2'})] + ), + }, + } + flexmock(module).should_receive('get_properties').and_return(schema['items']['properties']) + flexmock(module.ruamel.yaml.comments).should_receive('CommentedSeq').replace_with(list) + flexmock(module).should_receive('add_comments_to_configuration_sequence') + flexmock(module).should_receive('add_comments_to_configuration_object') + + config = module.schema_to_sample_configuration(schema) + + assert config == [OrderedDict([('field1', 'Example 1'), ('field2', 'Example 2')])] + + def test_schema_to_sample_configuration_with_unsupported_schema_raises(): schema = {'gobbledygook': [{'type': 'not-your'}]} diff --git a/tests/unit/hooks/test_dispatch.py b/tests/unit/hooks/test_dispatch.py index 26df72d6..cdbcde1a 100644 --- a/tests/unit/hooks/test_dispatch.py +++ b/tests/unit/hooks/test_dispatch.py @@ -77,10 +77,12 @@ def test_call_hooks_calls_skips_return_values_for_missing_hooks(): assert return_values == expected_return_values -def test_call_hooks_calls_skips_return_values_for_null_hooks(): +def test_call_hooks_calls_treats_null_hook_as_optionless(): config = {'super_hook': flexmock(), 'other_hook': None} - expected_return_values = {'super_hook': flexmock()} - flexmock(module).should_receive('call_hook').and_return(expected_return_values['super_hook']) + expected_return_values = {'super_hook': flexmock(), 'other_hook': flexmock()} + flexmock(module).should_receive('call_hook').and_return( + expected_return_values['super_hook'] + ).and_return(expected_return_values['other_hook']) return_values = module.call_hooks( 'do_stuff', config, 'prefix', ('super_hook', 'other_hook'), 55 diff --git a/tests/unit/hooks/test_mariadb.py b/tests/unit/hooks/test_mariadb.py index fb5612be..97db8ff2 100644 --- a/tests/unit/hooks/test_mariadb.py +++ b/tests/unit/hooks/test_mariadb.py @@ -75,7 +75,12 @@ def test_dump_data_sources_dumps_each_database(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -100,7 +105,12 @@ def test_dump_data_sources_dumps_with_password(): ).and_return(process).once() assert module.dump_data_sources( - [database], {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + [database], + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -120,7 +130,12 @@ def test_dump_data_sources_dumps_all_databases_at_once(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -143,7 +158,12 @@ def test_dump_data_sources_dumps_all_databases_separately_when_format_configured assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -449,7 +469,12 @@ def test_dump_data_sources_errors_for_missing_all_databases(): with pytest.raises(ValueError): assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) @@ -463,7 +488,12 @@ def test_dump_data_sources_does_not_error_for_missing_all_databases_with_dry_run assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=True + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=True, ) == [] ) diff --git a/tests/unit/hooks/test_mongodb.py b/tests/unit/hooks/test_mongodb.py index b08dfaa4..37e05d05 100644 --- a/tests/unit/hooks/test_mongodb.py +++ b/tests/unit/hooks/test_mongodb.py @@ -43,7 +43,12 @@ def test_dump_data_sources_runs_mongodump_for_each_database(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -60,7 +65,12 @@ def test_dump_data_sources_with_dry_run_skips_mongodump(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=True + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=True, ) == [] ) @@ -93,7 +103,12 @@ def test_dump_data_sources_runs_mongodump_with_hostname_and_port(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -133,7 +148,12 @@ def test_dump_data_sources_runs_mongodump_with_username_and_password(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -153,7 +173,12 @@ def test_dump_data_sources_runs_mongodump_with_directory_format(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [] ) @@ -183,7 +208,12 @@ def test_dump_data_sources_runs_mongodump_with_options(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -203,7 +233,12 @@ def test_dump_data_sources_runs_mongodumpall_for_all_databases(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] diff --git a/tests/unit/hooks/test_mysql.py b/tests/unit/hooks/test_mysql.py index 496e6663..2213c6c9 100644 --- a/tests/unit/hooks/test_mysql.py +++ b/tests/unit/hooks/test_mysql.py @@ -75,7 +75,12 @@ def test_dump_data_sources_dumps_each_database(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -100,7 +105,12 @@ def test_dump_data_sources_dumps_with_password(): ).and_return(process).once() assert module.dump_data_sources( - [database], {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + [database], + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -120,7 +130,12 @@ def test_dump_data_sources_dumps_all_databases_at_once(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -143,7 +158,12 @@ def test_dump_data_sources_dumps_all_databases_separately_when_format_configured assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -447,7 +467,12 @@ def test_dump_data_sources_errors_for_missing_all_databases(): with pytest.raises(ValueError): assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) @@ -461,7 +486,12 @@ def test_dump_data_sources_does_not_error_for_missing_all_databases_with_dry_run assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=True + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=True, ) == [] ) diff --git a/tests/unit/hooks/test_postgresql.py b/tests/unit/hooks/test_postgresql.py index 229a94e4..1026f066 100644 --- a/tests/unit/hooks/test_postgresql.py +++ b/tests/unit/hooks/test_postgresql.py @@ -253,7 +253,12 @@ def test_dump_data_sources_runs_pg_dump_for_each_database(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -267,7 +272,12 @@ def test_dump_data_sources_raises_when_no_database_names_to_dump(): with pytest.raises(ValueError): module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) @@ -278,7 +288,12 @@ def test_dump_data_sources_does_not_raise_when_no_database_names_to_dump(): flexmock(module).should_receive('database_names_to_dump').and_return(()) module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=True + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=True, ) == [] @@ -298,7 +313,12 @@ def test_dump_data_sources_with_duplicate_dump_skips_pg_dump(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [] ) @@ -320,7 +340,12 @@ def test_dump_data_sources_with_dry_run_skips_pg_dump(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=True + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=True, ) == [] ) @@ -360,7 +385,12 @@ def test_dump_data_sources_runs_pg_dump_with_hostname_and_port(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -398,7 +428,12 @@ def test_dump_data_sources_runs_pg_dump_with_username_and_password(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -436,7 +471,12 @@ def test_dump_data_sources_with_username_injection_attack_gets_escaped(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -470,7 +510,12 @@ def test_dump_data_sources_runs_pg_dump_with_directory_format(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [] ) @@ -507,7 +552,12 @@ def test_dump_data_sources_runs_pg_dump_with_options(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -531,7 +581,12 @@ def test_dump_data_sources_runs_pg_dumpall_for_all_databases(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] @@ -567,7 +622,12 @@ def test_dump_data_sources_runs_non_default_pg_dump(): ).and_return(process).once() assert module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [process] diff --git a/tests/unit/hooks/test_sqlite.py b/tests/unit/hooks/test_sqlite.py index 460a08d9..96ece9b6 100644 --- a/tests/unit/hooks/test_sqlite.py +++ b/tests/unit/hooks/test_sqlite.py @@ -28,7 +28,12 @@ def test_dump_data_sources_logs_and_skips_if_dump_already_exists(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == [] ) @@ -53,7 +58,12 @@ def test_dump_data_sources_dumps_each_database(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -85,7 +95,12 @@ def test_dump_data_sources_with_path_injection_attack_gets_escaped(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -108,7 +123,12 @@ def test_dump_data_sources_with_non_existent_path_warns_and_dumps_database(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -133,7 +153,12 @@ def test_dump_data_sources_with_name_all_warns_and_dumps_all_databases(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=False + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=False, ) == processes ) @@ -152,7 +177,12 @@ def test_dump_data_sources_does_not_dump_if_dry_run(): assert ( module.dump_data_sources( - databases, {}, 'test.yaml', borgmatic_runtime_directory='/run/borgmatic', dry_run=True + databases, + {}, + 'test.yaml', + borgmatic_runtime_directory='/run/borgmatic', + source_directories=[], + dry_run=True, ) == [] )