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.

ProtocolV2ParserTest.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*
  2. * Copyright (C) 2018, 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.transport;
  11. import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
  12. import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
  13. import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
  14. import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
  15. import static org.eclipse.jgit.transport.ObjectIdMatcher.hasOnlyObjectIds;
  16. import static org.hamcrest.MatcherAssert.assertThat;
  17. import static org.hamcrest.Matchers.hasItems;
  18. import static org.junit.Assert.assertEquals;
  19. import static org.junit.Assert.assertFalse;
  20. import static org.junit.Assert.assertThrows;
  21. import static org.junit.Assert.assertTrue;
  22. import java.io.ByteArrayInputStream;
  23. import java.io.ByteArrayOutputStream;
  24. import java.io.IOException;
  25. import org.eclipse.jgit.errors.PackProtocolException;
  26. import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
  27. import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
  28. import org.eclipse.jgit.junit.TestRepository;
  29. import org.eclipse.jgit.lib.Config;
  30. import org.eclipse.jgit.revwalk.RevCommit;
  31. import org.junit.Before;
  32. import org.junit.Test;
  33. public class ProtocolV2ParserTest {
  34. private TestRepository<InMemoryRepository> testRepo;
  35. @Before
  36. public void setUp() throws Exception {
  37. testRepo = new TestRepository<>(newRepo("protocol-v2-parser-test"));
  38. }
  39. private static InMemoryRepository newRepo(String name) {
  40. return new InMemoryRepository(new DfsRepositoryDescription(name));
  41. }
  42. private static class ConfigBuilder {
  43. private boolean allowRefInWant;
  44. private boolean allowFilter;
  45. private ConfigBuilder() {
  46. }
  47. static ConfigBuilder start() {
  48. return new ConfigBuilder();
  49. }
  50. static TransferConfig getDefault() {
  51. return start().done();
  52. }
  53. ConfigBuilder allowRefInWant() {
  54. allowRefInWant = true;
  55. return this;
  56. }
  57. ConfigBuilder allowFilter() {
  58. allowFilter = true;
  59. return this;
  60. }
  61. TransferConfig done() {
  62. Config rc = new Config();
  63. rc.setBoolean("uploadpack", null, "allowrefinwant", allowRefInWant);
  64. rc.setBoolean("uploadpack", null, "allowfilter", allowFilter);
  65. return new TransferConfig(rc);
  66. }
  67. }
  68. /*
  69. * Convert the input lines to the PacketLine that the parser reads.
  70. */
  71. private static PacketLineIn formatAsPacketLine(String... inputLines)
  72. throws IOException {
  73. ByteArrayOutputStream send = new ByteArrayOutputStream();
  74. PacketLineOut pckOut = new PacketLineOut(send);
  75. for (String line : inputLines) {
  76. if (PacketLineIn.isEnd(line)) {
  77. pckOut.end();
  78. } else if (PacketLineIn.isDelimiter(line)) {
  79. pckOut.writeDelim();
  80. } else {
  81. pckOut.writeString(line);
  82. }
  83. }
  84. return new PacketLineIn(new ByteArrayInputStream(send.toByteArray()));
  85. }
  86. /*
  87. * Successful fetch with the basic core commands of the protocol.
  88. */
  89. @Test
  90. public void testFetchBasicArguments()
  91. throws PackProtocolException, IOException {
  92. PacketLineIn pckIn = formatAsPacketLine(
  93. PacketLineIn.delimiter(),
  94. "thin-pack", "no-progress", "include-tag", "ofs-delta",
  95. "want 4624442d68ee402a94364191085b77137618633e",
  96. "want f900c8326a43303685c46b279b9f70411bff1a4b",
  97. "have 554f6e41067b9e3e565b6988a8294fac1cb78f4b",
  98. "have abc760ab9ad72f08209943251b36cb886a578f87", "done",
  99. PacketLineIn.end());
  100. ProtocolV2Parser parser = new ProtocolV2Parser(
  101. ConfigBuilder.getDefault());
  102. FetchV2Request request = parser.parseFetchRequest(pckIn);
  103. assertTrue(request.getClientCapabilities()
  104. .contains(GitProtocolConstants.OPTION_THIN_PACK));
  105. assertTrue(request.getClientCapabilities()
  106. .contains(GitProtocolConstants.OPTION_NO_PROGRESS));
  107. assertTrue(request.getClientCapabilities()
  108. .contains(GitProtocolConstants.OPTION_INCLUDE_TAG));
  109. assertTrue(request.getClientCapabilities()
  110. .contains(GitProtocolConstants.CAPABILITY_OFS_DELTA));
  111. assertThat(request.getWantIds(),
  112. hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e",
  113. "f900c8326a43303685c46b279b9f70411bff1a4b"));
  114. assertThat(request.getPeerHas(),
  115. hasOnlyObjectIds("554f6e41067b9e3e565b6988a8294fac1cb78f4b",
  116. "abc760ab9ad72f08209943251b36cb886a578f87"));
  117. assertTrue(request.getWantedRefs().isEmpty());
  118. assertTrue(request.wasDoneReceived());
  119. }
  120. @Test
  121. public void testFetchWithShallow_deepen() throws IOException {
  122. PacketLineIn pckIn = formatAsPacketLine(
  123. PacketLineIn.delimiter(),
  124. "deepen 15",
  125. "deepen-relative",
  126. "shallow 28274d02c489f4c7e68153056e9061a46f62d7a0",
  127. "shallow 145e683b229dcab9d0e2ccb01b386f9ecc17d29d",
  128. PacketLineIn.end());
  129. ProtocolV2Parser parser = new ProtocolV2Parser(
  130. ConfigBuilder.getDefault());
  131. FetchV2Request request = parser.parseFetchRequest(pckIn);
  132. assertThat(request.getClientShallowCommits(),
  133. hasOnlyObjectIds("28274d02c489f4c7e68153056e9061a46f62d7a0",
  134. "145e683b229dcab9d0e2ccb01b386f9ecc17d29d"));
  135. assertTrue(request.getDeepenNotRefs().isEmpty());
  136. assertEquals(15, request.getDepth());
  137. assertTrue(request.getClientCapabilities()
  138. .contains(GitProtocolConstants.OPTION_DEEPEN_RELATIVE));
  139. }
  140. @Test
  141. public void testFetchWithShallow_deepenNot() throws IOException {
  142. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  143. "shallow 28274d02c489f4c7e68153056e9061a46f62d7a0",
  144. "shallow 145e683b229dcab9d0e2ccb01b386f9ecc17d29d",
  145. "deepen-not a08595f76159b09d57553e37a5123f1091bb13e7",
  146. PacketLineIn.end());
  147. ProtocolV2Parser parser = new ProtocolV2Parser(
  148. ConfigBuilder.getDefault());
  149. FetchV2Request request = parser.parseFetchRequest(pckIn);
  150. assertThat(request.getClientShallowCommits(),
  151. hasOnlyObjectIds("28274d02c489f4c7e68153056e9061a46f62d7a0",
  152. "145e683b229dcab9d0e2ccb01b386f9ecc17d29d"));
  153. assertThat(request.getDeepenNotRefs(),
  154. hasItems("a08595f76159b09d57553e37a5123f1091bb13e7"));
  155. }
  156. @Test
  157. public void testFetchWithShallow_deepenSince() throws IOException {
  158. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  159. "shallow 28274d02c489f4c7e68153056e9061a46f62d7a0",
  160. "shallow 145e683b229dcab9d0e2ccb01b386f9ecc17d29d",
  161. "deepen-since 123123123",
  162. PacketLineIn.end());
  163. ProtocolV2Parser parser = new ProtocolV2Parser(
  164. ConfigBuilder.getDefault());
  165. FetchV2Request request = parser.parseFetchRequest(pckIn);
  166. assertThat(request.getClientShallowCommits(),
  167. hasOnlyObjectIds("28274d02c489f4c7e68153056e9061a46f62d7a0",
  168. "145e683b229dcab9d0e2ccb01b386f9ecc17d29d"));
  169. assertEquals(123123123, request.getDeepenSince());
  170. }
  171. @Test
  172. public void testFetchWithNoneFilter() throws IOException {
  173. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  174. "filter blob:none",
  175. PacketLineIn.end());
  176. ProtocolV2Parser parser = new ProtocolV2Parser(
  177. ConfigBuilder.start().allowFilter().done());
  178. FetchV2Request request = parser.parseFetchRequest(pckIn);
  179. assertFalse(request.getFilterSpec().allowsType(OBJ_BLOB));
  180. assertTrue(request.getFilterSpec().allowsType(OBJ_TREE));
  181. assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT));
  182. assertTrue(request.getFilterSpec().allowsType(OBJ_TAG));
  183. assertEquals(-1, request.getFilterSpec().getBlobLimit());
  184. assertEquals(-1, request.getFilterSpec().getTreeDepthLimit());
  185. }
  186. @Test
  187. public void testFetchWithBlobSizeFilter() throws IOException {
  188. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  189. "filter blob:limit=15",
  190. PacketLineIn.end());
  191. ProtocolV2Parser parser = new ProtocolV2Parser(
  192. ConfigBuilder.start().allowFilter().done());
  193. FetchV2Request request = parser.parseFetchRequest(pckIn);
  194. assertTrue(request.getFilterSpec().allowsType(OBJ_BLOB));
  195. assertTrue(request.getFilterSpec().allowsType(OBJ_TREE));
  196. assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT));
  197. assertTrue(request.getFilterSpec().allowsType(OBJ_TAG));
  198. assertEquals(15, request.getFilterSpec().getBlobLimit());
  199. assertEquals(-1, request.getFilterSpec().getTreeDepthLimit());
  200. }
  201. @Test
  202. public void testFetchWithTreeDepthFilter() throws IOException {
  203. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  204. "filter tree:3",
  205. PacketLineIn.end());
  206. ProtocolV2Parser parser = new ProtocolV2Parser(
  207. ConfigBuilder.start().allowFilter().done());
  208. FetchV2Request request = parser.parseFetchRequest(pckIn);
  209. assertTrue(request.getFilterSpec().allowsType(OBJ_BLOB));
  210. assertTrue(request.getFilterSpec().allowsType(OBJ_TREE));
  211. assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT));
  212. assertTrue(request.getFilterSpec().allowsType(OBJ_TAG));
  213. assertEquals(-1, request.getFilterSpec().getBlobLimit());
  214. assertEquals(3, request.getFilterSpec().getTreeDepthLimit());
  215. }
  216. @Test
  217. public void testFetchMustNotHaveMultipleFilters() throws IOException {
  218. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  219. "filter blob:none",
  220. "filter blob:limit=12",
  221. PacketLineIn.end());
  222. ProtocolV2Parser parser = new ProtocolV2Parser(
  223. ConfigBuilder.start().allowFilter().done());
  224. assertThrows(PackProtocolException.class,
  225. () -> parser.parseFetchRequest(pckIn));
  226. }
  227. @Test
  228. public void testFetchFilterWithoutAllowFilter() throws IOException {
  229. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  230. "filter blob:limit=12", PacketLineIn.end());
  231. ProtocolV2Parser parser = new ProtocolV2Parser(
  232. ConfigBuilder.getDefault());
  233. assertThrows(PackProtocolException.class,
  234. () -> parser.parseFetchRequest(pckIn));
  235. }
  236. @Test
  237. public void testFetchWithRefInWant() throws Exception {
  238. RevCommit one = testRepo.commit().message("1").create();
  239. RevCommit two = testRepo.commit().message("2").create();
  240. testRepo.update("branchA", one);
  241. testRepo.update("branchB", two);
  242. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  243. "want e4980cdc48cfa1301493ca94eb70523f6788b819",
  244. "want-ref refs/heads/branchA",
  245. PacketLineIn.end());
  246. ProtocolV2Parser parser = new ProtocolV2Parser(
  247. ConfigBuilder.start().allowRefInWant().done());
  248. FetchV2Request request = parser.parseFetchRequest(pckIn);
  249. assertEquals(1, request.getWantedRefs().size());
  250. assertThat(request.getWantedRefs(),
  251. hasItems("refs/heads/branchA"));
  252. assertEquals(1, request.getWantIds().size());
  253. assertThat(request.getWantIds(), hasOnlyObjectIds(
  254. "e4980cdc48cfa1301493ca94eb70523f6788b819"));
  255. }
  256. @Test
  257. public void testFetchWithRefInWantUnknownRef() throws Exception {
  258. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  259. "want e4980cdc48cfa1301493ca94eb70523f6788b819",
  260. "want-ref refs/heads/branchC",
  261. PacketLineIn.end());
  262. ProtocolV2Parser parser = new ProtocolV2Parser(
  263. ConfigBuilder.start().allowRefInWant().done());
  264. RevCommit one = testRepo.commit().message("1").create();
  265. RevCommit two = testRepo.commit().message("2").create();
  266. testRepo.update("branchA", one);
  267. testRepo.update("branchB", two);
  268. FetchV2Request request = parser.parseFetchRequest(pckIn);
  269. assertEquals(1, request.getWantedRefs().size());
  270. assertThat(request.getWantedRefs(), hasItems("refs/heads/branchC"));
  271. }
  272. @Test
  273. public void testLsRefsMinimalReq() throws IOException {
  274. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  275. PacketLineIn.end());
  276. ProtocolV2Parser parser = new ProtocolV2Parser(
  277. ConfigBuilder.getDefault());
  278. LsRefsV2Request req = parser.parseLsRefsRequest(pckIn);
  279. assertFalse(req.getPeel());
  280. assertFalse(req.getSymrefs());
  281. assertEquals(0, req.getRefPrefixes().size());
  282. }
  283. @Test
  284. public void testLsRefsSymrefs() throws IOException {
  285. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(), "symrefs",
  286. PacketLineIn.end());
  287. ProtocolV2Parser parser = new ProtocolV2Parser(
  288. ConfigBuilder.getDefault());
  289. LsRefsV2Request req = parser.parseLsRefsRequest(pckIn);
  290. assertFalse(req.getPeel());
  291. assertTrue(req.getSymrefs());
  292. assertEquals(0, req.getRefPrefixes().size());
  293. }
  294. @Test
  295. public void testLsRefsPeel() throws IOException {
  296. PacketLineIn pckIn = formatAsPacketLine(
  297. PacketLineIn.delimiter(),
  298. "peel",
  299. PacketLineIn.end());
  300. ProtocolV2Parser parser = new ProtocolV2Parser(
  301. ConfigBuilder.getDefault());
  302. LsRefsV2Request req = parser.parseLsRefsRequest(pckIn);
  303. assertTrue(req.getPeel());
  304. assertFalse(req.getSymrefs());
  305. assertEquals(0, req.getRefPrefixes().size());
  306. }
  307. @Test
  308. public void testLsRefsRefPrefixes() throws IOException {
  309. PacketLineIn pckIn = formatAsPacketLine(PacketLineIn.delimiter(),
  310. "ref-prefix refs/for", "ref-prefix refs/heads",
  311. PacketLineIn.end());
  312. ProtocolV2Parser parser = new ProtocolV2Parser(
  313. ConfigBuilder.getDefault());
  314. LsRefsV2Request req = parser.parseLsRefsRequest(pckIn);
  315. assertFalse(req.getPeel());
  316. assertFalse(req.getSymrefs());
  317. assertEquals(2, req.getRefPrefixes().size());
  318. assertThat(req.getRefPrefixes(), hasItems("refs/for", "refs/heads"));
  319. }
  320. }