diff --git a/priam/src/main/java/com/netflix/priam/backup/BackupVerification.java b/priam/src/main/java/com/netflix/priam/backup/BackupVerification.java index 67b01b086..2a655606b 100644 --- a/priam/src/main/java/com/netflix/priam/backup/BackupVerification.java +++ b/priam/src/main/java/com/netflix/priam/backup/BackupVerification.java @@ -13,6 +13,8 @@ */ package com.netflix.priam.backup; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.netflix.priam.backupv2.IMetaProxy; import com.netflix.priam.utils.DateUtil; import com.netflix.priam.utils.DateUtil.DateRange; @@ -68,38 +70,21 @@ public IMetaProxy getMetaProxy(BackupVersion backupVersion) { return null; } - public Optional verifyLatestBackup( + public ImmutableMap> findMissingBackupFilesInRange( BackupVersion backupVersion, boolean force, DateRange dateRange) throws IllegalArgumentException { IMetaProxy metaProxy = getMetaProxy(backupVersion); + ImmutableMap.Builder> mapBuilder = + ImmutableMap.builder(); for (BackupMetadata backupMetadata : backupStatusMgr.getLatestBackupMetadata(backupVersion, dateRange)) { - if (backupMetadata.getLastValidated() == null || force) { - Optional result = verifyBackup(metaProxy, backupMetadata); - if (result.isPresent()) { - return result; - } - } else { - updateLatestResult(backupMetadata); - return Optional.of(latestResult); - } + List missingFiles = + backupMetadata.getLastValidated() == null || force + ? verifyBackup(metaProxy, backupMetadata).filesInMetaOnly + : new ArrayList<>(); + mapBuilder.put(backupMetadata, ImmutableSet.copyOf(missingFiles)); } - latestResult = null; - return Optional.empty(); - } - - public List verifyBackupsInRange( - BackupVersion backupVersion, DateRange dateRange) throws IllegalArgumentException { - IMetaProxy metaProxy = getMetaProxy(backupVersion); - List results = new ArrayList<>(); - for (BackupMetadata backupMetadata : - backupStatusMgr.getLatestBackupMetadata(backupVersion, dateRange)) { - if (backupMetadata.getLastValidated() != null - || verifyBackup(metaProxy, backupMetadata).isPresent()) { - results.add(backupMetadata); - } - } - return results; + return mapBuilder.build(); } /** returns the latest valid backup verification result if we have found one within the SLO * */ @@ -107,7 +92,7 @@ public Optional getLatestVerfifiedBackupTime() { return latestResult == null ? Optional.empty() : Optional.of(latestResult.snapshotInstant); } - private Optional verifyBackup( + private BackupVerificationResult verifyBackup( IMetaProxy metaProxy, BackupMetadata latestBackupMetaData) { Path metadataLocation = Paths.get(latestBackupMetaData.getSnapshotLocation()); metadataLocation = metadataLocation.subpath(1, metadataLocation.getNameCount()); @@ -119,9 +104,8 @@ private Optional verifyBackup( Date now = new Date(DateUtil.getInstant().toEpochMilli()); latestBackupMetaData.setLastValidated(now); backupStatusMgr.update(latestBackupMetaData); - return Optional.of(result); } - return Optional.empty(); + return result; } private void updateLatestResult(BackupMetadata backupMetadata) { diff --git a/priam/src/main/java/com/netflix/priam/backupv2/BackupVerificationTask.java b/priam/src/main/java/com/netflix/priam/backupv2/BackupVerificationTask.java index 06dc0646e..702d65ece 100644 --- a/priam/src/main/java/com/netflix/priam/backupv2/BackupVerificationTask.java +++ b/priam/src/main/java/com/netflix/priam/backupv2/BackupVerificationTask.java @@ -30,7 +30,9 @@ import com.netflix.priam.utils.DateUtil.DateRange; import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Singleton; import org.slf4j.Logger; @@ -84,21 +86,28 @@ public void execute() throws Exception { Instant slo = now.minus(backupRestoreConfig.getBackupVerificationSLOInHours(), ChronoUnit.HOURS); DateRange dateRange = new DateRange(slo, now); - List verifiedBackups = - backupVerification.verifyBackupsInRange( - BackupVersion.SNAPSHOT_META_SERVICE, dateRange); + Set verifiedBackups = + backupVerification + .findMissingBackupFilesInRange( + BackupVersion.SNAPSHOT_META_SERVICE, false /* force */, dateRange) + .entrySet() + .stream() + .filter(entry -> entry.getValue().isEmpty()) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); verifiedBackups .stream() - .filter(result -> result.getLastValidated().toInstant().isAfter(now)) + .filter(metadata -> metadata.getLastValidated().toInstant().isAfter(now)) .forEach( - result -> { + metadata -> { logger.info( "Sending {} message for backup: {}", AbstractBackupPath.BackupFileType.SNAPSHOT_VERIFIED, - result.getSnapshotLocation()); + metadata.getSnapshotLocation()); backupNotificationMgr.notify( - result.getSnapshotLocation(), result.getStart().toInstant()); + metadata.getSnapshotLocation(), + metadata.getStart().toInstant()); }); if (verifiedBackups.isEmpty()) { diff --git a/priam/src/main/java/com/netflix/priam/resources/BackupServlet.java b/priam/src/main/java/com/netflix/priam/resources/BackupServlet.java index 6d8e20cfa..5d9bd92b2 100644 --- a/priam/src/main/java/com/netflix/priam/resources/BackupServlet.java +++ b/priam/src/main/java/com/netflix/priam/resources/BackupServlet.java @@ -16,6 +16,8 @@ */ package com.netflix.priam.resources; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.netflix.priam.backup.*; import com.netflix.priam.backup.AbstractBackupPath.BackupFileType; import com.netflix.priam.config.IBackupRestoreConfig; @@ -23,6 +25,7 @@ import com.netflix.priam.scheduler.PriamScheduler; import com.netflix.priam.utils.DateUtil; import com.netflix.priam.utils.DateUtil.DateRange; +import com.netflix.priam.utils.GsonJsonSerializer; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.*; @@ -215,19 +218,12 @@ public Response snapshotsByDate(@PathParam("date") String date) throws Exception @Produces(MediaType.APPLICATION_JSON) public Response validateSnapshotByDate( @PathParam("daterange") String daterange, - @DefaultValue("false") @QueryParam("force") boolean force) - throws Exception { + @DefaultValue("false") @QueryParam("force") boolean force) { DateUtil.DateRange dateRange = new DateUtil.DateRange(daterange); - Optional result = - backupVerification.verifyLatestBackup( + ImmutableMap> result = + backupVerification.findMissingBackupFilesInRange( BackupVersion.SNAPSHOT_BACKUP, force, dateRange); - if (!result.isPresent()) { - return Response.noContent() - .entity("No valid meta found for provided time range") - .build(); - } - - return Response.ok(result.get().toString()).build(); + return Response.ok(GsonJsonSerializer.getGson().toJson(result)).build(); } /* diff --git a/priam/src/main/java/com/netflix/priam/resources/BackupServletV2.java b/priam/src/main/java/com/netflix/priam/resources/BackupServletV2.java index b55a1edef..fe6bc58b5 100644 --- a/priam/src/main/java/com/netflix/priam/resources/BackupServletV2.java +++ b/priam/src/main/java/com/netflix/priam/resources/BackupServletV2.java @@ -17,6 +17,8 @@ package com.netflix.priam.resources; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.netflix.priam.backup.*; import com.netflix.priam.backupv2.BackupTTLTask; import com.netflix.priam.backupv2.BackupV2Service; @@ -121,19 +123,12 @@ public Response info(@PathParam("date") String date) { @Path("/validate/{daterange}") public Response validateV2SnapshotByDate( @PathParam("daterange") String daterange, - @DefaultValue("false") @QueryParam("force") boolean force) - throws Exception { + @DefaultValue("false") @QueryParam("force") boolean force) { DateUtil.DateRange dateRange = new DateUtil.DateRange(daterange); - Optional result = - backupVerification.verifyLatestBackup( + ImmutableMap> result = + backupVerification.findMissingBackupFilesInRange( BackupVersion.SNAPSHOT_META_SERVICE, force, dateRange); - if (!result.isPresent()) { - return Response.noContent() - .entity("No valid meta found for provided time range") - .build(); - } - - return Response.ok(result.get().toString()).build(); + return Response.ok(GsonJsonSerializer.getGson().toJson(result)).build(); } @GET diff --git a/priam/src/test/java/com/netflix/priam/backup/TestBackupVerification.java b/priam/src/test/java/com/netflix/priam/backup/TestBackupVerification.java index dd233cc12..739abd56d 100644 --- a/priam/src/test/java/com/netflix/priam/backup/TestBackupVerification.java +++ b/priam/src/test/java/com/netflix/priam/backup/TestBackupVerification.java @@ -17,6 +17,9 @@ package com.netflix.priam.backup; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.truth.Truth; import com.google.inject.Guice; import com.google.inject.Injector; import com.netflix.priam.backup.AbstractBackupPath.BackupFileType; @@ -31,9 +34,7 @@ import java.nio.file.Paths; import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.Date; -import java.util.List; -import java.util.Optional; +import java.util.*; import mockit.Mock; import mockit.MockUp; import org.apache.commons.io.FileUtils; @@ -91,34 +92,43 @@ public void cleanup() { } @Test - public void noBackup() throws Exception { - Optional backupVerificationResultOptinal = - backupVerification.verifyLatestBackup( + public void noBackup() { + ImmutableMap> missingFiles = + backupVerification.findMissingBackupFilesInRange( BackupVersion.SNAPSHOT_BACKUP, false, new DateRange(Instant.now(), Instant.now())); - Assert.assertFalse(backupVerificationResultOptinal.isPresent()); + Truth.assertThat(missingFiles).isEmpty(); - backupVerificationResultOptinal = - backupVerification.verifyLatestBackup( + missingFiles = + backupVerification.findMissingBackupFilesInRange( BackupVersion.SNAPSHOT_META_SERVICE, false, new DateRange(Instant.now(), Instant.now())); - Assert.assertFalse(backupVerificationResultOptinal.isPresent()); + Truth.assertThat(missingFiles).isEmpty(); } @Test public void noBackupDateRange() throws Exception { - List backupVerificationResults = - backupVerification.verifyBackupsInRange( - BackupVersion.SNAPSHOT_BACKUP, new DateRange(Instant.now(), Instant.now())); - Assert.assertFalse(backupVerificationResults.size() > 0); + long foundBackups = + backupVerification + .findMissingBackupFilesInRange( + BackupVersion.SNAPSHOT_BACKUP, + false /* force */, + new DateRange(Instant.now(), Instant.now())) + .entrySet() + .size(); + Truth.assertThat(foundBackups).isEqualTo(0L); - backupVerificationResults = - backupVerification.verifyBackupsInRange( - BackupVersion.SNAPSHOT_META_SERVICE, - new DateRange(Instant.now(), Instant.now())); - Assert.assertFalse(backupVerificationResults.size() > 0); + foundBackups = + backupVerification + .findMissingBackupFilesInRange( + BackupVersion.SNAPSHOT_META_SERVICE, + false /* force */, + new DateRange(Instant.now(), Instant.now())) + .entrySet() + .size(); + Truth.assertThat(foundBackups).isEqualTo(0L); } private void setUp() throws Exception { @@ -152,13 +162,12 @@ private void setUp() throws Exception { public void verifyBackupVersion1() throws Exception { setUp(); // Verify for backup version 1.0 - Optional backupVerificationResultOptinal = - backupVerification.verifyLatestBackup( + ImmutableMap> missingFiles = + backupVerification.findMissingBackupFilesInRange( BackupVersion.SNAPSHOT_BACKUP, false, new DateRange(backupDate + "," + backupDate)); - Assert.assertTrue(backupVerificationResultOptinal.isPresent()); - Assert.assertEquals(Instant.EPOCH, backupVerificationResultOptinal.get().snapshotInstant); + Truth.assertThat(missingFiles.values().stream().allMatch(Set::isEmpty)).isTrue(); Optional backupMetadata = backupStatusMgr .getLatestBackupMetadata( @@ -184,12 +193,17 @@ public void verifyBackupVersion1() throws Exception { public void verifyBackupVersion1DateRange() throws Exception { setUp(); // Verify for backup version 1.0 - List backupVerificationResults = - backupVerification.verifyBackupsInRange( - BackupVersion.SNAPSHOT_BACKUP, - new DateRange(backupDate + "," + backupDateEnd)); - Assert.assertTrue(!backupVerificationResults.isEmpty()); - Assert.assertTrue(backupVerificationResults.size() == numFakeBackups); + long missingFilesCount = + backupVerification + .findMissingBackupFilesInRange( + BackupVersion.SNAPSHOT_BACKUP, + false /* force */, + new DateRange(backupDate + "," + backupDateEnd)) + .values() + .stream() + .filter(AbstractCollection::isEmpty) + .count(); + Truth.assertThat(missingFilesCount).isEqualTo(numFakeBackups); List backupMetadata = backupStatusMgr.getLatestBackupMetadata( BackupVersion.SNAPSHOT_BACKUP, @@ -211,14 +225,12 @@ public void verifyBackupVersion1DateRange() throws Exception { public void verifyBackupVersion2() throws Exception { setUp(); // Verify for backup version 2.0 - Optional backupVerificationResultOptinal = - backupVerification.verifyLatestBackup( + ImmutableMap> missingFiles = + backupVerification.findMissingBackupFilesInRange( BackupVersion.SNAPSHOT_META_SERVICE, false, new DateRange(backupDate + "," + backupDate)); - Assert.assertTrue(backupVerificationResultOptinal.isPresent()); - Assert.assertEquals(Instant.EPOCH, backupVerificationResultOptinal.get().snapshotInstant); - Assert.assertEquals("some_random", backupVerificationResultOptinal.get().remotePath); + Truth.assertThat(missingFiles.values().stream().allMatch(Set::isEmpty)).isTrue(); Optional backupMetadata = backupStatusMgr @@ -230,21 +242,6 @@ public void verifyBackupVersion2() throws Exception { Assert.assertTrue(backupMetadata.isPresent()); Assert.assertNotNull(backupMetadata.get().getLastValidated()); - // Retry the verification, it should not try and re-verify - backupVerificationResultOptinal = - backupVerification.verifyLatestBackup( - BackupVersion.SNAPSHOT_META_SERVICE, - false, - new DateRange(backupDate + "," + backupDate)); - Assert.assertTrue(backupVerificationResultOptinal.isPresent()); - Assert.assertEquals( - DateUtil.parseInstant(backupDate), - backupVerificationResultOptinal.get().snapshotInstant); - Assert.assertNotEquals("some_random", backupVerificationResultOptinal.get().remotePath); - Assert.assertEquals( - location.subpath(1, location.getNameCount()).toString(), - backupVerificationResultOptinal.get().remotePath); - backupMetadata = backupStatusMgr .getLatestBackupMetadata( @@ -260,12 +257,17 @@ public void verifyBackupVersion2() throws Exception { public void verifyBackupVersion2DateRange() throws Exception { setUp(); // Verify for backup version 2.0 - List backupVerificationResults = - backupVerification.verifyBackupsInRange( - BackupVersion.SNAPSHOT_META_SERVICE, - new DateRange(backupDate + "," + backupDateEnd)); - Assert.assertTrue(!backupVerificationResults.isEmpty()); - Assert.assertTrue(backupVerificationResults.size() == numFakeBackups); + long missingFilesCount = + backupVerification + .findMissingBackupFilesInRange( + BackupVersion.SNAPSHOT_META_SERVICE, + false /* force */, + new DateRange(backupDate + "," + backupDateEnd)) + .values() + .stream() + .filter(AbstractCollection::isEmpty) + .count(); + Truth.assertThat(missingFilesCount).isEqualTo(numFakeBackups); List backupMetadata = backupStatusMgr.getLatestBackupMetadata( BackupVersion.SNAPSHOT_META_SERVICE, diff --git a/priam/src/test/java/com/netflix/priam/backupv2/TestBackupVerificationTask.java b/priam/src/test/java/com/netflix/priam/backupv2/TestBackupVerificationTask.java index 50874d71e..b94fb8e94 100644 --- a/priam/src/test/java/com/netflix/priam/backupv2/TestBackupVerificationTask.java +++ b/priam/src/test/java/com/netflix/priam/backupv2/TestBackupVerificationTask.java @@ -17,7 +17,8 @@ package com.netflix.priam.backupv2; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.truth.Truth; import com.google.inject.Guice; import com.google.inject.Injector; @@ -31,9 +32,7 @@ import com.netflix.spectator.api.Registry; import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.Date; -import java.util.List; -import java.util.Optional; +import java.util.*; import javax.inject.Inject; import mockit.*; import org.junit.Before; @@ -56,39 +55,36 @@ public void setUp() { badVerifications = injector.getInstance(Registry.class) .counter(Metrics.METRIC_PREFIX + "backup.verification.failure"); + MockBackupVerification.clearMissingFiles(); } private static final class MockBackupVerification extends MockUp { private static boolean throwError; - private static ImmutableList results; - private static ImmutableList verifiedBackups; + private static final Map> verifiedBackups; - public static void setResults(BackupVerificationResult... newResults) { - results = ImmutableList.copyOf(newResults); + static { + verifiedBackups = new HashMap<>(); } - public static void setVerifiedBackups(BackupMetadata... newVerifiedBackups) { - verifiedBackups = ImmutableList.copyOf(newVerifiedBackups); + public static void updateMissingFiles( + BackupMetadata newVerifiedBackups, ImmutableSet missingFiles) { + verifiedBackups.put(newVerifiedBackups, missingFiles); } - public static void shouldThrow(boolean newThrowError) { - throwError = newThrowError; + public static void clearMissingFiles() { + verifiedBackups.clear(); } - @Mock - public List verifyBackupsInRange( - BackupVersion backupVersion, DateRange dateRange) - throws UnsupportedTypeException, IllegalArgumentException { - if (throwError) throw new IllegalArgumentException("DummyError"); - return verifiedBackups; + public static void shouldThrow(boolean newThrowError) { + throwError = newThrowError; } @Mock - public Optional verifyLatestBackup( + public ImmutableMap> findMissingBackupFilesInRange( BackupVersion backupVersion, boolean force, DateRange dateRange) throws UnsupportedTypeException, IllegalArgumentException { if (throwError) throw new IllegalArgumentException("DummyError"); - return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0)); + return ImmutableMap.copyOf(verifiedBackups); } } @@ -104,7 +100,8 @@ public void throwError() { @Test public void validBackups() throws Exception { MockBackupVerification.shouldThrow(false); - MockBackupVerification.setVerifiedBackups(getRecentlyValidatedMetadata()); + MockBackupVerification.updateMissingFiles( + getRecentlyValidatedMetadata(), ImmutableSet.of()); backupVerificationService.execute(); Truth.assertThat(badVerifications.count()).isEqualTo(0); new Verifications() { @@ -116,17 +113,25 @@ public void validBackups() throws Exception { } @Test - public void invalidBackups() { + public void invalidBackups() throws Exception { MockBackupVerification.shouldThrow(false); - MockBackupVerification.setVerifiedBackups(getInvalidBackupMetadata()); - Assertions.assertThrows( - NullPointerException.class, () -> backupVerificationService.execute()); + MockBackupVerification.updateMissingFiles( + getInvalidBackupMetadata(), ImmutableSet.of("foo")); + backupVerificationService.execute(); + Truth.assertThat(badVerifications.count()).isEqualTo(1); + new Verifications() { + { + backupNotificationMgr.notify(anyString, (Instant) any); + times = 0; + } + }; } @Test public void previouslyVerifiedBackups() throws Exception { MockBackupVerification.shouldThrow(false); - MockBackupVerification.setVerifiedBackups(getPreviouslyValidatedMetadata()); + MockBackupVerification.updateMissingFiles( + getPreviouslyValidatedMetadata(), ImmutableSet.of()); backupVerificationService.execute(); Truth.assertThat(badVerifications.count()).isEqualTo(0); new Verifications() { @@ -140,7 +145,6 @@ public void previouslyVerifiedBackups() throws Exception { @Test public void noBackups() throws Exception { MockBackupVerification.shouldThrow(false); - MockBackupVerification.setVerifiedBackups(); backupVerificationService.execute(); Truth.assertThat(badVerifications.count()).isEqualTo(1); new Verifications() { @@ -163,7 +167,8 @@ public void testRestoreMode(@Mocked InstanceState state) throws Exception { Truth.assertThat(badVerifications.count()).isEqualTo(0); new Verifications() { { - backupVerification.verifyBackupsInRange((BackupVersion) any, (DateRange) any); + backupVerification.findMissingBackupFilesInRange( + (BackupVersion) any, anyBoolean, (DateRange) any); maxTimes = 0; } diff --git a/priam/src/test/java/com/netflix/priam/resources/BackupServletV2Test.java b/priam/src/test/java/com/netflix/priam/resources/BackupServletV2Test.java index 4c3848e0f..52cea0122 100644 --- a/priam/src/test/java/com/netflix/priam/resources/BackupServletV2Test.java +++ b/priam/src/test/java/com/netflix/priam/resources/BackupServletV2Test.java @@ -2,6 +2,8 @@ import static org.junit.Assert.assertEquals; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.inject.Guice; import com.google.inject.Injector; import com.netflix.priam.backup.*; @@ -154,14 +156,14 @@ private void expectCassandraStartup() { } @Test - public void testValidate() throws Exception { + public void testValidate() { new Expectations() { { - backupVerification.verifyLatestBackup( + backupVerification.findMissingBackupFilesInRange( BackupVersion.SNAPSHOT_META_SERVICE, anyBoolean, new DateUtil.DateRange((Instant) any, (Instant) any)); - result = Optional.of(getBackupVerificationResult()); + result = getBackupsWithAllFiles(); } }; Response response = @@ -169,46 +171,28 @@ public void testValidate() throws Exception { new DateUtil.DateRange(Instant.now(), Instant.now()).toString(), true); assertEquals(200, response.getStatus()); assertEquals( - GsonJsonSerializer.getGson().toJson(getBackupVerificationResult()), + GsonJsonSerializer.getGson().toJson(getBackupsWithAllFiles()), response.getEntity().toString()); } @Test - public void testValidateNoBackups() throws Exception { + public void testValidateNoBackups() { new Expectations() { { - backupVerification.verifyLatestBackup( + backupVerification.findMissingBackupFilesInRange( BackupVersion.SNAPSHOT_META_SERVICE, anyBoolean, new DateUtil.DateRange((Instant) any, (Instant) any)); - result = Optional.empty(); - } - }; - Response response = - resource.validateV2SnapshotByDate( - new DateUtil.DateRange(Instant.now(), Instant.now()).toString(), true); - assertEquals(204, response.getStatus()); - assertEquals( - response.getEntity().toString(), "No valid meta found for provided time range"); - } - - @Test - public void testValidateV2SnapshotByDate() throws Exception { - new Expectations() { - { - backupVerification.verifyLatestBackup( - BackupVersion.SNAPSHOT_META_SERVICE, - anyBoolean, - new DateUtil.DateRange((Instant) any, (Instant) any)); - result = Optional.of(getBackupVerificationResult()); + result = getBackupsWithMissingFiles(); } }; Response response = resource.validateV2SnapshotByDate( new DateUtil.DateRange(Instant.now(), Instant.now()).toString(), true); + System.out.println(response.getEntity().toString()); assertEquals(200, response.getStatus()); assertEquals( - GsonJsonSerializer.getGson().toJson(getBackupVerificationResult()), + GsonJsonSerializer.getGson().toJson(getBackupsWithMissingFiles()), response.getEntity().toString()); } @@ -290,17 +274,15 @@ public void testBackUpInfoNoBackups() { response.getEntity().toString()); } - private static BackupVerificationResult getBackupVerificationResult() { - BackupVerificationResult result = new BackupVerificationResult(); - result.valid = true; - result.manifestAvailable = true; - result.remotePath = "some_random"; - result.filesMatched = 123; - result.snapshotInstant = Instant.EPOCH; - return result; + private static ImmutableMap> getBackupsWithAllFiles() { + return ImmutableMap.of(getBackupMetaData(), ImmutableSet.of()); + } + + private static ImmutableMap> getBackupsWithMissingFiles() { + return ImmutableMap.of(getBackupMetaData(), ImmutableSet.of("foo")); } - private static BackupMetadata getBackupMetaData() throws Exception { + private static BackupMetadata getBackupMetaData() { BackupMetadata backupMetadata = new BackupMetadata( BackupVersion.SNAPSHOT_META_SERVICE,