/* * Copyright (C) 2020, Google LLC and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at * https://www.eclipse.org/org/documents/edl-v10.php. * * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.internal.revwalk; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.Optional; import java.util.stream.Stream; import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.junit.TestRepository.CommitBuilder; import org.eclipse.jgit.revwalk.ObjectReachabilityChecker; import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevObject; import org.junit.Before; import org.junit.Test; public abstract class ObjectReachabilityTestCase extends LocalDiskRepositoryTestCase { private TestRepository repo; private AddressableRevCommit baseCommit; private AddressableRevCommit branchACommit; private AddressableRevCommit branchBCommit; private AddressableRevCommit mergeCommit; abstract ObjectReachabilityChecker getChecker( TestRepository repository) throws Exception; // Pair of commit and blob inside it protected static class AddressableRevCommit { RevCommit commit; RevBlob blob; AddressableRevCommit(RevCommit commit, RevBlob blob) { this.commit = commit; this.blob = blob; } } @Override @Before public void setUp() throws Exception { super.setUp(); FileRepository db = createWorkRepository(); repo = new TestRepository<>(db); prepareRepo(); } @Test public void blob_in_base_reachable_from_branches() throws Exception { ObjectReachabilityChecker checker = getChecker(repo); RevObject baseBlob = baseCommit.blob; assertReachable("reachable from one branch", checker.areAllReachable( Arrays.asList(baseBlob), Stream.of(branchACommit.commit))); assertReachable("reachable from another branch", checker.areAllReachable( Arrays.asList(baseBlob), Stream.of(branchBCommit.commit))); } @Test public void blob_reachable_from_owning_commit() throws Exception { ObjectReachabilityChecker checker = getChecker(repo); RevObject branchABlob = branchACommit.blob; assertReachable("reachable from itself", checker.areAllReachable(Arrays.asList(branchABlob), Stream.of(branchACommit.commit))); } @Test public void blob_in_branch_reachable_from_merge() throws Exception { ObjectReachabilityChecker checker = getChecker(repo); RevObject branchABlob = branchACommit.blob; assertReachable("reachable from merge", checker.areAllReachable( Arrays.asList(branchABlob), Stream.of(mergeCommit.commit))); } @Test public void blob_unreachable_from_earlier_commit() throws Exception { ObjectReachabilityChecker checker = getChecker(repo); RevObject branchABlob = branchACommit.blob; assertUnreachable("unreachable from earlier commit", checker.areAllReachable(Arrays.asList(branchABlob), Stream.of(baseCommit.commit))); } @Test public void blob_unreachable_from_parallel_branch() throws Exception { ObjectReachabilityChecker checker = getChecker(repo); RevObject branchABlob = branchACommit.blob; assertUnreachable("unreachable from another branch", checker.areAllReachable(Arrays.asList(branchABlob), Stream.of(branchBCommit.commit))); } private void prepareRepo() throws Exception { baseCommit = createCommit("base"); branchACommit = createCommit("branchA", baseCommit); branchBCommit = createCommit("branchB", baseCommit); mergeCommit = createCommit("merge", branchACommit, branchBCommit); // Bitmaps are generated from references repo.update("refs/heads/a", branchACommit.commit); repo.update("refs/heads/b", branchBCommit.commit); repo.update("refs/heads/merge", mergeCommit.commit); } private AddressableRevCommit createCommit(String blobPath, AddressableRevCommit... parents) throws Exception { RevBlob blob = repo.blob(blobPath + " content"); CommitBuilder commitBuilder = repo.commit(); for (int i = 0; i < parents.length; i++) { commitBuilder.parent(parents[i].commit); } commitBuilder.add(blobPath, blob); RevCommit commit = commitBuilder.create(); return new AddressableRevCommit(commit, blob); } private static void assertReachable(String msg, Optional result) { assertFalse(msg, result.isPresent()); } private static void assertUnreachable(String msg, Optional result) { assertTrue(msg, result.isPresent()); } }