Selaa lähdekoodia

improve borg check --repair healing tests, see #8302

test the healing more thoroughly:
- preservation of correct chunks list in .chunks_healthy
- check that .chunks_healthy is removed after healing
- check that doing another borg check --repair run does not find
  something to heal, again.

also did a datatype consistency fix for item.chunks_healthy list
members: they are now post processed in the same way as item.chunks,
so they have type ChunkListEntry rather than simple tuple.
Thomas Waldmann 10 kuukautta sitten
vanhempi
sitoutus
c6f95de492
2 muutettua tiedostoa jossa 18 lisäystä ja 3 poistoa
  1. 2 0
      src/borg/archive.py
  2. 16 3
      src/borg/testsuite/archiver/check_cmd.py

+ 2 - 0
src/borg/archive.py

@@ -282,6 +282,8 @@ class DownloadPipeline:
                 item = Item(internal_dict=_item)
                 item = Item(internal_dict=_item)
                 if "chunks" in item:
                 if "chunks" in item:
                     item.chunks = [ChunkListEntry(*e) for e in item.chunks]
                     item.chunks = [ChunkListEntry(*e) for e in item.chunks]
+                if "chunks_healthy" in item:
+                    item.chunks_healthy = [ChunkListEntry(*e) for e in item.chunks_healthy]
                 if filter and not filter(item):
                 if filter and not filter(item):
                     continue
                     continue
                 if preload and "chunks" in item:
                 if preload and "chunks" in item:

+ 16 - 3
src/borg/testsuite/archiver/check_cmd.py

@@ -115,14 +115,20 @@ def test_missing_file_chunk(archivers, request):
     output = cmd(archiver, "list", "archive1", "--format={health}#{path}{NL}", exit_code=0)
     output = cmd(archiver, "list", "archive1", "--format={health}#{path}{NL}", exit_code=0)
     assert "broken#" in output
     assert "broken#" in output
 
 
-    # check that the file in the old archives has now a different chunk list without the killed chunk
+    # check that the file in the old archives has now a different chunk list without the killed chunk.
+    # also check that the correct original chunks list is preserved in item.chunks_healthy.
     for archive_name in ("archive1", "archive2"):
     for archive_name in ("archive1", "archive2"):
         archive, repository = open_archive(archiver.repository_path, archive_name)
         archive, repository = open_archive(archiver.repository_path, archive_name)
         with repository:
         with repository:
             for item in archive.iter_items():
             for item in archive.iter_items():
                 if item.path.endswith(src_file):
                 if item.path.endswith(src_file):
-                    assert valid_chunks != item.chunks
+                    assert len(valid_chunks) == len(item.chunks)
                     assert killed_chunk not in item.chunks
                     assert killed_chunk not in item.chunks
+                    assert valid_chunks != item.chunks
+                    assert "chunks_healthy" in item
+                    assert len(valid_chunks) == len(item.chunks_healthy)
+                    assert killed_chunk in item.chunks_healthy
+                    assert valid_chunks == item.chunks_healthy
                     break
                     break
             else:
             else:
                 pytest.fail("should not happen")  # convert 'fail'
                 pytest.fail("should not happen")  # convert 'fail'
@@ -136,13 +142,15 @@ def test_missing_file_chunk(archivers, request):
     assert "Healed previously missing file chunk" in output
     assert "Healed previously missing file chunk" in output
     assert f"{src_file}: Completely healed previously damaged file!" in output
     assert f"{src_file}: Completely healed previously damaged file!" in output
 
 
-    # check that the file in the old archives has the correct chunks again
+    # check that the file in the old archives has the correct chunks again.
+    # also check that chunks_healthy list is removed as it is not needed any more.
     for archive_name in ("archive1", "archive2"):
     for archive_name in ("archive1", "archive2"):
         archive, repository = open_archive(archiver.repository_path, archive_name)
         archive, repository = open_archive(archiver.repository_path, archive_name)
         with repository:
         with repository:
             for item in archive.iter_items():
             for item in archive.iter_items():
                 if item.path.endswith(src_file):
                 if item.path.endswith(src_file):
                     assert valid_chunks == item.chunks
                     assert valid_chunks == item.chunks
+                    assert "chunks_healthy" not in item
                     break
                     break
             else:
             else:
                 pytest.fail("should not happen")
                 pytest.fail("should not happen")
@@ -151,6 +159,11 @@ def test_missing_file_chunk(archivers, request):
     output = cmd(archiver, "list", "archive1", "--format={health}#{path}{NL}", exit_code=0)
     output = cmd(archiver, "list", "archive1", "--format={health}#{path}{NL}", exit_code=0)
     assert "broken#" not in output
     assert "broken#" not in output
 
 
+    # check should be fine now (and not show it has healed anything).
+    output = cmd(archiver, "check", "-v", "--repair", exit_code=0)
+    assert "Healed previously missing file chunk" not in output
+    assert "testsuite/archiver.py: Completely healed previously damaged file!" not in output
+
 
 
 def test_missing_archive_item_chunk(archivers, request):
 def test_missing_archive_item_chunk(archivers, request):
     archiver = request.getfixturevalue(archivers)
     archiver = request.getfixturevalue(archivers)