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 12KB

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