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.

PacketLineInTest.java 9.5KB

Client-side protocol V2 support for fetching Make all transports request protocol V2 when fetching. Depending on the transport, set the GIT_PROTOCOL environment variable (file and ssh), pass the Git-Protocol header (http), or set the hidden "\0version=2\0" (git anon). We'll fall back to V0 if the server doesn't reply with a version 2 answer. A user can control which protocol the client requests via the git config protocol.version; if not set, JGit requests protocol V2 for fetching. Pushing always uses protocol V0 still. In the API, there is only a new Transport.openFetch() version that takes a collection of RefSpecs plus additional patterns to construct the Ref prefixes for the "ls-refs" command in protocol V2. If none are given, the server will still advertise all refs, even in protocol V2. BasePackConnection.readAdvertisedRefs() handles falling back to protocol V0. It newly returns true if V0 was used and the advertised refs were read, and false if V2 is used and an explicit "ls-refs" is needed. (This can't be done transparently inside readAdvertisedRefs() because a "stateless RPC" transport like TransportHttp may need to open a new connection for writing.) BasePackFetchConnection implements the changes needed for the protocol V2 "fetch" command (stateless protocol, simplified ACK handling, delimiters, section headers). In TransportHttp, change readSmartHeaders() to also recognize the "version 2" packet line as a valid smart server indication. Adapt tests, and run all the HTTP tests not only with both HTTP connection factories (JDK and Apache HttpClient) but also with both protocol V0 and V2. The SSH tests are much slower and much more focused on the SSH protocol and SSH key handling. Factor out two very simple cloning and pulling tests and make those run with protocol V2. Bug: 553083 Change-Id: I357c7f5daa7efb2872f1c64ee6f6d54229031ae1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
3 years ago
Client-side protocol V2 support for fetching Make all transports request protocol V2 when fetching. Depending on the transport, set the GIT_PROTOCOL environment variable (file and ssh), pass the Git-Protocol header (http), or set the hidden "\0version=2\0" (git anon). We'll fall back to V0 if the server doesn't reply with a version 2 answer. A user can control which protocol the client requests via the git config protocol.version; if not set, JGit requests protocol V2 for fetching. Pushing always uses protocol V0 still. In the API, there is only a new Transport.openFetch() version that takes a collection of RefSpecs plus additional patterns to construct the Ref prefixes for the "ls-refs" command in protocol V2. If none are given, the server will still advertise all refs, even in protocol V2. BasePackConnection.readAdvertisedRefs() handles falling back to protocol V0. It newly returns true if V0 was used and the advertised refs were read, and false if V2 is used and an explicit "ls-refs" is needed. (This can't be done transparently inside readAdvertisedRefs() because a "stateless RPC" transport like TransportHttp may need to open a new connection for writing.) BasePackFetchConnection implements the changes needed for the protocol V2 "fetch" command (stateless protocol, simplified ACK handling, delimiters, section headers). In TransportHttp, change readSmartHeaders() to also recognize the "version 2" packet line as a valid smart server indication. Adapt tests, and run all the HTTP tests not only with both HTTP connection factories (JDK and Apache HttpClient) but also with both protocol V0 and V2. The SSH tests are much slower and much more focused on the SSH protocol and SSH key handling. Factor out two very simple cloning and pulling tests and make those run with protocol V2. Bug: 553083 Change-Id: I357c7f5daa7efb2872f1c64ee6f6d54229031ae1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
3 years ago
Client-side protocol V2 support for fetching Make all transports request protocol V2 when fetching. Depending on the transport, set the GIT_PROTOCOL environment variable (file and ssh), pass the Git-Protocol header (http), or set the hidden "\0version=2\0" (git anon). We'll fall back to V0 if the server doesn't reply with a version 2 answer. A user can control which protocol the client requests via the git config protocol.version; if not set, JGit requests protocol V2 for fetching. Pushing always uses protocol V0 still. In the API, there is only a new Transport.openFetch() version that takes a collection of RefSpecs plus additional patterns to construct the Ref prefixes for the "ls-refs" command in protocol V2. If none are given, the server will still advertise all refs, even in protocol V2. BasePackConnection.readAdvertisedRefs() handles falling back to protocol V0. It newly returns true if V0 was used and the advertised refs were read, and false if V2 is used and an explicit "ls-refs" is needed. (This can't be done transparently inside readAdvertisedRefs() because a "stateless RPC" transport like TransportHttp may need to open a new connection for writing.) BasePackFetchConnection implements the changes needed for the protocol V2 "fetch" command (stateless protocol, simplified ACK handling, delimiters, section headers). In TransportHttp, change readSmartHeaders() to also recognize the "version 2" packet line as a valid smart server indication. Adapt tests, and run all the HTTP tests not only with both HTTP connection factories (JDK and Apache HttpClient) but also with both protocol V0 and V2. The SSH tests are much slower and much more focused on the SSH protocol and SSH key handling. Factor out two very simple cloning and pulling tests and make those run with protocol V2. Bug: 553083 Change-Id: I357c7f5daa7efb2872f1c64ee6f6d54229031ae1 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. * Copyright (C) 2009, 2020 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.transport;
  11. import static org.junit.Assert.assertEquals;
  12. import static org.junit.Assert.assertFalse;
  13. import static org.junit.Assert.assertSame;
  14. import static org.junit.Assert.assertThrows;
  15. import static org.junit.Assert.assertTrue;
  16. import static org.junit.Assert.fail;
  17. import java.io.ByteArrayInputStream;
  18. import java.io.IOException;
  19. import org.eclipse.jgit.errors.PackProtocolException;
  20. import org.eclipse.jgit.lib.Constants;
  21. import org.eclipse.jgit.lib.MutableObjectId;
  22. import org.eclipse.jgit.lib.ObjectId;
  23. import org.junit.Test;
  24. // Note, test vectors created with:
  25. //
  26. // perl -e 'printf "%4.4x%s\n", 4+length($ARGV[0]),$ARGV[0]'
  27. public class PacketLineInTest {
  28. private ByteArrayInputStream rawIn;
  29. private PacketLineIn in;
  30. // readString
  31. @Test
  32. public void testReadString1() throws IOException {
  33. init("0006a\n0007bc\n");
  34. assertEquals("a", in.readString());
  35. assertEquals("bc", in.readString());
  36. assertEOF();
  37. }
  38. @Test
  39. public void testReadString2() throws IOException {
  40. init("0032want fcfcfb1fd94829c1a1704f894fc111d14770d34e\n");
  41. final String act = in.readString();
  42. assertEquals("want fcfcfb1fd94829c1a1704f894fc111d14770d34e", act);
  43. assertEOF();
  44. }
  45. @Test
  46. public void testReadString4() throws IOException {
  47. init("0005a0006bc");
  48. assertEquals("a", in.readString());
  49. assertEquals("bc", in.readString());
  50. assertEOF();
  51. }
  52. @Test
  53. public void testReadString5() throws IOException {
  54. // accept both upper and lower case
  55. init("000Fhi i am a s");
  56. assertEquals("hi i am a s", in.readString());
  57. assertEOF();
  58. init("000fhi i am a s");
  59. assertEquals("hi i am a s", in.readString());
  60. assertEOF();
  61. }
  62. @Test
  63. public void testReadString_LenHELO() {
  64. init("HELO");
  65. try {
  66. in.readString();
  67. fail("incorrectly accepted invalid packet header");
  68. } catch (IOException e) {
  69. assertEquals("Invalid packet line header: HELO", e.getMessage());
  70. }
  71. }
  72. @Test
  73. public void testReadString_Len0002() {
  74. init("0002");
  75. try {
  76. in.readString();
  77. fail("incorrectly accepted invalid packet header");
  78. } catch (IOException e) {
  79. assertEquals("Invalid packet line header: 0002", e.getMessage());
  80. }
  81. }
  82. @Test
  83. public void testReadString_Len0003() {
  84. init("0003");
  85. try {
  86. in.readString();
  87. fail("incorrectly accepted invalid packet header");
  88. } catch (IOException e) {
  89. assertEquals("Invalid packet line header: 0003", e.getMessage());
  90. }
  91. }
  92. @Test
  93. public void testReadString_Len0004() throws IOException {
  94. init("0004");
  95. final String act = in.readString();
  96. assertEquals("", act);
  97. assertFalse(PacketLineIn.isEnd(act));
  98. assertFalse(PacketLineIn.isDelimiter(act));
  99. assertEOF();
  100. }
  101. @Test
  102. public void testReadString_End() throws IOException {
  103. init("0000");
  104. String act = in.readString();
  105. assertTrue(PacketLineIn.isEnd(act));
  106. assertFalse(PacketLineIn.isDelimiter(act));
  107. assertEOF();
  108. }
  109. @Test
  110. public void testReadString_Delim() throws IOException {
  111. init("0001");
  112. String act = in.readString();
  113. assertTrue(PacketLineIn.isDelimiter(act));
  114. assertFalse(PacketLineIn.isEnd(act));
  115. assertEOF();
  116. }
  117. // readStringNoLF
  118. @Test
  119. public void testReadStringRaw1() throws IOException {
  120. init("0005a0006bc");
  121. assertEquals("a", in.readStringRaw());
  122. assertEquals("bc", in.readStringRaw());
  123. assertEOF();
  124. }
  125. @Test
  126. public void testReadStringRaw2() throws IOException {
  127. init("0031want fcfcfb1fd94829c1a1704f894fc111d14770d34e");
  128. final String act = in.readStringRaw();
  129. assertEquals("want fcfcfb1fd94829c1a1704f894fc111d14770d34e", act);
  130. assertEOF();
  131. }
  132. @Test
  133. public void testReadStringRaw3() throws IOException {
  134. init("0004");
  135. final String act = in.readStringRaw();
  136. assertEquals("", act);
  137. assertFalse(PacketLineIn.isEnd(act));
  138. assertEOF();
  139. }
  140. @Test
  141. public void testReadStringRaw_End() throws IOException {
  142. init("0000");
  143. assertTrue(PacketLineIn.isEnd(in.readString()));
  144. assertEOF();
  145. }
  146. @Test
  147. public void testReadStringRaw4() {
  148. init("HELO");
  149. try {
  150. in.readStringRaw();
  151. fail("incorrectly accepted invalid packet header");
  152. } catch (IOException e) {
  153. assertEquals("Invalid packet line header: HELO", e.getMessage());
  154. }
  155. }
  156. // readACK
  157. @Test
  158. public void testReadACK_NAK() throws IOException {
  159. final ObjectId expid = ObjectId
  160. .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
  161. final MutableObjectId actid = new MutableObjectId();
  162. actid.fromString(expid.name());
  163. init("0008NAK\n");
  164. assertSame(PacketLineIn.AckNackResult.NAK, in.readACK(actid));
  165. assertEquals(expid, actid);
  166. assertEOF();
  167. }
  168. @Test
  169. public void testReadACK_ACK1() throws IOException {
  170. final ObjectId expid = ObjectId
  171. .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
  172. final MutableObjectId actid = new MutableObjectId();
  173. init("0031ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e\n");
  174. assertSame(PacketLineIn.AckNackResult.ACK, in.readACK(actid));
  175. assertEquals(expid, actid);
  176. assertEOF();
  177. }
  178. @Test
  179. public void testReadACK_ACKcontinue1() throws IOException {
  180. final ObjectId expid = ObjectId
  181. .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
  182. final MutableObjectId actid = new MutableObjectId();
  183. init("003aACK fcfcfb1fd94829c1a1704f894fc111d14770d34e continue\n");
  184. assertSame(PacketLineIn.AckNackResult.ACK_CONTINUE, in.readACK(actid));
  185. assertEquals(expid, actid);
  186. assertEOF();
  187. }
  188. @Test
  189. public void testReadACK_ACKcommon1() throws IOException {
  190. final ObjectId expid = ObjectId
  191. .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
  192. final MutableObjectId actid = new MutableObjectId();
  193. init("0038ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e common\n");
  194. assertSame(PacketLineIn.AckNackResult.ACK_COMMON, in.readACK(actid));
  195. assertEquals(expid, actid);
  196. assertEOF();
  197. }
  198. @Test
  199. public void testReadACK_ACKready1() throws IOException {
  200. final ObjectId expid = ObjectId
  201. .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
  202. final MutableObjectId actid = new MutableObjectId();
  203. init("0037ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e ready\n");
  204. assertSame(PacketLineIn.AckNackResult.ACK_READY, in.readACK(actid));
  205. assertEquals(expid, actid);
  206. assertEOF();
  207. }
  208. @Test
  209. public void testReadACK_Invalid1() {
  210. init("HELO");
  211. try {
  212. in.readACK(new MutableObjectId());
  213. fail("incorrectly accepted invalid packet header");
  214. } catch (IOException e) {
  215. assertEquals("Invalid packet line header: HELO", e.getMessage());
  216. }
  217. }
  218. @Test
  219. public void testReadACK_Invalid2() {
  220. init("0009HELO\n");
  221. try {
  222. in.readACK(new MutableObjectId());
  223. fail("incorrectly accepted invalid ACK/NAK");
  224. } catch (IOException e) {
  225. assertEquals("Expected ACK/NAK, got: HELO", e.getMessage());
  226. }
  227. }
  228. @Test
  229. public void testReadACK_Invalid3() {
  230. String s = "ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e neverhappen";
  231. init("003d" + s + "\n");
  232. try {
  233. in.readACK(new MutableObjectId());
  234. fail("incorrectly accepted unsupported ACK status");
  235. } catch (IOException e) {
  236. assertEquals("Expected ACK/NAK, got: " + s, e.getMessage());
  237. }
  238. }
  239. @Test
  240. public void testReadACK_Invalid4() {
  241. init("0000");
  242. try {
  243. in.readACK(new MutableObjectId());
  244. fail("incorrectly accepted no ACK/NAK");
  245. } catch (IOException e) {
  246. assertEquals("Expected ACK/NAK, found EOF", e.getMessage());
  247. }
  248. }
  249. @Test
  250. public void testReadACK_ERR() throws IOException {
  251. init("001aERR want is not valid\n");
  252. try {
  253. in.readACK(new MutableObjectId());
  254. fail("incorrectly accepted ERR");
  255. } catch (PackProtocolException e) {
  256. assertEquals("want is not valid", e.getMessage());
  257. }
  258. }
  259. // parseACKv2
  260. @Test
  261. public void testParseAckV2_NAK() throws IOException {
  262. final ObjectId expid = ObjectId
  263. .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
  264. final MutableObjectId actid = new MutableObjectId();
  265. actid.fromString(expid.name());
  266. assertSame(PacketLineIn.AckNackResult.NAK,
  267. PacketLineIn.parseACKv2("NAK", actid));
  268. assertEquals(expid, actid);
  269. }
  270. @Test
  271. public void testParseAckV2_ACK() throws IOException {
  272. final ObjectId expid = ObjectId
  273. .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
  274. final MutableObjectId actid = new MutableObjectId();
  275. assertSame(PacketLineIn.AckNackResult.ACK_COMMON,
  276. PacketLineIn.parseACKv2(
  277. "ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e", actid));
  278. assertEquals(expid, actid);
  279. }
  280. @Test
  281. public void testParseAckV2_Ready() throws IOException {
  282. final ObjectId expid = ObjectId
  283. .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
  284. final MutableObjectId actid = new MutableObjectId();
  285. actid.fromString(expid.name());
  286. assertSame(PacketLineIn.AckNackResult.ACK_READY,
  287. PacketLineIn.parseACKv2("ready", actid));
  288. assertEquals(expid, actid);
  289. }
  290. @Test
  291. public void testParseAckV2_ERR() {
  292. IOException e = assertThrows(IOException.class, () -> PacketLineIn
  293. .parseACKv2("ERR want is not valid", new MutableObjectId()));
  294. assertTrue(e.getMessage().contains("want is not valid"));
  295. }
  296. @Test
  297. public void testParseAckV2_Invalid() {
  298. IOException e = assertThrows(IOException.class,
  299. () -> PacketLineIn.parseACKv2("HELO", new MutableObjectId()));
  300. assertTrue(e.getMessage().contains("xpected ACK/NAK"));
  301. }
  302. // test support
  303. private void init(String msg) {
  304. rawIn = new ByteArrayInputStream(Constants.encodeASCII(msg));
  305. in = new PacketLineIn(rawIn);
  306. }
  307. private void assertEOF() {
  308. assertEquals(-1, rawIn.read());
  309. }
  310. }