You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CanonicalTreeParserTest.java 11KB

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