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