From 3bda843139364a8d0218d5df160db1851fac4c42 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Wed, 15 Jan 2025 19:48:08 -0800 Subject: [PATCH] Fix the "spot" check to have a nicer error when there are no source paths to compare. --- NEWS | 1 + borgmatic/actions/check.py | 8 ++++++++ tests/unit/actions/test_check.py | 31 ++++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 48dd7fd8..9a43aa16 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,7 @@ * #965: Fix a borgmatic runtime directory error when running the "spot" check with a database hook enabled. * Fix the "spot" check to no longer consider pipe files within an archive for file comparisons. + * Fix the "spot" check to have a nicer error when there are no source paths to compare. * Fix auto-excluding of special files (when databases are configured) to support relative source directory paths. * Drop support for Python 3.8, which has been end-of-lifed. diff --git a/borgmatic/actions/check.py b/borgmatic/actions/check.py index cf22d5a3..472dabe6 100644 --- a/borgmatic/actions/check.py +++ b/borgmatic/actions/check.py @@ -629,6 +629,14 @@ def spot_check( ) logger.debug(f'{log_prefix}: {len(archive_paths)} total archive paths for spot check') + if len(source_paths) == 0: + logger.debug( + f'{log_prefix}: Paths in latest archive but not source paths: {", ".join(set(archive_paths)) or "none"}' + ) + raise ValueError( + f'Spot check failed: There are no source paths to compare against the archive' + ) + # Calculate the percentage delta between the source paths count and the archive paths count, and # compare that delta to the configured count tolerance percentage. count_delta_percentage = abs(len(source_paths) - len(archive_paths)) / len(source_paths) * 100 diff --git a/tests/unit/actions/test_check.py b/tests/unit/actions/test_check.py index 327024c9..d5e0ea4a 100644 --- a/tests/unit/actions/test_check.py +++ b/tests/unit/actions/test_check.py @@ -1251,7 +1251,7 @@ def test_spot_check_without_any_configuration_errors(): ) -def test_spot_check_data_tolerance_percenatge_greater_than_data_sample_percentage_errors(): +def test_spot_check_data_tolerance_percentage_greater_than_data_sample_percentage_errors(): with pytest.raises(ValueError): module.spot_check( repository={'path': 'repo'}, @@ -1369,6 +1369,35 @@ def test_spot_check_with_high_enough_tolerances_does_not_raise(): ) +def test_spot_check_without_any_source_paths_errors(): + flexmock(module).should_receive('collect_spot_check_source_paths').and_return(()) + flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return( + 'archive' + ) + flexmock(module).should_receive('collect_spot_check_archive_paths').and_return(('/foo', '/bar')) + flexmock(module).should_receive('compare_spot_check_hashes').never() + + with pytest.raises(ValueError): + module.spot_check( + repository={'path': 'repo'}, + config={ + 'checks': [ + { + 'name': 'spot', + 'count_tolerance_percentage': 10, + 'data_tolerance_percentage': 40, + 'data_sample_percentage': 50, + }, + ] + }, + local_borg_version=flexmock(), + global_arguments=flexmock(), + local_path=flexmock(), + remote_path=flexmock(), + borgmatic_runtime_directory='/run/borgmatic', + ) + + def test_run_check_checks_archives_for_configured_repository(): flexmock(module.logger).answer = lambda message: None flexmock(module.borgmatic.config.validate).should_receive('repositories_match').never()