View Javadoc
1   /*
2    * Copyright (C) 2020, Google LLC and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.internal.revwalk;
11  
12  import static org.junit.Assert.assertFalse;
13  import static org.junit.Assert.assertTrue;
14  
15  import java.util.Arrays;
16  import java.util.Optional;
17  import java.util.stream.Stream;
18  
19  import org.eclipse.jgit.internal.storage.file.FileRepository;
20  import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
21  import org.eclipse.jgit.junit.TestRepository;
22  import org.eclipse.jgit.junit.TestRepository.CommitBuilder;
23  import org.eclipse.jgit.revwalk.ObjectReachabilityChecker;
24  import org.eclipse.jgit.revwalk.RevBlob;
25  import org.eclipse.jgit.revwalk.RevCommit;
26  import org.eclipse.jgit.revwalk.RevObject;
27  import org.junit.Before;
28  import org.junit.Test;
29  
30  public abstract class ObjectReachabilityTestCase
31  		extends LocalDiskRepositoryTestCase {
32  
33  	private TestRepository<FileRepository> repo;
34  	private AddressableRevCommit baseCommit;
35  	private AddressableRevCommit branchACommit;
36  	private AddressableRevCommit branchBCommit;
37  	private AddressableRevCommit mergeCommit;
38  
39  	abstract ObjectReachabilityChecker getChecker(
40  			TestRepository<FileRepository> repository) throws Exception;
41  
42  	// Pair of commit and blob inside it
43  	protected static class AddressableRevCommit {
44  		RevCommit commit;
45  
46  		RevBlob blob;
47  
48  		AddressableRevCommit(RevCommit commit, RevBlob blob) {
49  			this.commit = commit;
50  			this.blob = blob;
51  		}
52  	}
53  
54  	/** {@inheritDoc} */
55  	@Override
56  	@Before
57  	public void setUp() throws Exception {
58  		super.setUp();
59  		FileRepository db = createWorkRepository();
60  		repo = new TestRepository<>(db);
61  		prepareRepo();
62  	}
63  
64  	@Test
65  	public void blob_in_base_reachable_from_branches() throws Exception {
66  		ObjectReachabilityChecker checker = getChecker(repo);
67  
68  		RevObject baseBlob = baseCommit.blob;
69  		assertReachable("reachable from one branch", checker.areAllReachable(
70  				Arrays.asList(baseBlob), Stream.of(branchACommit.commit)));
71  		assertReachable("reachable from another branch",
72  				checker.areAllReachable(
73  						Arrays.asList(baseBlob),
74  						Stream.of(branchBCommit.commit)));
75  	}
76  
77  	@Test
78  	public void blob_reachable_from_owning_commit() throws Exception {
79  		ObjectReachabilityChecker checker = getChecker(repo);
80  
81  		RevObject branchABlob = branchACommit.blob;
82  		assertReachable("reachable from itself",
83  				checker.areAllReachable(Arrays.asList(branchABlob),
84  						Stream.of(branchACommit.commit)));
85  	}
86  
87  	@Test
88  	public void blob_in_branch_reachable_from_merge() throws Exception {
89  		ObjectReachabilityChecker checker = getChecker(repo);
90  
91  		RevObject branchABlob = branchACommit.blob;
92  		assertReachable("reachable from merge", checker.areAllReachable(
93  				Arrays.asList(branchABlob), Stream.of(mergeCommit.commit)));
94  	}
95  
96  	@Test
97  	public void blob_unreachable_from_earlier_commit() throws Exception {
98  		ObjectReachabilityChecker checker = getChecker(repo);
99  
100 		RevObject branchABlob = branchACommit.blob;
101 		assertUnreachable("unreachable from earlier commit",
102 				checker.areAllReachable(Arrays.asList(branchABlob),
103 						Stream.of(baseCommit.commit)));
104 	}
105 
106 	@Test
107 	public void blob_unreachable_from_parallel_branch() throws Exception {
108 		ObjectReachabilityChecker checker = getChecker(repo);
109 
110 		RevObject branchABlob = branchACommit.blob;
111 		assertUnreachable("unreachable from another branch",
112 				checker.areAllReachable(Arrays.asList(branchABlob),
113 						Stream.of(branchBCommit.commit)));
114 	}
115 
116 	private void prepareRepo() throws Exception {
117 		baseCommit = createCommit("base");
118 		branchACommit = createCommit("branchA", baseCommit);
119 		branchBCommit = createCommit("branchB", baseCommit);
120 		mergeCommit = createCommit("merge", branchACommit, branchBCommit);
121 
122 		// Bitmaps are generated from references
123 		repo.update("refs/heads/a", branchACommit.commit);
124 		repo.update("refs/heads/b", branchBCommit.commit);
125 		repo.update("refs/heads/merge", mergeCommit.commit);
126 	}
127 
128 	private AddressableRevCommit createCommit(String blobPath, AddressableRevCommit... parents) throws Exception {
129 		RevBlob blob = repo.blob(blobPath + " content");
130 		CommitBuilder commitBuilder = repo.commit();
131 		for (int i = 0; i < parents.length; i++) {
132 			commitBuilder.parent(parents[i].commit);
133 		}
134 		commitBuilder.add(blobPath, blob);
135 
136 		RevCommit commit = commitBuilder.create();
137 		return new AddressableRevCommit(commit, blob);
138 	}
139 
140 	private static void assertReachable(String msg, Optional<RevObject> result) {
141 		assertFalse(msg, result.isPresent());
142 	}
143 
144 	private static void assertUnreachable(String msg, Optional<RevObject> result) {
145 		assertTrue(msg, result.isPresent());
146 	}
147 }