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