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    * 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.revwalk.ReachabilityChecker;
23  import org.eclipse.jgit.revwalk.RevCommit;
24  import org.junit.Before;
25  import org.junit.Test;
26  
27  public abstract class ReachabilityCheckerTestCase
28  		extends LocalDiskRepositoryTestCase {
29  
30  	protected abstract ReachabilityChecker getChecker(
31  			TestRepository<FileRepository> repository) throws Exception;
32  
33  	TestRepository<FileRepository> repo;
34  
35  	/** {@inheritDoc} */
36  	@Override
37  	@Before
38  	public void setUp() throws Exception {
39  		super.setUp();
40  		FileRepository db = createWorkRepository();
41  		repo = new TestRepository<>(db);
42  	}
43  
44  	@Test
45  	public void reachable() throws Exception {
46  		RevCommit a = repo.commit().create();
47  		RevCommit b1 = repo.commit(a);
48  		RevCommit b2 = repo.commit(b1);
49  		RevCommit c1 = repo.commit(a);
50  		RevCommit c2 = repo.commit(c1);
51  		repo.update("refs/heads/checker", b2);
52  
53  		ReachabilityChecker checker = getChecker(repo);
54  
55  		assertReachable("reachable from one tip",
56  				checker.areAllReachable(Arrays.asList(a), Stream.of(c2)));
57  		assertReachable("reachable from another tip",
58  				checker.areAllReachable(Arrays.asList(a), Stream.of(b2)));
59  		assertReachable("reachable from itself",
60  				checker.areAllReachable(Arrays.asList(a), Stream.of(a)));
61  	}
62  
63  	@Test
64  	public void reachable_merge() throws Exception {
65  		RevCommit a = repo.commit().create();
66  		RevCommit b1 = repo.commit(a);
67  		RevCommit b2 = repo.commit(b1);
68  		RevCommit c1 = repo.commit(a);
69  		RevCommit c2 = repo.commit(c1);
70  		RevCommit merge = repo.commit(c2, b2);
71  		repo.update("refs/heads/checker", merge);
72  
73  		ReachabilityChecker checker = getChecker(repo);
74  
75  		assertReachable("reachable through one branch",
76  				checker.areAllReachable(Arrays.asList(b1),
77  						Stream.of(merge)));
78  		assertReachable("reachable through another branch",
79  				checker.areAllReachable(Arrays.asList(c1),
80  						Stream.of(merge)));
81  		assertReachable("reachable, before the branching",
82  				checker.areAllReachable(Arrays.asList(a),
83  						Stream.of(merge)));
84  	}
85  
86  	@Test
87  	public void unreachable_isLaterCommit() throws Exception {
88  		RevCommit a = repo.commit().create();
89  		RevCommit b1 = repo.commit(a);
90  		RevCommit b2 = repo.commit(b1);
91  		repo.update("refs/heads/checker", b2);
92  
93  		ReachabilityChecker checker = getChecker(repo);
94  
95  		assertUnreachable("unreachable from the future",
96  				checker.areAllReachable(Arrays.asList(b2), Stream.of(b1)));
97  	}
98  
99  	@Test
100 	public void unreachable_differentBranch() throws Exception {
101 		RevCommit a = repo.commit().create();
102 		RevCommit b1 = repo.commit(a);
103 		RevCommit b2 = repo.commit(b1);
104 		RevCommit c1 = repo.commit(a);
105 		repo.update("refs/heads/checker", b2);
106 
107 		ReachabilityChecker checker = getChecker(repo);
108 
109 		assertUnreachable("unreachable from different branch",
110 				checker.areAllReachable(Arrays.asList(c1), Stream.of(b2)));
111 	}
112 
113 	@Test
114 	public void reachable_longChain() throws Exception {
115 		RevCommit root = repo.commit().create();
116 		RevCommit head = root;
117 		for (int i = 0; i < 10000; i++) {
118 			head = repo.commit(head);
119 		}
120 		repo.update("refs/heads/master", head);
121 
122 		ReachabilityChecker checker = getChecker(repo);
123 
124 		assertReachable("reachable with long chain in the middle", checker
125 				.areAllReachable(Arrays.asList(root), Stream.of(head)));
126 	}
127 
128 	private static void assertReachable(String msg,
129 			Optional<RevCommit> result) {
130 		assertFalse(msg, result.isPresent());
131 	}
132 
133 	private static void assertUnreachable(String msg,
134 			Optional<RevCommit> result) {
135 		assertTrue(msg, result.isPresent());
136 	}
137 }