Browse Source
No Eclipse support for this project is provided, because the Jetty project does not publish a complete P2 repository. Change-Id: Ic5fe2e79bb216e36920fd4a70ec15dd6ccfd1468 Signed-off-by: Shawn O. Pearce <spearce@spearce.org>stable-0.7
Shawn O. Pearce
15 years ago
22 changed files with 3476 additions and 18 deletions
@ -0,0 +1,108 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- |
||||||
|
Copyright (C) 2009-2010, Google Inc. |
||||||
|
Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.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. |
||||||
|
--> |
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
||||||
|
<modelVersion>4.0.0</modelVersion> |
||||||
|
|
||||||
|
<parent> |
||||||
|
<groupId>org.eclipse.jgit</groupId> |
||||||
|
<artifactId>org.eclipse.jgit-parent</artifactId> |
||||||
|
<version>0.6.0-SNAPSHOT</version> |
||||||
|
</parent> |
||||||
|
|
||||||
|
<artifactId>org.eclipse.jgit.http.test</artifactId> |
||||||
|
<name>JGit - HTTP Tests</name> |
||||||
|
|
||||||
|
<description> |
||||||
|
Tests for the HTTP transport. |
||||||
|
</description> |
||||||
|
|
||||||
|
<dependencies> |
||||||
|
<dependency> |
||||||
|
<groupId>junit</groupId> |
||||||
|
<artifactId>junit</artifactId> |
||||||
|
<scope>test</scope> |
||||||
|
</dependency> |
||||||
|
|
||||||
|
<dependency> |
||||||
|
<groupId>org.eclipse.jgit</groupId> |
||||||
|
<artifactId>org.eclipse.jgit</artifactId> |
||||||
|
<version>${project.version}</version> |
||||||
|
<scope>test</scope> |
||||||
|
</dependency> |
||||||
|
|
||||||
|
<dependency> |
||||||
|
<groupId>org.eclipse.jgit</groupId> |
||||||
|
<artifactId>org.eclipse.jgit.junit</artifactId> |
||||||
|
<version>${project.version}</version> |
||||||
|
<scope>test</scope> |
||||||
|
</dependency> |
||||||
|
|
||||||
|
<dependency> |
||||||
|
<groupId>org.eclipse.jgit</groupId> |
||||||
|
<artifactId>org.eclipse.jgit.http.server</artifactId> |
||||||
|
<version>${project.version}</version> |
||||||
|
<scope>test</scope> |
||||||
|
</dependency> |
||||||
|
|
||||||
|
<dependency> |
||||||
|
<groupId>org.eclipse.jetty</groupId> |
||||||
|
<artifactId>jetty-servlet</artifactId> |
||||||
|
<scope>test</scope> |
||||||
|
</dependency> |
||||||
|
</dependencies> |
||||||
|
|
||||||
|
<build> |
||||||
|
<testSourceDirectory>tst/</testSourceDirectory> |
||||||
|
|
||||||
|
<testResources> |
||||||
|
<testResource> |
||||||
|
<directory>tst-rsrc/</directory> |
||||||
|
</testResource> |
||||||
|
</testResources> |
||||||
|
</build> |
||||||
|
</project> |
@ -0,0 +1,136 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2009-2010, 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.http.test; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper; |
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request; |
||||||
|
import org.eclipse.jgit.http.server.resolver.AsIsFileService; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException; |
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
|
||||||
|
public class AsIsServiceTest extends LocalDiskRepositoryTestCase { |
||||||
|
private Repository db; |
||||||
|
|
||||||
|
private AsIsFileService service; |
||||||
|
|
||||||
|
protected void setUp() throws Exception { |
||||||
|
super.setUp(); |
||||||
|
|
||||||
|
db = createBareRepository(); |
||||||
|
service = new AsIsFileService(); |
||||||
|
} |
||||||
|
|
||||||
|
public void testDisabledSingleton() throws ServiceNotAuthorizedException { |
||||||
|
service = AsIsFileService.DISABLED; |
||||||
|
try { |
||||||
|
service.access(new R(null, "1.2.3.4"), db); |
||||||
|
fail("Created session for anonymous user: null"); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
service.access(new R("bob", "1.2.3.4"), db); |
||||||
|
fail("Created session for user: \"bob\""); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_Default() throws ServiceNotEnabledException, |
||||||
|
ServiceNotAuthorizedException { |
||||||
|
service.access(new R(null, "1.2.3.4"), db); |
||||||
|
service.access(new R("bob", "1.2.3.4"), db); |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_Disabled() throws ServiceNotAuthorizedException { |
||||||
|
db.getConfig().setBoolean("http", null, "getanyfile", false); |
||||||
|
|
||||||
|
try { |
||||||
|
service.access(new R(null, "1.2.3.4"), db); |
||||||
|
fail("Created session for anonymous user: null"); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
service.access(new R("bob", "1.2.3.4"), db); |
||||||
|
fail("Created session for user: \"bob\""); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_Enabled() throws ServiceNotEnabledException, |
||||||
|
ServiceNotAuthorizedException { |
||||||
|
db.getConfig().setBoolean("http", null, "getanyfile", true); |
||||||
|
service.access(new R(null, "1.2.3.4"), db); |
||||||
|
service.access(new R("bob", "1.2.3.4"), db); |
||||||
|
} |
||||||
|
|
||||||
|
private final class R extends HttpServletRequestWrapper { |
||||||
|
private final String user; |
||||||
|
|
||||||
|
private final String host; |
||||||
|
|
||||||
|
R(final String user, final String host) { |
||||||
|
super(new Request() /* can't pass null, sigh */); |
||||||
|
this.user = user; |
||||||
|
this.host = host; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getRemoteHost() { |
||||||
|
return host; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getRemoteUser() { |
||||||
|
return user; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,198 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2009-2010, 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.http.test; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper; |
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request; |
||||||
|
import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ReceivePackFactory; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException; |
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; |
||||||
|
import org.eclipse.jgit.lib.PersonIdent; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.transport.ReceivePack; |
||||||
|
|
||||||
|
public class DefaultReceivePackFactoryTest extends LocalDiskRepositoryTestCase { |
||||||
|
private Repository db; |
||||||
|
|
||||||
|
private ReceivePackFactory factory; |
||||||
|
|
||||||
|
protected void setUp() throws Exception { |
||||||
|
super.setUp(); |
||||||
|
|
||||||
|
db = createBareRepository(); |
||||||
|
factory = new DefaultReceivePackFactory(); |
||||||
|
} |
||||||
|
|
||||||
|
public void testDisabledSingleton() throws ServiceNotAuthorizedException { |
||||||
|
factory = ReceivePackFactory.DISABLED; |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R(null, "localhost"), db); |
||||||
|
fail("Created session for anonymous user: null"); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R("", "localhost"), db); |
||||||
|
fail("Created session for anonymous user: \"\""); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R("bob", "localhost"), db); |
||||||
|
fail("Created session for user: \"bob\""); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_NullUser() throws ServiceNotEnabledException { |
||||||
|
try { |
||||||
|
factory.create(new R(null, "localhost"), db); |
||||||
|
fail("Created session for anonymous user: null"); |
||||||
|
} catch (ServiceNotAuthorizedException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_EmptyStringUser() throws ServiceNotEnabledException { |
||||||
|
try { |
||||||
|
factory.create(new R("", "localhost"), db); |
||||||
|
fail("Created session for anonymous user: \"\""); |
||||||
|
} catch (ServiceNotAuthorizedException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_AuthUser() throws ServiceNotEnabledException, |
||||||
|
ServiceNotAuthorizedException { |
||||||
|
ReceivePack rp; |
||||||
|
rp = factory.create(new R("bob", "1.2.3.4"), db); |
||||||
|
assertNotNull("have ReceivePack", rp); |
||||||
|
assertSame(db, rp.getRepository()); |
||||||
|
|
||||||
|
PersonIdent id = rp.getRefLogIdent(); |
||||||
|
assertNotNull(id); |
||||||
|
assertEquals("bob", id.getName()); |
||||||
|
assertEquals("bob@1.2.3.4", id.getEmailAddress()); |
||||||
|
|
||||||
|
// Should have inherited off the current system, which is mocked
|
||||||
|
assertEquals(author.getTimeZoneOffset(), id.getTimeZoneOffset()); |
||||||
|
assertEquals(author.getWhen(), id.getWhen()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_Disabled() throws ServiceNotAuthorizedException { |
||||||
|
db.getConfig().setBoolean("http", null, "receivepack", false); |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R(null, "localhost"), db); |
||||||
|
fail("Created session for anonymous user: null"); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R("", "localhost"), db); |
||||||
|
fail("Created session for anonymous user: \"\""); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R("bob", "localhost"), db); |
||||||
|
fail("Created session for user: \"bob\""); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_Enabled() throws ServiceNotEnabledException, |
||||||
|
ServiceNotAuthorizedException { |
||||||
|
db.getConfig().setBoolean("http", null, "receivepack", true); |
||||||
|
ReceivePack rp; |
||||||
|
|
||||||
|
rp = factory.create(new R(null, "1.2.3.4"), db); |
||||||
|
assertNotNull("have ReceivePack", rp); |
||||||
|
assertSame(db, rp.getRepository()); |
||||||
|
|
||||||
|
PersonIdent id = rp.getRefLogIdent(); |
||||||
|
assertNotNull(id); |
||||||
|
assertEquals("anonymous", id.getName()); |
||||||
|
assertEquals("anonymous@1.2.3.4", id.getEmailAddress()); |
||||||
|
|
||||||
|
// Should have inherited off the current system, which is mocked
|
||||||
|
assertEquals(author.getTimeZoneOffset(), id.getTimeZoneOffset()); |
||||||
|
assertEquals(author.getWhen(), id.getWhen()); |
||||||
|
|
||||||
|
rp = factory.create(new R("bob", "1.2.3.4"), db); |
||||||
|
assertNotNull("have ReceivePack", rp); |
||||||
|
} |
||||||
|
|
||||||
|
private final class R extends HttpServletRequestWrapper { |
||||||
|
private final String user; |
||||||
|
|
||||||
|
private final String host; |
||||||
|
|
||||||
|
R(final String user, final String host) { |
||||||
|
super(new Request() /* can't pass null, sigh */); |
||||||
|
this.user = user; |
||||||
|
this.host = host; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getRemoteHost() { |
||||||
|
return host; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getRemoteUser() { |
||||||
|
return user; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,160 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2009-2010, 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.http.test; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper; |
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request; |
||||||
|
import org.eclipse.jgit.http.server.resolver.DefaultUploadPackFactory; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException; |
||||||
|
import org.eclipse.jgit.http.server.resolver.UploadPackFactory; |
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.transport.UploadPack; |
||||||
|
|
||||||
|
public class DefaultUploadPackFactoryTest extends LocalDiskRepositoryTestCase { |
||||||
|
private Repository db; |
||||||
|
|
||||||
|
private UploadPackFactory factory; |
||||||
|
|
||||||
|
protected void setUp() throws Exception { |
||||||
|
super.setUp(); |
||||||
|
|
||||||
|
db = createBareRepository(); |
||||||
|
factory = new DefaultUploadPackFactory(); |
||||||
|
} |
||||||
|
|
||||||
|
public void testDisabledSingleton() throws ServiceNotAuthorizedException { |
||||||
|
factory = UploadPackFactory.DISABLED; |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R(null, "localhost"), db); |
||||||
|
fail("Created session for anonymous user: null"); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R("", "localhost"), db); |
||||||
|
fail("Created session for anonymous user: \"\""); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R("bob", "localhost"), db); |
||||||
|
fail("Created session for user: \"bob\""); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_Default() throws ServiceNotEnabledException, |
||||||
|
ServiceNotAuthorizedException { |
||||||
|
UploadPack up; |
||||||
|
|
||||||
|
up = factory.create(new R(null, "1.2.3.4"), db); |
||||||
|
assertNotNull("have UploadPack", up); |
||||||
|
assertSame(db, up.getRepository()); |
||||||
|
|
||||||
|
up = factory.create(new R("bob", "1.2.3.4"), db); |
||||||
|
assertNotNull("have UploadPack", up); |
||||||
|
assertSame(db, up.getRepository()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_Disabled() throws ServiceNotAuthorizedException { |
||||||
|
db.getConfig().setBoolean("http", null, "uploadpack", false); |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R(null, "localhost"), db); |
||||||
|
fail("Created session for anonymous user: null"); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
factory.create(new R("bob", "localhost"), db); |
||||||
|
fail("Created session for user: \"bob\""); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
// expected not authorized
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testCreate_Enabled() throws ServiceNotEnabledException, |
||||||
|
ServiceNotAuthorizedException { |
||||||
|
db.getConfig().setBoolean("http", null, "uploadpack", true); |
||||||
|
UploadPack up; |
||||||
|
|
||||||
|
up = factory.create(new R(null, "1.2.3.4"), db); |
||||||
|
assertNotNull("have UploadPack", up); |
||||||
|
assertSame(db, up.getRepository()); |
||||||
|
|
||||||
|
up = factory.create(new R("bob", "1.2.3.4"), db); |
||||||
|
assertNotNull("have UploadPack", up); |
||||||
|
assertSame(db, up.getRepository()); |
||||||
|
} |
||||||
|
|
||||||
|
private final class R extends HttpServletRequestWrapper { |
||||||
|
private final String user; |
||||||
|
|
||||||
|
private final String host; |
||||||
|
|
||||||
|
R(final String user, final String host) { |
||||||
|
super(new Request() /* can't pass null, sigh */); |
||||||
|
this.user = user; |
||||||
|
this.host = host; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getRemoteHost() { |
||||||
|
return host; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getRemoteUser() { |
||||||
|
return user; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,246 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2010, 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.http.test; |
||||||
|
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT; |
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_PRAGMA; |
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_USER_AGENT; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.net.URI; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.DefaultServlet; |
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler; |
||||||
|
import org.eclipse.jgit.errors.NotSupportedException; |
||||||
|
import org.eclipse.jgit.http.test.util.AccessEvent; |
||||||
|
import org.eclipse.jgit.http.test.util.HttpTestCase; |
||||||
|
import org.eclipse.jgit.junit.TestRepository; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.NullProgressMonitor; |
||||||
|
import org.eclipse.jgit.lib.Ref; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.revwalk.RevBlob; |
||||||
|
import org.eclipse.jgit.revwalk.RevCommit; |
||||||
|
import org.eclipse.jgit.transport.FetchConnection; |
||||||
|
import org.eclipse.jgit.transport.HttpTransport; |
||||||
|
import org.eclipse.jgit.transport.Transport; |
||||||
|
import org.eclipse.jgit.transport.TransportHttp; |
||||||
|
import org.eclipse.jgit.transport.URIish; |
||||||
|
|
||||||
|
public class DumbClientDumbServerTest extends HttpTestCase { |
||||||
|
private Repository remoteRepository; |
||||||
|
|
||||||
|
private URIish remoteURI; |
||||||
|
|
||||||
|
private RevBlob A_txt; |
||||||
|
|
||||||
|
private RevCommit A, B; |
||||||
|
|
||||||
|
protected void setUp() throws Exception { |
||||||
|
super.setUp(); |
||||||
|
|
||||||
|
final TestRepository src = createTestRepository(); |
||||||
|
final File srcGit = src.getRepository().getDirectory(); |
||||||
|
final URI base = srcGit.getParentFile().toURI(); |
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/git"); |
||||||
|
app.setResourceBase(base.toString()); |
||||||
|
app.addServlet(DefaultServlet.class, "/"); |
||||||
|
|
||||||
|
server.setUp(); |
||||||
|
|
||||||
|
remoteRepository = src.getRepository(); |
||||||
|
remoteURI = toURIish(app, srcGit.getName()); |
||||||
|
|
||||||
|
A_txt = src.blob("A"); |
||||||
|
A = src.commit().add("A_txt", A_txt).create(); |
||||||
|
B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create(); |
||||||
|
src.update(master, B); |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote() throws IOException { |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
|
||||||
|
assertEquals("http", remoteURI.getScheme()); |
||||||
|
|
||||||
|
Map<String, Ref> map; |
||||||
|
Transport t = Transport.open(dst, remoteURI); |
||||||
|
try { |
||||||
|
// I didn't make up these public interface names, I just
|
||||||
|
// approved them for inclusion into the code base. Sorry.
|
||||||
|
// --spearce
|
||||||
|
//
|
||||||
|
assertTrue("isa TransportHttp", t instanceof TransportHttp); |
||||||
|
assertTrue("isa HttpTransport", t instanceof HttpTransport); |
||||||
|
|
||||||
|
FetchConnection c = t.openFetch(); |
||||||
|
try { |
||||||
|
map = c.getRefsMap(); |
||||||
|
} finally { |
||||||
|
c.close(); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertNotNull("have map of refs", map); |
||||||
|
assertEquals(2, map.size()); |
||||||
|
|
||||||
|
assertNotNull("has " + master, map.get(master)); |
||||||
|
assertEquals(B, map.get(master).getObjectId()); |
||||||
|
|
||||||
|
assertNotNull("has " + Constants.HEAD, map.get(Constants.HEAD)); |
||||||
|
assertEquals(B, map.get(Constants.HEAD).getObjectId()); |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
assertEquals(2, requests.size()); |
||||||
|
assertEquals(0, getRequests(remoteURI, "git-upload-pack").size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath()); |
||||||
|
assertEquals(1, info.getParameters().size()); |
||||||
|
assertEquals("git-upload-pack", info.getParameter("service")); |
||||||
|
assertEquals("no-cache", info.getRequestHeader(HDR_PRAGMA)); |
||||||
|
assertNotNull("has user-agent", info.getRequestHeader(HDR_USER_AGENT)); |
||||||
|
assertTrue("is jgit agent", info.getRequestHeader(HDR_USER_AGENT) |
||||||
|
.startsWith("JGit/")); |
||||||
|
assertEquals("application/x-git-upload-pack-advertisement, */*", info |
||||||
|
.getRequestHeader(HDR_ACCEPT)); |
||||||
|
assertEquals(200, info.getStatus()); |
||||||
|
|
||||||
|
AccessEvent head = requests.get(1); |
||||||
|
assertEquals("GET", head.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "HEAD"), head.getPath()); |
||||||
|
assertEquals(0, head.getParameters().size()); |
||||||
|
assertEquals("no-cache", head.getRequestHeader(HDR_PRAGMA)); |
||||||
|
assertNotNull("has user-agent", head.getRequestHeader(HDR_USER_AGENT)); |
||||||
|
assertTrue("is jgit agent", head.getRequestHeader(HDR_USER_AGENT) |
||||||
|
.startsWith("JGit/")); |
||||||
|
assertEquals(200, head.getStatus()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInitialClone_Loose() throws Exception { |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
assertFalse(dst.hasObject(A_txt)); |
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI); |
||||||
|
try { |
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt)); |
||||||
|
assertEquals(B, dst.getRef(master).getObjectId()); |
||||||
|
fsck(dst, B); |
||||||
|
|
||||||
|
List<AccessEvent> loose = getRequests(loose(remoteURI, A_txt)); |
||||||
|
assertEquals(1, loose.size()); |
||||||
|
assertEquals("GET", loose.get(0).getMethod()); |
||||||
|
assertEquals(0, loose.get(0).getParameters().size()); |
||||||
|
assertEquals(200, loose.get(0).getStatus()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInitialClone_Packed() throws Exception { |
||||||
|
new TestRepository(remoteRepository).packAndPrune(); |
||||||
|
|
||||||
|
Repository dst = createBareRepository(); |
||||||
|
assertFalse(dst.hasObject(A_txt)); |
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI); |
||||||
|
try { |
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt)); |
||||||
|
assertEquals(B, dst.getRef(master).getObjectId()); |
||||||
|
fsck(dst, B); |
||||||
|
|
||||||
|
List<AccessEvent> req; |
||||||
|
AccessEvent event; |
||||||
|
|
||||||
|
req = getRequests(loose(remoteURI, B)); |
||||||
|
assertEquals(1, req.size()); |
||||||
|
event = req.get(0); |
||||||
|
assertEquals("GET", event.getMethod()); |
||||||
|
assertEquals(0, event.getParameters().size()); |
||||||
|
assertEquals(404, event.getStatus()); |
||||||
|
|
||||||
|
req = getRequests(join(remoteURI, "objects/info/packs")); |
||||||
|
assertEquals(1, req.size()); |
||||||
|
event = req.get(0); |
||||||
|
assertEquals("GET", event.getMethod()); |
||||||
|
assertEquals(0, event.getParameters().size()); |
||||||
|
assertEquals("no-cache", event.getRequestHeader(HDR_PRAGMA)); |
||||||
|
assertNotNull("has user-agent", event.getRequestHeader(HDR_USER_AGENT)); |
||||||
|
assertTrue("is jgit agent", event.getRequestHeader(HDR_USER_AGENT) |
||||||
|
.startsWith("JGit/")); |
||||||
|
assertEquals(200, event.getStatus()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testPushNotSupported() throws Exception { |
||||||
|
final TestRepository src = createTestRepository(); |
||||||
|
final RevCommit Q = src.commit().create(); |
||||||
|
final Repository db = src.getRepository(); |
||||||
|
|
||||||
|
Transport t = Transport.open(db, remoteURI); |
||||||
|
try { |
||||||
|
try { |
||||||
|
t.push(NullProgressMonitor.INSTANCE, push(src, Q)); |
||||||
|
fail("push incorrectly completed against a dumb server"); |
||||||
|
} catch (NotSupportedException nse) { |
||||||
|
String exp = "remote does not support smart HTTP push"; |
||||||
|
assertEquals(exp, nse.getMessage()); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,261 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2010, 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.http.test; |
||||||
|
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT; |
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE; |
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_PRAGMA; |
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_USER_AGENT; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler; |
||||||
|
import org.eclipse.jetty.servlet.ServletHolder; |
||||||
|
import org.eclipse.jgit.errors.NotSupportedException; |
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException; |
||||||
|
import org.eclipse.jgit.http.server.GitServlet; |
||||||
|
import org.eclipse.jgit.http.server.resolver.RepositoryResolver; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException; |
||||||
|
import org.eclipse.jgit.http.test.util.AccessEvent; |
||||||
|
import org.eclipse.jgit.http.test.util.HttpTestCase; |
||||||
|
import org.eclipse.jgit.junit.TestRepository; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.NullProgressMonitor; |
||||||
|
import org.eclipse.jgit.lib.Ref; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.revwalk.RevBlob; |
||||||
|
import org.eclipse.jgit.revwalk.RevCommit; |
||||||
|
import org.eclipse.jgit.transport.FetchConnection; |
||||||
|
import org.eclipse.jgit.transport.HttpTransport; |
||||||
|
import org.eclipse.jgit.transport.Transport; |
||||||
|
import org.eclipse.jgit.transport.TransportHttp; |
||||||
|
import org.eclipse.jgit.transport.URIish; |
||||||
|
|
||||||
|
public class DumbClientSmartServerTest extends HttpTestCase { |
||||||
|
private Repository remoteRepository; |
||||||
|
|
||||||
|
private URIish remoteURI; |
||||||
|
|
||||||
|
private RevBlob A_txt; |
||||||
|
|
||||||
|
private RevCommit A, B; |
||||||
|
|
||||||
|
protected void setUp() throws Exception { |
||||||
|
super.setUp(); |
||||||
|
|
||||||
|
final TestRepository src = createTestRepository(); |
||||||
|
final String srcName = src.getRepository().getDirectory().getName(); |
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/git"); |
||||||
|
GitServlet gs = new GitServlet(); |
||||||
|
gs.setRepositoryResolver(new RepositoryResolver() { |
||||||
|
public Repository open(HttpServletRequest req, String name) |
||||||
|
throws RepositoryNotFoundException, |
||||||
|
ServiceNotEnabledException { |
||||||
|
if (!name.equals(srcName)) |
||||||
|
throw new RepositoryNotFoundException(name); |
||||||
|
|
||||||
|
final Repository db = src.getRepository(); |
||||||
|
db.incrementOpen(); |
||||||
|
return db; |
||||||
|
} |
||||||
|
}); |
||||||
|
app.addServlet(new ServletHolder(gs), "/*"); |
||||||
|
|
||||||
|
server.setUp(); |
||||||
|
|
||||||
|
remoteRepository = src.getRepository(); |
||||||
|
remoteURI = toURIish(app, srcName); |
||||||
|
|
||||||
|
A_txt = src.blob("A"); |
||||||
|
A = src.commit().add("A_txt", A_txt).create(); |
||||||
|
B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create(); |
||||||
|
src.update(master, B); |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote() throws IOException { |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
|
||||||
|
assertEquals("http", remoteURI.getScheme()); |
||||||
|
|
||||||
|
Map<String, Ref> map; |
||||||
|
Transport t = Transport.open(dst, remoteURI); |
||||||
|
((TransportHttp) t).setUseSmartHttp(false); |
||||||
|
try { |
||||||
|
// I didn't make up these public interface names, I just
|
||||||
|
// approved them for inclusion into the code base. Sorry.
|
||||||
|
// --spearce
|
||||||
|
//
|
||||||
|
assertTrue("isa TransportHttp", t instanceof TransportHttp); |
||||||
|
assertTrue("isa HttpTransport", t instanceof HttpTransport); |
||||||
|
|
||||||
|
FetchConnection c = t.openFetch(); |
||||||
|
try { |
||||||
|
map = c.getRefsMap(); |
||||||
|
} finally { |
||||||
|
c.close(); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertNotNull("have map of refs", map); |
||||||
|
assertEquals(2, map.size()); |
||||||
|
|
||||||
|
assertNotNull("has " + master, map.get(master)); |
||||||
|
assertEquals(B, map.get(master).getObjectId()); |
||||||
|
|
||||||
|
assertNotNull("has " + Constants.HEAD, map.get(Constants.HEAD)); |
||||||
|
assertEquals(B, map.get(Constants.HEAD).getObjectId()); |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
assertEquals(2, requests.size()); |
||||||
|
assertEquals(0, getRequests(remoteURI, "git-upload-pack").size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath()); |
||||||
|
assertEquals(0, info.getParameters().size()); |
||||||
|
assertNull("no service parameter", info.getParameter("service")); |
||||||
|
assertEquals("no-cache", info.getRequestHeader(HDR_PRAGMA)); |
||||||
|
assertNotNull("has user-agent", info.getRequestHeader(HDR_USER_AGENT)); |
||||||
|
assertTrue("is jgit agent", info.getRequestHeader(HDR_USER_AGENT) |
||||||
|
.startsWith("JGit/")); |
||||||
|
assertEquals("*/*", info.getRequestHeader(HDR_ACCEPT)); |
||||||
|
assertEquals(200, info.getStatus()); |
||||||
|
assertEquals("text/plain;charset=UTF-8", info |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
|
||||||
|
AccessEvent head = requests.get(1); |
||||||
|
assertEquals("GET", head.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "HEAD"), head.getPath()); |
||||||
|
assertEquals(0, head.getParameters().size()); |
||||||
|
assertEquals(200, head.getStatus()); |
||||||
|
assertEquals("text/plain", head.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInitialClone_Small() throws Exception { |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
assertFalse(dst.hasObject(A_txt)); |
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI); |
||||||
|
((TransportHttp) t).setUseSmartHttp(false); |
||||||
|
try { |
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt)); |
||||||
|
assertEquals(B, dst.getRef(master).getObjectId()); |
||||||
|
fsck(dst, B); |
||||||
|
|
||||||
|
List<AccessEvent> loose = getRequests(loose(remoteURI, A_txt)); |
||||||
|
assertEquals(1, loose.size()); |
||||||
|
assertEquals("GET", loose.get(0).getMethod()); |
||||||
|
assertEquals(0, loose.get(0).getParameters().size()); |
||||||
|
assertEquals(200, loose.get(0).getStatus()); |
||||||
|
assertEquals("application/x-git-loose-object", loose.get(0) |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInitialClone_Packed() throws Exception { |
||||||
|
new TestRepository(remoteRepository).packAndPrune(); |
||||||
|
|
||||||
|
Repository dst = createBareRepository(); |
||||||
|
assertFalse(dst.hasObject(A_txt)); |
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI); |
||||||
|
((TransportHttp) t).setUseSmartHttp(false); |
||||||
|
try { |
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt)); |
||||||
|
assertEquals(B, dst.getRef(master).getObjectId()); |
||||||
|
fsck(dst, B); |
||||||
|
|
||||||
|
List<AccessEvent> req; |
||||||
|
|
||||||
|
req = getRequests(loose(remoteURI, B)); |
||||||
|
assertEquals(1, req.size()); |
||||||
|
assertEquals("GET", req.get(0).getMethod()); |
||||||
|
assertEquals(0, req.get(0).getParameters().size()); |
||||||
|
assertEquals(404, req.get(0).getStatus()); |
||||||
|
|
||||||
|
req = getRequests(join(remoteURI, "objects/info/packs")); |
||||||
|
assertEquals(1, req.size()); |
||||||
|
assertEquals("GET", req.get(0).getMethod()); |
||||||
|
assertEquals(0, req.get(0).getParameters().size()); |
||||||
|
assertEquals(200, req.get(0).getStatus()); |
||||||
|
assertEquals("text/plain;charset=UTF-8", req.get(0).getResponseHeader( |
||||||
|
HDR_CONTENT_TYPE)); |
||||||
|
} |
||||||
|
|
||||||
|
public void testPushNotSupported() throws Exception { |
||||||
|
final TestRepository src = createTestRepository(); |
||||||
|
final RevCommit Q = src.commit().create(); |
||||||
|
final Repository db = src.getRepository(); |
||||||
|
|
||||||
|
Transport t = Transport.open(db, remoteURI); |
||||||
|
((TransportHttp) t).setUseSmartHttp(false); |
||||||
|
try { |
||||||
|
try { |
||||||
|
t.push(NullProgressMonitor.INSTANCE, push(src, Q)); |
||||||
|
fail("push incorrectly completed against a smart server"); |
||||||
|
} catch (NotSupportedException nse) { |
||||||
|
String exp = "smart HTTP push disabled"; |
||||||
|
assertEquals(exp, nse.getMessage()); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,85 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2009-2010, 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.http.test; |
||||||
|
|
||||||
|
import java.net.HttpURLConnection; |
||||||
|
import java.net.URI; |
||||||
|
|
||||||
|
import junit.framework.TestCase; |
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler; |
||||||
|
import org.eclipse.jetty.servlet.ServletHolder; |
||||||
|
import org.eclipse.jgit.http.server.glue.ErrorServlet; |
||||||
|
import org.eclipse.jgit.http.test.util.AppServer; |
||||||
|
|
||||||
|
public class ErrorServletTest extends TestCase { |
||||||
|
private AppServer server; |
||||||
|
|
||||||
|
protected void setUp() throws Exception { |
||||||
|
super.setUp(); |
||||||
|
|
||||||
|
server = new AppServer(); |
||||||
|
|
||||||
|
ServletContextHandler ctx = server.addContext("/"); |
||||||
|
ctx.addServlet(new ServletHolder(new ErrorServlet(404)), "/404"); |
||||||
|
ctx.addServlet(new ServletHolder(new ErrorServlet(500)), "/500"); |
||||||
|
|
||||||
|
server.setUp(); |
||||||
|
} |
||||||
|
|
||||||
|
protected void tearDown() throws Exception { |
||||||
|
if (server != null) { |
||||||
|
server.tearDown(); |
||||||
|
} |
||||||
|
super.tearDown(); |
||||||
|
} |
||||||
|
|
||||||
|
public void testHandler() throws Exception { |
||||||
|
final URI uri = server.getURI(); |
||||||
|
assertEquals(404, ((HttpURLConnection) uri.resolve("/404").toURL() |
||||||
|
.openConnection()).getResponseCode()); |
||||||
|
assertEquals(500, ((HttpURLConnection) uri.resolve("/500").toURL() |
||||||
|
.openConnection()).getResponseCode()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,137 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2010, 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.http.test; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException; |
||||||
|
import org.eclipse.jgit.http.server.resolver.FileResolver; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException; |
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
|
||||||
|
public class FileResolverTest extends LocalDiskRepositoryTestCase { |
||||||
|
public void testUnreasonableNames() throws ServiceNotEnabledException { |
||||||
|
assertUnreasonable(""); |
||||||
|
assertUnreasonable("a\\b"); |
||||||
|
assertUnreasonable("../b"); |
||||||
|
assertUnreasonable("a/../b"); |
||||||
|
assertUnreasonable("a/./b"); |
||||||
|
assertUnreasonable("a//b"); |
||||||
|
|
||||||
|
if (new File("/foo").isAbsolute()) |
||||||
|
assertUnreasonable("/foo"); |
||||||
|
|
||||||
|
if (new File("//server/share").isAbsolute()) |
||||||
|
assertUnreasonable("//server/share"); |
||||||
|
|
||||||
|
if (new File("C:/windows").isAbsolute()) |
||||||
|
assertUnreasonable("C:/windows"); |
||||||
|
} |
||||||
|
|
||||||
|
private void assertUnreasonable(String name) |
||||||
|
throws ServiceNotEnabledException { |
||||||
|
FileResolver r = new FileResolver(new File("."), false); |
||||||
|
try { |
||||||
|
r.open(null, name); |
||||||
|
fail("Opened unreasonable name \"" + name + "\""); |
||||||
|
} catch (RepositoryNotFoundException e) { |
||||||
|
assertEquals("repository not found: " + name, e.getMessage()); |
||||||
|
assertNull("has no cause", e.getCause()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testExportOk() throws IOException { |
||||||
|
final Repository a = createBareRepository(); |
||||||
|
final String name = a.getDirectory().getName(); |
||||||
|
final File base = a.getDirectory().getParentFile(); |
||||||
|
final File export = new File(a.getDirectory(), "git-daemon-export-ok"); |
||||||
|
FileResolver resolver; |
||||||
|
|
||||||
|
assertFalse("no git-daemon-export-ok", export.exists()); |
||||||
|
resolver = new FileResolver(base, false /* require flag */); |
||||||
|
try { |
||||||
|
resolver.open(null, name); |
||||||
|
fail("opened non-exported repository"); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
assertEquals("Service not enabled", e.getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
resolver = new FileResolver(base, true /* export all */); |
||||||
|
try { |
||||||
|
resolver.open(null, name).close(); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
fail("did not honor export-all flag"); |
||||||
|
} |
||||||
|
|
||||||
|
export.createNewFile(); |
||||||
|
assertTrue("has git-daemon-export-ok", export.exists()); |
||||||
|
resolver = new FileResolver(base, false /* require flag */); |
||||||
|
try { |
||||||
|
resolver.open(null, name).close(); |
||||||
|
} catch (ServiceNotEnabledException e) { |
||||||
|
fail("did not honor git-daemon-export-ok"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testNotAGitRepository() throws IOException, |
||||||
|
ServiceNotEnabledException { |
||||||
|
final Repository a = createBareRepository(); |
||||||
|
final String name = a.getDirectory().getName() + "-not-a-git"; |
||||||
|
final File base = a.getDirectory().getParentFile(); |
||||||
|
FileResolver resolver = new FileResolver(base, false); |
||||||
|
|
||||||
|
try { |
||||||
|
resolver.open(null, name); |
||||||
|
} catch (RepositoryNotFoundException e) { |
||||||
|
assertEquals("repository not found: " + name, e.getMessage()); |
||||||
|
|
||||||
|
Throwable why = e.getCause(); |
||||||
|
assertNotNull("has cause", why); |
||||||
|
assertEquals("repository not found: " |
||||||
|
+ new File(base, name).getAbsolutePath(), why.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,119 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2010, 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.http.test; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import javax.servlet.ServletException; |
||||||
|
|
||||||
|
import junit.framework.TestCase; |
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler; |
||||||
|
import org.eclipse.jetty.servlet.ServletHolder; |
||||||
|
import org.eclipse.jgit.http.server.GitServlet; |
||||||
|
import org.eclipse.jgit.http.test.util.AppServer; |
||||||
|
import org.eclipse.jgit.http.test.util.MockServletConfig; |
||||||
|
import org.eclipse.jgit.http.test.util.RecordingLogger; |
||||||
|
|
||||||
|
public class GitServletInitTest extends TestCase { |
||||||
|
private AppServer server; |
||||||
|
|
||||||
|
protected void tearDown() throws Exception { |
||||||
|
if (server != null) { |
||||||
|
server.tearDown(); |
||||||
|
server = null; |
||||||
|
} |
||||||
|
super.tearDown(); |
||||||
|
} |
||||||
|
|
||||||
|
public void testDefaultConstructor_NoBasePath() throws Exception { |
||||||
|
GitServlet s = new GitServlet(); |
||||||
|
try { |
||||||
|
s.init(new MockServletConfig()); |
||||||
|
fail("Init did not crash due to missing parameter"); |
||||||
|
} catch (ServletException e) { |
||||||
|
assertTrue(e.getMessage().contains("base-path")); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testDefaultConstructor_WithBasePath() throws Exception { |
||||||
|
MockServletConfig c = new MockServletConfig(); |
||||||
|
c.setInitParameter("base-path", "."); |
||||||
|
c.setInitParameter("export-all", "false"); |
||||||
|
|
||||||
|
GitServlet s = new GitServlet(); |
||||||
|
s.init(c); |
||||||
|
s.destroy(); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInitUnderContainer_NoBasePath() throws Exception { |
||||||
|
server = new AppServer(); |
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/"); |
||||||
|
ServletHolder s = app.addServlet(GitServlet.class, "/git"); |
||||||
|
s.setInitOrder(1); |
||||||
|
|
||||||
|
server.setUp(); |
||||||
|
|
||||||
|
List<RecordingLogger.Warning> events = RecordingLogger.getWarnings(); |
||||||
|
assertFalse("Servlet started without base-path", events.isEmpty()); |
||||||
|
|
||||||
|
Throwable why = events.get(0).getCause(); |
||||||
|
assertTrue("Caught ServletException", why instanceof ServletException); |
||||||
|
assertTrue("Wanted base-path", why.getMessage().contains("base-path")); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInitUnderContainer_WithBasePath() throws Exception { |
||||||
|
server = new AppServer(); |
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/"); |
||||||
|
ServletHolder s = app.addServlet(GitServlet.class, "/git"); |
||||||
|
s.setInitOrder(1); |
||||||
|
s.setInitParameter("base-path", "."); |
||||||
|
s.setInitParameter("export-all", "true"); |
||||||
|
|
||||||
|
server.setUp(); |
||||||
|
assertTrue("no warnings", RecordingLogger.getWarnings().isEmpty()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,328 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2009-2010, 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.http.test; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.net.URI; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.DefaultServlet; |
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler; |
||||||
|
import org.eclipse.jetty.servlet.ServletHolder; |
||||||
|
import org.eclipse.jgit.errors.NoRemoteRepositoryException; |
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException; |
||||||
|
import org.eclipse.jgit.errors.TransportException; |
||||||
|
import org.eclipse.jgit.http.server.GitServlet; |
||||||
|
import org.eclipse.jgit.http.server.resolver.RepositoryResolver; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException; |
||||||
|
import org.eclipse.jgit.http.test.util.AccessEvent; |
||||||
|
import org.eclipse.jgit.http.test.util.HttpTestCase; |
||||||
|
import org.eclipse.jgit.junit.TestRepository; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.Ref; |
||||||
|
import org.eclipse.jgit.lib.RefUpdate; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.revwalk.RevCommit; |
||||||
|
import org.eclipse.jgit.transport.FetchConnection; |
||||||
|
import org.eclipse.jgit.transport.Transport; |
||||||
|
import org.eclipse.jgit.transport.URIish; |
||||||
|
|
||||||
|
public class HttpClientTests extends HttpTestCase { |
||||||
|
private TestRepository remoteRepository; |
||||||
|
|
||||||
|
private URIish dumbAuthNoneURI; |
||||||
|
|
||||||
|
private URIish dumbAuthBasicURI; |
||||||
|
|
||||||
|
private URIish smartAuthNoneURI; |
||||||
|
|
||||||
|
private URIish smartAuthBasicURI; |
||||||
|
|
||||||
|
protected void setUp() throws Exception { |
||||||
|
super.setUp(); |
||||||
|
|
||||||
|
remoteRepository = createTestRepository(); |
||||||
|
remoteRepository.update(master, remoteRepository.commit().create()); |
||||||
|
|
||||||
|
ServletContextHandler dNone = dumb("/dnone"); |
||||||
|
ServletContextHandler dBasic = server.authBasic(dumb("/dbasic")); |
||||||
|
|
||||||
|
ServletContextHandler sNone = smart("/snone"); |
||||||
|
ServletContextHandler sBasic = server.authBasic(smart("/sbasic")); |
||||||
|
|
||||||
|
server.setUp(); |
||||||
|
|
||||||
|
final String srcName = nameOf(remoteRepository); |
||||||
|
dumbAuthNoneURI = toURIish(dNone, srcName); |
||||||
|
dumbAuthBasicURI = toURIish(dBasic, srcName); |
||||||
|
|
||||||
|
smartAuthNoneURI = toURIish(sNone, srcName); |
||||||
|
smartAuthBasicURI = toURIish(sBasic, srcName); |
||||||
|
} |
||||||
|
|
||||||
|
private ServletContextHandler dumb(final String path) { |
||||||
|
final File srcGit = remoteRepository.getRepository().getDirectory(); |
||||||
|
final URI base = srcGit.getParentFile().toURI(); |
||||||
|
|
||||||
|
ServletContextHandler ctx = server.addContext(path); |
||||||
|
ctx.setResourceBase(base.toString()); |
||||||
|
ctx.addServlet(DefaultServlet.class, "/"); |
||||||
|
return ctx; |
||||||
|
} |
||||||
|
|
||||||
|
private ServletContextHandler smart(final String path) { |
||||||
|
GitServlet gs = new GitServlet(); |
||||||
|
gs.setRepositoryResolver(new RepositoryResolver() { |
||||||
|
public Repository open(HttpServletRequest req, String name) |
||||||
|
throws RepositoryNotFoundException, |
||||||
|
ServiceNotEnabledException { |
||||||
|
if (!name.equals(nameOf(remoteRepository))) |
||||||
|
throw new RepositoryNotFoundException(name); |
||||||
|
|
||||||
|
final Repository db = remoteRepository.getRepository(); |
||||||
|
db.incrementOpen(); |
||||||
|
return db; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
ServletContextHandler ctx = server.addContext(path); |
||||||
|
ctx.addServlet(new ServletHolder(gs), "/*"); |
||||||
|
return ctx; |
||||||
|
} |
||||||
|
|
||||||
|
private static String nameOf(final TestRepository db) { |
||||||
|
return db.getRepository().getDirectory().getName(); |
||||||
|
} |
||||||
|
|
||||||
|
public void testRepositoryNotFound_Dumb() throws Exception { |
||||||
|
URIish uri = toURIish("/dumb.none/not-found"); |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
Transport t = Transport.open(dst, uri); |
||||||
|
try { |
||||||
|
try { |
||||||
|
t.openFetch(); |
||||||
|
fail("connection opened to not found repository"); |
||||||
|
} catch (NoRemoteRepositoryException err) { |
||||||
|
String exp = uri + ": " + uri |
||||||
|
+ "/info/refs?service=git-upload-pack not found"; |
||||||
|
assertEquals(exp, err.getMessage()); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testRepositoryNotFound_Smart() throws Exception { |
||||||
|
URIish uri = toURIish("/smart.none/not-found"); |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
Transport t = Transport.open(dst, uri); |
||||||
|
try { |
||||||
|
try { |
||||||
|
t.openFetch(); |
||||||
|
fail("connection opened to not found repository"); |
||||||
|
} catch (NoRemoteRepositoryException err) { |
||||||
|
String exp = uri + ": " + uri |
||||||
|
+ "/info/refs?service=git-upload-pack not found"; |
||||||
|
assertEquals(exp, err.getMessage()); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote_Dumb_DetachedHEAD() throws Exception { |
||||||
|
Repository src = remoteRepository.getRepository(); |
||||||
|
RefUpdate u = src.updateRef(Constants.HEAD, true); |
||||||
|
RevCommit Q = remoteRepository.commit().message("Q").create(); |
||||||
|
u.setNewObjectId(Q); |
||||||
|
assertEquals(RefUpdate.Result.FORCED, u.forceUpdate()); |
||||||
|
|
||||||
|
Repository dst = createBareRepository(); |
||||||
|
Ref head; |
||||||
|
Transport t = Transport.open(dst, dumbAuthNoneURI); |
||||||
|
try { |
||||||
|
FetchConnection c = t.openFetch(); |
||||||
|
try { |
||||||
|
head = c.getRef(Constants.HEAD); |
||||||
|
} finally { |
||||||
|
c.close(); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
assertNotNull("has " + Constants.HEAD, head); |
||||||
|
assertEquals(Q, head.getObjectId()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote_Dumb_NoHEAD() throws Exception { |
||||||
|
Repository src = remoteRepository.getRepository(); |
||||||
|
File headref = new File(src.getDirectory(), Constants.HEAD); |
||||||
|
assertTrue("HEAD used to be present", headref.delete()); |
||||||
|
assertFalse("HEAD is gone", headref.exists()); |
||||||
|
|
||||||
|
Repository dst = createBareRepository(); |
||||||
|
Ref head; |
||||||
|
Transport t = Transport.open(dst, dumbAuthNoneURI); |
||||||
|
try { |
||||||
|
FetchConnection c = t.openFetch(); |
||||||
|
try { |
||||||
|
head = c.getRef(Constants.HEAD); |
||||||
|
} finally { |
||||||
|
c.close(); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
assertNull("has no " + Constants.HEAD, head); |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote_Smart_DetachedHEAD() throws Exception { |
||||||
|
Repository src = remoteRepository.getRepository(); |
||||||
|
RefUpdate u = src.updateRef(Constants.HEAD, true); |
||||||
|
RevCommit Q = remoteRepository.commit().message("Q").create(); |
||||||
|
u.setNewObjectId(Q); |
||||||
|
assertEquals(RefUpdate.Result.FORCED, u.forceUpdate()); |
||||||
|
|
||||||
|
Repository dst = createBareRepository(); |
||||||
|
Ref head; |
||||||
|
Transport t = Transport.open(dst, smartAuthNoneURI); |
||||||
|
try { |
||||||
|
FetchConnection c = t.openFetch(); |
||||||
|
try { |
||||||
|
head = c.getRef(Constants.HEAD); |
||||||
|
} finally { |
||||||
|
c.close(); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
assertNotNull("has " + Constants.HEAD, head); |
||||||
|
assertEquals(Q, head.getObjectId()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote_Smart_WithQueryParameters() throws Exception { |
||||||
|
URIish myURI = toURIish("/snone/do?r=1&p=test.git"); |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
Transport t = Transport.open(dst, myURI); |
||||||
|
try { |
||||||
|
try { |
||||||
|
t.openFetch(); |
||||||
|
fail("test did not fail to find repository as expected"); |
||||||
|
} catch (NoRemoteRepositoryException err) { |
||||||
|
// expected
|
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
assertEquals(1, requests.size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals("/snone/do", info.getPath()); |
||||||
|
assertEquals(3, info.getParameters().size()); |
||||||
|
assertEquals("1", info.getParameter("r")); |
||||||
|
assertEquals("test.git/info/refs", info.getParameter("p")); |
||||||
|
assertEquals("git-upload-pack", info.getParameter("service")); |
||||||
|
assertEquals(404, info.getStatus()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote_Dumb_NeedsAuth() throws Exception { |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
Transport t = Transport.open(dst, dumbAuthBasicURI); |
||||||
|
try { |
||||||
|
try { |
||||||
|
t.openFetch(); |
||||||
|
fail("connection opened even info/refs needs auth basic"); |
||||||
|
} catch (TransportException err) { |
||||||
|
String status = "401 Unauthorized"; |
||||||
|
String exp = dumbAuthBasicURI + ": " + status; |
||||||
|
assertEquals(exp, err.getMessage()); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote_Smart_UploadPackNeedsAuth() throws Exception { |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
Transport t = Transport.open(dst, smartAuthBasicURI); |
||||||
|
try { |
||||||
|
try { |
||||||
|
t.openFetch(); |
||||||
|
fail("connection opened even though service disabled"); |
||||||
|
} catch (TransportException err) { |
||||||
|
String status = "401 Unauthorized"; |
||||||
|
String exp = smartAuthBasicURI + ": " + status; |
||||||
|
assertEquals(exp, err.getMessage()); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote_Smart_UploadPackDisabled() throws Exception { |
||||||
|
Repository src = remoteRepository.getRepository(); |
||||||
|
src.getConfig().setBoolean("http", null, "uploadpack", false); |
||||||
|
src.getConfig().save(); |
||||||
|
|
||||||
|
Repository dst = createBareRepository(); |
||||||
|
Transport t = Transport.open(dst, smartAuthNoneURI); |
||||||
|
try { |
||||||
|
try { |
||||||
|
t.openFetch(); |
||||||
|
fail("connection opened even though service disabled"); |
||||||
|
} catch (TransportException err) { |
||||||
|
String exp = smartAuthNoneURI |
||||||
|
+ ": git-upload-pack not permitted"; |
||||||
|
assertEquals(exp, err.getMessage()); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,556 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2009-2010, 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.http.test; |
||||||
|
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_ENCODING; |
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_LENGTH; |
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.PrintWriter; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import javax.servlet.Filter; |
||||||
|
import javax.servlet.FilterChain; |
||||||
|
import javax.servlet.FilterConfig; |
||||||
|
import javax.servlet.ServletException; |
||||||
|
import javax.servlet.ServletRequest; |
||||||
|
import javax.servlet.ServletResponse; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.FilterHolder; |
||||||
|
import org.eclipse.jetty.servlet.FilterMapping; |
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler; |
||||||
|
import org.eclipse.jetty.servlet.ServletHolder; |
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException; |
||||||
|
import org.eclipse.jgit.errors.TransportException; |
||||||
|
import org.eclipse.jgit.http.server.GitServlet; |
||||||
|
import org.eclipse.jgit.http.server.resolver.RepositoryResolver; |
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException; |
||||||
|
import org.eclipse.jgit.http.test.util.AccessEvent; |
||||||
|
import org.eclipse.jgit.http.test.util.HttpTestCase; |
||||||
|
import org.eclipse.jgit.junit.TestRepository; |
||||||
|
import org.eclipse.jgit.junit.TestRng; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.NullProgressMonitor; |
||||||
|
import org.eclipse.jgit.lib.ObjectId; |
||||||
|
import org.eclipse.jgit.lib.Ref; |
||||||
|
import org.eclipse.jgit.lib.ReflogReader; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.lib.RepositoryConfig; |
||||||
|
import org.eclipse.jgit.revwalk.RevBlob; |
||||||
|
import org.eclipse.jgit.revwalk.RevCommit; |
||||||
|
import org.eclipse.jgit.transport.FetchConnection; |
||||||
|
import org.eclipse.jgit.transport.HttpTransport; |
||||||
|
import org.eclipse.jgit.transport.RemoteRefUpdate; |
||||||
|
import org.eclipse.jgit.transport.Transport; |
||||||
|
import org.eclipse.jgit.transport.TransportHttp; |
||||||
|
import org.eclipse.jgit.transport.URIish; |
||||||
|
|
||||||
|
public class SmartClientSmartServerTest extends HttpTestCase { |
||||||
|
private static final String HDR_TRANSFER_ENCODING = "Transfer-Encoding"; |
||||||
|
|
||||||
|
private Repository remoteRepository; |
||||||
|
|
||||||
|
private URIish remoteURI; |
||||||
|
|
||||||
|
private URIish brokenURI; |
||||||
|
|
||||||
|
private RevBlob A_txt; |
||||||
|
|
||||||
|
private RevCommit A, B; |
||||||
|
|
||||||
|
protected void setUp() throws Exception { |
||||||
|
super.setUp(); |
||||||
|
|
||||||
|
final TestRepository src = createTestRepository(); |
||||||
|
final String srcName = src.getRepository().getDirectory().getName(); |
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/git"); |
||||||
|
GitServlet gs = new GitServlet(); |
||||||
|
gs.setRepositoryResolver(new RepositoryResolver() { |
||||||
|
public Repository open(HttpServletRequest req, String name) |
||||||
|
throws RepositoryNotFoundException, |
||||||
|
ServiceNotEnabledException { |
||||||
|
if (!name.equals(srcName)) |
||||||
|
throw new RepositoryNotFoundException(name); |
||||||
|
|
||||||
|
final Repository db = src.getRepository(); |
||||||
|
db.incrementOpen(); |
||||||
|
return db; |
||||||
|
} |
||||||
|
}); |
||||||
|
app.addServlet(new ServletHolder(gs), "/*"); |
||||||
|
|
||||||
|
ServletContextHandler broken = server.addContext("/bad"); |
||||||
|
broken.addFilter(new FilterHolder(new Filter() { |
||||||
|
public void doFilter(ServletRequest request, |
||||||
|
ServletResponse response, FilterChain chain) |
||||||
|
throws IOException, ServletException { |
||||||
|
final HttpServletResponse r = (HttpServletResponse) response; |
||||||
|
r.setContentType("text/plain"); |
||||||
|
r.setCharacterEncoding("UTF-8"); |
||||||
|
PrintWriter w = r.getWriter(); |
||||||
|
w.print("OK"); |
||||||
|
w.close(); |
||||||
|
} |
||||||
|
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException { |
||||||
|
//
|
||||||
|
} |
||||||
|
|
||||||
|
public void destroy() { |
||||||
|
//
|
||||||
|
} |
||||||
|
}), "/" + srcName + "/git-upload-pack", FilterMapping.DEFAULT); |
||||||
|
broken.addServlet(new ServletHolder(gs), "/*"); |
||||||
|
|
||||||
|
server.setUp(); |
||||||
|
|
||||||
|
remoteRepository = src.getRepository(); |
||||||
|
remoteURI = toURIish(app, srcName); |
||||||
|
brokenURI = toURIish(broken, srcName); |
||||||
|
|
||||||
|
A_txt = src.blob("A"); |
||||||
|
A = src.commit().add("A_txt", A_txt).create(); |
||||||
|
B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create(); |
||||||
|
src.update(master, B); |
||||||
|
|
||||||
|
src.update("refs/garbage/a/very/long/ref/name/to/compress", B); |
||||||
|
} |
||||||
|
|
||||||
|
public void testListRemote() throws IOException { |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
|
||||||
|
assertEquals("http", remoteURI.getScheme()); |
||||||
|
|
||||||
|
Map<String, Ref> map; |
||||||
|
Transport t = Transport.open(dst, remoteURI); |
||||||
|
try { |
||||||
|
// I didn't make up these public interface names, I just
|
||||||
|
// approved them for inclusion into the code base. Sorry.
|
||||||
|
// --spearce
|
||||||
|
//
|
||||||
|
assertTrue("isa TransportHttp", t instanceof TransportHttp); |
||||||
|
assertTrue("isa HttpTransport", t instanceof HttpTransport); |
||||||
|
|
||||||
|
FetchConnection c = t.openFetch(); |
||||||
|
try { |
||||||
|
map = c.getRefsMap(); |
||||||
|
} finally { |
||||||
|
c.close(); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertNotNull("have map of refs", map); |
||||||
|
assertEquals(3, map.size()); |
||||||
|
|
||||||
|
assertNotNull("has " + master, map.get(master)); |
||||||
|
assertEquals(B, map.get(master).getObjectId()); |
||||||
|
|
||||||
|
assertNotNull("has " + Constants.HEAD, map.get(Constants.HEAD)); |
||||||
|
assertEquals(B, map.get(Constants.HEAD).getObjectId()); |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
assertEquals(1, requests.size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath()); |
||||||
|
assertEquals(1, info.getParameters().size()); |
||||||
|
assertEquals("git-upload-pack", info.getParameter("service")); |
||||||
|
assertEquals(200, info.getStatus()); |
||||||
|
assertEquals("application/x-git-upload-pack-advertisement", info |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING)); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInitialClone_Small() throws Exception { |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
assertFalse(dst.hasObject(A_txt)); |
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI); |
||||||
|
try { |
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt)); |
||||||
|
assertEquals(B, dst.getRef(master).getObjectId()); |
||||||
|
fsck(dst, B); |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
assertEquals(2, requests.size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath()); |
||||||
|
assertEquals(1, info.getParameters().size()); |
||||||
|
assertEquals("git-upload-pack", info.getParameter("service")); |
||||||
|
assertEquals(200, info.getStatus()); |
||||||
|
assertEquals("application/x-git-upload-pack-advertisement", info |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING)); |
||||||
|
|
||||||
|
AccessEvent service = requests.get(1); |
||||||
|
assertEquals("POST", service.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "git-upload-pack"), service.getPath()); |
||||||
|
assertEquals(0, service.getParameters().size()); |
||||||
|
assertNotNull("has content-length", service |
||||||
|
.getRequestHeader(HDR_CONTENT_LENGTH)); |
||||||
|
assertNull("not chunked", service |
||||||
|
.getRequestHeader(HDR_TRANSFER_ENCODING)); |
||||||
|
assertNull("no compression (too small)", service |
||||||
|
.getRequestHeader(HDR_CONTENT_ENCODING)); |
||||||
|
|
||||||
|
assertEquals(200, service.getStatus()); |
||||||
|
assertEquals("application/x-git-upload-pack-result", service |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
assertNull("no compression (never compressed)", service |
||||||
|
.getResponseHeader(HDR_CONTENT_ENCODING)); |
||||||
|
} |
||||||
|
|
||||||
|
public void testFetchUpdateExisting() throws Exception { |
||||||
|
// Bootstrap by doing the clone.
|
||||||
|
//
|
||||||
|
TestRepository dst = createTestRepository(); |
||||||
|
Transport t = Transport.open(dst.getRepository(), remoteURI); |
||||||
|
try { |
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
assertEquals(B, dst.getRepository().getRef(master).getObjectId()); |
||||||
|
List<AccessEvent> cloneRequests = getRequests(); |
||||||
|
|
||||||
|
// Force enough into the local client that enumeration will
|
||||||
|
// need multiple packets, but not too many to overflow and
|
||||||
|
// not pick up the ACK_COMMON message.
|
||||||
|
//
|
||||||
|
TestRepository.BranchBuilder b = dst.branch(master); |
||||||
|
for (int i = 0; i < 32 - 1; i++) |
||||||
|
b.commit().tick(3600 /* 1 hour */).message("c" + i).create(); |
||||||
|
|
||||||
|
// Create a new commit on the remote.
|
||||||
|
//
|
||||||
|
b = new TestRepository(remoteRepository).branch(master); |
||||||
|
RevCommit Z = b.commit().message("Z").create(); |
||||||
|
|
||||||
|
// Now incrementally update.
|
||||||
|
//
|
||||||
|
t = Transport.open(dst.getRepository(), remoteURI); |
||||||
|
try { |
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
assertEquals(Z, dst.getRepository().getRef(master).getObjectId()); |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
requests.removeAll(cloneRequests); |
||||||
|
assertEquals(3, requests.size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath()); |
||||||
|
assertEquals(1, info.getParameters().size()); |
||||||
|
assertEquals("git-upload-pack", info.getParameter("service")); |
||||||
|
assertEquals(200, info.getStatus()); |
||||||
|
assertEquals("application/x-git-upload-pack-advertisement", info |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
|
||||||
|
// We should have needed two requests to perform the fetch
|
||||||
|
// due to the high number of local unknown commits.
|
||||||
|
//
|
||||||
|
AccessEvent service = requests.get(1); |
||||||
|
assertEquals("POST", service.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "git-upload-pack"), service.getPath()); |
||||||
|
assertEquals(0, service.getParameters().size()); |
||||||
|
assertNotNull("has content-length", service |
||||||
|
.getRequestHeader(HDR_CONTENT_LENGTH)); |
||||||
|
assertNull("not chunked", service |
||||||
|
.getRequestHeader(HDR_TRANSFER_ENCODING)); |
||||||
|
|
||||||
|
assertEquals(200, service.getStatus()); |
||||||
|
assertEquals("application/x-git-upload-pack-result", service |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
|
||||||
|
service = requests.get(2); |
||||||
|
assertEquals("POST", service.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "git-upload-pack"), service.getPath()); |
||||||
|
assertEquals(0, service.getParameters().size()); |
||||||
|
assertNotNull("has content-length", service |
||||||
|
.getRequestHeader(HDR_CONTENT_LENGTH)); |
||||||
|
assertNull("not chunked", service |
||||||
|
.getRequestHeader(HDR_TRANSFER_ENCODING)); |
||||||
|
|
||||||
|
assertEquals(200, service.getStatus()); |
||||||
|
assertEquals("application/x-git-upload-pack-result", service |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInitialClone_BrokenServer() throws Exception { |
||||||
|
Repository dst = createBareRepository(); |
||||||
|
assertFalse(dst.hasObject(A_txt)); |
||||||
|
|
||||||
|
Transport t = Transport.open(dst, brokenURI); |
||||||
|
try { |
||||||
|
try { |
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); |
||||||
|
fail("fetch completed despite upload-pack being broken"); |
||||||
|
} catch (TransportException err) { |
||||||
|
String exp = brokenURI + ": expected" |
||||||
|
+ " Content-Type application/x-git-upload-pack-result;" |
||||||
|
+ " received Content-Type text/plain;charset=UTF-8"; |
||||||
|
assertEquals(exp, err.getMessage()); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
assertEquals(2, requests.size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals(join(brokenURI, "info/refs"), info.getPath()); |
||||||
|
assertEquals(1, info.getParameters().size()); |
||||||
|
assertEquals("git-upload-pack", info.getParameter("service")); |
||||||
|
assertEquals(200, info.getStatus()); |
||||||
|
assertEquals("application/x-git-upload-pack-advertisement", info |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
|
||||||
|
AccessEvent service = requests.get(1); |
||||||
|
assertEquals("POST", service.getMethod()); |
||||||
|
assertEquals(join(brokenURI, "git-upload-pack"), service.getPath()); |
||||||
|
assertEquals(0, service.getParameters().size()); |
||||||
|
assertEquals(200, service.getStatus()); |
||||||
|
assertEquals("text/plain;charset=UTF-8", service |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
} |
||||||
|
|
||||||
|
public void testPush_NotAuthorized() throws Exception { |
||||||
|
final TestRepository src = createTestRepository(); |
||||||
|
final RevBlob Q_txt = src.blob("new text"); |
||||||
|
final RevCommit Q = src.commit().add("Q", Q_txt).create(); |
||||||
|
final Repository db = src.getRepository(); |
||||||
|
final String dstName = Constants.R_HEADS + "new.branch"; |
||||||
|
Transport t; |
||||||
|
|
||||||
|
// push anonymous shouldn't be allowed.
|
||||||
|
//
|
||||||
|
t = Transport.open(db, remoteURI); |
||||||
|
try { |
||||||
|
final String srcExpr = Q.name(); |
||||||
|
final boolean forceUpdate = false; |
||||||
|
final String localName = null; |
||||||
|
final ObjectId oldId = null; |
||||||
|
|
||||||
|
RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(), |
||||||
|
srcExpr, dstName, forceUpdate, localName, oldId); |
||||||
|
try { |
||||||
|
t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u)); |
||||||
|
fail("anonymous push incorrectly accepted without error"); |
||||||
|
} catch (TransportException e) { |
||||||
|
final String status = "401 Unauthorized"; |
||||||
|
final String exp = remoteURI.toString() + ": " + status; |
||||||
|
assertEquals(exp, e.getMessage()); |
||||||
|
} |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
assertEquals(1, requests.size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath()); |
||||||
|
assertEquals(1, info.getParameters().size()); |
||||||
|
assertEquals("git-receive-pack", info.getParameter("service")); |
||||||
|
assertEquals(401, info.getStatus()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testPush_CreateBranch() throws Exception { |
||||||
|
final TestRepository src = createTestRepository(); |
||||||
|
final RevBlob Q_txt = src.blob("new text"); |
||||||
|
final RevCommit Q = src.commit().add("Q", Q_txt).create(); |
||||||
|
final Repository db = src.getRepository(); |
||||||
|
final String dstName = Constants.R_HEADS + "new.branch"; |
||||||
|
Transport t; |
||||||
|
|
||||||
|
enableReceivePack(); |
||||||
|
|
||||||
|
t = Transport.open(db, remoteURI); |
||||||
|
try { |
||||||
|
final String srcExpr = Q.name(); |
||||||
|
final boolean forceUpdate = false; |
||||||
|
final String localName = null; |
||||||
|
final ObjectId oldId = null; |
||||||
|
|
||||||
|
RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(), |
||||||
|
srcExpr, dstName, forceUpdate, localName, oldId); |
||||||
|
t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u)); |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertTrue(remoteRepository.hasObject(Q_txt)); |
||||||
|
assertNotNull("has " + dstName, remoteRepository.getRef(dstName)); |
||||||
|
assertEquals(Q, remoteRepository.getRef(dstName).getObjectId()); |
||||||
|
fsck(remoteRepository, Q); |
||||||
|
|
||||||
|
final ReflogReader log = remoteRepository.getReflogReader(dstName); |
||||||
|
assertNotNull("has log for " + dstName); |
||||||
|
|
||||||
|
final ReflogReader.Entry last = log.getLastEntry(); |
||||||
|
assertNotNull("has last entry", last); |
||||||
|
assertEquals(ObjectId.zeroId(), last.getOldId()); |
||||||
|
assertEquals(Q, last.getNewId()); |
||||||
|
assertEquals("anonymous", last.getWho().getName()); |
||||||
|
|
||||||
|
// Assumption: The host name we use to contact the server should
|
||||||
|
// be the server's own host name, because it should be the loopback
|
||||||
|
// network interface.
|
||||||
|
//
|
||||||
|
final String clientHost = remoteURI.getHost(); |
||||||
|
assertEquals("anonymous@" + clientHost, last.getWho().getEmailAddress()); |
||||||
|
assertEquals("push: created", last.getComment()); |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
assertEquals(2, requests.size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath()); |
||||||
|
assertEquals(1, info.getParameters().size()); |
||||||
|
assertEquals("git-receive-pack", info.getParameter("service")); |
||||||
|
assertEquals(200, info.getStatus()); |
||||||
|
assertEquals("application/x-git-receive-pack-advertisement", info |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
|
||||||
|
AccessEvent service = requests.get(1); |
||||||
|
assertEquals("POST", service.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "git-receive-pack"), service.getPath()); |
||||||
|
assertEquals(0, service.getParameters().size()); |
||||||
|
assertNotNull("has content-length", service |
||||||
|
.getRequestHeader(HDR_CONTENT_LENGTH)); |
||||||
|
assertNull("not chunked", service |
||||||
|
.getRequestHeader(HDR_TRANSFER_ENCODING)); |
||||||
|
|
||||||
|
assertEquals(200, service.getStatus()); |
||||||
|
assertEquals("application/x-git-receive-pack-result", service |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
} |
||||||
|
|
||||||
|
public void testPush_ChunkedEncoding() throws Exception { |
||||||
|
final TestRepository src = createTestRepository(); |
||||||
|
final RevBlob Q_bin = src.blob(new TestRng("Q").nextBytes(128 * 1024)); |
||||||
|
final RevCommit Q = src.commit().add("Q", Q_bin).create(); |
||||||
|
final Repository db = src.getRepository(); |
||||||
|
final String dstName = Constants.R_HEADS + "new.branch"; |
||||||
|
Transport t; |
||||||
|
|
||||||
|
enableReceivePack(); |
||||||
|
|
||||||
|
db.getConfig().setInt("core", null, "compression", 0); |
||||||
|
db.getConfig().setInt("http", null, "postbuffer", 8 * 1024); |
||||||
|
db.getConfig().save(); |
||||||
|
|
||||||
|
t = Transport.open(db, remoteURI); |
||||||
|
try { |
||||||
|
final String srcExpr = Q.name(); |
||||||
|
final boolean forceUpdate = false; |
||||||
|
final String localName = null; |
||||||
|
final ObjectId oldId = null; |
||||||
|
|
||||||
|
RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(), |
||||||
|
srcExpr, dstName, forceUpdate, localName, oldId); |
||||||
|
t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u)); |
||||||
|
} finally { |
||||||
|
t.close(); |
||||||
|
} |
||||||
|
|
||||||
|
assertTrue(remoteRepository.hasObject(Q_bin)); |
||||||
|
assertNotNull("has " + dstName, remoteRepository.getRef(dstName)); |
||||||
|
assertEquals(Q, remoteRepository.getRef(dstName).getObjectId()); |
||||||
|
fsck(remoteRepository, Q); |
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests(); |
||||||
|
assertEquals(2, requests.size()); |
||||||
|
|
||||||
|
AccessEvent info = requests.get(0); |
||||||
|
assertEquals("GET", info.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath()); |
||||||
|
assertEquals(1, info.getParameters().size()); |
||||||
|
assertEquals("git-receive-pack", info.getParameter("service")); |
||||||
|
assertEquals(200, info.getStatus()); |
||||||
|
assertEquals("application/x-git-receive-pack-advertisement", info |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
|
||||||
|
AccessEvent service = requests.get(1); |
||||||
|
assertEquals("POST", service.getMethod()); |
||||||
|
assertEquals(join(remoteURI, "git-receive-pack"), service.getPath()); |
||||||
|
assertEquals(0, service.getParameters().size()); |
||||||
|
assertNull("no content-length", service |
||||||
|
.getRequestHeader(HDR_CONTENT_LENGTH)); |
||||||
|
assertEquals("chunked", service.getRequestHeader(HDR_TRANSFER_ENCODING)); |
||||||
|
|
||||||
|
assertEquals(200, service.getStatus()); |
||||||
|
assertEquals("application/x-git-receive-pack-result", service |
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE)); |
||||||
|
} |
||||||
|
|
||||||
|
private void enableReceivePack() throws IOException { |
||||||
|
final RepositoryConfig cfg = remoteRepository.getConfig(); |
||||||
|
cfg.setBoolean("http", null, "receivepack", true); |
||||||
|
cfg.save(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,181 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2010, 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.http.test.util; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.TreeMap; |
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request; |
||||||
|
import org.eclipse.jetty.server.Response; |
||||||
|
|
||||||
|
/** A single request made through {@link AppServer}. */ |
||||||
|
public class AccessEvent { |
||||||
|
private final String method; |
||||||
|
|
||||||
|
private final String uri; |
||||||
|
|
||||||
|
private final Map<String, String> requestHeaders; |
||||||
|
|
||||||
|
private final Map<String, String[]> parameters; |
||||||
|
|
||||||
|
private final int status; |
||||||
|
|
||||||
|
private final Map<String, String> responseHeaders; |
||||||
|
|
||||||
|
AccessEvent(final Request req, final Response rsp) { |
||||||
|
method = req.getMethod(); |
||||||
|
uri = req.getRequestURI(); |
||||||
|
requestHeaders = cloneHeaders(req); |
||||||
|
parameters = clone(req.getParameterMap()); |
||||||
|
|
||||||
|
status = rsp.getStatus(); |
||||||
|
responseHeaders = cloneHeaders(rsp); |
||||||
|
} |
||||||
|
|
||||||
|
private static Map<String, String> cloneHeaders(final Request req) { |
||||||
|
Map<String, String> r = new TreeMap<String, String>(); |
||||||
|
Enumeration hn = req.getHeaderNames(); |
||||||
|
while (hn.hasMoreElements()) { |
||||||
|
String key = (String) hn.nextElement(); |
||||||
|
if (!r.containsKey(key)) { |
||||||
|
r.put(key, req.getHeader(key)); |
||||||
|
} |
||||||
|
} |
||||||
|
return Collections.unmodifiableMap(r); |
||||||
|
} |
||||||
|
|
||||||
|
private static Map<String, String> cloneHeaders(final Response rsp) { |
||||||
|
Map<String, String> r = new TreeMap<String, String>(); |
||||||
|
Enumeration<String> hn = rsp.getHttpFields().getFieldNames(); |
||||||
|
while (hn.hasMoreElements()) { |
||||||
|
String key = hn.nextElement(); |
||||||
|
if (!r.containsKey(key)) { |
||||||
|
Enumeration<String> v = rsp.getHttpFields().getValues(key); |
||||||
|
r.put(key, v.nextElement()); |
||||||
|
} |
||||||
|
} |
||||||
|
return Collections.unmodifiableMap(r); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
private static Map<String, String[]> clone(Map parameterMap) { |
||||||
|
return new TreeMap<String, String[]>(parameterMap); |
||||||
|
} |
||||||
|
|
||||||
|
/** @return {@code "GET"} or {@code "POST"} */ |
||||||
|
public String getMethod() { |
||||||
|
return method; |
||||||
|
} |
||||||
|
|
||||||
|
/** @return path of the file on the server, e.g. {@code /git/HEAD}. */ |
||||||
|
public String getPath() { |
||||||
|
return uri; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param name |
||||||
|
* name of the request header to read. |
||||||
|
* @return first value of the request header; null if not sent. |
||||||
|
*/ |
||||||
|
public String getRequestHeader(String name) { |
||||||
|
return requestHeaders.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param name |
||||||
|
* name of the request parameter to read. |
||||||
|
* @return first value of the request parameter; null if not sent. |
||||||
|
*/ |
||||||
|
public String getParameter(String name) { |
||||||
|
String[] r = parameters.get(name); |
||||||
|
return r != null && 1 <= r.length ? r[0] : null; |
||||||
|
} |
||||||
|
|
||||||
|
/** @return all parameters in the request. */ |
||||||
|
public Map<String, String[]> getParameters() { |
||||||
|
return parameters; |
||||||
|
} |
||||||
|
|
||||||
|
/** @return HTTP status code of the response, e.g. 200, 403, 500. */ |
||||||
|
public int getStatus() { |
||||||
|
return status; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param name |
||||||
|
* name of the response header to read. |
||||||
|
* @return first value of the response header; null if not sent. |
||||||
|
*/ |
||||||
|
public String getResponseHeader(String name) { |
||||||
|
return responseHeaders.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString() { |
||||||
|
StringBuilder b = new StringBuilder(); |
||||||
|
b.append(method); |
||||||
|
b.append(' '); |
||||||
|
b.append(uri); |
||||||
|
if (!parameters.isEmpty()) { |
||||||
|
b.append('?'); |
||||||
|
boolean first = true; |
||||||
|
for (Map.Entry<String, String[]> e : parameters.entrySet()) { |
||||||
|
for (String val : e.getValue()) { |
||||||
|
if (!first) { |
||||||
|
b.append('&'); |
||||||
|
} |
||||||
|
first = false; |
||||||
|
|
||||||
|
b.append(e.getKey()); |
||||||
|
b.append('='); |
||||||
|
b.append(val); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
b.append(' '); |
||||||
|
b.append(status); |
||||||
|
return b.toString(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,295 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2010, 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.http.test.util; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.net.InetAddress; |
||||||
|
import java.net.URI; |
||||||
|
import java.net.URISyntaxException; |
||||||
|
import java.net.UnknownHostException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import junit.framework.Assert; |
||||||
|
|
||||||
|
import org.eclipse.jetty.http.security.Constraint; |
||||||
|
import org.eclipse.jetty.http.security.Password; |
||||||
|
import org.eclipse.jetty.security.Authenticator; |
||||||
|
import org.eclipse.jetty.security.ConstraintMapping; |
||||||
|
import org.eclipse.jetty.security.ConstraintSecurityHandler; |
||||||
|
import org.eclipse.jetty.security.MappedLoginService; |
||||||
|
import org.eclipse.jetty.security.authentication.BasicAuthenticator; |
||||||
|
import org.eclipse.jetty.server.Connector; |
||||||
|
import org.eclipse.jetty.server.Server; |
||||||
|
import org.eclipse.jetty.server.UserIdentity; |
||||||
|
import org.eclipse.jetty.server.handler.ContextHandlerCollection; |
||||||
|
import org.eclipse.jetty.server.handler.RequestLogHandler; |
||||||
|
import org.eclipse.jetty.server.nio.SelectChannelConnector; |
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler; |
||||||
|
import org.eclipse.jetty.util.thread.QueuedThreadPool; |
||||||
|
import org.eclipse.jgit.transport.URIish; |
||||||
|
|
||||||
|
/** |
||||||
|
* Tiny web application server for unit testing. |
||||||
|
* <p> |
||||||
|
* Tests should start the server in their {@code setUp()} method and stop the |
||||||
|
* server in their {@code tearDown()} method. Only while started the server's |
||||||
|
* URL and/or port number can be obtained. |
||||||
|
*/ |
||||||
|
public class AppServer { |
||||||
|
/** Realm name for the secure access areas. */ |
||||||
|
public static final String realm = "Secure Area"; |
||||||
|
|
||||||
|
/** Username for secured access areas. */ |
||||||
|
public static final String username = "agitter"; |
||||||
|
|
||||||
|
/** Password for {@link #username} in secured access areas. */ |
||||||
|
public static final String password = "letmein"; |
||||||
|
|
||||||
|
static { |
||||||
|
// Install a logger that throws warning messages.
|
||||||
|
//
|
||||||
|
final String prop = "org.eclipse.jetty.util.log.class"; |
||||||
|
System.setProperty(prop, RecordingLogger.class.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
private final Server server; |
||||||
|
|
||||||
|
private final Connector connector; |
||||||
|
|
||||||
|
private final ContextHandlerCollection contexts; |
||||||
|
|
||||||
|
private final TestRequestLog log; |
||||||
|
|
||||||
|
public AppServer() { |
||||||
|
connector = new SelectChannelConnector(); |
||||||
|
connector.setPort(0); |
||||||
|
try { |
||||||
|
final InetAddress me = InetAddress.getByName("localhost"); |
||||||
|
connector.setHost(me.getHostAddress()); |
||||||
|
} catch (UnknownHostException e) { |
||||||
|
throw new RuntimeException("Cannot find localhost", e); |
||||||
|
} |
||||||
|
|
||||||
|
// We need a handful of threads in the thread pool, otherwise
|
||||||
|
// our tests will deadlock when they can't open enough requests.
|
||||||
|
// In theory we only need 1 concurrent connection at a time, but
|
||||||
|
// I suspect the JRE isn't doing request pipelining on existing
|
||||||
|
// connections like we want it to.
|
||||||
|
//
|
||||||
|
final QueuedThreadPool pool = new QueuedThreadPool(); |
||||||
|
pool.setMinThreads(1); |
||||||
|
pool.setMaxThreads(4); |
||||||
|
pool.setMaxQueued(8); |
||||||
|
|
||||||
|
contexts = new ContextHandlerCollection(); |
||||||
|
|
||||||
|
log = new TestRequestLog(); |
||||||
|
|
||||||
|
final RequestLogHandler logHandler = new RequestLogHandler(); |
||||||
|
logHandler.setHandler(contexts); |
||||||
|
logHandler.setRequestLog(log); |
||||||
|
|
||||||
|
server = new Server(); |
||||||
|
server.setConnectors(new Connector[] { connector }); |
||||||
|
server.setThreadPool(pool); |
||||||
|
server.setHandler(logHandler); |
||||||
|
|
||||||
|
server.setStopAtShutdown(false); |
||||||
|
server.setGracefulShutdown(0); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new servlet context within the server. |
||||||
|
* <p> |
||||||
|
* This method should be invoked before the server is started, once for each |
||||||
|
* context the caller wants to register. |
||||||
|
* |
||||||
|
* @param path |
||||||
|
* path of the context; use "/" for the root context if binding |
||||||
|
* to the root is desired. |
||||||
|
* @return the context to add servlets into. |
||||||
|
*/ |
||||||
|
public ServletContextHandler addContext(String path) { |
||||||
|
assertNotYetSetUp(); |
||||||
|
if ("".equals(path)) |
||||||
|
path = "/"; |
||||||
|
|
||||||
|
ServletContextHandler ctx = new ServletContextHandler(); |
||||||
|
ctx.setContextPath(path); |
||||||
|
contexts.addHandler(ctx); |
||||||
|
|
||||||
|
return ctx; |
||||||
|
} |
||||||
|
|
||||||
|
public ServletContextHandler authBasic(ServletContextHandler ctx) { |
||||||
|
assertNotYetSetUp(); |
||||||
|
auth(ctx, new BasicAuthenticator()); |
||||||
|
return ctx; |
||||||
|
} |
||||||
|
|
||||||
|
private void auth(ServletContextHandler ctx, Authenticator authType) { |
||||||
|
final String role = "can-access"; |
||||||
|
|
||||||
|
MappedLoginService users = new MappedLoginService() { |
||||||
|
@Override |
||||||
|
protected UserIdentity loadUser(String who) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void loadUsers() throws IOException { |
||||||
|
putUser(username, new Password(password), new String[] { role }); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
ConstraintMapping cm = new ConstraintMapping(); |
||||||
|
cm.setConstraint(new Constraint()); |
||||||
|
cm.getConstraint().setAuthenticate(true); |
||||||
|
cm.getConstraint().setDataConstraint(Constraint.DC_NONE); |
||||||
|
cm.getConstraint().setRoles(new String[] { role }); |
||||||
|
cm.setPathSpec("/*"); |
||||||
|
|
||||||
|
ConstraintSecurityHandler sec = new ConstraintSecurityHandler(); |
||||||
|
sec.setStrict(false); |
||||||
|
sec.setRealmName(realm); |
||||||
|
sec.setAuthenticator(authType); |
||||||
|
sec.setLoginService(users); |
||||||
|
sec.setConstraintMappings(new ConstraintMapping[] { cm }); |
||||||
|
sec.setHandler(ctx); |
||||||
|
|
||||||
|
contexts.removeHandler(ctx); |
||||||
|
contexts.addHandler(sec); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Start the server on a random local port. |
||||||
|
* |
||||||
|
* @throws Exception |
||||||
|
* the server cannot be started, testing is not possible. |
||||||
|
*/ |
||||||
|
public void setUp() throws Exception { |
||||||
|
RecordingLogger.clear(); |
||||||
|
log.clear(); |
||||||
|
server.start(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Shutdown the server. |
||||||
|
* |
||||||
|
* @throws Exception |
||||||
|
* the server refuses to halt, or wasn't running. |
||||||
|
*/ |
||||||
|
public void tearDown() throws Exception { |
||||||
|
RecordingLogger.clear(); |
||||||
|
log.clear(); |
||||||
|
server.stop(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the URI to reference this server. |
||||||
|
* <p> |
||||||
|
* The returned URI includes the proper host name and port number, but does |
||||||
|
* not contain a path. |
||||||
|
* |
||||||
|
* @return URI to reference this server's root context. |
||||||
|
*/ |
||||||
|
public URI getURI() { |
||||||
|
assertAlreadySetUp(); |
||||||
|
String host = connector.getHost(); |
||||||
|
if (host.contains(":") && !host.startsWith("[")) |
||||||
|
host = "[" + host + "]"; |
||||||
|
final String uri = "http://" + host + ":" + getPort(); |
||||||
|
try { |
||||||
|
return new URI(uri); |
||||||
|
} catch (URISyntaxException e) { |
||||||
|
throw new RuntimeException("Unexpected URI error on " + uri, e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** @return the local port number the server is listening on. */ |
||||||
|
public int getPort() { |
||||||
|
assertAlreadySetUp(); |
||||||
|
return ((SelectChannelConnector) connector).getLocalPort(); |
||||||
|
} |
||||||
|
|
||||||
|
/** @return all requests since the server was started. */ |
||||||
|
public List<AccessEvent> getRequests() { |
||||||
|
return new ArrayList<AccessEvent>(log.getEvents()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param base |
||||||
|
* base URI used to access the server. |
||||||
|
* @param path |
||||||
|
* the path to locate requests for, relative to {@code base}. |
||||||
|
* @return all requests which match the given path. |
||||||
|
*/ |
||||||
|
public List<AccessEvent> getRequests(URIish base, String path) { |
||||||
|
return getRequests(HttpTestCase.join(base, path)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param path |
||||||
|
* the path to locate requests for. |
||||||
|
* @return all requests which match the given path. |
||||||
|
*/ |
||||||
|
public List<AccessEvent> getRequests(String path) { |
||||||
|
ArrayList<AccessEvent> r = new ArrayList<AccessEvent>(); |
||||||
|
for (AccessEvent event : log.getEvents()) { |
||||||
|
if (event.getPath().equals(path)) { |
||||||
|
r.add(event); |
||||||
|
} |
||||||
|
} |
||||||
|
return r; |
||||||
|
} |
||||||
|
|
||||||
|
private void assertNotYetSetUp() { |
||||||
|
Assert.assertFalse("server is not running", server.isRunning()); |
||||||
|
} |
||||||
|
|
||||||
|
private void assertAlreadySetUp() { |
||||||
|
Assert.assertTrue("server is running", server.isRunning()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,161 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2009-2010, 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.http.test.util; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.net.URI; |
||||||
|
import java.net.URISyntaxException; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler; |
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; |
||||||
|
import org.eclipse.jgit.junit.TestRepository; |
||||||
|
import org.eclipse.jgit.lib.AnyObjectId; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.ObjectId; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.revwalk.RevCommit; |
||||||
|
import org.eclipse.jgit.revwalk.RevObject; |
||||||
|
import org.eclipse.jgit.transport.RefSpec; |
||||||
|
import org.eclipse.jgit.transport.RemoteRefUpdate; |
||||||
|
import org.eclipse.jgit.transport.URIish; |
||||||
|
|
||||||
|
/** Base class for HTTP related transport testing. */ |
||||||
|
public abstract class HttpTestCase extends LocalDiskRepositoryTestCase { |
||||||
|
protected static final String master = Constants.R_HEADS + Constants.MASTER; |
||||||
|
|
||||||
|
/** In-memory application server; subclass must start. */ |
||||||
|
protected AppServer server; |
||||||
|
|
||||||
|
protected void setUp() throws Exception { |
||||||
|
super.setUp(); |
||||||
|
server = new AppServer(); |
||||||
|
} |
||||||
|
|
||||||
|
protected void tearDown() throws Exception { |
||||||
|
server.tearDown(); |
||||||
|
super.tearDown(); |
||||||
|
} |
||||||
|
|
||||||
|
protected TestRepository createTestRepository() throws Exception { |
||||||
|
return new TestRepository(createBareRepository()); |
||||||
|
} |
||||||
|
|
||||||
|
protected URIish toURIish(String path) throws URISyntaxException { |
||||||
|
URI u = server.getURI().resolve(path); |
||||||
|
return new URIish(u.toString()); |
||||||
|
} |
||||||
|
|
||||||
|
protected URIish toURIish(ServletContextHandler app, String name) |
||||||
|
throws URISyntaxException { |
||||||
|
String p = app.getContextPath(); |
||||||
|
if (!p.endsWith("/") && !name.startsWith("/")) |
||||||
|
p += "/"; |
||||||
|
p += name; |
||||||
|
return toURIish(p); |
||||||
|
} |
||||||
|
|
||||||
|
protected List<AccessEvent> getRequests() { |
||||||
|
return server.getRequests(); |
||||||
|
} |
||||||
|
|
||||||
|
protected List<AccessEvent> getRequests(URIish base, String path) { |
||||||
|
return server.getRequests(base, path); |
||||||
|
} |
||||||
|
|
||||||
|
protected List<AccessEvent> getRequests(String path) { |
||||||
|
return server.getRequests(path); |
||||||
|
} |
||||||
|
|
||||||
|
protected static void fsck(Repository db, RevObject... tips) |
||||||
|
throws Exception { |
||||||
|
new TestRepository(db).fsck(tips); |
||||||
|
} |
||||||
|
|
||||||
|
protected static Set<RefSpec> mirror(String... refs) { |
||||||
|
HashSet<RefSpec> r = new HashSet<RefSpec>(); |
||||||
|
for (String name : refs) { |
||||||
|
RefSpec rs = new RefSpec(name); |
||||||
|
rs = rs.setDestination(name); |
||||||
|
rs = rs.setForceUpdate(true); |
||||||
|
r.add(rs); |
||||||
|
} |
||||||
|
return r; |
||||||
|
} |
||||||
|
|
||||||
|
protected static Collection<RemoteRefUpdate> push(TestRepository from, |
||||||
|
RevCommit q) throws IOException { |
||||||
|
final Repository db = from.getRepository(); |
||||||
|
final String srcExpr = q.name(); |
||||||
|
final String dstName = master; |
||||||
|
final boolean forceUpdate = true; |
||||||
|
final String localName = null; |
||||||
|
final ObjectId oldId = null; |
||||||
|
|
||||||
|
RemoteRefUpdate u = new RemoteRefUpdate(db, srcExpr, dstName, |
||||||
|
forceUpdate, localName, oldId); |
||||||
|
return Collections.singleton(u); |
||||||
|
} |
||||||
|
|
||||||
|
public static String loose(URIish base, AnyObjectId id) { |
||||||
|
final String objectName = id.name(); |
||||||
|
final String d = objectName.substring(0, 2); |
||||||
|
final String f = objectName.substring(2); |
||||||
|
return join(base, "objects/" + d + "/" + f); |
||||||
|
} |
||||||
|
|
||||||
|
public static String join(URIish base, String path) { |
||||||
|
if (path.startsWith("/")) |
||||||
|
fail("Cannot join absolute path " + path + " to URIish " + base); |
||||||
|
|
||||||
|
String dir = base.getPath(); |
||||||
|
if (!dir.endsWith("/")) |
||||||
|
dir += "/"; |
||||||
|
return dir + path; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,85 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2010, 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.http.test.util; |
||||||
|
|
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import javax.servlet.ServletConfig; |
||||||
|
import javax.servlet.ServletContext; |
||||||
|
|
||||||
|
public class MockServletConfig implements ServletConfig { |
||||||
|
private final Map<String, String> parameters = new HashMap<String, String>(); |
||||||
|
|
||||||
|
public void setInitParameter(String name, String value) { |
||||||
|
parameters.put(name, value); |
||||||
|
} |
||||||
|
|
||||||
|
public String getInitParameter(String name) { |
||||||
|
return parameters.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration getInitParameterNames() { |
||||||
|
final Iterator<String> i = parameters.keySet().iterator(); |
||||||
|
return new Enumeration<String>() { |
||||||
|
public boolean hasMoreElements() { |
||||||
|
return i.hasNext(); |
||||||
|
} |
||||||
|
|
||||||
|
public String nextElement() { |
||||||
|
return i.next(); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
public String getServletName() { |
||||||
|
return "MOCK_SERVLET"; |
||||||
|
} |
||||||
|
|
||||||
|
public ServletContext getServletContext() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,146 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2010, 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.http.test.util; |
||||||
|
|
||||||
|
import java.text.MessageFormat; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.eclipse.jetty.util.log.Logger; |
||||||
|
|
||||||
|
/** Logs warnings into an array for later inspection. */ |
||||||
|
public class RecordingLogger implements Logger { |
||||||
|
private static List<Warning> warnings = new ArrayList<Warning>(); |
||||||
|
|
||||||
|
/** Clear the warnings, automatically done by {@link AppServer#setUp()} */ |
||||||
|
public static void clear() { |
||||||
|
synchronized (warnings) { |
||||||
|
warnings.clear(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** @return the warnings (if any) from the last execution */ |
||||||
|
public static List<Warning> getWarnings() { |
||||||
|
synchronized (warnings) { |
||||||
|
ArrayList<Warning> copy = new ArrayList<Warning>(warnings); |
||||||
|
return Collections.unmodifiableList(copy); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("serial") |
||||||
|
public static class Warning extends Exception { |
||||||
|
public Warning(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
public Warning(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private final String name; |
||||||
|
|
||||||
|
public RecordingLogger() { |
||||||
|
this(""); |
||||||
|
} |
||||||
|
|
||||||
|
public RecordingLogger(final String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public Logger getLogger(@SuppressWarnings("hiding") String name) { |
||||||
|
return new RecordingLogger(name); |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
public void warn(String msg, Object arg0, Object arg1) { |
||||||
|
synchronized (warnings) { |
||||||
|
warnings.add(new Warning(MessageFormat.format(msg, arg0, arg1))); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void warn(String msg, Throwable th) { |
||||||
|
synchronized (warnings) { |
||||||
|
warnings.add(new Warning(msg, th)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void warn(String msg) { |
||||||
|
synchronized (warnings) { |
||||||
|
warnings.add(new Warning(msg)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void debug(String msg, Object arg0, Object arg1) { |
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
} |
||||||
|
|
||||||
|
public void debug(String msg, Throwable th) { |
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
} |
||||||
|
|
||||||
|
public void debug(String msg) { |
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
} |
||||||
|
|
||||||
|
public void info(String msg, Object arg0, Object arg1) { |
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
} |
||||||
|
|
||||||
|
public void info(String msg) { |
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
} |
||||||
|
|
||||||
|
public boolean isDebugEnabled() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDebugEnabled(boolean enabled) { |
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2010, 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.http.test.util; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request; |
||||||
|
import org.eclipse.jetty.server.RequestLog; |
||||||
|
import org.eclipse.jetty.server.Response; |
||||||
|
import org.eclipse.jetty.util.component.AbstractLifeCycle; |
||||||
|
|
||||||
|
/** Logs request made through {@link AppServer}. */ |
||||||
|
class TestRequestLog extends AbstractLifeCycle implements RequestLog { |
||||||
|
private final List<AccessEvent> events = new ArrayList<AccessEvent>(); |
||||||
|
|
||||||
|
/** Reset the log back to its original empty state. */ |
||||||
|
synchronized void clear() { |
||||||
|
events.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
/** @return all of the events made since the last clear. */ |
||||||
|
synchronized List<AccessEvent> getEvents() { |
||||||
|
return events; |
||||||
|
} |
||||||
|
|
||||||
|
public synchronized void log(Request request, Response response) { |
||||||
|
events.add(new AccessEvent(request, response)); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue