Add JUnit tests for HTTP transport
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>
This commit is contained in:
parent
d5bc8be743
commit
f5eb0d9366
|
@ -0,0 +1 @@
|
|||
/target
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009, Google Inc.
|
||||
* Copyright (C) 2009-2010, Google Inc.
|
||||
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
|
||||
* Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
|
||||
* and other copyright owners as documented in the project's IP log.
|
||||
|
@ -57,8 +57,10 @@
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.jgit.lib.AnyObjectId;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.FileBasedConfig;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
|
@ -404,6 +406,14 @@ protected String read(final File f) throws IOException {
|
|||
return new String(body, 0, body.length, "UTF-8");
|
||||
}
|
||||
|
||||
protected static void assertEquals(AnyObjectId exp, AnyObjectId act) {
|
||||
if (exp != null)
|
||||
exp = exp.copy();
|
||||
if (act != null)
|
||||
act = act.copy();
|
||||
Assert.assertEquals(exp, act);
|
||||
}
|
||||
|
||||
private static String[] toEnvArray(final Map<String, String> env) {
|
||||
final String[] envp = new String[env.size()];
|
||||
int i = 0;
|
||||
|
|
|
@ -44,11 +44,15 @@
|
|||
package org.eclipse.jgit.junit;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
@ -60,21 +64,30 @@
|
|||
import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
|
||||
import org.eclipse.jgit.dircache.DirCacheEditor.DeleteTree;
|
||||
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
|
||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
import org.eclipse.jgit.errors.ObjectWritingException;
|
||||
import org.eclipse.jgit.lib.AnyObjectId;
|
||||
import org.eclipse.jgit.lib.Commit;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.FileMode;
|
||||
import org.eclipse.jgit.lib.LockFile;
|
||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||
import org.eclipse.jgit.lib.ObjectChecker;
|
||||
import org.eclipse.jgit.lib.ObjectDatabase;
|
||||
import org.eclipse.jgit.lib.ObjectDirectory;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectWriter;
|
||||
import org.eclipse.jgit.lib.PackFile;
|
||||
import org.eclipse.jgit.lib.PackWriter;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.RefUpdate;
|
||||
import org.eclipse.jgit.lib.RefWriter;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.Tag;
|
||||
import org.eclipse.jgit.lib.PackIndex.MutableEntry;
|
||||
import org.eclipse.jgit.revwalk.ObjectWalk;
|
||||
import org.eclipse.jgit.revwalk.RevBlob;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevObject;
|
||||
|
@ -428,26 +441,25 @@ public <T extends AnyObjectId> T update(String ref, T obj) throws Exception {
|
|||
* @throws Exception
|
||||
*/
|
||||
public void updateServerInfo() throws Exception {
|
||||
if (db.getObjectDatabase() instanceof ObjectDirectory) {
|
||||
final ObjectDatabase odb = db.getObjectDatabase();
|
||||
if (odb instanceof ObjectDirectory) {
|
||||
RefWriter rw = new RefWriter(db.getAllRefs().values()) {
|
||||
@Override
|
||||
protected void writeFile(final String name, final byte[] bin)
|
||||
throws IOException {
|
||||
final File p = new File(db.getDirectory(), name);
|
||||
final LockFile lck = new LockFile(p);
|
||||
if (!lck.lock())
|
||||
throw new ObjectWritingException("Can't write " + p);
|
||||
try {
|
||||
lck.write(bin);
|
||||
} catch (IOException ioe) {
|
||||
throw new ObjectWritingException("Can't write " + p);
|
||||
}
|
||||
if (!lck.commit())
|
||||
throw new ObjectWritingException("Can't write " + p);
|
||||
TestRepository.this.writeFile(name, bin);
|
||||
}
|
||||
};
|
||||
rw.writePackedRefs();
|
||||
rw.writeInfoRefs();
|
||||
|
||||
final StringBuilder w = new StringBuilder();
|
||||
for (PackFile p : ((ObjectDirectory) odb).getPacks()) {
|
||||
w.append("P ");
|
||||
w.append(p.getPackFile().getName());
|
||||
w.append('\n');
|
||||
}
|
||||
writeFile("objects/info/packs", Constants.encodeASCII(w.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -484,6 +496,132 @@ public BranchBuilder branch(String ref) {
|
|||
return new BranchBuilder(ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run consistency checks against the object database.
|
||||
* <p>
|
||||
* This method completes silently if the checks pass. A temporary revision
|
||||
* pool is constructed during the checking.
|
||||
*
|
||||
* @param tips
|
||||
* the tips to start checking from; if not supplied the refs of
|
||||
* the repository are used instead.
|
||||
* @throws MissingObjectException
|
||||
* @throws IncorrectObjectTypeException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void fsck(RevObject... tips) throws MissingObjectException,
|
||||
IncorrectObjectTypeException, IOException {
|
||||
ObjectWalk ow = new ObjectWalk(db);
|
||||
if (tips.length != 0) {
|
||||
for (RevObject o : tips)
|
||||
ow.markStart(ow.parseAny(o));
|
||||
} else {
|
||||
for (Ref r : db.getAllRefs().values())
|
||||
ow.markStart(ow.parseAny(r.getObjectId()));
|
||||
}
|
||||
|
||||
ObjectChecker oc = new ObjectChecker();
|
||||
for (;;) {
|
||||
final RevCommit o = ow.next();
|
||||
if (o == null)
|
||||
break;
|
||||
|
||||
final byte[] bin = db.openObject(o).getCachedBytes();
|
||||
oc.checkCommit(bin);
|
||||
assertHash(o, bin);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
final RevObject o = ow.nextObject();
|
||||
if (o == null)
|
||||
break;
|
||||
|
||||
final byte[] bin = db.openObject(o).getCachedBytes();
|
||||
oc.check(o.getType(), bin);
|
||||
assertHash(o, bin);
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertHash(RevObject id, byte[] bin) {
|
||||
MessageDigest md = Constants.newMessageDigest();
|
||||
md.update(Constants.encodedTypeString(id.getType()));
|
||||
md.update((byte) ' ');
|
||||
md.update(Constants.encodeASCII(bin.length));
|
||||
md.update((byte) 0);
|
||||
md.update(bin);
|
||||
Assert.assertEquals(id.copy(), ObjectId.fromRaw(md.digest()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack all reachable objects in the repository into a single pack file.
|
||||
* <p>
|
||||
* All loose objects are automatically pruned. Existing packs however are
|
||||
* not removed.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void packAndPrune() throws Exception {
|
||||
final ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
|
||||
final PackWriter pw = new PackWriter(db, NullProgressMonitor.INSTANCE);
|
||||
|
||||
Set<ObjectId> all = new HashSet<ObjectId>();
|
||||
for (Ref r : db.getAllRefs().values())
|
||||
all.add(r.getObjectId());
|
||||
pw.preparePack(all, Collections.<ObjectId> emptySet());
|
||||
|
||||
final ObjectId name = pw.computeName();
|
||||
FileOutputStream out;
|
||||
|
||||
final File pack = nameFor(odb, name, ".pack");
|
||||
out = new FileOutputStream(pack);
|
||||
try {
|
||||
pw.writePack(out);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
pack.setReadOnly();
|
||||
|
||||
final File idx = nameFor(odb, name, ".idx");
|
||||
out = new FileOutputStream(idx);
|
||||
try {
|
||||
pw.writeIndex(out);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
idx.setReadOnly();
|
||||
|
||||
odb.openPack(pack, idx);
|
||||
updateServerInfo();
|
||||
prunePacked(odb);
|
||||
}
|
||||
|
||||
private void prunePacked(ObjectDirectory odb) {
|
||||
for (PackFile p : odb.getPacks()) {
|
||||
for (MutableEntry e : p)
|
||||
odb.fileFor(e.toObjectId()).delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static File nameFor(ObjectDirectory odb, ObjectId name, String t) {
|
||||
File packdir = new File(odb.getDirectory(), "pack");
|
||||
return new File(packdir, "pack-" + name.name() + t);
|
||||
}
|
||||
|
||||
private void writeFile(final String name, final byte[] bin)
|
||||
throws IOException, ObjectWritingException {
|
||||
final File p = new File(db.getDirectory(), name);
|
||||
final LockFile lck = new LockFile(p);
|
||||
if (!lck.lock())
|
||||
throw new ObjectWritingException("Can't write " + p);
|
||||
try {
|
||||
lck.write(bin);
|
||||
} catch (IOException ioe) {
|
||||
throw new ObjectWritingException("Can't write " + p);
|
||||
}
|
||||
if (!lck.commit())
|
||||
throw new ObjectWritingException("Can't write " + p);
|
||||
}
|
||||
|
||||
/** Helper to build a branch with one or more commits */
|
||||
public class BranchBuilder {
|
||||
private final String ref;
|
||||
|
|
|
@ -155,6 +155,8 @@ private static class HttpConfig {
|
|||
|
||||
private final ProxySelector proxySelector;
|
||||
|
||||
private boolean useSmartHttp = true;
|
||||
|
||||
TransportHttp(final Repository local, final URIish uri)
|
||||
throws NotSupportedException {
|
||||
super(local, uri);
|
||||
|
@ -171,6 +173,20 @@ private static class HttpConfig {
|
|||
proxySelector = ProxySelector.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle whether or not smart HTTP transport should be used.
|
||||
* <p>
|
||||
* This flag exists primarily to support backwards compatibility testing
|
||||
* within a testing framework, there is no need to modify it in most
|
||||
* applications.
|
||||
*
|
||||
* @param on
|
||||
* if {@code true} (default), smart HTTP is enabled.
|
||||
*/
|
||||
public void setUseSmartHttp(final boolean on) {
|
||||
useSmartHttp = on;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchConnection openFetch() throws TransportException,
|
||||
NotSupportedException {
|
||||
|
@ -271,6 +287,10 @@ public PushConnection openPush() throws NotSupportedException,
|
|||
readSmartHeaders(in, service);
|
||||
return new SmartHttpPushConnection(in);
|
||||
|
||||
} else if (!useSmartHttp) {
|
||||
final String msg = "smart HTTP push disabled";
|
||||
throw new NotSupportedException(msg);
|
||||
|
||||
} else {
|
||||
final String msg = "remote does not support smart HTTP push";
|
||||
throw new NotSupportedException(msg);
|
||||
|
@ -303,9 +323,11 @@ private HttpURLConnection connect(final String service)
|
|||
b.append('/');
|
||||
b.append(Constants.INFO_REFS);
|
||||
|
||||
b.append(b.indexOf("?") < 0 ? '?' : '&');
|
||||
b.append("service=");
|
||||
b.append(service);
|
||||
if (useSmartHttp) {
|
||||
b.append(b.indexOf("?") < 0 ? '?' : '&');
|
||||
b.append("service=");
|
||||
b.append(service);
|
||||
}
|
||||
|
||||
u = new URL(b.toString());
|
||||
} catch (MalformedURLException e) {
|
||||
|
@ -314,8 +336,12 @@ private HttpURLConnection connect(final String service)
|
|||
|
||||
try {
|
||||
final HttpURLConnection conn = httpOpen(u);
|
||||
String expType = "application/x-" + service + "-advertisement";
|
||||
conn.setRequestProperty(HDR_ACCEPT, expType + ", */*");
|
||||
if (useSmartHttp) {
|
||||
String expType = "application/x-" + service + "-advertisement";
|
||||
conn.setRequestProperty(HDR_ACCEPT, expType + ", */*");
|
||||
} else {
|
||||
conn.setRequestProperty(HDR_ACCEPT, "*/*");
|
||||
}
|
||||
final int status = HttpSupport.response(conn);
|
||||
switch (status) {
|
||||
case HttpURLConnection.HTTP_OK:
|
||||
|
|
10
pom.xml
10
pom.xml
|
@ -138,6 +138,8 @@
|
|||
|
||||
<servlet-api-CQ>CQ 3565</servlet-api-CQ>
|
||||
<servlet-api-version>2.5</servlet-api-version>
|
||||
|
||||
<jetty-version>7.0.1.v20091125</jetty-version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
|
@ -265,6 +267,12 @@
|
|||
<artifactId>servlet-api</artifactId>
|
||||
<version>${servlet-api-version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<version>${jetty-version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
@ -298,6 +306,8 @@
|
|||
<module>org.eclipse.jgit.http.server</module>
|
||||
<module>org.eclipse.jgit.pgm</module>
|
||||
<module>org.eclipse.jgit.junit</module>
|
||||
|
||||
<module>org.eclipse.jgit.test</module>
|
||||
<module>org.eclipse.jgit.http.test</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
Loading…
Reference in New Issue