View Javadoc
1   /*
2    * Copyright (c) 2019, 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    * http://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  
11  package org.eclipse.jgit.internal.transport.connectivity;
12  
13  import static org.mockito.Mockito.doThrow;
14  import static org.mockito.Mockito.verify;
15  
16  import java.util.Arrays;
17  import java.util.Collections;
18  import java.util.HashSet;
19  import java.util.Set;
20  
21  import org.eclipse.jgit.errors.MissingObjectException;
22  import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
23  import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
24  import org.eclipse.jgit.junit.TestRepository;
25  import org.eclipse.jgit.lib.Constants;
26  import org.eclipse.jgit.lib.ObjectId;
27  import org.eclipse.jgit.lib.ProgressMonitor;
28  import org.eclipse.jgit.revwalk.RevCommit;
29  import org.eclipse.jgit.transport.PackParser;
30  import org.eclipse.jgit.transport.ReceiveCommand;
31  import org.eclipse.jgit.transport.ConnectivityChecker;
32  import org.eclipse.jgit.transport.ConnectivityChecker.ConnectivityCheckInfo;
33  import org.junit.Before;
34  import org.junit.Rule;
35  import org.junit.Test;
36  import org.mockito.Mock;
37  import org.mockito.junit.MockitoJUnit;
38  import org.mockito.junit.MockitoRule;
39  
40  public class IterativeConnectivityCheckerTest {
41  	@Rule
42  	public MockitoRule rule = MockitoJUnit.rule();
43  
44  	private ObjectId branchHeadObjectId;
45  
46  	private ObjectId openRewiewObjectId;
47  
48  	private ObjectId newCommitObjectId;
49  	private ObjectId otherHaveObjectId = ObjectId
50  			.fromString("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF");
51  
52  	private Set<ObjectId> advertisedHaves;
53  
54  	@Mock
55  	private ConnectivityChecker connectivityCheckerDelegate;
56  
57  	@Mock
58  	private ProgressMonitor pm;
59  
60  	@Mock
61  	private PackParser parser;
62  
63  	private RevCommit branchHeadCommitObject;
64  	private RevCommit openReviewCommitObject;
65  	private RevCommit newCommitObject;
66  
67  	private ConnectivityCheckInfo connectivityCheckInfo;
68  	private IterativeConnectivityChecker connectivityChecker;
69  
70  	private TestRepository tr;
71  
72  	@Before
73  	public void setUp() throws Exception {
74  		tr = new TestRepository<>(
75  				new InMemoryRepository(new DfsRepositoryDescription("test")));
76  		connectivityChecker = new IterativeConnectivityChecker(
77  				connectivityCheckerDelegate);
78  		connectivityCheckInfo = new ConnectivityCheckInfo();
79  		connectivityCheckInfo.setParser(parser);
80  		connectivityCheckInfo.setRepository(tr.getRepository());
81  		connectivityCheckInfo.setWalk(tr.getRevWalk());
82  
83  		branchHeadCommitObject = tr.commit().create();
84  		branchHeadObjectId = branchHeadCommitObject.getId();
85  
86  		openReviewCommitObject = tr.commit().create();
87  		openRewiewObjectId = openReviewCommitObject.getId();
88  
89  		advertisedHaves = wrap(branchHeadObjectId, openRewiewObjectId,
90  				otherHaveObjectId);
91  	}
92  
93  	@Test
94  	public void testSuccessfulNewBranchBasedOnOld() throws Exception {
95  		createNewCommit(branchHeadCommitObject);
96  		connectivityCheckInfo.setCommands(
97  				Collections.singletonList(createNewBrachCommand()));
98  
99  		connectivityChecker.checkConnectivity(connectivityCheckInfo,
100 				advertisedHaves, pm);
101 
102 		verify(connectivityCheckerDelegate).checkConnectivity(
103 				connectivityCheckInfo,
104 				wrap(branchHeadObjectId /* as direct parent */),
105 				pm);
106 	}
107 
108 	@Test
109 	public void testSuccessfulNewBranchBasedOnOldWithTip() throws Exception {
110 		createNewCommit(branchHeadCommitObject);
111 		connectivityCheckInfo.setCommands(
112 				Collections.singletonList(createNewBrachCommand()));
113 
114 		connectivityChecker.setForcedHaves(wrap(openRewiewObjectId));
115 
116 		connectivityChecker.checkConnectivity(connectivityCheckInfo,
117 				advertisedHaves, pm);
118 
119 		verify(connectivityCheckerDelegate).checkConnectivity(
120 				connectivityCheckInfo,
121 				wrap(branchHeadObjectId /* as direct parent */,
122 						openRewiewObjectId),
123 				pm);
124 	}
125 
126 	@Test
127 	public void testSuccessfulNewBranchMerge() throws Exception {
128 		createNewCommit(branchHeadCommitObject, openReviewCommitObject);
129 		connectivityCheckInfo.setCommands(
130 				Collections.singletonList(createNewBrachCommand()));
131 
132 		connectivityChecker.checkConnectivity(connectivityCheckInfo,
133 				advertisedHaves, pm);
134 
135 		verify(connectivityCheckerDelegate).checkConnectivity(
136 				connectivityCheckInfo,
137 				wrap(branchHeadObjectId /* as direct parent */,
138 						openRewiewObjectId),
139 				pm);
140 	}
141 
142 	@Test
143 	public void testSuccessfulNewBranchBasedOnNewWithTip() throws Exception {
144 		createNewCommit();
145 		connectivityCheckInfo.setCommands(
146 				Collections.singletonList(createNewBrachCommand()));
147 
148 		connectivityChecker.setForcedHaves(wrap(openRewiewObjectId));
149 
150 		connectivityChecker.checkConnectivity(connectivityCheckInfo,
151 				advertisedHaves, pm);
152 
153 		verify(connectivityCheckerDelegate).checkConnectivity(
154 				connectivityCheckInfo, wrap(openRewiewObjectId), pm);
155 	}
156 
157 	@Test
158 	public void testSuccessfulPushOldBranch() throws Exception {
159 		createNewCommit(branchHeadCommitObject);
160 		connectivityCheckInfo.setCommands(
161 				Collections.singletonList(pushOldBranchCommand()));
162 
163 		connectivityChecker.checkConnectivity(connectivityCheckInfo,
164 				advertisedHaves, pm);
165 
166 		verify(connectivityCheckerDelegate).checkConnectivity(
167 				connectivityCheckInfo, wrap(branchHeadObjectId /* as direct parent */),
168 				pm);
169 	}
170 
171 	@Test
172 	public void testSuccessfulPushOldBranchMergeCommit() throws Exception {
173 		createNewCommit(branchHeadCommitObject, openReviewCommitObject);
174 		connectivityCheckInfo.setCommands(
175 				Collections.singletonList(pushOldBranchCommand()));
176 
177 		connectivityChecker.checkConnectivity(connectivityCheckInfo,
178 				advertisedHaves, pm);
179 
180 		verify(connectivityCheckerDelegate).checkConnectivity(
181 				connectivityCheckInfo,
182 				wrap(branchHeadObjectId /* as direct parent */,
183 						openRewiewObjectId),
184 				pm);
185 	}
186 
187 
188 	@Test
189 	public void testNoChecksIfCantFindSubset() throws Exception {
190 		createNewCommit();
191 		connectivityCheckInfo.setCommands(
192 				Collections.singletonList(createNewBrachCommand()));
193 
194 		connectivityChecker.checkConnectivity(connectivityCheckInfo,
195 				advertisedHaves, pm);
196 
197 		verify(connectivityCheckerDelegate)
198 				.checkConnectivity(connectivityCheckInfo, advertisedHaves, pm);
199 	}
200 
201 	@Test
202 	public void testReiterateInCaseNotSuccessful() throws Exception {
203 		createNewCommit(branchHeadCommitObject);
204 		connectivityCheckInfo.setCommands(
205 				Collections.singletonList(createNewBrachCommand()));
206 
207 		doThrow(new MissingObjectException(branchHeadCommitObject,
208 				Constants.OBJ_COMMIT)).when(connectivityCheckerDelegate)
209 						.checkConnectivity(connectivityCheckInfo,
210 								wrap(branchHeadObjectId /* as direct parent */), pm);
211 
212 		connectivityChecker.checkConnectivity(connectivityCheckInfo,
213 				advertisedHaves, pm);
214 
215 		verify(connectivityCheckerDelegate)
216 				.checkConnectivity(connectivityCheckInfo, advertisedHaves, pm);
217 	}
218 
219 	@Test
220 	public void testDependOnGrandparent() throws Exception {
221 		RevCommit grandparent = tr.commit(new RevCommit[] {});
222 		RevCommit parent = tr.commit(grandparent);
223 		createNewCommit(parent);
224 
225 		branchHeadCommitObject = tr.commit(grandparent);
226 		branchHeadObjectId = branchHeadCommitObject.getId();
227 		tr.getRevWalk().dispose();
228 
229 		connectivityCheckInfo.setCommands(
230 				Collections.singletonList(createNewBrachCommand()));
231 
232 		connectivityChecker.checkConnectivity(connectivityCheckInfo,
233 				advertisedHaves, pm);
234 
235 		verify(connectivityCheckerDelegate)
236 				.checkConnectivity(connectivityCheckInfo, advertisedHaves, pm);
237 	}
238 
239 	private static Set<ObjectId> wrap(ObjectId... objectIds) {
240 		return new HashSet<>(Arrays.asList(objectIds));
241 	}
242 
243 	private ReceiveCommand createNewBrachCommand() {
244 		return new ReceiveCommand(ObjectId.zeroId(), newCommitObjectId,
245 				"totally/a/new/branch");
246 	}
247 
248 	private ReceiveCommand pushOldBranchCommand() {
249 		return new ReceiveCommand(branchHeadObjectId, newCommitObjectId,
250 				"push/to/an/old/branch");
251 	}
252 
253 	private void createNewCommit(RevCommit... parents) throws Exception {
254 		newCommitObject = tr.commit(parents);
255 		newCommitObjectId = newCommitObject.getId();
256 	}
257 
258 }