diff options
author | Git Development Community <git@vger.kernel.org> | 2009-09-29 16:47:03 -0700 |
---|---|---|
committer | Shawn O. Pearce <spearce@spearce.org> | 2009-09-29 16:47:03 -0700 |
commit | 1a6964c8274c50f0253db75f010d78ef0e739343 (patch) | |
tree | ca833cc7cf6fc8c7b9850dee258f3a356c790ffc /org.eclipse.jgit.test/tst/org/eclipse/jgit/transport | |
download | jgit-1a6964c8274c50f0253db75f010d78ef0e739343.tar.gz jgit-1a6964c8274c50f0253db75f010d78ef0e739343.zip |
Initial JGit contribution to eclipse.org
Per CQ 3448 this is the initial contribution of the JGit project
to eclipse.org. It is derived from the historical JGit repository
at commit 3a2dd9921c8a08740a9e02c421469e5b1a9e47cb.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'org.eclipse.jgit.test/tst/org/eclipse/jgit/transport')
12 files changed, 2819 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java new file mode 100644 index 0000000000..fb9b358b2a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2008, Google Inc. + * Copyright (C) 2008, Mike Ralphson <mike@abacus.co.uk> + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * 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.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jgit.errors.MissingBundlePrerequisiteException; +import org.eclipse.jgit.errors.NotSupportedException; +import org.eclipse.jgit.errors.TransportException; +import org.eclipse.jgit.lib.NullProgressMonitor; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; + +public class BundleWriterTest extends RepositoryTestCase { + + public void testWrite0() throws Exception { + // Create a tiny bundle, (well one of) the first commits only + final byte[] bundle = makeBundle("refs/heads/firstcommit", + "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1", null); + + // Then we clone a new repo from that bundle and do a simple test. This + // makes sure + // we could read the bundle we created. + Repository newRepo = createNewEmptyRepo(); + FetchResult fetchResult = fetchFromBundle(newRepo, bundle); + Ref advertisedRef = fetchResult + .getAdvertisedRef("refs/heads/firstcommit"); + + // We expect firstcommit to appear by id + assertEquals("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1", advertisedRef + .getObjectId().name()); + // ..and by name as the bundle created a new ref + assertEquals("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1", newRepo + .resolve("refs/heads/firstcommit").name()); + } + + /** + * Incremental bundle test + * + * @throws Exception + */ + public void testWrite1() throws Exception { + byte[] bundle; + + // Create a small bundle, an early commit + bundle = makeBundle("refs/heads/aa", db.resolve("a").name(), null); + + // Then we clone a new repo from that bundle and do a simple test. This + // makes sure + // we could read the bundle we created. + Repository newRepo = createNewEmptyRepo(); + FetchResult fetchResult = fetchFromBundle(newRepo, bundle); + Ref advertisedRef = fetchResult.getAdvertisedRef("refs/heads/aa"); + + assertEquals(db.resolve("a").name(), advertisedRef.getObjectId().name()); + assertEquals(db.resolve("a").name(), newRepo.resolve("refs/heads/aa") + .name()); + assertNull(newRepo.resolve("refs/heads/a")); + + // Next an incremental bundle + bundle = makeBundle("refs/heads/cc", db.resolve("c").name(), + new RevWalk(db).parseCommit(db.resolve("a").toObjectId())); + fetchResult = fetchFromBundle(newRepo, bundle); + advertisedRef = fetchResult.getAdvertisedRef("refs/heads/cc"); + assertEquals(db.resolve("c").name(), advertisedRef.getObjectId().name()); + assertEquals(db.resolve("c").name(), newRepo.resolve("refs/heads/cc") + .name()); + assertNull(newRepo.resolve("refs/heads/c")); + assertNull(newRepo.resolve("refs/heads/a")); // still unknown + + try { + // Check that we actually needed the first bundle + Repository newRepo2 = createNewEmptyRepo(); + fetchResult = fetchFromBundle(newRepo2, bundle); + fail("We should not be able to fetch from bundle with prerequisites that are not fulfilled"); + } catch (MissingBundlePrerequisiteException e) { + assertTrue(e.getMessage() + .indexOf(db.resolve("refs/heads/a").name()) >= 0); + } + } + + private FetchResult fetchFromBundle(final Repository newRepo, + final byte[] bundle) throws URISyntaxException, + NotSupportedException, TransportException { + final URIish uri = new URIish("in-memory://"); + final ByteArrayInputStream in = new ByteArrayInputStream(bundle); + final RefSpec rs = new RefSpec("refs/heads/*:refs/heads/*"); + final Set<RefSpec> refs = Collections.singleton(rs); + return new TransportBundleStream(newRepo, uri, in).fetch( + NullProgressMonitor.INSTANCE, refs); + } + + private byte[] makeBundle(final String name, + final String anObjectToInclude, final RevCommit assume) + throws FileNotFoundException, IOException { + final BundleWriter bw; + + bw = new BundleWriter(db, NullProgressMonitor.INSTANCE); + bw.include(name, ObjectId.fromString(anObjectToInclude)); + if (assume != null) + bw.assume(assume); + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + bw.writeBundle(out); + return out.toByteArray(); + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java new file mode 100644 index 0000000000..78f4393c3a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com> + * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * 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.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.PackFile; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.lib.TextProgressMonitor; +import org.eclipse.jgit.util.JGitTestUtil; + +/** + * Test indexing of git packs. A pack is read from a stream, copied + * to a new pack and an index is created. Then the packs are tested + * to make sure they contain the expected objects (well we don't test + * for all of them unless the packs are very small). + */ +public class IndexPackTest extends RepositoryTestCase { + + /** + * Test indexing one of the test packs in the egit repo. It has deltas. + * + * @throws IOException + */ + public void test1() throws IOException { + File packFile = JGitTestUtil.getTestResourceFile("pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack"); + final InputStream is = new FileInputStream(packFile); + try { + IndexPack pack = new IndexPack(db, is, new File(trash, "tmp_pack1")); + pack.index(new TextProgressMonitor()); + PackFile file = new PackFile(new File(trash, "tmp_pack1.idx"), new File(trash, "tmp_pack1.pack")); + assertTrue(file.hasObject(ObjectId.fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904"))); + assertTrue(file.hasObject(ObjectId.fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab"))); + assertTrue(file.hasObject(ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"))); + assertTrue(file.hasObject(ObjectId.fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3"))); + assertTrue(file.hasObject(ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"))); + assertTrue(file.hasObject(ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"))); + assertTrue(file.hasObject(ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"))); + assertTrue(file.hasObject(ObjectId.fromString("c59759f143fb1fe21c197981df75a7ee00290799"))); + } finally { + is.close(); + } + } + + /** + * This is just another pack. It so happens that we have two convenient pack to + * test with in the repository. + * + * @throws IOException + */ + public void test2() throws IOException { + File packFile = JGitTestUtil.getTestResourceFile("pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.pack"); + final InputStream is = new FileInputStream(packFile); + try { + IndexPack pack = new IndexPack(db, is, new File(trash, "tmp_pack2")); + pack.index(new TextProgressMonitor()); + PackFile file = new PackFile(new File(trash, "tmp_pack2.idx"), new File(trash, "tmp_pack2.pack")); + assertTrue(file.hasObject(ObjectId.fromString("02ba32d3649e510002c21651936b7077aa75ffa9"))); + assertTrue(file.hasObject(ObjectId.fromString("0966a434eb1a025db6b71485ab63a3bfbea520b6"))); + assertTrue(file.hasObject(ObjectId.fromString("09efc7e59a839528ac7bda9fa020dc9101278680"))); + assertTrue(file.hasObject(ObjectId.fromString("0a3d7772488b6b106fb62813c4d6d627918d9181"))); + assertTrue(file.hasObject(ObjectId.fromString("1004d0d7ac26fbf63050a234c9b88a46075719d3"))); + assertTrue(file.hasObject(ObjectId.fromString("10da5895682013006950e7da534b705252b03be6"))); + assertTrue(file.hasObject(ObjectId.fromString("1203b03dc816ccbb67773f28b3c19318654b0bc8"))); + assertTrue(file.hasObject(ObjectId.fromString("15fae9e651043de0fd1deef588aa3fbf5a7a41c6"))); + assertTrue(file.hasObject(ObjectId.fromString("16f9ec009e5568c435f473ba3a1df732d49ce8c3"))); + assertTrue(file.hasObject(ObjectId.fromString("1fd7d579fb6ae3fe942dc09c2c783443d04cf21e"))); + assertTrue(file.hasObject(ObjectId.fromString("20a8ade77639491ea0bd667bf95de8abf3a434c8"))); + assertTrue(file.hasObject(ObjectId.fromString("2675188fd86978d5bc4d7211698b2118ae3bf658"))); + // and lots more... + } finally { + is.close(); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/LongMapTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/LongMapTest.java new file mode 100644 index 0000000000..abb6fe0db0 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/LongMapTest.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2009, Google Inc. + * 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 junit.framework.TestCase; + +public class LongMapTest extends TestCase { + private LongMap<Long> map; + + protected void setUp() throws Exception { + super.setUp(); + map = new LongMap<Long>(); + } + + public void testEmptyMap() { + assertFalse(map.containsKey(0)); + assertFalse(map.containsKey(1)); + + assertNull(map.get(0)); + assertNull(map.get(1)); + + assertNull(map.remove(0)); + assertNull(map.remove(1)); + } + + public void testInsertMinValue() { + final Long min = Long.valueOf(Long.MIN_VALUE); + assertNull(map.put(Long.MIN_VALUE, min)); + assertTrue(map.containsKey(Long.MIN_VALUE)); + assertSame(min, map.get(Long.MIN_VALUE)); + assertFalse(map.containsKey(Integer.MIN_VALUE)); + } + + public void testReplaceMaxValue() { + final Long min = Long.valueOf(Long.MAX_VALUE); + final Long one = Long.valueOf(1); + assertNull(map.put(Long.MAX_VALUE, min)); + assertSame(min, map.get(Long.MAX_VALUE)); + assertSame(min, map.put(Long.MAX_VALUE, one)); + assertSame(one, map.get(Long.MAX_VALUE)); + } + + public void testRemoveOne() { + final long start = 1; + assertNull(map.put(start, Long.valueOf(start))); + assertEquals(Long.valueOf(start), map.remove(start)); + assertFalse(map.containsKey(start)); + } + + public void testRemoveCollision1() { + // This test relies upon the fact that we always >>> 1 the value + // to derive an unsigned hash code. Thus, 0 and 1 fall into the + // same hash bucket. Further it relies on the fact that we add + // the 2nd put at the top of the chain, so removing the 1st will + // cause a different code path. + // + assertNull(map.put(0, Long.valueOf(0))); + assertNull(map.put(1, Long.valueOf(1))); + assertEquals(Long.valueOf(0), map.remove(0)); + + assertFalse(map.containsKey(0)); + assertTrue(map.containsKey(1)); + } + + public void testRemoveCollision2() { + // This test relies upon the fact that we always >>> 1 the value + // to derive an unsigned hash code. Thus, 0 and 1 fall into the + // same hash bucket. Further it relies on the fact that we add + // the 2nd put at the top of the chain, so removing the 2nd will + // cause a different code path. + // + assertNull(map.put(0, Long.valueOf(0))); + assertNull(map.put(1, Long.valueOf(1))); + assertEquals(Long.valueOf(1), map.remove(1)); + + assertTrue(map.containsKey(0)); + assertFalse(map.containsKey(1)); + } + + public void testSmallMap() { + final long start = 12; + final long n = 8; + for (long i = start; i < start + n; i++) + assertNull(map.put(i, Long.valueOf(i))); + for (long i = start; i < start + n; i++) + assertEquals(Long.valueOf(i), map.get(i)); + } + + public void testLargeMap() { + final long start = Integer.MAX_VALUE; + final long n = 100000; + for (long i = start; i < start + n; i++) + assertNull(map.put(i, Long.valueOf(i))); + for (long i = start; i < start + n; i++) + assertEquals(Long.valueOf(i), map.get(i)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java new file mode 100644 index 0000000000..f66e2fd33e --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2008, Google Inc. + * 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.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.transport.OpenSshConfig.Host; + +public class OpenSshConfigTest extends RepositoryTestCase { + private File home; + + private File configFile; + + private OpenSshConfig osc; + + public void setUp() throws Exception { + super.setUp(); + + home = new File(trash, "home"); + home.mkdir(); + + configFile = new File(new File(home, ".ssh"), "config"); + configFile.getParentFile().mkdir(); + + System.setProperty("user.name", "jex_junit"); + osc = new OpenSshConfig(home, configFile); + } + + private void config(final String data) throws IOException { + final OutputStreamWriter fw = new OutputStreamWriter( + new FileOutputStream(configFile), "UTF-8"); + fw.write(data); + fw.close(); + } + + public void testNoConfig() { + final Host h = osc.lookup("repo.or.cz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex_junit", h.getUser()); + assertEquals(22, h.getPort()); + assertNull(h.getIdentityFile()); + } + + public void testSeparatorParsing() throws Exception { + config("Host\tfirst\n" + + "\tHostName\tfirst.tld\n" + + "\n" + + "Host second\n" + + " HostName\tsecond.tld\n" + + "Host=third\n" + + "HostName=third.tld\n\n\n" + + "\t Host = fourth\n\n\n" + + " \t HostName\t=fourth.tld\n" + + "Host\t = last\n" + + "HostName \t last.tld"); + assertNotNull(osc.lookup("first")); + assertEquals("first.tld", osc.lookup("first").getHostName()); + assertNotNull(osc.lookup("second")); + assertEquals("second.tld", osc.lookup("second").getHostName()); + assertNotNull(osc.lookup("third")); + assertEquals("third.tld", osc.lookup("third").getHostName()); + assertNotNull(osc.lookup("fourth")); + assertEquals("fourth.tld", osc.lookup("fourth").getHostName()); + assertNotNull(osc.lookup("last")); + assertEquals("last.tld", osc.lookup("last").getHostName()); + } + + public void testQuoteParsing() throws Exception { + config("Host \"good\"\n" + + " HostName=\"good.tld\"\n" + + " Port=\"6007\"\n" + + " User=\"gooduser\"\n" + + "Host multiple unquoted and \"quoted\" \"hosts\"\n" + + " Port=\"2222\"\n" + + "Host \"spaced\"\n" + + "# Bad host name, but testing preservation of spaces\n" + + " HostName=\" spaced\ttld \"\n" + + "# Misbalanced quotes\n" + + "Host \"bad\"\n" + + "# OpenSSH doesn't allow this but ...\n" + + " HostName=bad.tld\"\n"); + assertEquals("good.tld", osc.lookup("good").getHostName()); + assertEquals("gooduser", osc.lookup("good").getUser()); + assertEquals(6007, osc.lookup("good").getPort()); + assertEquals(2222, osc.lookup("multiple").getPort()); + assertEquals(2222, osc.lookup("quoted").getPort()); + assertEquals(2222, osc.lookup("and").getPort()); + assertEquals(2222, osc.lookup("unquoted").getPort()); + assertEquals(2222, osc.lookup("hosts").getPort()); + assertEquals(" spaced\ttld ", osc.lookup("spaced").getHostName()); + assertEquals("bad.tld\"", osc.lookup("bad").getHostName()); + } + + public void testAlias_DoesNotMatch() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n"); + final Host h = osc.lookup("repo.or.cz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex_junit", h.getUser()); + assertEquals(22, h.getPort()); + assertNull(h.getIdentityFile()); + } + + public void testAlias_OptionsSet() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\tPort 2222\n" + + "\tUser jex\n" + "\tIdentityFile .ssh/id_jex\n" + + "\tForwardX11 no\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex", h.getUser()); + assertEquals(2222, h.getPort()); + assertEquals(new File(home, ".ssh/id_jex"), h.getIdentityFile()); + } + + public void testAlias_OptionsKeywordCaseInsensitive() throws Exception { + config("hOsT orcz\n" + "\thOsTnAmE repo.or.cz\n" + "\tPORT 2222\n" + + "\tuser jex\n" + "\tidentityfile .ssh/id_jex\n" + + "\tForwardX11 no\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex", h.getUser()); + assertEquals(2222, h.getPort()); + assertEquals(new File(home, ".ssh/id_jex"), h.getIdentityFile()); + } + + public void testAlias_OptionsInherit() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\n" + "Host *\n" + + "\tHostName not.a.host.example.com\n" + "\tPort 2222\n" + + "\tUser jex\n" + "\tIdentityFile .ssh/id_jex\n" + + "\tForwardX11 no\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex", h.getUser()); + assertEquals(2222, h.getPort()); + assertEquals(new File(home, ".ssh/id_jex"), h.getIdentityFile()); + } + + public void testAlias_PreferredAuthenticationsDefault() throws Exception { + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertNull(h.getPreferredAuthentications()); + } + + public void testAlias_PreferredAuthentications() throws Exception { + config("Host orcz\n" + "\tPreferredAuthentications publickey\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("publickey", h.getPreferredAuthentications()); + } + + public void testAlias_InheritPreferredAuthentications() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\n" + "Host *\n" + + "\tPreferredAuthentications publickey, hostbased\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("publickey,hostbased", h.getPreferredAuthentications()); + } + + public void testAlias_BatchModeDefault() throws Exception { + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals(false, h.isBatchMode()); + } + + public void testAlias_BatchModeYes() throws Exception { + config("Host orcz\n" + "\tBatchMode yes\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals(true, h.isBatchMode()); + } + + public void testAlias_InheritBatchMode() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\n" + "Host *\n" + + "\tBatchMode yes\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals(true, h.isBatchMode()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java new file mode 100644 index 0000000000..1bcac9e37b --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2009, Google Inc. + * 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.io.ByteArrayInputStream; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.MutableObjectId; +import org.eclipse.jgit.lib.ObjectId; + +// Note, test vectors created with: +// +// perl -e 'printf "%4.4x%s\n", 4+length($ARGV[0]),$ARGV[0]' + +public class PacketLineInTest extends TestCase { + private ByteArrayInputStream rawIn; + + private PacketLineIn in; + + // readString + + public void testReadString1() throws IOException { + init("0006a\n0007bc\n"); + assertEquals("a", in.readString()); + assertEquals("bc", in.readString()); + assertEOF(); + } + + public void testReadString2() throws IOException { + init("0032want fcfcfb1fd94829c1a1704f894fc111d14770d34e\n"); + final String act = in.readString(); + assertEquals("want fcfcfb1fd94829c1a1704f894fc111d14770d34e", act); + assertEOF(); + } + + public void testReadString4() throws IOException { + init("0005a0006bc"); + assertEquals("a", in.readString()); + assertEquals("bc", in.readString()); + assertEOF(); + } + + public void testReadString5() throws IOException { + // accept both upper and lower case + init("000Fhi i am a s"); + assertEquals("hi i am a s", in.readString()); + assertEOF(); + + init("000fhi i am a s"); + assertEquals("hi i am a s", in.readString()); + assertEOF(); + } + + public void testReadString_LenHELO() { + init("HELO"); + try { + in.readString(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: HELO", e.getMessage()); + } + } + + public void testReadString_Len0001() { + init("0001"); + try { + in.readString(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: 0001", e.getMessage()); + } + } + + public void testReadString_Len0002() { + init("0002"); + try { + in.readString(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: 0002", e.getMessage()); + } + } + + public void testReadString_Len0003() { + init("0003"); + try { + in.readString(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: 0003", e.getMessage()); + } + } + + public void testReadString_Len0004() throws IOException { + init("0004"); + final String act = in.readString(); + assertEquals("", act); + assertNotSame(PacketLineIn.END, act); + assertEOF(); + } + + public void testReadString_End() throws IOException { + init("0000"); + assertSame(PacketLineIn.END, in.readString()); + assertEOF(); + } + + // readStringNoLF + + public void testReadStringRaw1() throws IOException { + init("0005a0006bc"); + assertEquals("a", in.readStringRaw()); + assertEquals("bc", in.readStringRaw()); + assertEOF(); + } + + public void testReadStringRaw2() throws IOException { + init("0031want fcfcfb1fd94829c1a1704f894fc111d14770d34e"); + final String act = in.readStringRaw(); + assertEquals("want fcfcfb1fd94829c1a1704f894fc111d14770d34e", act); + assertEOF(); + } + + public void testReadStringRaw3() throws IOException { + init("0004"); + final String act = in.readStringRaw(); + assertEquals("", act); + assertNotSame(PacketLineIn.END, act); + assertEOF(); + } + + public void testReadStringRaw_End() throws IOException { + init("0000"); + assertSame(PacketLineIn.END, in.readStringRaw()); + assertEOF(); + } + + public void testReadStringRaw4() { + init("HELO"); + try { + in.readStringRaw(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: HELO", e.getMessage()); + } + } + + // readACK + + public void testReadACK_NAK() throws IOException { + final ObjectId expid = ObjectId + .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e"); + final MutableObjectId actid = new MutableObjectId(); + actid.fromString(expid.name()); + + init("0008NAK\n"); + assertSame(PacketLineIn.AckNackResult.NAK, in.readACK(actid)); + assertTrue(actid.equals(expid)); + assertEOF(); + } + + public void testReadACK_ACK1() throws IOException { + final ObjectId expid = ObjectId + .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e"); + final MutableObjectId actid = new MutableObjectId(); + + init("0031ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e\n"); + assertSame(PacketLineIn.AckNackResult.ACK, in.readACK(actid)); + assertTrue(actid.equals(expid)); + assertEOF(); + } + + public void testReadACK_ACKcontinue1() throws IOException { + final ObjectId expid = ObjectId + .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e"); + final MutableObjectId actid = new MutableObjectId(); + + init("003aACK fcfcfb1fd94829c1a1704f894fc111d14770d34e continue\n"); + assertSame(PacketLineIn.AckNackResult.ACK_CONTINUE, in.readACK(actid)); + assertTrue(actid.equals(expid)); + assertEOF(); + } + + public void testReadACK_Invalid1() { + init("HELO"); + try { + in.readACK(new MutableObjectId()); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: HELO", e.getMessage()); + } + } + + public void testReadACK_Invalid2() { + init("0009HELO\n"); + try { + in.readACK(new MutableObjectId()); + fail("incorrectly accepted invalid ACK/NAK"); + } catch (IOException e) { + assertEquals("Expected ACK/NAK, got: HELO", e.getMessage()); + } + } + + public void testReadACK_Invalid3() { + init("0000"); + try { + in.readACK(new MutableObjectId()); + fail("incorrectly accepted no ACK/NAK"); + } catch (IOException e) { + assertEquals("Expected ACK/NAK, found EOF", e.getMessage()); + } + } + + // test support + + private void init(final String msg) { + rawIn = new ByteArrayInputStream(Constants.encodeASCII(msg)); + in = new PacketLineIn(rawIn); + } + + private void assertEOF() { + assertEquals(-1, rawIn.read()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineOutTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineOutTest.java new file mode 100644 index 0000000000..6eb98ac126 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineOutTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2009, Google Inc. + * 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.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; + +// Note, test vectors created with: +// +// perl -e 'printf "%4.4x%s\n", 4+length($ARGV[0]),$ARGV[0]' + +public class PacketLineOutTest extends TestCase { + private ByteArrayOutputStream rawOut; + + private PacketLineOut out; + + protected void setUp() throws Exception { + super.setUp(); + rawOut = new ByteArrayOutputStream(); + out = new PacketLineOut(rawOut); + } + + // writeString + + public void testWriteString1() throws IOException { + out.writeString("a"); + out.writeString("bc"); + assertBuffer("0005a0006bc"); + } + + public void testWriteString2() throws IOException { + out.writeString("a\n"); + out.writeString("bc\n"); + assertBuffer("0006a\n0007bc\n"); + } + + public void testWriteString3() throws IOException { + out.writeString(""); + assertBuffer("0004"); + } + + // end + + public void testWriteEnd() throws IOException { + final int[] flushCnt = new int[1]; + final OutputStream mockout = new OutputStream() { + @Override + public void write(int arg0) throws IOException { + rawOut.write(arg0); + } + + @Override + public void flush() throws IOException { + flushCnt[0]++; + } + }; + + new PacketLineOut(mockout).end(); + assertBuffer("0000"); + assertEquals(1, flushCnt[0]); + } + + // writePacket + + public void testWritePacket1() throws IOException { + out.writePacket(new byte[] { 'a' }); + assertBuffer("0005a"); + } + + public void testWritePacket2() throws IOException { + out.writePacket(new byte[] { 'a', 'b', 'c', 'd' }); + assertBuffer("0008abcd"); + } + + public void testWritePacket3() throws IOException { + final int buflen = SideBandOutputStream.MAX_BUF + - SideBandOutputStream.HDR_SIZE; + final byte[] buf = new byte[buflen]; + for (int i = 0; i < buf.length; i++) { + buf[i] = (byte) i; + } + out.writePacket(buf); + out.flush(); + + final byte[] act = rawOut.toByteArray(); + final String explen = Integer.toString(buf.length + 4, 16); + assertEquals(4 + buf.length, act.length); + assertEquals(new String(act, 0, 4, "UTF-8"), explen); + for (int i = 0, j = 4; i < buf.length; i++, j++) { + assertEquals(buf[i], act[j]); + } + } + + // writeChannelPacket + + public void testWriteChannelPacket1() throws IOException { + out.writeChannelPacket(1, new byte[] { 'a' }, 0, 1); + assertBuffer("0006\001a"); + } + + public void testWriteChannelPacket2() throws IOException { + out.writeChannelPacket(2, new byte[] { 'b' }, 0, 1); + assertBuffer("0006\002b"); + } + + public void testWriteChannelPacket3() throws IOException { + out.writeChannelPacket(3, new byte[] { 'c' }, 0, 1); + assertBuffer("0006\003c"); + } + + // flush + + public void testFlush() throws IOException { + final int[] flushCnt = new int[1]; + final OutputStream mockout = new OutputStream() { + @Override + public void write(int arg0) throws IOException { + fail("should not write"); + } + + @Override + public void flush() throws IOException { + flushCnt[0]++; + } + }; + + new PacketLineOut(mockout).flush(); + assertEquals(1, flushCnt[0]); + } + + private void assertBuffer(final String exp) throws IOException { + assertEquals(exp, new String(rawOut.toByteArray(), + Constants.CHARACTER_ENCODING)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushProcessTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushProcessTest.java new file mode 100644 index 0000000000..4a47456f69 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushProcessTest.java @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * 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.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.eclipse.jgit.errors.NotSupportedException; +import org.eclipse.jgit.errors.TransportException; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ProgressMonitor; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.lib.TextProgressMonitor; +import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.transport.RemoteRefUpdate.Status; + +public class PushProcessTest extends RepositoryTestCase { + private PushProcess process; + + private MockTransport transport; + + private HashSet<RemoteRefUpdate> refUpdates; + + private HashSet<Ref> advertisedRefs; + + private Status connectionUpdateStatus; + + @Override + public void setUp() throws Exception { + super.setUp(); + transport = new MockTransport(db, new URIish()); + refUpdates = new HashSet<RemoteRefUpdate>(); + advertisedRefs = new HashSet<Ref>(); + connectionUpdateStatus = Status.OK; + } + + /** + * Test for fast-forward remote update. + * + * @throws IOException + */ + public void testUpdateFastForward() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.OK, true); + } + + /** + * Test for non fast-forward remote update, when remote object is not known + * to local repository. + * + * @throws IOException + */ + public void testUpdateNonFastForwardUnknownObject() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("0000000000000000000000000000000000000001")); + testOneUpdateStatus(rru, ref, Status.REJECTED_NONFASTFORWARD, null); + } + + /** + * Test for non fast-forward remote update, when remote object is known to + * local repository, but it is not an ancestor of new object. + * + * @throws IOException + */ + public void testUpdateNonFastForward() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "ac7e7e44c1885efb472ad54a78327d66bfc4ecef", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + testOneUpdateStatus(rru, ref, Status.REJECTED_NONFASTFORWARD, null); + } + + /** + * Test for non fast-forward remote update, when force update flag is set. + * + * @throws IOException + */ + public void testUpdateNonFastForwardForced() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "ac7e7e44c1885efb472ad54a78327d66bfc4ecef", + "refs/heads/master", true, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + testOneUpdateStatus(rru, ref, Status.OK, false); + } + + /** + * Test for remote ref creation. + * + * @throws IOException + */ + public void testUpdateCreateRef() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "ac7e7e44c1885efb472ad54a78327d66bfc4ecef", + "refs/heads/master", false, null, null); + testOneUpdateStatus(rru, null, Status.OK, true); + } + + /** + * Test for remote ref deletion. + * + * @throws IOException + */ + public void testUpdateDelete() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, null, + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + testOneUpdateStatus(rru, ref, Status.OK, true); + } + + /** + * Test for remote ref deletion (try), when that ref doesn't exist on remote + * repo. + * + * @throws IOException + */ + public void testUpdateDeleteNonExisting() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, null, + "refs/heads/master", false, null, null); + testOneUpdateStatus(rru, null, Status.NON_EXISTING, null); + } + + /** + * Test for remote ref update, when it is already up to date. + * + * @throws IOException + */ + public void testUpdateUpToDate() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + testOneUpdateStatus(rru, ref, Status.UP_TO_DATE, null); + } + + /** + * Test for remote ref update with expected remote object. + * + * @throws IOException + */ + public void testUpdateExpectedRemote() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, ObjectId + .fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.OK, true); + } + + /** + * Test for remote ref update with expected old object set, when old object + * is not that expected one. + * + * @throws IOException + */ + public void testUpdateUnexpectedRemote() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, ObjectId + .fromString("0000000000000000000000000000000000000001")); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.REJECTED_REMOTE_CHANGED, null); + } + + /** + * Test for remote ref update with expected old object set, when old object + * is not that expected one and force update flag is set (which should have + * lower priority) - shouldn't change behavior. + * + * @throws IOException + */ + public void testUpdateUnexpectedRemoteVsForce() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", true, null, ObjectId + .fromString("0000000000000000000000000000000000000001")); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.REJECTED_REMOTE_CHANGED, null); + } + + /** + * Test for remote ref update, when connection rejects update. + * + * @throws IOException + */ + public void testUpdateRejectedByConnection() throws IOException { + connectionUpdateStatus = Status.REJECTED_OTHER_REASON; + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.REJECTED_OTHER_REASON, null); + } + + /** + * Test for remote refs updates with mixed cases that shouldn't depend on + * each other. + * + * @throws IOException + */ + public void testUpdateMixedCases() throws IOException { + final RemoteRefUpdate rruOk = new RemoteRefUpdate(db, null, + "refs/heads/master", false, null, null); + final Ref refToChange = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + final RemoteRefUpdate rruReject = new RemoteRefUpdate(db, null, + "refs/heads/nonexisting", false, null, null); + refUpdates.add(rruOk); + refUpdates.add(rruReject); + advertisedRefs.add(refToChange); + executePush(); + assertEquals(Status.OK, rruOk.getStatus()); + assertEquals(true, rruOk.isFastForward()); + assertEquals(Status.NON_EXISTING, rruReject.getStatus()); + } + + /** + * Test for local tracking ref update. + * + * @throws IOException + */ + public void testTrackingRefUpdateEnabled() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, "refs/remotes/test/master", null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + refUpdates.add(rru); + advertisedRefs.add(ref); + final PushResult result = executePush(); + final TrackingRefUpdate tru = result + .getTrackingRefUpdate("refs/remotes/test/master"); + assertNotNull(tru); + assertEquals("refs/remotes/test/master", tru.getLocalName()); + assertEquals(Result.NEW, tru.getResult()); + } + + /** + * Test for local tracking ref update disabled. + * + * @throws IOException + */ + public void testTrackingRefUpdateDisabled() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + refUpdates.add(rru); + advertisedRefs.add(ref); + final PushResult result = executePush(); + assertTrue(result.getTrackingRefUpdates().isEmpty()); + } + + /** + * Test for local tracking ref update when remote update has failed. + * + * @throws IOException + */ + public void testTrackingRefUpdateOnReject() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "ac7e7e44c1885efb472ad54a78327d66bfc4ecef", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + final PushResult result = testOneUpdateStatus(rru, ref, + Status.REJECTED_NONFASTFORWARD, null); + assertTrue(result.getTrackingRefUpdates().isEmpty()); + } + + /** + * Test for push operation result - that contains expected elements. + * + * @throws IOException + */ + public void testPushResult() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, "refs/remotes/test/master", null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + refUpdates.add(rru); + advertisedRefs.add(ref); + final PushResult result = executePush(); + assertEquals(1, result.getTrackingRefUpdates().size()); + assertEquals(1, result.getAdvertisedRefs().size()); + assertEquals(1, result.getRemoteUpdates().size()); + assertNotNull(result.getTrackingRefUpdate("refs/remotes/test/master")); + assertNotNull(result.getAdvertisedRef("refs/heads/master")); + assertNotNull(result.getRemoteUpdate("refs/heads/master")); + } + + private PushResult testOneUpdateStatus(final RemoteRefUpdate rru, + final Ref advertisedRef, final Status expectedStatus, + Boolean fastForward) throws NotSupportedException, + TransportException { + refUpdates.add(rru); + if (advertisedRef != null) + advertisedRefs.add(advertisedRef); + final PushResult result = executePush(); + assertEquals(expectedStatus, rru.getStatus()); + if (fastForward != null) + assertEquals(fastForward.booleanValue(), rru.isFastForward()); + return result; + } + + private PushResult executePush() throws NotSupportedException, + TransportException { + process = new PushProcess(transport, refUpdates); + return process.execute(new TextProgressMonitor()); + } + + private class MockTransport extends Transport { + MockTransport(Repository local, URIish uri) { + super(local, uri); + } + + @Override + public FetchConnection openFetch() throws NotSupportedException, + TransportException { + throw new NotSupportedException("mock"); + } + + @Override + public PushConnection openPush() throws NotSupportedException, + TransportException { + return new MockPushConnection(); + } + + @Override + public void close() { + // nothing here + } + } + + private class MockPushConnection extends BaseConnection implements + PushConnection { + MockPushConnection() { + final Map<String, Ref> refsMap = new HashMap<String, Ref>(); + for (final Ref r : advertisedRefs) + refsMap.put(r.getName(), r); + available(refsMap); + } + + @Override + public void close() { + // nothing here + } + + public void push(ProgressMonitor monitor, + Map<String, RemoteRefUpdate> refsToUpdate) + throws TransportException { + for (final RemoteRefUpdate rru : refsToUpdate.values()) { + assertEquals(Status.NOT_ATTEMPTED, rru.getStatus()); + rru.setStatus(connectionUpdateStatus); + } + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java new file mode 100644 index 0000000000..38dbe0962e --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * 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 junit.framework.TestCase; + +import org.eclipse.jgit.lib.Ref; + +public class RefSpecTest extends TestCase { + public void testMasterMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec(sn + ":" + sn); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(sn, rs.getSource()); + assertEquals(sn, rs.getDestination()); + assertEquals(sn + ":" + sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertTrue(rs.matchSource(r)); + assertTrue(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testSplitLastColon() { + final String lhs = ":m:a:i:n:t"; + final String rhs = "refs/heads/maint"; + final RefSpec rs = new RefSpec(lhs + ":" + rhs); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(lhs, rs.getSource()); + assertEquals(rhs, rs.getDestination()); + assertEquals(lhs + ":" + rhs, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + } + + public void testForceMasterMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec("+" + sn + ":" + sn); + assertTrue(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(sn, rs.getSource()); + assertEquals(sn, rs.getDestination()); + assertEquals("+" + sn + ":" + sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertTrue(rs.matchSource(r)); + assertTrue(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec(sn); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(sn, rs.getSource()); + assertNull(rs.getDestination()); + assertEquals(sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertTrue(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testForceMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec("+" + sn); + assertTrue(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(sn, rs.getSource()); + assertNull(rs.getDestination()); + assertEquals("+" + sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertTrue(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testDeleteMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec(":" + sn); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertNull(rs.getSource()); + assertEquals(sn, rs.getDestination()); + assertEquals(":" + sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertFalse(rs.matchSource(r)); + assertTrue(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testForceRemotesOrigin() { + final String srcn = "refs/heads/*"; + final String dstn = "refs/remotes/origin/*"; + final RefSpec rs = new RefSpec("+" + srcn + ":" + dstn); + assertTrue(rs.isForceUpdate()); + assertTrue(rs.isWildcard()); + assertEquals(srcn, rs.getSource()); + assertEquals(dstn, rs.getDestination()); + assertEquals("+" + srcn + ":" + dstn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r; + RefSpec expanded; + + r = new Ref(Ref.Storage.LOOSE, "refs/heads/master", null); + assertTrue(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + expanded = rs.expandFromSource(r); + assertNotSame(rs, expanded); + assertTrue(expanded.isForceUpdate()); + assertFalse(expanded.isWildcard()); + assertEquals(r.getName(), expanded.getSource()); + assertEquals("refs/remotes/origin/master", expanded.getDestination()); + + r = new Ref(Ref.Storage.LOOSE, "refs/remotes/origin/next", null); + assertFalse(rs.matchSource(r)); + assertTrue(rs.matchDestination(r)); + + r = new Ref(Ref.Storage.LOOSE, "refs/tags/v1.0", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testCreateEmpty() { + final RefSpec rs = new RefSpec(); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals("HEAD", rs.getSource()); + assertNull(rs.getDestination()); + assertEquals("HEAD", rs.toString()); + } + + public void testSetForceUpdate() { + final String s = "refs/heads/*:refs/remotes/origin/*"; + final RefSpec a = new RefSpec(s); + assertFalse(a.isForceUpdate()); + RefSpec b = a.setForceUpdate(true); + assertNotSame(a, b); + assertFalse(a.isForceUpdate()); + assertTrue(b.isForceUpdate()); + assertEquals(s, a.toString()); + assertEquals("+" + s, b.toString()); + } + + public void testSetSource() { + final RefSpec a = new RefSpec(); + final RefSpec b = a.setSource("refs/heads/master"); + assertNotSame(a, b); + assertEquals("HEAD", a.toString()); + assertEquals("refs/heads/master", b.toString()); + } + + public void testSetDestination() { + final RefSpec a = new RefSpec(); + final RefSpec b = a.setDestination("refs/heads/master"); + assertNotSame(a, b); + assertEquals("HEAD", a.toString()); + assertEquals("HEAD:refs/heads/master", b.toString()); + } + + public void testSetDestination_SourceNull() { + final RefSpec a = new RefSpec(); + RefSpec b; + + b = a.setDestination("refs/heads/master"); + b = b.setSource(null); + assertNotSame(a, b); + assertEquals("HEAD", a.toString()); + assertEquals(":refs/heads/master", b.toString()); + } + + public void testSetSourceDestination() { + final RefSpec a = new RefSpec(); + final RefSpec b; + b = a.setSourceDestination("refs/heads/*", "refs/remotes/origin/*"); + assertNotSame(a, b); + assertEquals("HEAD", a.toString()); + assertEquals("refs/heads/*:refs/remotes/origin/*", b.toString()); + } + + public void testExpandFromDestination_NonWildcard() { + final String src = "refs/heads/master"; + final String dst = "refs/remotes/origin/master"; + final RefSpec a = new RefSpec(src + ":" + dst); + final RefSpec r = a.expandFromDestination(dst); + assertSame(a, r); + assertFalse(r.isWildcard()); + assertEquals(src, r.getSource()); + assertEquals(dst, r.getDestination()); + } + + public void testExpandFromDestination_Wildcard() { + final String src = "refs/heads/master"; + final String dst = "refs/remotes/origin/master"; + final RefSpec a = new RefSpec("refs/heads/*:refs/remotes/origin/*"); + final RefSpec r = a.expandFromDestination(dst); + assertNotSame(a, r); + assertFalse(r.isWildcard()); + assertEquals(src, r.getSource()); + assertEquals(dst, r.getDestination()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java new file mode 100644 index 0000000000..3d9b51f9b6 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * 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.List; + +import junit.framework.TestCase; + +import org.eclipse.jgit.errors.ConfigInvalidException; +import org.eclipse.jgit.lib.Config; + +public class RemoteConfigTest extends TestCase { + private Config config; + + protected void setUp() throws Exception { + super.setUp(); + config = new Config(); + } + + private void readConfig(final String dat) throws ConfigInvalidException { + config = new Config(); + config.fromText(dat); + } + + private void checkConfig(final String exp) { + assertEquals(exp, config.toText()); + } + + private static void assertEquals(final String exp, final URIish act) { + assertEquals(exp, act != null ? act.toString() : null); + } + + public void testSimple() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + final List<URIish> allURIs = rc.getURIs(); + RefSpec spec; + + assertEquals("spearce", rc.getName()); + assertNotNull(allURIs); + assertNotNull(rc.getFetchRefSpecs()); + assertNotNull(rc.getPushRefSpecs()); + assertNotNull(rc.getTagOpt()); + assertEquals(0, rc.getTimeout()); + assertSame(TagOpt.AUTO_FOLLOW, rc.getTagOpt()); + + assertEquals(1, allURIs.size()); + assertEquals("http://www.spearce.org/egit.git", allURIs.get(0)); + + assertEquals(1, rc.getFetchRefSpecs().size()); + spec = rc.getFetchRefSpecs().get(0); + assertTrue(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/heads/*", spec.getSource()); + assertEquals("refs/remotes/spearce/*", spec.getDestination()); + + assertEquals(0, rc.getPushRefSpecs().size()); + } + + public void testSimpleNoTags() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n" + + "tagopt = --no-tags\n"); + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertSame(TagOpt.NO_TAGS, rc.getTagOpt()); + } + + public void testSimpleAlwaysTags() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n" + + "tagopt = --tags\n"); + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertSame(TagOpt.FETCH_TAGS, rc.getTagOpt()); + } + + public void testMirror() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/heads/*\n" + + "fetch = refs/tags/*:refs/tags/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + final List<URIish> allURIs = rc.getURIs(); + RefSpec spec; + + assertEquals("spearce", rc.getName()); + assertNotNull(allURIs); + assertNotNull(rc.getFetchRefSpecs()); + assertNotNull(rc.getPushRefSpecs()); + + assertEquals(1, allURIs.size()); + assertEquals("http://www.spearce.org/egit.git", allURIs.get(0)); + + assertEquals(2, rc.getFetchRefSpecs().size()); + + spec = rc.getFetchRefSpecs().get(0); + assertTrue(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/heads/*", spec.getSource()); + assertEquals("refs/heads/*", spec.getDestination()); + + spec = rc.getFetchRefSpecs().get(1); + assertFalse(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/tags/*", spec.getSource()); + assertEquals("refs/tags/*", spec.getDestination()); + + assertEquals(0, rc.getPushRefSpecs().size()); + } + + public void testBackup() throws Exception { + readConfig("[remote \"backup\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "url = user@repo.or.cz:/srv/git/egit.git\n" + + "push = +refs/heads/*:refs/heads/*\n" + + "push = refs/tags/*:refs/tags/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "backup"); + final List<URIish> allURIs = rc.getURIs(); + RefSpec spec; + + assertEquals("backup", rc.getName()); + assertNotNull(allURIs); + assertNotNull(rc.getFetchRefSpecs()); + assertNotNull(rc.getPushRefSpecs()); + + assertEquals(2, allURIs.size()); + assertEquals("http://www.spearce.org/egit.git", allURIs.get(0)); + assertEquals("user@repo.or.cz:/srv/git/egit.git", allURIs.get(1)); + + assertEquals(0, rc.getFetchRefSpecs().size()); + + assertEquals(2, rc.getPushRefSpecs().size()); + spec = rc.getPushRefSpecs().get(0); + assertTrue(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/heads/*", spec.getSource()); + assertEquals("refs/heads/*", spec.getDestination()); + + spec = rc.getPushRefSpecs().get(1); + assertFalse(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/tags/*", spec.getSource()); + assertEquals("refs/tags/*", spec.getDestination()); + } + + public void testUploadPack() throws Exception { + readConfig("[remote \"example\"]\n" + + "url = user@example.com:egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/example/*\n" + + "uploadpack = /path/to/git/git-upload-pack\n" + + "receivepack = /path/to/git/git-receive-pack\n"); + + final RemoteConfig rc = new RemoteConfig(config, "example"); + final List<URIish> allURIs = rc.getURIs(); + RefSpec spec; + + assertEquals("example", rc.getName()); + assertNotNull(allURIs); + assertNotNull(rc.getFetchRefSpecs()); + assertNotNull(rc.getPushRefSpecs()); + + assertEquals(1, allURIs.size()); + assertEquals("user@example.com:egit.git", allURIs.get(0)); + + assertEquals(1, rc.getFetchRefSpecs().size()); + spec = rc.getFetchRefSpecs().get(0); + assertTrue(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/heads/*", spec.getSource()); + assertEquals("refs/remotes/example/*", spec.getDestination()); + + assertEquals(0, rc.getPushRefSpecs().size()); + + assertEquals("/path/to/git/git-upload-pack", rc.getUploadPack()); + assertEquals("/path/to/git/git-receive-pack", rc.getReceivePack()); + } + + public void testUnknown() throws Exception { + readConfig(""); + + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertEquals(0, rc.getURIs().size()); + assertEquals(0, rc.getFetchRefSpecs().size()); + assertEquals(0, rc.getPushRefSpecs().size()); + assertEquals("git-upload-pack", rc.getUploadPack()); + assertEquals("git-receive-pack", rc.getReceivePack()); + } + + public void testAddURI() throws Exception { + readConfig(""); + + final URIish uri = new URIish("/some/dir"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertEquals(0, rc.getURIs().size()); + + assertTrue(rc.addURI(uri)); + assertEquals(1, rc.getURIs().size()); + assertSame(uri, rc.getURIs().get(0)); + + assertFalse(rc.addURI(new URIish(uri.toString()))); + assertEquals(1, rc.getURIs().size()); + } + + public void testRemoveFirstURI() throws Exception { + readConfig(""); + + final URIish a = new URIish("/some/dir"); + final URIish b = new URIish("/another/dir"); + final URIish c = new URIish("/more/dirs"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertTrue(rc.addURI(a)); + assertTrue(rc.addURI(b)); + assertTrue(rc.addURI(c)); + + assertEquals(3, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(b, rc.getURIs().get(1)); + assertSame(c, rc.getURIs().get(2)); + + assertTrue(rc.removeURI(a)); + assertEquals(2, rc.getURIs().size()); + assertSame(b, rc.getURIs().get(0)); + assertSame(c, rc.getURIs().get(1)); + } + + public void testRemoveMiddleURI() throws Exception { + readConfig(""); + + final URIish a = new URIish("/some/dir"); + final URIish b = new URIish("/another/dir"); + final URIish c = new URIish("/more/dirs"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertTrue(rc.addURI(a)); + assertTrue(rc.addURI(b)); + assertTrue(rc.addURI(c)); + + assertEquals(3, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(b, rc.getURIs().get(1)); + assertSame(c, rc.getURIs().get(2)); + + assertTrue(rc.removeURI(b)); + assertEquals(2, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(c, rc.getURIs().get(1)); + } + + public void testRemoveLastURI() throws Exception { + readConfig(""); + + final URIish a = new URIish("/some/dir"); + final URIish b = new URIish("/another/dir"); + final URIish c = new URIish("/more/dirs"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertTrue(rc.addURI(a)); + assertTrue(rc.addURI(b)); + assertTrue(rc.addURI(c)); + + assertEquals(3, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(b, rc.getURIs().get(1)); + assertSame(c, rc.getURIs().get(2)); + + assertTrue(rc.removeURI(c)); + assertEquals(2, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(b, rc.getURIs().get(1)); + } + + public void testRemoveOnlyURI() throws Exception { + readConfig(""); + + final URIish a = new URIish("/some/dir"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertTrue(rc.addURI(a)); + + assertEquals(1, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + + assertTrue(rc.removeURI(a)); + assertEquals(0, rc.getURIs().size()); + } + + public void testCreateOrigin() throws Exception { + final RemoteConfig rc = new RemoteConfig(config, "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.update(config); + checkConfig("[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n"); + } + + public void testSaveAddURI() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + rc.addURI(new URIish("/some/dir")); + assertEquals(2, rc.getURIs().size()); + rc.update(config); + checkConfig("[remote \"spearce\"]\n" + + "\turl = http://www.spearce.org/egit.git\n" + + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/spearce/*\n"); + } + + public void testSaveRemoveLastURI() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "url = /some/dir\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertEquals(2, rc.getURIs().size()); + rc.removeURI(new URIish("/some/dir")); + assertEquals(1, rc.getURIs().size()); + rc.update(config); + checkConfig("[remote \"spearce\"]\n" + + "\turl = http://www.spearce.org/egit.git\n" + + "\tfetch = +refs/heads/*:refs/remotes/spearce/*\n"); + } + + public void testSaveRemoveFirstURI() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "url = /some/dir\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertEquals(2, rc.getURIs().size()); + rc.removeURI(new URIish("http://www.spearce.org/egit.git")); + assertEquals(1, rc.getURIs().size()); + rc.update(config); + checkConfig("[remote \"spearce\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/spearce/*\n"); + } + + public void testSaveNoTags() throws Exception { + final RemoteConfig rc = new RemoteConfig(config, "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.setTagOpt(TagOpt.NO_TAGS); + rc.update(config); + checkConfig("[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n" + + "\ttagopt = --no-tags\n"); + } + + public void testSaveAllTags() throws Exception { + final RemoteConfig rc = new RemoteConfig(config, "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.setTagOpt(TagOpt.FETCH_TAGS); + rc.update(config); + checkConfig("[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n" + + "\ttagopt = --tags\n"); + } + + public void testSimpleTimeout() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n" + + "timeout = 12\n"); + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertEquals(12, rc.getTimeout()); + } + + public void testSaveTimeout() throws Exception { + final RemoteConfig rc = new RemoteConfig(config, "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.setTimeout(60); + rc.update(config); + checkConfig("[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n" + + "\ttimeout = 60\n"); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java new file mode 100644 index 0000000000..3c79f138c8 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2009, Google Inc. + * 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.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; + +// Note, test vectors created with: +// +// perl -e 'printf "%4.4x%s\n", 4+length($ARGV[0]),$ARGV[0]' + +public class SideBandOutputStreamTest extends TestCase { + private ByteArrayOutputStream rawOut; + + private PacketLineOut pckOut; + + protected void setUp() throws Exception { + super.setUp(); + rawOut = new ByteArrayOutputStream(); + pckOut = new PacketLineOut(rawOut); + } + + public void testWrite_CH_DATA() throws IOException { + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_DATA, pckOut); + out.write(new byte[] { 'a', 'b', 'c' }); + assertBuffer("0008\001abc"); + } + + public void testWrite_CH_PROGRESS() throws IOException { + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_PROGRESS, pckOut); + out.write(new byte[] { 'a', 'b', 'c' }); + assertBuffer("0008\002abc"); + } + + public void testWrite_CH_ERROR() throws IOException { + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_ERROR, pckOut); + out.write(new byte[] { 'a', 'b', 'c' }); + assertBuffer("0008\003abc"); + } + + public void testWrite_Small() throws IOException { + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_DATA, pckOut); + out.write('a'); + out.write('b'); + out.write('c'); + assertBuffer("0006\001a0006\001b0006\001c"); + } + + public void testWrite_Large() throws IOException { + final int buflen = SideBandOutputStream.MAX_BUF + - SideBandOutputStream.HDR_SIZE; + final byte[] buf = new byte[buflen]; + for (int i = 0; i < buf.length; i++) { + buf[i] = (byte) i; + } + + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_DATA, pckOut); + out.write(buf); + + final byte[] act = rawOut.toByteArray(); + final String explen = Integer.toString(buf.length + 5, 16); + assertEquals(5 + buf.length, act.length); + assertEquals(new String(act, 0, 4, "UTF-8"), explen); + assertEquals(1, act[4]); + for (int i = 0, j = 5; i < buf.length; i++, j++) { + assertEquals(buf[i], act[j]); + } + } + + public void testFlush() throws IOException { + final int[] flushCnt = new int[1]; + final OutputStream mockout = new OutputStream() { + @Override + public void write(int arg0) throws IOException { + fail("should not write"); + } + + @Override + public void flush() throws IOException { + flushCnt[0]++; + } + }; + + new SideBandOutputStream(SideBandOutputStream.CH_DATA, + new PacketLineOut(mockout)).flush(); + assertEquals(0, flushCnt[0]); + + new SideBandOutputStream(SideBandOutputStream.CH_ERROR, + new PacketLineOut(mockout)).flush(); + assertEquals(1, flushCnt[0]); + + new SideBandOutputStream(SideBandOutputStream.CH_PROGRESS, + new PacketLineOut(mockout)).flush(); + assertEquals(2, flushCnt[0]); + } + + private void assertBuffer(final String exp) throws IOException { + assertEquals(exp, new String(rawOut.toByteArray(), + Constants.CHARACTER_ENCODING)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java new file mode 100644 index 0000000000..75e661bcf9 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * 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.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import org.eclipse.jgit.lib.RepositoryConfig; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class TransportTest extends RepositoryTestCase { + private Transport transport; + + private RemoteConfig remoteConfig; + + @Override + public void setUp() throws Exception { + super.setUp(); + final RepositoryConfig config = db.getConfig(); + remoteConfig = new RemoteConfig(config, "test"); + remoteConfig.addURI(new URIish("http://everyones.loves.git/u/2")); + transport = null; + } + + @Override + protected void tearDown() throws Exception { + if (transport != null) { + transport.close(); + transport = null; + } + super.tearDown(); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion with simple RefSpec - no + * wildcard, no tracking ref in repo configuration. + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesNoWildcardNoTracking() + throws IOException { + transport = Transport.open(db, remoteConfig); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(Collections.nCopies(1, new RefSpec( + "refs/heads/master:refs/heads/x"))); + + assertEquals(1, result.size()); + final RemoteRefUpdate rru = result.iterator().next(); + assertNull(rru.getExpectedOldObjectId()); + assertFalse(rru.isForceUpdate()); + assertEquals("refs/heads/master", rru.getSrcRef()); + assertEquals(db.resolve("refs/heads/master"), rru.getNewObjectId()); + assertEquals("refs/heads/x", rru.getRemoteName()); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion with no-destination RefSpec + * (destination should be set up for the same name as source). + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesNoWildcardNoDestination() + throws IOException { + transport = Transport.open(db, remoteConfig); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(Collections.nCopies(1, new RefSpec( + "+refs/heads/master"))); + + assertEquals(1, result.size()); + final RemoteRefUpdate rru = result.iterator().next(); + assertNull(rru.getExpectedOldObjectId()); + assertTrue(rru.isForceUpdate()); + assertEquals("refs/heads/master", rru.getSrcRef()); + assertEquals(db.resolve("refs/heads/master"), rru.getNewObjectId()); + assertEquals("refs/heads/master", rru.getRemoteName()); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion with wildcard RefSpec. + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesWildcardNoTracking() throws IOException { + transport = Transport.open(db, remoteConfig); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(Collections.nCopies(1, new RefSpec( + "+refs/heads/*:refs/heads/test/*"))); + + assertEquals(12, result.size()); + boolean foundA = false; + boolean foundB = false; + for (final RemoteRefUpdate rru : result) { + if ("refs/heads/a".equals(rru.getSrcRef()) + && "refs/heads/test/a".equals(rru.getRemoteName())) + foundA = true; + if ("refs/heads/b".equals(rru.getSrcRef()) + && "refs/heads/test/b".equals(rru.getRemoteName())) + foundB = true; + } + assertTrue(foundA); + assertTrue(foundB); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion for more than one RefSpecs + * handling. + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesTwoRefSpecs() throws IOException { + transport = Transport.open(db, remoteConfig); + final RefSpec specA = new RefSpec("+refs/heads/a:refs/heads/b"); + final RefSpec specC = new RefSpec("+refs/heads/c:refs/heads/d"); + final Collection<RefSpec> specs = Arrays.asList(specA, specC); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(specs); + + assertEquals(2, result.size()); + boolean foundA = false; + boolean foundC = false; + for (final RemoteRefUpdate rru : result) { + if ("refs/heads/a".equals(rru.getSrcRef()) + && "refs/heads/b".equals(rru.getRemoteName())) + foundA = true; + if ("refs/heads/c".equals(rru.getSrcRef()) + && "refs/heads/d".equals(rru.getRemoteName())) + foundC = true; + } + assertTrue(foundA); + assertTrue(foundC); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion for tracking ref search. + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesTrackingRef() throws IOException { + remoteConfig.addFetchRefSpec(new RefSpec( + "refs/heads/*:refs/remotes/test/*")); + transport = Transport.open(db, remoteConfig); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(Collections.nCopies(1, new RefSpec( + "+refs/heads/a:refs/heads/a"))); + + assertEquals(1, result.size()); + final TrackingRefUpdate tru = result.iterator().next() + .getTrackingRefUpdate(); + assertEquals("refs/remotes/test/a", tru.getLocalName()); + assertEquals("refs/heads/a", tru.getRemoteName()); + assertEquals(db.resolve("refs/heads/a"), tru.getNewObjectId()); + assertNull(tru.getOldObjectId()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java new file mode 100644 index 0000000000..2598fdc1f5 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * 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 junit.framework.TestCase; + +public class URIishTest extends TestCase { + + public void testUnixFile() throws Exception { + final String str = "/home/m y"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals(str, u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testWindowsFile() throws Exception { + final String str = "D:/m y"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals(str, u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testWindowsFile2() throws Exception { + final String str = "D:\\m y"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals("D:/m y", u.getPath()); + assertEquals("D:/m y", u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testUNC() throws Exception { + final String str = "\\\\some\\place"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals("//some/place", u.getPath()); + assertEquals("//some/place", u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testFileProtoUnix() throws Exception { + final String str = "file:///home/m y"; + URIish u = new URIish(str); + assertEquals("file", u.getScheme()); + assertFalse(u.isRemote()); + assertEquals("/home/m y", u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testFileProtoWindows() throws Exception { + final String str = "file:///D:/m y"; + URIish u = new URIish(str); + assertEquals("file", u.getScheme()); + assertFalse(u.isRemote()); + assertEquals("D:/m y", u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitProtoUnix() throws Exception { + final String str = "git://example.com/home/m y"; + URIish u = new URIish(str); + assertEquals("git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("example.com", u.getHost()); + assertEquals("/home/m y", u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitProtoUnixPort() throws Exception { + final String str = "git://example.com:333/home/m y"; + URIish u = new URIish(str); + assertEquals("git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("example.com", u.getHost()); + assertEquals("/home/m y", u.getPath()); + assertEquals(333, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitProtoWindowsPort() throws Exception { + final String str = "git://example.com:338/D:/m y"; + URIish u = new URIish(str); + assertEquals("git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("D:/m y", u.getPath()); + assertEquals(338, u.getPort()); + assertEquals("example.com", u.getHost()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitProtoWindows() throws Exception { + final String str = "git://example.com/D:/m y"; + URIish u = new URIish(str); + assertEquals("git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("D:/m y", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testScpStyleWithoutUser() throws Exception { + final String str = "example.com:some/p ath"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testScpStyleWithUser() throws Exception { + final String str = "user@example.com:some/p ath"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("some/p ath", u.getPath()); + assertEquals("user", u.getUser()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitSshProto() throws Exception { + final String str = "git+ssh://example.com/some/p ath"; + URIish u = new URIish(str); + assertEquals("git+ssh", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testSshGitProto() throws Exception { + final String str = "ssh+git://example.com/some/p ath"; + URIish u = new URIish(str); + assertEquals("ssh+git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testSshProto() throws Exception { + final String str = "ssh://example.com/some/p ath"; + URIish u = new URIish(str); + assertEquals("ssh", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testSshProtoWithUserAndPort() throws Exception { + final String str = "ssh://user@example.com:33/some/p ath"; + URIish u = new URIish(str); + assertEquals("ssh", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals("user", u.getUser()); + assertNull(u.getPass()); + assertEquals(33, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testSshProtoWithUserPassAndPort() throws Exception { + final String str = "ssh://user:pass@example.com:33/some/p ath"; + URIish u = new URIish(str); + assertEquals("ssh", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals("user", u.getUser()); + assertEquals("pass", u.getPass()); + assertEquals(33, u.getPort()); + assertEquals(str, u.toPrivateString()); + assertEquals(u.setPass(null).toPrivateString(), u.toString()); + assertEquals(u, new URIish(str)); + } +} |