diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ObjectIdMatcher.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ObjectIdMatcher.java new file mode 100644 index 000000000..4c6e0f0ad --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ObjectIdMatcher.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2018, Google LLC. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport; + +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Sets; +import org.hamcrest.Description; +import org.hamcrest.Factory; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +/** + * Multiple tests check that a collection of ObjectIds contain certain SHA1 + * (written as strings). This matcher hides the ObjectId to string conversion to + * make the assertion more readable: + * + * assertThat(req.getWantsIds(), hasOnlyObjectIds("123123", "234234")); + */ +class ObjectIdMatcher extends TypeSafeMatcher> { + + private final Set expectedOids; + + private ObjectIdMatcher(Set oids) { + this.expectedOids = oids.stream().map(ObjectId::fromString) + .collect(Collectors.toSet()); + } + + @Override + public void describeTo(Description desc) { + desc.appendText("Object ids:"); + desc.appendValueList("<", ",", ">", expectedOids); + } + + @Override + protected boolean matchesSafely(Collection resultOids) { + return resultOids.containsAll(expectedOids) + && expectedOids.containsAll(resultOids); + } + + /** + * Assert that all and only the received {@link ObjectId object ids} are in + * the expected set. + *

+ * ObjectIds are compared by SHA1. + * + * @param oids + * Object ids to examine. + * @return true if examined and specified sets contains exactly the same + * elements. + */ + @Factory + static Matcher> hasOnlyObjectIds( + String... oids) { + return new ObjectIdMatcher(Sets.of(oids)); + } +} \ No newline at end of file diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java new file mode 100644 index 000000000..2c98c84ae --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2018, Google LLC. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.transport; + +import static org.eclipse.jgit.transport.ObjectIdMatcher.hasOnlyObjectIds; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.eclipse.jgit.errors.PackProtocolException; +import org.eclipse.jgit.lib.Config; +import org.junit.Test; + +public class ProtocolV0ParserTest { + /* + * Convert the input lines to the PacketLine that the parser reads. + */ + private static PacketLineIn formatAsPacketLine(String... inputLines) + throws IOException { + ByteArrayOutputStream send = new ByteArrayOutputStream(); + PacketLineOut pckOut = new PacketLineOut(send); + for (String line : inputLines) { + if (line == PacketLineIn.END) { + pckOut.end(); + } else if (line == PacketLineIn.DELIM) { + pckOut.writeDelim(); + } else { + pckOut.writeString(line); + } + } + + return new PacketLineIn(new ByteArrayInputStream(send.toByteArray())); + } + + private static TransferConfig defaultConfig() { + Config rc = new Config(); + rc.setBoolean("uploadpack", null, "allowfilter", true); + return new TransferConfig(rc); + } + + @Test + public void testRecvWantsWithCapabilities() + throws PackProtocolException, IOException { + PacketLineIn pckIn = formatAsPacketLine( + String.join(" ", "want", + "4624442d68ee402a94364191085b77137618633e", "thin-pack", + "no-progress", "include-tag", "ofs-delta", "\n"), + "want f900c8326a43303685c46b279b9f70411bff1a4b\n", + PacketLineIn.END); + ProtocolV0Parser parser = new ProtocolV0Parser(defaultConfig()); + FetchV0Request request = parser.recvWants(pckIn); + assertTrue(request.getClientCapabilities() + .contains(GitProtocolConstants.OPTION_THIN_PACK)); + assertTrue(request.getClientCapabilities() + .contains(GitProtocolConstants.OPTION_NO_PROGRESS)); + assertTrue(request.getClientCapabilities() + .contains(GitProtocolConstants.OPTION_INCLUDE_TAG)); + assertTrue(request.getClientCapabilities() + .contains(GitProtocolConstants.CAPABILITY_OFS_DELTA)); + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", + "f900c8326a43303685c46b279b9f70411bff1a4b")); + } + + @Test + public void testRecvWantsWithAgent() + throws PackProtocolException, IOException { + PacketLineIn pckIn = formatAsPacketLine( + String.join(" ", "want", + "4624442d68ee402a94364191085b77137618633e", "thin-pack", + "agent=JGit.test/0.0.1", "\n"), + "want f900c8326a43303685c46b279b9f70411bff1a4b\n", + PacketLineIn.END); + ProtocolV0Parser parser = new ProtocolV0Parser(defaultConfig()); + FetchV0Request request = parser.recvWants(pckIn); + assertTrue(request.getClientCapabilities() + .contains(GitProtocolConstants.OPTION_THIN_PACK)); + assertEquals(1, request.getClientCapabilities().size()); + assertEquals("JGit.test/0.0.1", request.getAgent()); + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", + "f900c8326a43303685c46b279b9f70411bff1a4b")); + } + + /* + * First round of protocol v0 negotiation. Client send wants, no + * capabilities. + */ + @Test + public void testRecvWantsWithoutCapabilities() + throws PackProtocolException, IOException { + PacketLineIn pckIn = formatAsPacketLine( + "want 4624442d68ee402a94364191085b77137618633e\n", + "want f900c8326a43303685c46b279b9f70411bff1a4b\n", + PacketLineIn.END); + ProtocolV0Parser parser = new ProtocolV0Parser(defaultConfig()); + FetchV0Request request = parser.recvWants(pckIn); + assertTrue(request.getClientCapabilities().isEmpty()); + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", + "f900c8326a43303685c46b279b9f70411bff1a4b")); + } + + @Test + public void testRecvWantsDeepen() + throws PackProtocolException, IOException { + PacketLineIn pckIn = formatAsPacketLine( + "want 4624442d68ee402a94364191085b77137618633e\n", + "want f900c8326a43303685c46b279b9f70411bff1a4b\n", "deepen 3\n", + PacketLineIn.END); + ProtocolV0Parser parser = new ProtocolV0Parser(defaultConfig()); + FetchV0Request request = parser.recvWants(pckIn); + assertTrue(request.getClientCapabilities().isEmpty()); + assertEquals(3, request.getDepth()); + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", + "f900c8326a43303685c46b279b9f70411bff1a4b")); + } + + @Test + public void testRecvWantsShallow() + throws PackProtocolException, IOException { + PacketLineIn pckIn = formatAsPacketLine( + "want 4624442d68ee402a94364191085b77137618633e\n", + "want f900c8326a43303685c46b279b9f70411bff1a4b\n", + "shallow 4b643d0ef739a1b494e7d6926d8d8ed80d35edf4\n", + PacketLineIn.END); + ProtocolV0Parser parser = new ProtocolV0Parser(defaultConfig()); + FetchV0Request request = parser.recvWants(pckIn); + assertTrue(request.getClientCapabilities().isEmpty()); + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", + "f900c8326a43303685c46b279b9f70411bff1a4b")); + assertThat(request.getClientShallowCommits(), + hasOnlyObjectIds("4b643d0ef739a1b494e7d6926d8d8ed80d35edf4")); + } + + @Test + public void testRecvWantsFilter() + throws PackProtocolException, IOException { + PacketLineIn pckIn = formatAsPacketLine( + "want 4624442d68ee402a94364191085b77137618633e\n", + "want f900c8326a43303685c46b279b9f70411bff1a4b\n", + "filter blob:limit=13000\n", + PacketLineIn.END); + ProtocolV0Parser parser = new ProtocolV0Parser(defaultConfig()); + FetchV0Request request = parser.recvWants(pckIn); + assertTrue(request.getClientCapabilities().isEmpty()); + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", + "f900c8326a43303685c46b279b9f70411bff1a4b")); + assertEquals(13000, request.getFilterBlobLimit()); + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java index 7cfe66fe9..6b1cbdd54 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java @@ -48,20 +48,17 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.eclipse.jgit.transport.ObjectIdMatcher.hasOnlyObjectIds; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; import org.eclipse.jgit.errors.PackProtocolException; import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription; import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.lib.Config; -import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.revwalk.RevCommit; import org.junit.Before; import org.junit.Rule; @@ -139,12 +136,6 @@ public class ProtocolV2ParserTest { return new PacketLineIn(new ByteArrayInputStream(send.toByteArray())); } - private static List objIdsAsStrings(Collection objIds) { - // TODO(ifrade) Translate this to a matcher, so it would read as - // assertThat(req.wantsIds(), hasObjectIds("...", "...")) - return objIds.stream().map(ObjectId::name).collect(Collectors.toList()); - } - /* * Succesful fetch with the basic core commands of the protocol. */ @@ -171,11 +162,11 @@ public class ProtocolV2ParserTest { .contains(GitProtocolConstants.OPTION_INCLUDE_TAG)); assertTrue(request.getClientCapabilities() .contains(GitProtocolConstants.CAPABILITY_OFS_DELTA)); - assertThat(objIdsAsStrings(request.getWantIds()), - hasItems("4624442d68ee402a94364191085b77137618633e", + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", "f900c8326a43303685c46b279b9f70411bff1a4b")); - assertThat(objIdsAsStrings(request.getPeerHas()), - hasItems("554f6e41067b9e3e565b6988a8294fac1cb78f4b", + assertThat(request.getPeerHas(), + hasOnlyObjectIds("554f6e41067b9e3e565b6988a8294fac1cb78f4b", "abc760ab9ad72f08209943251b36cb886a578f87")); assertTrue(request.getWantedRefs().isEmpty()); assertTrue(request.wasDoneReceived()); @@ -194,8 +185,8 @@ public class ProtocolV2ParserTest { ConfigBuilder.getDefault()); FetchV2Request request = parser.parseFetchRequest(pckIn, testRepo.getRepository().getRefDatabase()); - assertThat(objIdsAsStrings(request.getClientShallowCommits()), - hasItems("28274d02c489f4c7e68153056e9061a46f62d7a0", + assertThat(request.getClientShallowCommits(), + hasOnlyObjectIds("28274d02c489f4c7e68153056e9061a46f62d7a0", "145e683b229dcab9d0e2ccb01b386f9ecc17d29d")); assertTrue(request.getDeepenNotRefs().isEmpty()); assertEquals(15, request.getDepth()); @@ -214,8 +205,8 @@ public class ProtocolV2ParserTest { ConfigBuilder.getDefault()); FetchV2Request request = parser.parseFetchRequest(pckIn, testRepo.getRepository().getRefDatabase()); - assertThat(objIdsAsStrings(request.getClientShallowCommits()), - hasItems("28274d02c489f4c7e68153056e9061a46f62d7a0", + assertThat(request.getClientShallowCommits(), + hasOnlyObjectIds("28274d02c489f4c7e68153056e9061a46f62d7a0", "145e683b229dcab9d0e2ccb01b386f9ecc17d29d")); assertThat(request.getDeepenNotRefs(), hasItems("a08595f76159b09d57553e37a5123f1091bb13e7")); @@ -232,8 +223,8 @@ public class ProtocolV2ParserTest { ConfigBuilder.getDefault()); FetchV2Request request = parser.parseFetchRequest(pckIn, testRepo.getRepository().getRefDatabase()); - assertThat(objIdsAsStrings(request.getClientShallowCommits()), - hasItems("28274d02c489f4c7e68153056e9061a46f62d7a0", + assertThat(request.getClientShallowCommits(), + hasOnlyObjectIds("28274d02c489f4c7e68153056e9061a46f62d7a0", "145e683b229dcab9d0e2ccb01b386f9ecc17d29d")); assertEquals(123123123, request.getDeepenSince()); } @@ -309,9 +300,9 @@ public class ProtocolV2ParserTest { assertThat(request.getWantedRefs().keySet(), hasItems("refs/heads/branchA")); assertEquals(2, request.getWantIds().size()); - assertThat(objIdsAsStrings(request.getWantIds()), - hasItems("e4980cdc48cfa1301493ca94eb70523f6788b819", - one.getName())); + assertThat(request.getWantIds(), hasOnlyObjectIds( + "e4980cdc48cfa1301493ca94eb70523f6788b819", + one.getName())); } @Test