1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.treewalk.filter;
45
46 import static org.junit.Assert.assertArrayEquals;
47 import static org.junit.Assert.assertFalse;
48 import static org.junit.Assert.assertTrue;
49 import static org.junit.Assert.fail;
50
51 import java.io.IOException;
52 import java.util.ArrayList;
53 import java.util.Arrays;
54 import java.util.HashMap;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.Set;
58
59 import org.eclipse.jgit.dircache.DirCache;
60 import org.eclipse.jgit.dircache.DirCacheEditor;
61 import org.eclipse.jgit.dircache.DirCacheEntry;
62 import org.eclipse.jgit.dircache.DirCacheIterator;
63 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
64 import org.eclipse.jgit.errors.MissingObjectException;
65 import org.eclipse.jgit.errors.StopWalkException;
66 import org.eclipse.jgit.lib.FileMode;
67 import org.eclipse.jgit.lib.ObjectReader;
68 import org.eclipse.jgit.lib.Sets;
69 import org.eclipse.jgit.treewalk.TreeWalk;
70 import org.junit.Before;
71 import org.junit.Test;
72
73 public class PathFilterGroupTest {
74
75 private TreeFilter filter;
76
77 private Map<String, TreeFilter> singles;
78
79 @Before
80 public void setup() {
81
82 String[] paths = new String[] {
83 "/a",
84 "/a/b",
85 "a",
86 "b/c",
87 "c/d/e",
88 "c/d/f",
89 "d/e/f/g",
90 "d/e/f/g.x"
91 };
92
93 filter = PathFilterGroup.createFromStrings(paths);
94 singles = new HashMap<>();
95 for (String path : paths) {
96 singles.put(path, PathFilterGroup.createFromStrings(path));
97 }
98 }
99
100 @Test
101 public void testExact() throws MissingObjectException,
102 IncorrectObjectTypeException, IOException {
103 assertMatches(Sets.of("a"), fakeWalk("a"));
104 assertMatches(Sets.of("b/c"), fakeWalk("b/c"));
105 assertMatches(Sets.of("c/d/e"), fakeWalk("c/d/e"));
106 assertMatches(Sets.of("c/d/f"), fakeWalk("c/d/f"));
107 assertMatches(Sets.of("d/e/f/g"), fakeWalk("d/e/f/g"));
108 assertMatches(Sets.of("d/e/f/g.x"), fakeWalk("d/e/f/g.x"));
109 }
110
111 @Test
112 public void testNoMatchButClose() throws MissingObjectException,
113 IncorrectObjectTypeException, IOException {
114 assertNoMatches(fakeWalk("a+"));
115 assertNoMatches(fakeWalk("b+/c"));
116 assertNoMatches(fakeWalk("c+/d/e"));
117 assertNoMatches(fakeWalk("c+/d/f"));
118 assertNoMatches(fakeWalk("c/d.a"));
119 assertNoMatches(fakeWalk("d+/e/f/g"));
120 }
121
122 @Test
123 public void testJustCommonPrefixIsNotMatch() throws MissingObjectException,
124 IncorrectObjectTypeException, IOException {
125 assertNoMatches(fakeWalk("b/a"));
126 assertNoMatches(fakeWalk("b/d"));
127 assertNoMatches(fakeWalk("c/d/a"));
128 assertNoMatches(fakeWalk("d/e/e"));
129 assertNoMatches(fakeWalk("d/e/f/g.y"));
130 }
131
132 @Test
133 public void testKeyIsPrefixOfFilter() throws MissingObjectException,
134 IncorrectObjectTypeException, IOException {
135 assertMatches(Sets.of("b/c"), fakeWalkAtSubtree("b"));
136 assertMatches(Sets.of("c/d/e", "c/d/f"), fakeWalkAtSubtree("c/d"));
137 assertMatches(Sets.of("c/d/e", "c/d/f"), fakeWalkAtSubtree("c"));
138 assertMatches(Sets.of("d/e/f/g", "d/e/f/g.x"),
139 fakeWalkAtSubtree("d/e/f"));
140 assertMatches(Sets.of("d/e/f/g", "d/e/f/g.x"),
141 fakeWalkAtSubtree("d/e"));
142 assertMatches(Sets.of("d/e/f/g", "d/e/f/g.x"), fakeWalkAtSubtree("d"));
143
144 assertNoMatches(fakeWalk("b"));
145 assertNoMatches(fakeWalk("c/d"));
146 assertNoMatches(fakeWalk("c"));
147 assertNoMatches(fakeWalk("d/e/f"));
148 assertNoMatches(fakeWalk("d/e"));
149 assertNoMatches(fakeWalk("d"));
150
151 }
152
153 @Test
154 public void testFilterIsPrefixOfKey() throws MissingObjectException,
155 IncorrectObjectTypeException, IOException {
156 assertMatches(Sets.of("a"), fakeWalk("a/b"));
157 assertMatches(Sets.of("b/c"), fakeWalk("b/c/d"));
158 assertMatches(Sets.of("c/d/e"), fakeWalk("c/d/e/f"));
159 assertMatches(Sets.of("c/d/f"), fakeWalk("c/d/f/g"));
160 assertMatches(Sets.of("d/e/f/g"), fakeWalk("d/e/f/g/h"));
161 assertMatches(Sets.of("d/e/f/g"), fakeWalk("d/e/f/g/y"));
162 assertMatches(Sets.of("d/e/f/g.x"), fakeWalk("d/e/f/g.x/h"));
163 }
164
165 @Test
166 public void testLongPaths() throws MissingObjectException,
167 IncorrectObjectTypeException, IOException {
168 TreeFilter longPathFilter = PathFilterGroup
169 .createFromStrings(
170 "tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java",
171 "tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest2.java");
172 assertFalse(longPathFilter
173 .include(fakeWalk("tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java")));
174 assertFalse(longPathFilter.include(fakeWalk("tst/a-other-in-same")));
175 assertFalse(longPathFilter.include(fakeWalk("a-nothing-in-common")));
176 }
177
178 @Test
179 public void testStopWalk() throws MissingObjectException,
180 IncorrectObjectTypeException, IOException {
181
182 filter.include(fakeWalk("d/e/f/f"));
183
184
185 try {
186 filter.include(fakeWalk("de"));
187 fail("StopWalkException expected");
188 } catch (StopWalkException e) {
189
190 }
191
192
193 filter.include(fakeWalk("d-"));
194
195
196 try {
197 filter.include(fakeWalk("d0"));
198 fail("StopWalkException expected");
199 } catch (StopWalkException e) {
200
201 }
202
203
204 filter.include(fakeWalk("d/e/f/g/h.txt"));
205
206
207 filter.include(fakeWalk("d/e/f/g.y"));
208 singles.get("d/e/f/g").include(fakeWalk("d/e/f/g.y"));
209
210
211 try {
212 filter.include(fakeWalk("\u00C0"));
213 fail("StopWalkException expected");
214 } catch (StopWalkException e) {
215
216 }
217 }
218
219 private void assertNoMatches(TreeWalk tw) throws MissingObjectException,
220 IncorrectObjectTypeException, IOException {
221 assertMatches(Sets.<String> of(), tw);
222 }
223
224 private void assertMatches(Set<String> expect, TreeWalk tw)
225 throws MissingObjectException, IncorrectObjectTypeException,
226 IOException {
227 List<String> actual = new ArrayList<>();
228 for (String path : singles.keySet()) {
229 if (includes(singles.get(path), tw)) {
230 actual.add(path);
231 }
232 }
233
234 String[] e = expect.toArray(new String[expect.size()]);
235 String[] a = actual.toArray(new String[actual.size()]);
236 Arrays.sort(e);
237 Arrays.sort(a);
238 assertArrayEquals(e, a);
239
240 if (expect.isEmpty()) {
241 assertFalse(includes(filter, tw));
242 } else {
243 assertTrue(includes(filter, tw));
244 }
245 }
246
247 private static boolean includes(TreeFilter f, TreeWalk tw)
248 throws MissingObjectException, IncorrectObjectTypeException,
249 IOException {
250 try {
251 return f.include(tw);
252 } catch (StopWalkException e) {
253 return false;
254 }
255 }
256
257 TreeWalk fakeWalk(final String path) throws IOException {
258 DirCache dc = DirCache.newInCore();
259 DirCacheEditor dce = dc.editor();
260 dce.add(new DirCacheEditor.PathEdit(path) {
261
262 @Override
263 public void apply(DirCacheEntry ent) {
264 ent.setFileMode(FileMode.REGULAR_FILE);
265 }
266 });
267 dce.finish();
268
269 TreeWalk ret = new TreeWalk((ObjectReader) null);
270 ret.reset();
271 ret.setRecursive(true);
272 ret.addTree(new DirCacheIterator(dc));
273 ret.next();
274 return ret;
275 }
276
277 TreeWalk fakeWalkAtSubtree(final String path) throws IOException {
278 DirCache dc = DirCache.newInCore();
279 DirCacheEditor dce = dc.editor();
280 dce.add(new DirCacheEditor.PathEdit(path + "/README") {
281 @Override
282 public void apply(DirCacheEntry ent) {
283 ent.setFileMode(FileMode.REGULAR_FILE);
284 }
285 });
286 dce.finish();
287
288 TreeWalk ret = new TreeWalk((ObjectReader) null);
289 ret.addTree(new DirCacheIterator(dc));
290 ret.next();
291 while (!path.equals(ret.getPathString())) {
292 if (ret.isSubtree()) {
293 ret.enterSubtree();
294 }
295 ret.next();
296 }
297 return ret;
298 }
299 }