View Javadoc
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  
11  package org.eclipse.jgit.transport;
12  
13  import static org.junit.Assert.assertEquals;
14  import static org.junit.Assert.assertFalse;
15  import static org.junit.Assert.assertSame;
16  import static org.junit.Assert.assertThrows;
17  import static org.junit.Assert.assertTrue;
18  import static org.junit.Assert.fail;
19  
20  import java.io.ByteArrayInputStream;
21  import java.io.IOException;
22  
23  import org.eclipse.jgit.errors.PackProtocolException;
24  import org.eclipse.jgit.lib.Constants;
25  import org.eclipse.jgit.lib.MutableObjectId;
26  import org.eclipse.jgit.lib.ObjectId;
27  import org.junit.Test;
28  
29  // Note, test vectors created with:
30  //
31  // perl -e 'printf "%4.4x%s\n", 4+length($ARGV[0]),$ARGV[0]'
32  
33  public class PacketLineInTest {
34  	private ByteArrayInputStream rawIn;
35  
36  	private PacketLineIn in;
37  
38  	// readString
39  
40  	@Test
41  	public void testReadString1() throws IOException {
42  		init("0006a\n0007bc\n");
43  		assertEquals("a", in.readString());
44  		assertEquals("bc", in.readString());
45  		assertEOF();
46  	}
47  
48  	@Test
49  	public void testReadString2() throws IOException {
50  		init("0032want fcfcfb1fd94829c1a1704f894fc111d14770d34e\n");
51  		final String act = in.readString();
52  		assertEquals("want fcfcfb1fd94829c1a1704f894fc111d14770d34e", act);
53  		assertEOF();
54  	}
55  
56  	@Test
57  	public void testReadString4() throws IOException {
58  		init("0005a0006bc");
59  		assertEquals("a", in.readString());
60  		assertEquals("bc", in.readString());
61  		assertEOF();
62  	}
63  
64  	@Test
65  	public void testReadString5() throws IOException {
66  		// accept both upper and lower case
67  		init("000Fhi i am a s");
68  		assertEquals("hi i am a s", in.readString());
69  		assertEOF();
70  
71  		init("000fhi i am a s");
72  		assertEquals("hi i am a s", in.readString());
73  		assertEOF();
74  	}
75  
76  	@Test
77  	public void testReadString_LenHELO() {
78  		init("HELO");
79  		try {
80  			in.readString();
81  			fail("incorrectly accepted invalid packet header");
82  		} catch (IOException e) {
83  			assertEquals("Invalid packet line header: HELO", e.getMessage());
84  		}
85  	}
86  
87  	@Test
88  	public void testReadString_Len0002() {
89  		init("0002");
90  		try {
91  			in.readString();
92  			fail("incorrectly accepted invalid packet header");
93  		} catch (IOException e) {
94  			assertEquals("Invalid packet line header: 0002", e.getMessage());
95  		}
96  	}
97  
98  	@Test
99  	public void testReadString_Len0003() {
100 		init("0003");
101 		try {
102 			in.readString();
103 			fail("incorrectly accepted invalid packet header");
104 		} catch (IOException e) {
105 			assertEquals("Invalid packet line header: 0003", e.getMessage());
106 		}
107 	}
108 
109 	@Test
110 	public void testReadString_Len0004() throws IOException {
111 		init("0004");
112 		final String act = in.readString();
113 		assertEquals("", act);
114 		assertFalse(PacketLineIn.isEnd(act));
115 		assertFalse(PacketLineIn.isDelimiter(act));
116 		assertEOF();
117 	}
118 
119 	@Test
120 	public void testReadString_End() throws IOException {
121 		init("0000");
122 		String act = in.readString();
123 		assertTrue(PacketLineIn.isEnd(act));
124 		assertFalse(PacketLineIn.isDelimiter(act));
125 		assertEOF();
126 	}
127 
128 	@Test
129 	public void testReadString_Delim() throws IOException {
130 		init("0001");
131 		String act = in.readString();
132 		assertTrue(PacketLineIn.isDelimiter(act));
133 		assertFalse(PacketLineIn.isEnd(act));
134 		assertEOF();
135 	}
136 
137 	// readStringNoLF
138 
139 	@Test
140 	public void testReadStringRaw1() throws IOException {
141 		init("0005a0006bc");
142 		assertEquals("a", in.readStringRaw());
143 		assertEquals("bc", in.readStringRaw());
144 		assertEOF();
145 	}
146 
147 	@Test
148 	public void testReadStringRaw2() throws IOException {
149 		init("0031want fcfcfb1fd94829c1a1704f894fc111d14770d34e");
150 		final String act = in.readStringRaw();
151 		assertEquals("want fcfcfb1fd94829c1a1704f894fc111d14770d34e", act);
152 		assertEOF();
153 	}
154 
155 	@Test
156 	public void testReadStringRaw3() throws IOException {
157 		init("0004");
158 		final String act = in.readStringRaw();
159 		assertEquals("", act);
160 		assertFalse(PacketLineIn.isEnd(act));
161 		assertEOF();
162 	}
163 
164 	@Test
165 	public void testReadStringRaw_End() throws IOException {
166 		init("0000");
167 		assertTrue(PacketLineIn.isEnd(in.readString()));
168 		assertEOF();
169 	}
170 
171 	@Test
172 	public void testReadStringRaw4() {
173 		init("HELO");
174 		try {
175 			in.readStringRaw();
176 			fail("incorrectly accepted invalid packet header");
177 		} catch (IOException e) {
178 			assertEquals("Invalid packet line header: HELO", e.getMessage());
179 		}
180 	}
181 
182 	// readACK
183 
184 	@Test
185 	public void testReadACK_NAK() throws IOException {
186 		final ObjectId expid = ObjectId
187 				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
188 		final MutableObjectId actid = new MutableObjectId();
189 		actid.fromString(expid.name());
190 
191 		init("0008NAK\n");
192 		assertSame(PacketLineIn.AckNackResult.NAK, in.readACK(actid));
193 		assertEquals(expid, actid);
194 		assertEOF();
195 	}
196 
197 	@Test
198 	public void testReadACK_ACK1() throws IOException {
199 		final ObjectId expid = ObjectId
200 				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
201 		final MutableObjectId actid = new MutableObjectId();
202 
203 		init("0031ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e\n");
204 		assertSame(PacketLineIn.AckNackResult.ACK, in.readACK(actid));
205 		assertEquals(expid, actid);
206 		assertEOF();
207 	}
208 
209 	@Test
210 	public void testReadACK_ACKcontinue1() throws IOException {
211 		final ObjectId expid = ObjectId
212 				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
213 		final MutableObjectId actid = new MutableObjectId();
214 
215 		init("003aACK fcfcfb1fd94829c1a1704f894fc111d14770d34e continue\n");
216 		assertSame(PacketLineIn.AckNackResult.ACK_CONTINUE, in.readACK(actid));
217 		assertEquals(expid, actid);
218 		assertEOF();
219 	}
220 
221 	@Test
222 	public void testReadACK_ACKcommon1() throws IOException {
223 		final ObjectId expid = ObjectId
224 				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
225 		final MutableObjectId actid = new MutableObjectId();
226 
227 		init("0038ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e common\n");
228 		assertSame(PacketLineIn.AckNackResult.ACK_COMMON, in.readACK(actid));
229 		assertEquals(expid, actid);
230 		assertEOF();
231 	}
232 
233 	@Test
234 	public void testReadACK_ACKready1() throws IOException {
235 		final ObjectId expid = ObjectId
236 				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
237 		final MutableObjectId actid = new MutableObjectId();
238 
239 		init("0037ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e ready\n");
240 		assertSame(PacketLineIn.AckNackResult.ACK_READY, in.readACK(actid));
241 		assertEquals(expid, actid);
242 		assertEOF();
243 	}
244 
245 	@Test
246 	public void testReadACK_Invalid1() {
247 		init("HELO");
248 		try {
249 			in.readACK(new MutableObjectId());
250 			fail("incorrectly accepted invalid packet header");
251 		} catch (IOException e) {
252 			assertEquals("Invalid packet line header: HELO", e.getMessage());
253 		}
254 	}
255 
256 	@Test
257 	public void testReadACK_Invalid2() {
258 		init("0009HELO\n");
259 		try {
260 			in.readACK(new MutableObjectId());
261 			fail("incorrectly accepted invalid ACK/NAK");
262 		} catch (IOException e) {
263 			assertEquals("Expected ACK/NAK, got: HELO", e.getMessage());
264 		}
265 	}
266 
267 	@Test
268 	public void testReadACK_Invalid3() {
269 		String s = "ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e neverhappen";
270 		init("003d" + s + "\n");
271 		try {
272 			in.readACK(new MutableObjectId());
273 			fail("incorrectly accepted unsupported ACK status");
274 		} catch (IOException e) {
275 			assertEquals("Expected ACK/NAK, got: " + s, e.getMessage());
276 		}
277 	}
278 
279 	@Test
280 	public void testReadACK_Invalid4() {
281 		init("0000");
282 		try {
283 			in.readACK(new MutableObjectId());
284 			fail("incorrectly accepted no ACK/NAK");
285 		} catch (IOException e) {
286 			assertEquals("Expected ACK/NAK, found EOF", e.getMessage());
287 		}
288 	}
289 
290 	@Test
291 	public void testReadACK_ERR() throws IOException {
292 		init("001aERR want is not valid\n");
293 		try {
294 			in.readACK(new MutableObjectId());
295 			fail("incorrectly accepted ERR");
296 		} catch (PackProtocolException e) {
297 			assertEquals("want is not valid", e.getMessage());
298 		}
299 	}
300 
301 	// parseACKv2
302 
303 	@Test
304 	public void testParseAckV2_NAK() throws IOException {
305 		final ObjectId expid = ObjectId
306 				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
307 		final MutableObjectId actid = new MutableObjectId();
308 		actid.fromString(expid.name());
309 
310 		assertSame(PacketLineIn.AckNackResult.NAK,
311 				PacketLineIn.parseACKv2("NAK", actid));
312 		assertEquals(expid, actid);
313 	}
314 
315 	@Test
316 	public void testParseAckV2_ACK() throws IOException {
317 		final ObjectId expid = ObjectId
318 				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
319 		final MutableObjectId actid = new MutableObjectId();
320 
321 		assertSame(PacketLineIn.AckNackResult.ACK_COMMON,
322 				PacketLineIn.parseACKv2(
323 						"ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e", actid));
324 		assertEquals(expid, actid);
325 	}
326 
327 	@Test
328 	public void testParseAckV2_Ready() throws IOException {
329 		final ObjectId expid = ObjectId
330 				.fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e");
331 		final MutableObjectId actid = new MutableObjectId();
332 		actid.fromString(expid.name());
333 
334 		assertSame(PacketLineIn.AckNackResult.ACK_READY,
335 				PacketLineIn.parseACKv2("ready", actid));
336 		assertEquals(expid, actid);
337 	}
338 
339 	@Test
340 	public void testParseAckV2_ERR() {
341 		IOException e = assertThrows(IOException.class, () -> PacketLineIn
342 				.parseACKv2("ERR want is not valid", new MutableObjectId()));
343 		assertTrue(e.getMessage().contains("want is not valid"));
344 	}
345 
346 	@Test
347 	public void testParseAckV2_Invalid() {
348 		IOException e = assertThrows(IOException.class,
349 				() -> PacketLineIn.parseACKv2("HELO", new MutableObjectId()));
350 		assertTrue(e.getMessage().contains("xpected ACK/NAK"));
351 	}
352 
353 	// test support
354 
355 	private void init(String msg) {
356 		rawIn = new ByteArrayInputStream(Constants.encodeASCII(msg));
357 		in = new PacketLineIn(rawIn);
358 	}
359 
360 	private void assertEOF() {
361 		assertEquals(-1, rawIn.read());
362 	}
363 }