1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.treewalk;
12
13 import static java.nio.charset.StandardCharsets.UTF_8;
14 import static org.eclipse.jgit.lib.FileMode.REGULAR_FILE;
15 import static org.eclipse.jgit.lib.FileMode.SYMLINK;
16 import static org.junit.Assert.assertEquals;
17 import static org.junit.Assert.assertFalse;
18 import static org.junit.Assert.assertSame;
19 import static org.junit.Assert.assertTrue;
20
21 import java.io.ByteArrayOutputStream;
22
23 import org.eclipse.jgit.errors.CorruptObjectException;
24 import org.eclipse.jgit.lib.Constants;
25 import org.eclipse.jgit.lib.FileMode;
26 import org.eclipse.jgit.lib.ObjectId;
27 import org.eclipse.jgit.lib.TreeFormatter;
28 import org.eclipse.jgit.util.RawParseUtils;
29 import org.junit.Before;
30 import org.junit.Test;
31
32 public class CanonicalTreeParserTest {
33 private final CanonicalTreeParser ctp = new CanonicalTreeParser();
34
35 private final FileMode m644 = FileMode.REGULAR_FILE;
36
37 private final FileMode mt = FileMode.TREE;
38
39 private final ObjectId hash_a = ObjectId
40 .fromString("6b9c715d21d5486e59083fb6071566aa6ecd4d42");
41
42 private final ObjectId hash_foo = ObjectId
43 .fromString("a213e8e25bb2442326e86cbfb9ef56319f482869");
44
45 private final ObjectId hash_sometree = ObjectId
46 .fromString("daf4bdb0d7bb24319810fe0e73aa317663448c93");
47
48 private byte[] tree1;
49
50 private byte[] tree2;
51
52 private byte[] tree3;
53
54 @Before
55 public void setUp() throws Exception {
56 tree1 = mktree(entry(m644, "a", hash_a));
57 tree2 = mktree(entry(m644, "a", hash_a), entry(m644, "foo", hash_foo));
58 tree3 = mktree(entry(m644, "a", hash_a), entry(mt, "b_sometree",
59 hash_sometree), entry(m644, "foo", hash_foo));
60 }
61
62 private static byte[] mktree(byte[]... data) throws Exception {
63 final ByteArrayOutputStream out = new ByteArrayOutputStream();
64 for (byte[] e : data)
65 out.write(e);
66 return out.toByteArray();
67 }
68
69 private static byte[] entry(final FileMode mode, final String name,
70 final ObjectId id) throws Exception {
71 final ByteArrayOutputStream out = new ByteArrayOutputStream();
72 mode.copyTo(out);
73 out.write(' ');
74 out.write(Constants.encode(name));
75 out.write(0);
76 id.copyRawTo(out);
77 return out.toByteArray();
78 }
79
80 private String path() {
81 return RawParseUtils.decode(UTF_8, ctp.path,
82 ctp.pathOffset, ctp.pathLen);
83 }
84
85 @Test
86 public void testEmptyTree_AtEOF() throws Exception {
87 ctp.reset(new byte[0]);
88 assertTrue(ctp.eof());
89 }
90
91 @Test
92 public void testOneEntry_Forward() throws Exception {
93 ctp.reset(tree1);
94
95 assertTrue(ctp.first());
96 assertFalse(ctp.eof());
97 assertEquals(m644.getBits(), ctp.mode);
98 assertEquals("a", path());
99 assertEquals(hash_a, ctp.getEntryObjectId());
100
101 ctp.next(1);
102 assertFalse(ctp.first());
103 assertTrue(ctp.eof());
104 }
105
106 @Test
107 public void testTwoEntries_ForwardOneAtATime() throws Exception {
108 ctp.reset(tree2);
109
110 assertTrue(ctp.first());
111 assertFalse(ctp.eof());
112 assertEquals(m644.getBits(), ctp.mode);
113 assertEquals("a", path());
114 assertEquals(hash_a, ctp.getEntryObjectId());
115
116 ctp.next(1);
117 assertFalse(ctp.eof());
118 assertEquals(m644.getBits(), ctp.mode);
119 assertEquals("foo", path());
120 assertEquals(hash_foo, ctp.getEntryObjectId());
121
122 ctp.next(1);
123 assertFalse(ctp.first());
124 assertTrue(ctp.eof());
125 }
126
127 @Test
128 public void testOneEntry_Seek1IsEOF() throws Exception {
129 ctp.reset(tree1);
130 ctp.next(1);
131 assertTrue(ctp.eof());
132 }
133
134 @Test
135 public void testTwoEntries_Seek2IsEOF() throws Exception {
136 ctp.reset(tree2);
137 ctp.next(2);
138 assertTrue(ctp.eof());
139 }
140
141 @Test
142 public void testThreeEntries_Seek3IsEOF() throws Exception {
143 ctp.reset(tree3);
144 ctp.next(3);
145 assertTrue(ctp.eof());
146 }
147
148 @Test
149 public void testThreeEntries_Seek2() throws Exception {
150 ctp.reset(tree3);
151
152 ctp.next(2);
153 assertFalse(ctp.eof());
154 assertFalse(ctp.eof());
155 assertEquals(m644.getBits(), ctp.mode);
156 assertEquals("foo", path());
157 assertEquals(hash_foo, ctp.getEntryObjectId());
158
159 ctp.next(1);
160 assertTrue(ctp.eof());
161 }
162
163 @Test
164 public void testOneEntry_Backwards() throws Exception {
165 ctp.reset(tree1);
166 ctp.next(1);
167 assertFalse(ctp.first());
168 assertTrue(ctp.eof());
169
170 ctp.back(1);
171 assertTrue(ctp.first());
172 assertFalse(ctp.eof());
173 assertEquals(m644.getBits(), ctp.mode);
174 assertEquals("a", path());
175 assertEquals(hash_a, ctp.getEntryObjectId());
176 }
177
178 @Test
179 public void testTwoEntries_BackwardsOneAtATime() throws Exception {
180 ctp.reset(tree2);
181 ctp.next(2);
182 assertTrue(ctp.eof());
183
184 ctp.back(1);
185 assertFalse(ctp.eof());
186 assertEquals(m644.getBits(), ctp.mode);
187 assertEquals("foo", path());
188 assertEquals(hash_foo, ctp.getEntryObjectId());
189
190 ctp.back(1);
191 assertFalse(ctp.eof());
192 assertEquals(m644.getBits(), ctp.mode);
193 assertEquals("a", path());
194 assertEquals(hash_a, ctp.getEntryObjectId());
195 }
196
197 @Test
198 public void testTwoEntries_BackwardsTwo() throws Exception {
199 ctp.reset(tree2);
200 ctp.next(2);
201 assertTrue(ctp.eof());
202
203 ctp.back(2);
204 assertFalse(ctp.eof());
205 assertEquals(m644.getBits(), ctp.mode);
206 assertEquals("a", path());
207 assertEquals(hash_a, ctp.getEntryObjectId());
208
209 ctp.next(1);
210 assertFalse(ctp.eof());
211 assertEquals(m644.getBits(), ctp.mode);
212 assertEquals("foo", path());
213 assertEquals(hash_foo, ctp.getEntryObjectId());
214
215 ctp.next(1);
216 assertTrue(ctp.eof());
217 }
218
219 @Test
220 public void testThreeEntries_BackwardsTwo() throws Exception {
221 ctp.reset(tree3);
222 ctp.next(3);
223 assertTrue(ctp.eof());
224
225 ctp.back(2);
226 assertFalse(ctp.eof());
227 assertEquals(mt.getBits(), ctp.mode);
228 assertEquals("b_sometree", path());
229 assertEquals(hash_sometree, ctp.getEntryObjectId());
230
231 ctp.next(1);
232 assertFalse(ctp.eof());
233 assertEquals(m644.getBits(), ctp.mode);
234 assertEquals("foo", path());
235 assertEquals(hash_foo, ctp.getEntryObjectId());
236
237 ctp.next(1);
238 assertTrue(ctp.eof());
239 }
240
241 @Test
242 public void testBackwards_ConfusingPathName() throws Exception {
243 final String aVeryConfusingName = "confusing 644 entry 755 and others";
244 ctp.reset(mktree(entry(m644, "a", hash_a), entry(mt, aVeryConfusingName,
245 hash_sometree), entry(m644, "foo", hash_foo)));
246 ctp.next(3);
247 assertTrue(ctp.eof());
248
249 ctp.back(2);
250 assertFalse(ctp.eof());
251 assertEquals(mt.getBits(), ctp.mode);
252 assertEquals(aVeryConfusingName, path());
253 assertEquals(hash_sometree, ctp.getEntryObjectId());
254
255 ctp.back(1);
256 assertFalse(ctp.eof());
257 assertEquals(m644.getBits(), ctp.mode);
258 assertEquals("a", path());
259 assertEquals(hash_a, ctp.getEntryObjectId());
260 }
261
262 @Test
263 public void testBackwords_Prebuilts1() throws Exception {
264
265
266
267
268
269 final ObjectId common = ObjectId
270 .fromString("af7bf97cb9bce3f60f1d651a0ef862e9447dd8bc");
271 final ObjectId darwinx86 = ObjectId
272 .fromString("e927f7398240f78face99e1a738dac54ef738e37");
273 final ObjectId linuxx86 = ObjectId
274 .fromString("ac08dd97120c7cb7d06e98cd5b152011183baf21");
275 final ObjectId windows = ObjectId
276 .fromString("6c4c64c221a022bb973165192cca4812033479df");
277
278 ctp.reset(mktree(entry(mt, "common", common), entry(mt, "darwin-x86",
279 darwinx86), entry(mt, "linux-x86", linuxx86), entry(mt,
280 "windows", windows)));
281 ctp.next(3);
282 assertEquals("windows", ctp.getEntryPathString());
283 assertSame(mt, ctp.getEntryFileMode());
284 assertEquals(windows, ctp.getEntryObjectId());
285
286 ctp.back(1);
287 assertEquals("linux-x86", ctp.getEntryPathString());
288 assertSame(mt, ctp.getEntryFileMode());
289 assertEquals(linuxx86, ctp.getEntryObjectId());
290
291 ctp.next(1);
292 assertEquals("windows", ctp.getEntryPathString());
293 assertSame(mt, ctp.getEntryFileMode());
294 assertEquals(windows, ctp.getEntryObjectId());
295 }
296
297 @Test
298 public void testBackwords_Prebuilts2() throws Exception {
299
300
301
302
303
304 final ObjectId common = ObjectId
305 .fromString("af7bf97cb9bce3f60f1d651a0ef862e9447dd8bc");
306 final ObjectId darwinx86 = ObjectId
307 .fromString("0000000000000000000000000000000000000037");
308 final ObjectId linuxx86 = ObjectId
309 .fromString("ac08dd97120c7cb7d06e98cd5b152011183baf21");
310 final ObjectId windows = ObjectId
311 .fromString("6c4c64c221a022bb973165192cca4812033479df");
312
313 ctp.reset(mktree(entry(mt, "common", common), entry(mt, "darwin-x86",
314 darwinx86), entry(mt, "linux-x86", linuxx86), entry(mt,
315 "windows", windows)));
316 ctp.next(3);
317 assertEquals("windows", ctp.getEntryPathString());
318 assertSame(mt, ctp.getEntryFileMode());
319 assertEquals(windows, ctp.getEntryObjectId());
320
321 ctp.back(1);
322 assertEquals("linux-x86", ctp.getEntryPathString());
323 assertSame(mt, ctp.getEntryFileMode());
324 assertEquals(linuxx86, ctp.getEntryObjectId());
325
326 ctp.next(1);
327 assertEquals("windows", ctp.getEntryPathString());
328 assertSame(mt, ctp.getEntryFileMode());
329 assertEquals(windows, ctp.getEntryObjectId());
330 }
331
332 @Test
333 public void testFreakingHugePathName() throws Exception {
334 final int n = AbstractTreeIterator.DEFAULT_PATH_SIZE * 4;
335 final StringBuilder b = new StringBuilder(n);
336 for (int i = 0; i < n; i++)
337 b.append('q');
338 final String name = b.toString();
339 ctp.reset(entry(m644, name, hash_a));
340 assertFalse(ctp.eof());
341 assertEquals(name, RawParseUtils.decode(UTF_8, ctp.path,
342 ctp.pathOffset, ctp.pathLen));
343 }
344
345 @Test
346 public void testFindAttributesWhenFirst() throws CorruptObjectException {
347 TreeFormatter tree = new TreeFormatter();
348 tree.append(".gitattributes", REGULAR_FILE, hash_a);
349 ctp.reset(tree.toByteArray());
350
351 assertTrue(ctp.findFile(".gitattributes"));
352 assertEquals(REGULAR_FILE.getBits(), ctp.getEntryRawMode());
353 assertEquals(".gitattributes", ctp.getEntryPathString());
354 assertEquals(hash_a, ctp.getEntryObjectId());
355 }
356
357 @Test
358 public void testFindAttributesWhenSecond() throws CorruptObjectException {
359 TreeFormatter tree = new TreeFormatter();
360 tree.append(".config", SYMLINK, hash_a);
361 tree.append(".gitattributes", REGULAR_FILE, hash_foo);
362 ctp.reset(tree.toByteArray());
363
364 assertTrue(ctp.findFile(".gitattributes"));
365 assertEquals(REGULAR_FILE.getBits(), ctp.getEntryRawMode());
366 assertEquals(".gitattributes", ctp.getEntryPathString());
367 assertEquals(hash_foo, ctp.getEntryObjectId());
368 }
369
370 @Test
371 public void testFindAttributesWhenMissing() throws CorruptObjectException {
372 TreeFormatter tree = new TreeFormatter();
373 tree.append("src", REGULAR_FILE, hash_a);
374 tree.append("zoo", REGULAR_FILE, hash_foo);
375 ctp.reset(tree.toByteArray());
376
377 assertFalse(ctp.findFile(".gitattributes"));
378 assertEquals(11, ctp.idOffset());
379 assertEquals("src", ctp.getEntryPathString());
380 }
381 }