Fix old integration tests for migration period

This commit is contained in:
René Pfeuffer
2018-08-03 09:28:54 +02:00
parent ebe3ef8c3e
commit fd873877c4
31 changed files with 600 additions and 3218 deletions

View File

@@ -35,45 +35,22 @@ package sonia.scm.it;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import org.junit.After; import static sonia.scm.it.IntegrationTestUtil.createAdminClient;
import org.junit.Before;
import static sonia.scm.it.IntegrationTestUtil.*;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
public class AbstractAdminITCaseBase public class AbstractAdminITCaseBase
{ {
public AbstractAdminITCaseBase() {
/** client = createAdminClient();
* Method description
*
*/
@Before
public void login()
{
client = createClient();
authenticateAdmin(client);
}
/**
* Method description
*
*/
@After
public void logout()
{
logoutClient(client);
} }
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */ /** Field description */
protected Client client; protected final ScmClient client;
} }

View File

@@ -35,29 +35,26 @@ package sonia.scm.it;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import org.junit.After; import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.junit.runners.Parameterized.Parameters; import org.junit.runners.Parameterized.Parameters;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.user.UserTestData; import sonia.scm.user.UserTestData;
import static org.junit.Assert.*; import java.util.Collection;
import static sonia.scm.it.IntegrationTestUtil.*; import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static sonia.scm.it.IntegrationTestUtil.createAdminClient;
import static sonia.scm.it.IntegrationTestUtil.createResource;
import static sonia.scm.it.IntegrationTestUtil.post;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import java.util.ArrayList;
import java.util.Collection;
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
@@ -77,26 +74,24 @@ public abstract class AbstractPermissionITCaseBase<T>
public AbstractPermissionITCaseBase(Credentials credentials) public AbstractPermissionITCaseBase(Credentials credentials)
{ {
this.credentials = credentials; this.credentials = credentials;
this.client = credentials.isAnonymous()? ScmClient.anonymous(): new ScmClient(credentials.getUsername(), credentials.getPassword());
} }
//~--- methods --------------------------------------------------------------
//~--- methods --------------------------------------------------------------
/** /**
* Method description * Method description
* *
* *
* @return * @return
*/ */
@Parameters @Parameters(name = "{1}")
public static Collection<Credentials[]> createParameters() public static Collection<Object[]> createParameters()
{ {
Collection<Credentials[]> params = new ArrayList<>(); return asList(
new Object[] {new Credentials(), "anonymous"},
params.add(new Credentials[] { new Credentials() }); new Object[] {new Credentials("trillian", "a.trillian124"), "trillian" }
params.add(new Credentials[] { );
new Credentials("trillian", "a.trillian124") });
return params;
} }
/** /**
@@ -111,18 +106,13 @@ public abstract class AbstractPermissionITCaseBase<T>
trillian.setPassword("a.trillian124"); trillian.setPassword("a.trillian124");
Client client = createClient(); ScmClient client = createAdminClient();
authenticateAdmin(client); ClientResponse response = UserITUtil.postUser(client, trillian);
WebResource wr = createResource(client, "users");
ClientResponse response = wr.post(ClientResponse.class, trillian);
assertNotNull(response); assertNotNull(response);
assertEquals(201, response.getStatus()); assertEquals(201, response.getStatus());
response.close(); response.close();
logoutClient(client);
client.destroy();
} }
/** /**
@@ -132,15 +122,12 @@ public abstract class AbstractPermissionITCaseBase<T>
@AfterClass @AfterClass
public static void removeTestUser() public static void removeTestUser()
{ {
Client client = createClient(); ScmClient client = createAdminClient();
authenticateAdmin(client);
createResource(client, "users/trillian").delete(); createResource(client, "users/trillian").delete();
client.destroy();
} }
//~--- get methods ----------------------------------------------------------
//~--- get methods ----------------------------------------------------------
/** /**
* Method description * Method description
* *
@@ -189,30 +176,10 @@ public abstract class AbstractPermissionITCaseBase<T>
*/ */
protected abstract String getModifyPath(); protected abstract String getModifyPath();
protected abstract String getMediaType();
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
/**
* Method description
*
*/
@After
public void after()
{
client = createClient();
logout();
}
/**
* Method description
*
*/
@Before
public void before()
{
client = createClient();
login();
}
/** /**
* Method description * Method description
* *
@@ -220,9 +187,7 @@ public abstract class AbstractPermissionITCaseBase<T>
@Test @Test
public void create() public void create()
{ {
WebResource wr = createResource(client, getBasePath()); checkResponse(post(client, getBasePath(), getMediaType(), getCreateItem()));
checkResponse(wr.post(ClientResponse.class, getCreateItem()));
} }
/** /**
@@ -232,7 +197,7 @@ public abstract class AbstractPermissionITCaseBase<T>
@Test @Test
public void delete() public void delete()
{ {
WebResource wr = createResource(client, getDeletePath()); WebResource.Builder wr = createResource(client, getDeletePath());
checkResponse(wr.delete(ClientResponse.class)); checkResponse(wr.delete(ClientResponse.class));
} }
@@ -244,9 +209,9 @@ public abstract class AbstractPermissionITCaseBase<T>
@Test @Test
public void modify() public void modify()
{ {
WebResource wr = createResource(client, getModifyPath()); WebResource.Builder wr = createResource(client, getModifyPath());
checkResponse(wr.put(ClientResponse.class, getModifyItem())); checkResponse(wr.type(getMediaType()).put(ClientResponse.class, getModifyItem()));
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -258,7 +223,7 @@ public abstract class AbstractPermissionITCaseBase<T>
@Test @Test
public void get() public void get()
{ {
WebResource wr = createResource(client, getGetPath()); WebResource.Builder wr = createResource(client, getGetPath());
checkGetResponse(wr.get(ClientResponse.class)); checkGetResponse(wr.get(ClientResponse.class));
} }
@@ -270,7 +235,7 @@ public abstract class AbstractPermissionITCaseBase<T>
@Test @Test
public void getAll() public void getAll()
{ {
WebResource wr = createResource(client, getBasePath()); WebResource.Builder wr = createResource(client, getBasePath());
checkGetAllResponse(wr.get(ClientResponse.class)); checkGetAllResponse(wr.get(ClientResponse.class));
} }
@@ -321,36 +286,9 @@ public abstract class AbstractPermissionITCaseBase<T>
response.close(); response.close();
} }
/**
* Method description
*
*/
private void login()
{
if (!credentials.isAnonymous())
{
authenticate(client, credentials.getUsername(),
credentials.getPassword());
}
}
/**
* Method description
*
*/
private void logout()
{
if (!credentials.isAnonymous())
{
logoutClient(client);
}
}
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */ protected ScmClient client;
protected Client client;
/** Field description */
protected Credentials credentials; protected Credentials credentials;
} }

View File

@@ -1,308 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import sonia.scm.group.Group;
import sonia.scm.user.User;
import sonia.scm.user.UserTestData;
import sonia.scm.util.IOUtil;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import java.util.ArrayList;
import java.util.Collection;
/**
*
* @author Sebastian Sdorra
*/
@RunWith(Parameterized.class)
public class AdminPermissionITCase
{
/**
* Constructs ...
*
*
* @param credentials
*/
public AdminPermissionITCase(Credentials credentials)
{
this.credentials = credentials;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*/
@AfterClass
public static void cleanup()
{
Client client = createAdminClient();
createResource(client, "users/marvin").delete();
createResource(client, "groups/test-group").delete();
client.destroy();
}
/**
* Method description
*
*
* @return
*/
@Parameters
public static Collection<Object[]> createParameters()
{
Collection<Object[]> params = new ArrayList<>();
// params.add(new Object[] { new Credentials() });
User u = UserTestData.createMarvin();
u.setPassword("secret");
Client client = createAdminClient();
createResource(client, "users").post(u);
client.destroy();
params.add(new Object[] { new Credentials(u.getName(), u.getPassword()) });
return params;
}
/**
* Method description
*
*/
@BeforeClass
public static void setup()
{
Group group = new Group("xml", "test-group");
Client client = createAdminClient();
createResource(client, "groups").post(group);
client.destroy();
}
/**
* Method description
*
*/
@Before
public void login()
{
client = createClient();
if (!credentials.isAnonymous())
{
authenticate(client, credentials.getUsername(),
credentials.getPassword());
}
}
/**
* Method description
*
*/
@After
public void logout()
{
if (!credentials.isAnonymous())
{
logoutClient(client);
}
}
/**
* Method description
*
*/
@Test
public void testConfig()
{
checkResponse(createResource(client, "config").get(ClientResponse.class));
checkResponse(createResource(client, "config").post(ClientResponse.class));
}
/**
* Method description
*
*/
@Test
public void testGitConfig()
{
checkResponse(
createResource(client, "config/repositories/git").get(
ClientResponse.class));
checkResponse(
createResource(client, "config/repositories/git").post(
ClientResponse.class));
}
/**
* Method description
*
*/
@Test
public void testGroups()
{
checkResponse(createResource(client, "groups").get(ClientResponse.class));
checkResponse(createResource(client, "groups").post(ClientResponse.class));
checkResponse(
createResource(client, "groups/test-group").get(ClientResponse.class));
checkResponse(
createResource(client, "groups/test-group").put(ClientResponse.class));
checkResponse(
createResource(client, "groups/test-group").delete(
ClientResponse.class));
}
/**
* Method description
*
*/
@Test
public void testHgConfig()
{
checkResponse(
createResource(client, "config/repositories/hg").get(
ClientResponse.class));
checkResponse(
createResource(client, "config/repositories/hg").post(
ClientResponse.class));
}
/**
* Method description
*
*/
@Test
public void testPlugins()
{
checkResponse(createResource(client, "plugins").get(ClientResponse.class));
checkResponse(createResource(client,
"plugins/overview").get(ClientResponse.class));
checkResponse(
createResource(client, "plugins/installed").get(ClientResponse.class));
checkResponse(createResource(client,
"plugins/updates").get(ClientResponse.class));
checkResponse(
createResource(client, "plugins/available").get(ClientResponse.class));
}
/**
* Method description
*
*/
@Test
public void testSvnConfig()
{
checkResponse(
createResource(client, "config/repositories/svn").get(
ClientResponse.class));
checkResponse(
createResource(client, "config/repositories/svn").post(
ClientResponse.class));
}
/**
* Method description
*
*/
@Test
public void testUsers()
{
checkResponse(createResource(client, "users").get(ClientResponse.class));
checkResponse(createResource(client, "users").post(ClientResponse.class));
checkResponse(createResource(client,
"users/scmadmin").get(ClientResponse.class));
checkResponse(createResource(client,
"users/scmadmin").put(ClientResponse.class));
checkResponse(
createResource(client, "users/scmadmin").delete(ClientResponse.class));
}
/**
* Method description
*
*
* @param response
*/
private void checkResponse(ClientResponse response)
{
assertNotNull(response);
if (credentials.isAnonymous())
{
assertEquals(401, response.getStatus());
}
else
{
assertEquals(403, response.getStatus());
}
// fix jersey-client bug
IOUtil.close(response.getEntityInputStream());
response.close();
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private Client client;
/** Field description */
private Credentials credentials;
}

View File

@@ -1,285 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
import static sonia.scm.it.RepositoryITUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Ignore;
import sonia.scm.repository.client.api.RepositoryClient;
import sonia.scm.repository.client.api.RepositoryClientFactory;
/**
*
* @author Sebastian Sdorra
*/
@RunWith(Parameterized.class)
public class AnonymousAccessITCase
{
/** Field description */
private static final Permission PERMISSION_ANONYMOUS_WRITE =
new Permission("anonymous", PermissionType.WRITE);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param repositoryType
*/
public AnonymousAccessITCase(String repositoryType)
{
this.repositoryType = repositoryType;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Parameters
public static Collection<String[]> createParameters()
{
return createRepositoryTypeParameters();
}
/**
* Method description
*
*/
@AfterClass
public static void unsetAnonymousAccess()
{
toggleAnonymousAccess(false);
}
//~--- set methods ----------------------------------------------------------
/**
* Method description
*
*/
@BeforeClass
public static void setAnonymousAccess()
{
toggleAnonymousAccess(true);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param anonymousAccess
*/
private static void toggleAnonymousAccess(boolean anonymousAccess)
{
Client client = createAdminClient();
WebResource resource = createResource(client, "config");
ScmConfiguration config = resource.get(ScmConfiguration.class);
assertNotNull(config);
config.setAnonymousAccessEnabled(anonymousAccess);
ClientResponse response = resource.post(ClientResponse.class, config);
assertNotNull(response);
assertEquals(201, response.getStatus());
logoutClient(client);
}
/**
* Method description
*
*/
@Before
public void createTestRepository()
{
Client client = createAdminClient();
repository = RepositoryTestData.createHeartOfGold(repositoryType);
repository.setPublicReadable(true);
repository = createRepository(client, repository);
logoutClient(client);
}
/**
* Method description
*
*/
@After
public void removeTestRepository()
{
Client client = createAdminClient();
deleteRepository(client, repository.getId());
logoutClient(client);
}
/**
* Method description
*
* @throws IOException
*/
@Test
@Ignore
public void testAllowedAnonymousPush() throws IOException
{
Client client = createAdminClient();
WebResource resource = createResource(client,
"repository/".concat(repository.getId()));
repository.setPermissions(Arrays.asList(PERMISSION_ANONYMOUS_WRITE));
resource.post(ClientResponse.class, repository);
RepositoryClient repositoryClient = createAnonymousRepositoryClient();
createRandomFile(repositoryClient);
commit(repositoryClient, "added test files");
}
/**
* Method description
*
* TODO fix test case
*
* @throws IOException
*/
@Test @Ignore
public void testAnonymousClone() throws IOException
{
testSimpleAdminPush();
RepositoryClient client = createAnonymousRepositoryClient();
// client.checkout();
}
/**
* Method description
*
* @throws IOException
*/
@Ignore
@Test(expected = IOException.class)
public void testDeniedAnonymousPush() throws IOException
{
RepositoryClient repositoryClient = createAnonymousRepositoryClient();
createRandomFile(repositoryClient);
commit(repositoryClient, "added anonymous test file");
}
/**
* Method description
*
*
* @throws IOException
*/
@Test
public void testSimpleAdminPush() throws IOException
{
RepositoryClient repositoryClient = createAdminRepositoryClient();
createRandomFile(repositoryClient);
commit(repositoryClient, "added random file");
}
private RepositoryClient createAdminRepositoryClient() throws IOException {
return createRepositoryClient(ADMIN_USERNAME, ADMIN_PASSWORD);
}
private RepositoryClient createAnonymousRepositoryClient() throws IOException {
return createRepositoryClient(null, null);
}
private RepositoryClient createRepositoryClient(String username, String password) throws IOException {
File directory = temporaryFolder.newFolder();
String remoteUrl = repository.createUrl(BASE_URL);
RepositoryClientFactory factory = new RepositoryClientFactory();
return factory.create(repositoryType, remoteUrl, username, password, directory);
}
//~--- fields ---------------------------------------------------------------
/** Field description */
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
/** Field description */
private Repository repository;
/** Field description */
private final String repositoryType;
}

View File

@@ -1,96 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.Test;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
/**
*
* @author Sebastian Sdorra
*/
public class AuthenticationITCase
{
/**
* Method description
*
*
*/
@Test
public void testLogin()
{
Client client = createClient();
authenticateAdmin(client);
}
/**
* Method description
*
*/
@Test
public void testLoginFailed()
{
Client client = createClient();
ClientResponse response = authenticate(client, "dent", "trillian");
assertNotNull(response);
assertEquals(401, response.getStatus());
response.close();
}
/**
* Method description
*
*/
@Test
public void testLogout()
{
Client client = createClient();
authenticateAdmin(client);
logoutClient(client);
}
}

View File

@@ -1,131 +0,0 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
import com.google.common.base.Strings;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import sonia.scm.ScmState;
import static sonia.scm.it.IntegrationTestUtil.*;
import static sonia.scm.it.RepositoryITUtil.*;
import static sonia.scm.it.RepositoryITUtil.createRepository;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
/**
* Integration test for authorization with scope.
*
* @author Sebastian Sdorra
*/
public class AuthorizationScopeITCase {
private Repository heartOfGold;
private Repository puzzle42;
/**
* Create test repositories.
*/
@Before
public void createTestRepositories(){
Client adminClient = createAdminClient();
this.heartOfGold = createRepository(adminClient, RepositoryTestData.createHeartOfGold("git"));
this.puzzle42 = createRepository(adminClient, RepositoryTestData.create42Puzzle("git"));
}
/**
* Delete test repositories.
*/
@After
public void deleteTestRepositories(){
Client adminClient = createAdminClient();
deleteRepository(adminClient, heartOfGold.getId());
deleteRepository(adminClient, puzzle42.getId());
}
/**
* Read all available repositories without scope.
*/
@Test
public void testAuthenticateWithoutScope() {
Assert.assertEquals(2, getRepositories(createAuthenticationToken()).size());
}
/**
* Read all available repositories with a scope for only one of them.
*/
@Test
public void testAuthenticateWithScope() {
String scope = "repository:read:".concat(heartOfGold.getId());
Assert.assertEquals(1, getRepositories(createAuthenticationToken(scope)).size());
}
private List<Repository> getRepositories(String token) {
Client client = createClient();
WebResource wr = client.resource(createResourceUrl("repositories"));
return wr.header("Authorization", "Bearer ".concat(token)).get(new GenericType<List<Repository>>(){});
}
private String createAuthenticationToken() {
return createAuthenticationToken("");
}
private String createAuthenticationToken(String scope) {
Client client = createClient();
String url = createResourceUrl("auth/access_token");
WebResource wr = client.resource(url);
MultivaluedMap<String, String> formData = new MultivaluedMapImpl();
formData.add("username", ADMIN_USERNAME);
formData.add("password", ADMIN_PASSWORD);
formData.add("grant_type", "password");
if (!Strings.isNullOrEmpty(scope)) {
formData.add("scope", scope);
}
ClientResponse response = wr.type("application/x-www-form-urlencoded").post(ClientResponse.class, formData);
if (response.getStatus() >= 300 ){
Assert.fail("authentication failed with status code " + response.getStatus());
}
return response.getEntity(ScmState.class).getToken();
}
}

View File

@@ -1,296 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.ChangesetPagingResult;
import sonia.scm.repository.Modifications;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.util.IOUtil;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
import static sonia.scm.it.RepositoryITUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import sonia.scm.repository.client.api.RepositoryClient;
import sonia.scm.repository.client.api.RepositoryClientFactory;
/**
*
* @author Sebastian Sdorra
*/
@RunWith(Parameterized.class)
public class ChangesetViewerITCase extends AbstractAdminITCaseBase
{
/**
* Constructs ...
*
*
* @param repositoryType
*/
public ChangesetViewerITCase(String repositoryType)
{
this.repositoryType = repositoryType;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Parameters
public static Collection<String[]> createParameters()
{
return createRepositoryTypeParameters();
}
/**
* Method description
*
*
* @throws IOException
* @throws InterruptedException
*/
@Test
public void cachingTest() throws IOException, InterruptedException
{
RepositoryClient rc = createRepositoryClient();
// rc.checkout();
addTestFile(rc, "a", 1, false);
addTestFile(rc, "b", 2, true);
}
/**
* Method description
*
*
* @throws IOException
*/
@After
public void cleanup() throws IOException
{
IOUtil.delete(localDirectory, true);
deleteRepository(client, repository.getId());
}
/**
* Method description
*
*
* @throws IOException
*/
@Before
public void setup() throws IOException
{
repository = RepositoryTestData.createHeartOfGold(repositoryType);
repository = createRepository(client, repository);
localDirectory = File.createTempFile("scm-", ".unittest");
IOUtil.delete(localDirectory);
IOUtil.mkdirs(localDirectory);
}
/**
* Method description
*
*
* @throws IOException
* @throws InterruptedException
*/
@Test
public void simpleTest() throws IOException, InterruptedException
{
RepositoryClient rc = createRepositoryClient();
// rc.init();
addTestFile(rc, "a", 1, false);
}
/**
* Method description
*
*
* @param rc
* @param name
* @param count
* @param sleep
*
* @throws IOException
* @throws InterruptedException
* @throws RepositoryClientException
*/
private void addTestFile(RepositoryClient rc, String name, int count,
boolean sleep)
throws IOException, InterruptedException
{
File file = new File(localDirectory, name.concat(".txt"));
writeRandomContent(file);
rc.getAddCommand().add(name.concat(".txt"));
IntegrationTestUtil.commit(rc, "added-".concat(name).concat(".txt"));
if (sleep) {
// cache clear is async
Thread.sleep(500l);
}
ChangesetPagingResult cpr = getChangesets(repository);
if ("svn".equals(repositoryType)) {
assertEquals((count + 1), cpr.getTotal());
} else {
assertEquals(count, cpr.getTotal());
}
List<Changeset> changesets = cpr.getChangesets();
assertNotNull(changesets);
if ("svn".equals(repositoryType)) {
assertEquals((count + 1), changesets.size());
} else {
assertEquals(count, changesets.size());
}
Changeset c = changesets.get(0);
assertNotNull(c);
assertEquals("added-".concat(name).concat(".txt"), c.getDescription());
assertTrue(c.isValid());
Modifications m = c.getModifications();
assertNotNull(m);
List<String> added = m.getAdded();
assertNotNull(added);
assertFalse(added.isEmpty());
assertEquals(1, added.size());
//J-
assertThat(
added.get(0),
anyOf(
equalTo(name.concat(".txt")),
equalTo("/".concat(name).concat(".txt"))
)
);
//J+
}
private RepositoryClient createRepositoryClient() throws IOException {
RepositoryClientFactory factory = new RepositoryClientFactory();
return factory.create(
repositoryType, repository.createUrl(BASE_URL),
IntegrationTestUtil.ADMIN_USERNAME, IntegrationTestUtil.ADMIN_PASSWORD,
localDirectory
);
}
private void writeRandomContent(File file) throws IOException {
Random random = new Random();
byte[] data = new byte[random.nextInt(1024)];
try (FileOutputStream output = new FileOutputStream(file)) {
random.nextBytes(data);
output.write(data);
}
}
//~--- get methods ----------------------------------------------------------
private String getChangesetViewerUri(Repository repository) {
return "repositories/".concat(repository.getId()).concat("/changesets");
}
private ChangesetPagingResult getChangesets(Repository repository) {
WebResource resource = createResource(client,
getChangesetViewerUri(repository));
assertNotNull(resource);
ClientResponse response = resource.get(ClientResponse.class);
assertNotNull(response);
assertEquals(200, response.getStatus());
ChangesetPagingResult cpr = response.getEntity(ChangesetPagingResult.class);
assertNotNull(cpr);
return cpr;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private File localDirectory;
/** Field description */
private Repository repository;
/** Field description */
private final String repositoryType;
}

View File

@@ -1,191 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.util.IOUtil;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
import static sonia.scm.it.RepositoryITUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
/**
*
* @author Sebastian Sdorra
*/
@RunWith(Parameterized.class)
public class CreateRepositoriesITCase extends AbstractAdminITCaseBase
{
/**
* Constructs ...
*
*
* @param repositoryType
*/
public CreateRepositoriesITCase(String repositoryType)
{
this.repositoryType = repositoryType;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Parameters
public static Collection<String[]> createParameters()
{
Collection<String[]> params = new ArrayList<>();
params.add(new String[] { "git" });
params.add(new String[] { "svn" });
if (IOUtil.search("hg") != null)
{
params.add(new String[] { "hg" });
}
return params;
}
/**
* Method description
*
*
* @throws IOException
*/
@After
public void cleanup() throws IOException
{
deleteRepository(client, repository.getId());
}
/**
* Method description
*
*/
@Test
public void testCreate()
{
repository = RepositoryTestData.createHeartOfGold(repositoryType);
repository = createRepository(client, repository);
}
/**
* Method description
*
*/
@Test
public void testCreateAllreadyExists()
{
repository = RepositoryTestData.create42Puzzle(repositoryType);
repository = createRepository(client, repository);
WebResource wr = createResource(client, "repositories");
ClientResponse response =
wr.post(ClientResponse.class,
RepositoryTestData.create42Puzzle(repositoryType));
assertNotNull(response);
assertEquals(500, response.getStatus());
response.close();
}
/**
* Method description
*
*/
@Test
public void testCreateAllreadyExistsWithStructure()
{
repository = RepositoryTestData.create42Puzzle(repositoryType);
repository = createRepository(client, repository);
Repository r = RepositoryTestData.create42Puzzle(repositoryType);
r.setName(r.getName() + "/" + r.getName());
WebResource wr = createResource(client, "repositories");
ClientResponse response = wr.post(ClientResponse.class, r);
assertNotNull(response);
System.out.println( response.getStatus() );
assertEquals(500, response.getStatus());
response.close();
}
/**
* Method description
*
*/
@Test
public void testCreateWithStructure()
{
repository = RepositoryTestData.createHeartOfGold(repositoryType);
repository.setName("test/".concat(repository.getName()));
repository = createRepository(client, repository);
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private Repository repository;
/** Field description */
private String repositoryType;
}

View File

@@ -1,137 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import sonia.scm.user.User;
import sonia.scm.user.UserTestData;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
/**
*
* @author Sebastian Sdorra
*/
public class DeactivatedUserITCase
{
/**
* Method description
*
*/
@Before
public void createDeactivatedUser()
{
Client client = createAdminClient();
try
{
WebResource wr = createResource(client, "users");
slarti = UserTestData.createSlarti();
slarti.setPassword("slart123");
slarti.setActive(false);
ClientResponse response =
wr.type(MediaType.APPLICATION_XML).post(ClientResponse.class, slarti);
assertNotNull(response);
assertEquals(201, response.getStatus());
response.close();
}
finally
{
client.destroy();
}
}
/**
* Method description
*
*/
@After
public void destroyDeactivatedUser()
{
Client client = createAdminClient();
try
{
WebResource wr = createResource(client,
"users/".concat(slarti.getName()));
ClientResponse response =
wr.type(MediaType.APPLICATION_XML).delete(ClientResponse.class);
assertNotNull(response);
assertEquals(204, response.getStatus());
response.close();
}
finally
{
client.destroy();
}
}
/**
* Method description
*
*/
@Test
public void testFailedAuthentication()
{
Client client = createClient();
ClientResponse response = authenticate(client, slarti.getName(), "slart123");
assertNotNull(response);
assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus());
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private User slarti;
}

View File

@@ -36,251 +36,259 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException; import com.sun.jersey.api.client.UniformInterfaceException;
import java.io.IOException;
import java.util.UUID;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.shiro.crypto.hash.Sha256Hash; import org.apache.shiro.crypto.hash.Sha256Hash;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.After; import org.junit.After;
import org.junit.Test;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule; import org.junit.Rule;
import org.junit.rules.TemporaryFolder; import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import static sonia.scm.it.IntegrationTestUtil.*; import sonia.scm.api.rest.ObjectMapperProvider;
import static sonia.scm.it.RepositoryITUtil.*; import sonia.scm.api.v2.resources.RepositoryDto;
import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType; import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.user.UserTestData; import sonia.scm.user.UserTestData;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.IOException;
import java.util.UUID;
import static org.junit.Assert.assertArrayEquals;
import static sonia.scm.it.IntegrationTestUtil.BASE_URL;
import static sonia.scm.it.IntegrationTestUtil.REST_BASE_URL;
import static sonia.scm.it.IntegrationTestUtil.createAdminClient;
import static sonia.scm.it.IntegrationTestUtil.readJson;
import static sonia.scm.it.RepositoryITUtil.createRepository;
import static sonia.scm.it.RepositoryITUtil.deleteRepository;
/** /**
* Integration tests for git lfs. * Integration tests for git lfs.
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
public class GitLfsITCase { public class GitLfsITCase {
@Rule @Rule
public ExpectedException expectedException = ExpectedException.none(); public ExpectedException expectedException = ExpectedException.none();
@Rule @Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder(); public TemporaryFolder temporaryFolder = new TemporaryFolder();
private final ObjectMapper mapper = new ObjectMapper(); private final ObjectMapper mapper = new ObjectMapper();
private Client adminClient; private ScmClient adminClient;
private Repository repository; private RepositoryDto repository;
public GitLfsITCase() { public GitLfsITCase() {
mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector(TypeFactory.defaultInstance())); mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector(TypeFactory.defaultInstance()));
} }
// lifecycle methods // lifecycle methods
@Before @Before
public void setUpTestDependencies() { public void setUpTestDependencies() {
adminClient = createAdminClient(); adminClient = createAdminClient();
repository = createRepository(adminClient, RepositoryTestData.createHeartOfGold("git")); repository = createRepository(adminClient, readJson("repository-git.json"));
} }
@After @After
public void tearDownTestDependencies() { public void tearDownTestDependencies() {
deleteRepository(adminClient, repository.getId()); deleteRepository(adminClient, repository);
adminClient.destroy();
} }
// tests // tests
@Test @Test
public void testLfsAPIWithAdminPermissions() throws IOException { public void testLfsAPIWithAdminPermissions() throws IOException {
uploadAndDownload(adminClient); uploadAndDownload(adminClient);
} }
@Test @Test
@Ignore("permissions not yet implemented")
public void testLfsAPIWithOwnerPermissions() throws IOException { public void testLfsAPIWithOwnerPermissions() throws IOException {
uploadAndDownloadAsUser(PermissionType.OWNER); uploadAndDownloadAsUser(PermissionType.OWNER);
} }
private void uploadAndDownloadAsUser(PermissionType permissionType) throws IOException { private void uploadAndDownloadAsUser(PermissionType permissionType) throws IOException {
User trillian = UserTestData.createTrillian(); User trillian = UserTestData.createTrillian();
trillian.setPassword("secret123"); trillian.setPassword("secret123");
createUser(trillian); createUser(trillian);
try {
repository.getPermissions().add(new Permission(trillian.getId(), permissionType));
modifyRepository(repository);
Client client = createClient(); try {
authenticate(client, trillian.getId(), "secret123"); // TODO enable when permissions are implemented in v2
// repository.getPermissions().add(new Permission(trillian.getId(), permissionType));
// modifyRepository(repository);
ScmClient client = new ScmClient(trillian.getId(), "secret123");
uploadAndDownload(client); uploadAndDownload(client);
} finally { } finally {
removeUser(trillian); removeUser(trillian);
} }
} }
@Test @Test
@Ignore("permissions not yet implemented")
public void testLfsAPIWithWritePermissions() throws IOException { public void testLfsAPIWithWritePermissions() throws IOException {
uploadAndDownloadAsUser(PermissionType.WRITE); uploadAndDownloadAsUser(PermissionType.WRITE);
} }
private void createUser(User user) { private void createUser(User user) {
adminClient.resource(REST_BASE_URL + "users.json").post(user); adminClient.resource(REST_BASE_URL + "users.json").post(user);
} }
private void modifyRepository(Repository repository) { private void modifyRepository(Repository repository) {
adminClient.resource(REST_BASE_URL + "repositories/" + repository.getId() + ".json").put(repository); adminClient.resource(REST_BASE_URL + "repositories/" + repository.getId() + ".json").put(repository);
} }
private void removeUser(User user) { private void removeUser(User user) {
adminClient.resource(REST_BASE_URL + "users/" + user.getId() + ".json").delete(); adminClient.resource(REST_BASE_URL + "users/" + user.getId() + ".json").delete();
} }
@Test @Test
@Ignore("permissions not yet implemented")
public void testLfsAPIWithoutWritePermissions() throws IOException { public void testLfsAPIWithoutWritePermissions() throws IOException {
User trillian = UserTestData.createTrillian(); User trillian = UserTestData.createTrillian();
trillian.setPassword("secret123"); trillian.setPassword("secret123");
createUser(trillian); createUser(trillian);
expectedException.expect(UniformInterfaceException.class); expectedException.expect(UniformInterfaceException.class);
expectedException.expectMessage(Matchers.containsString("403")); expectedException.expectMessage(Matchers.containsString("403"));
try {
repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ));
modifyRepository(repository);
Client client = createClient();
authenticate(client, trillian.getId(), "secret123");
try {
// TODO enable when permissions are implemented in v2
// repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ));
// modifyRepository(repository);
ScmClient client = new ScmClient(trillian.getId(), "secret123");
uploadAndDownload(client); uploadAndDownload(client);
} finally { } finally {
removeUser(trillian); removeUser(trillian);
} }
} }
@Test @Test
@Ignore("permissions not yet implemented")
public void testLfsDownloadWithReadPermissions() throws IOException { public void testLfsDownloadWithReadPermissions() throws IOException {
User trillian = UserTestData.createTrillian(); User trillian = UserTestData.createTrillian();
trillian.setPassword("secret123"); trillian.setPassword("secret123");
createUser(trillian); createUser(trillian);
try { try {
repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ)); // TODO enable when permissions are implemented in v2
modifyRepository(repository); // repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ));
// modifyRepository(repository);
// upload data as admin // upload data as admin
String data = UUID.randomUUID().toString(); String data = UUID.randomUUID().toString();
byte[] dataAsBytes = data.getBytes(Charsets.UTF_8); byte[] dataAsBytes = data.getBytes(Charsets.UTF_8);
LfsObject lfsObject = upload(adminClient, dataAsBytes); LfsObject lfsObject = upload(adminClient, dataAsBytes);
Client client = createClient(); ScmClient client = new ScmClient(trillian.getId(), "secret123");
authenticate(client, trillian.getId(), "secret123");
// download as user // download as user
byte[] downloadedData = download(client, lfsObject); byte[] downloadedData = download(client, lfsObject);
// assert both are equal // assert both are equal
assertArrayEquals(dataAsBytes, downloadedData); assertArrayEquals(dataAsBytes, downloadedData);
} finally { } finally {
removeUser(trillian); removeUser(trillian);
} }
} }
// lfs api // lfs api
private void uploadAndDownload(Client client) throws IOException { private void uploadAndDownload(ScmClient client) throws IOException {
String data = UUID.randomUUID().toString(); String data = UUID.randomUUID().toString();
byte[] dataAsBytes = data.getBytes(Charsets.UTF_8); byte[] dataAsBytes = data.getBytes(Charsets.UTF_8);
LfsObject lfsObject = upload(client, dataAsBytes); LfsObject lfsObject = upload(client, dataAsBytes);
byte[] downloadedData = download(client, lfsObject); byte[] downloadedData = download(client, lfsObject);
assertArrayEquals(dataAsBytes, downloadedData); assertArrayEquals(dataAsBytes, downloadedData);
} }
private LfsObject upload(Client client, byte[] data) throws IOException { private LfsObject upload(ScmClient client, byte[] data) throws IOException {
LfsObject lfsObject = createLfsObject(data); LfsObject lfsObject = createLfsObject(data);
LfsRequestBody request = LfsRequestBody.createUploadRequest(lfsObject); LfsRequestBody request = LfsRequestBody.createUploadRequest(lfsObject);
LfsResponseBody response = request(client, request); LfsResponseBody response = request(client, request);
String uploadURL = response.objects[0].actions.upload.href; String uploadURL = response.objects[0].actions.upload.href;
client.resource(uploadURL).put(data); client.resource(uploadURL).put(data);
return lfsObject; return lfsObject;
} }
private LfsResponseBody request(Client client, LfsRequestBody request) throws IOException { private LfsResponseBody request(ScmClient client, LfsRequestBody request) throws IOException {
String batchUrl = createBatchUrl(); String batchUrl = createBatchUrl();
String requestAsString = mapper.writeValueAsString(request); String requestAsString = mapper.writeValueAsString(request);
return client String json = client
.resource(batchUrl) .resource(batchUrl)
.accept("application/vnd.git-lfs+json") .accept("application/vnd.git-lfs+json")
.header("Content-Type", "application/vnd.git-lfs+json") .header("Content-Type", "application/vnd.git-lfs+json")
.post(LfsResponseBody.class, requestAsString); .post(String.class, requestAsString);
return new ObjectMapperProvider().get().readValue(json, LfsResponseBody.class);
} }
private String createBatchUrl() { private String createBatchUrl() {
String url = repository.createUrl(BASE_URL); String url = BASE_URL + "git/" + repository.getNamespace() + "/" + repository.getName();
return url + "/info/lfs/objects/batch"; return url + "/info/lfs/objects/batch";
} }
private byte[] download(Client client, LfsObject lfsObject) throws IOException { private byte[] download(ScmClient client, LfsObject lfsObject) throws IOException {
LfsRequestBody request = LfsRequestBody.createDownloadRequest(lfsObject); LfsRequestBody request = LfsRequestBody.createDownloadRequest(lfsObject);
LfsResponseBody response = request(client, request); LfsResponseBody response = request(client, request);
String downloadUrl = response.objects[0].actions.download.href; String downloadUrl = response.objects[0].actions.download.href;
return client.resource(downloadUrl).get(byte[].class); return client.resource(downloadUrl).get(byte[].class);
} }
private LfsObject createLfsObject(byte[] data) { private LfsObject createLfsObject(byte[] data) {
Sha256Hash hash = new Sha256Hash(data); Sha256Hash hash = new Sha256Hash(data);
String oid = hash.toHex(); String oid = hash.toHex();
return new LfsObject(oid, data.length); return new LfsObject(oid, data.length);
} }
// LFS DTO objects // LFS DTO objects
@XmlRootElement @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
private static class LfsRequestBody { private static class LfsRequestBody {
private String operation; private String operation;
private String[] transfers = new String[]{ "basic" }; private String[] transfers = new String[]{ "basic" };
private LfsObject[] objects; private LfsObject[] objects;
public LfsRequestBody() { public LfsRequestBody() {
} }
private LfsRequestBody(String operation, LfsObject[] objects) { private LfsRequestBody(String operation, LfsObject[] objects) {
this.operation = operation; this.operation = operation;
this.objects = objects; this.objects = objects;
} }
public static LfsRequestBody createUploadRequest(LfsObject object) { public static LfsRequestBody createUploadRequest(LfsObject object) {
return new LfsRequestBody("upload", new LfsObject[]{object}); return new LfsRequestBody("upload", new LfsObject[]{object});
} }
public static LfsRequestBody createDownloadRequest(LfsObject object) { public static LfsRequestBody createDownloadRequest(LfsObject object) {
return new LfsRequestBody("download", new LfsObject[]{object}); return new LfsRequestBody("download", new LfsObject[]{object});
} }
} }
@XmlRootElement @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
private static class LfsResponseBody { private static class LfsResponseBody {
private LfsObject[] objects; private LfsObject[] objects;
public LfsResponseBody() { public LfsResponseBody() {
@@ -290,11 +298,11 @@ public class GitLfsITCase {
this.objects = objects; this.objects = objects;
} }
} }
@XmlRootElement @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
private static class LfsObject { private static class LfsObject {
private String oid; private String oid;
private long size; private long size;
private LfsActions actions; private LfsActions actions;
@@ -312,24 +320,24 @@ public class GitLfsITCase {
this.size = size; this.size = size;
this.actions = actions; this.actions = actions;
} }
} }
@XmlRootElement @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
private static class LfsActions { private static class LfsActions {
private LfsAction upload; private LfsAction upload;
private LfsAction download; private LfsAction download;
public LfsActions() { public LfsActions() {
} }
} }
@XmlRootElement @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
private static class LfsAction { private static class LfsAction {
private String href; private String href;
public LfsAction() { public LfsAction() {
@@ -338,7 +346,7 @@ public class GitLfsITCase {
public LfsAction(String href) { public LfsAction(String href) {
this.href = href; this.href = href;
} }
} }
} }

View File

@@ -32,103 +32,108 @@ package sonia.scm.it;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.sun.jersey.api.client.Client;
import java.io.File;
import java.io.IOException;
import org.junit.After; import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import static sonia.scm.it.IntegrationTestUtil.*; import sonia.scm.api.v2.resources.RepositoryDto;
import static sonia.scm.it.RepositoryITUtil.*;
import sonia.scm.repository.Person; import sonia.scm.repository.Person;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.repository.client.api.ClientCommand; import sonia.scm.repository.client.api.ClientCommand;
import sonia.scm.repository.client.api.RepositoryClient; import sonia.scm.repository.client.api.RepositoryClient;
import sonia.scm.repository.client.api.RepositoryClientFactory; import sonia.scm.repository.client.api.RepositoryClientFactory;
import java.io.File;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static sonia.scm.it.IntegrationTestUtil.ADMIN_PASSWORD;
import static sonia.scm.it.IntegrationTestUtil.ADMIN_USERNAME;
import static sonia.scm.it.IntegrationTestUtil.BASE_URL;
import static sonia.scm.it.IntegrationTestUtil.createAdminClient;
import static sonia.scm.it.IntegrationTestUtil.readJson;
import static sonia.scm.it.RepositoryITUtil.createRepository;
import static sonia.scm.it.RepositoryITUtil.deleteRepository;
/** /**
* Integration test for RepositoryPathMatching with ".git" and without ".git". * Integration test for RepositoryPathMatching with ".git" and without ".git".
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
* @since 1.54 * @since 1.54
*/ */
public class GitRepositoryPathMatcherITCase { public class GitRepositoryPathMatcherITCase {
private static final RepositoryClientFactory REPOSITORY_CLIENT_FACTORY = new RepositoryClientFactory(); private static final RepositoryClientFactory REPOSITORY_CLIENT_FACTORY = new RepositoryClientFactory();
@Rule @Rule
public TemporaryFolder tempFolder = new TemporaryFolder(); public TemporaryFolder tempFolder = new TemporaryFolder();
private Client apiClient; private ScmClient apiClient;
private Repository repository; private RepositoryDto repository;
@Before @Before
public void setUp() { public void setUp() {
apiClient = createAdminClient(); apiClient = createAdminClient();
Repository testRepository = RepositoryTestData.createHeartOfGold("git"); this.repository = createRepository(apiClient, readJson("repository-git.json"));
this.repository = createRepository(apiClient, testRepository);
} }
@After @After
public void tearDown() { public void tearDown() {
deleteRepository(apiClient, repository.getId()); deleteRepository(apiClient, repository);
} }
// tests begin // tests begin
@Test @Test
public void testWithoutDotGit() throws IOException { public void testWithoutDotGit() throws IOException {
String urlWithoutDotGit = createUrl(); String urlWithoutDotGit = createUrl();
cloneAndPush(urlWithoutDotGit); cloneAndPush(urlWithoutDotGit);
} }
@Test @Test
public void testWithDotGit() throws IOException { public void testWithDotGit() throws IOException {
String urlWithDotGit = createUrl() + ".git"; String urlWithDotGit = createUrl() + ".git";
cloneAndPush(urlWithDotGit); cloneAndPush(urlWithDotGit);
} }
// tests end // tests end
private String createUrl() { private String createUrl() {
return BASE_URL + "git/" + repository.getName(); return BASE_URL + "git/" + repository.getNamespace() + "/" + repository.getName();
} }
private void cloneAndPush( String url ) throws IOException { private void cloneAndPush( String url ) throws IOException {
cloneRepositoryAndPushFiles(url); cloneRepositoryAndPushFiles(url);
cloneRepositoryAndCheckFiles(url); cloneRepositoryAndCheckFiles(url);
} }
private void cloneRepositoryAndPushFiles(String url) throws IOException { private void cloneRepositoryAndPushFiles(String url) throws IOException {
RepositoryClient repositoryClient = createRepositoryClient(url); RepositoryClient repositoryClient = createRepositoryClient(url);
Files.write("a", new File(repositoryClient.getWorkingCopy(), "a.txt"), Charsets.UTF_8); Files.write("a", new File(repositoryClient.getWorkingCopy(), "a.txt"), Charsets.UTF_8);
repositoryClient.getAddCommand().add("a.txt"); repositoryClient.getAddCommand().add("a.txt");
commit(repositoryClient, "added a"); commit(repositoryClient, "added a");
Files.write("b", new File(repositoryClient.getWorkingCopy(), "b.txt"), Charsets.UTF_8); Files.write("b", new File(repositoryClient.getWorkingCopy(), "b.txt"), Charsets.UTF_8);
repositoryClient.getAddCommand().add("b.txt"); repositoryClient.getAddCommand().add("b.txt");
commit(repositoryClient, "added b"); commit(repositoryClient, "added b");
} }
private void cloneRepositoryAndCheckFiles(String url) throws IOException { private void cloneRepositoryAndCheckFiles(String url) throws IOException {
RepositoryClient repositoryClient = createRepositoryClient(url); RepositoryClient repositoryClient = createRepositoryClient(url);
File workingCopy = repositoryClient.getWorkingCopy(); File workingCopy = repositoryClient.getWorkingCopy();
File a = new File(workingCopy, "a.txt"); File a = new File(workingCopy, "a.txt");
assertTrue(a.exists()); assertTrue(a.exists());
assertEquals("a", Files.toString(a, Charsets.UTF_8)); assertEquals("a", Files.toString(a, Charsets.UTF_8));
File b = new File(workingCopy, "b.txt"); File b = new File(workingCopy, "b.txt");
assertTrue(b.exists()); assertTrue(b.exists());
assertEquals("b", Files.toString(b, Charsets.UTF_8)); assertEquals("b", Files.toString(b, Charsets.UTF_8));
} }
private void commit(RepositoryClient repositoryClient, String message) throws IOException { private void commit(RepositoryClient repositoryClient, String message) throws IOException {
repositoryClient.getCommitCommand().commit( repositoryClient.getCommitCommand().commit(
new Person("scmadmin", "scmadmin@scm-manager.org"), message new Person("scmadmin", "scmadmin@scm-manager.org"), message
); );
@@ -136,7 +141,7 @@ public class GitRepositoryPathMatcherITCase {
repositoryClient.getPushCommand().push(); repositoryClient.getPushCommand().push();
} }
} }
private RepositoryClient createRepositoryClient(String url) throws IOException { private RepositoryClient createRepositoryClient(String url) throws IOException {
return REPOSITORY_CLIENT_FACTORY.create("git", url, ADMIN_USERNAME, ADMIN_PASSWORD, tempFolder.newFolder()); return REPOSITORY_CLIENT_FACTORY.create("git", url, ADMIN_USERNAME, ADMIN_PASSWORD, tempFolder.newFolder());
} }

View File

@@ -1,265 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.AfterClass;
import org.junit.Test;
import sonia.scm.group.Group;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
*
* @author Sebastian Sdorra
*/
public class GroupITCase extends AbstractAdminITCaseBase
{
/**
* Method description
*
*/
@AfterClass
public static void cleanup()
{
Client client = createClient();
authenticateAdmin(client);
createResource(client, "groups/group-a").delete();
createResource(client, "groups/group-c").delete();
client.destroy();
}
/**
* Method description
*
*/
@Test
public void create()
{
Group group = new Group();
group.setName("group-a");
group.setDescription("group a");
List<String> members = new ArrayList<String>();
members.add("slarti");
members.add("marvin");
members.add("dent");
group.setMembers(members);
createGroup(group);
}
/**
* Method description
*
*/
@Test
public void delete()
{
Group group = new Group();
group.setName("group-b");
group.setDescription("group b");
List<String> members = new ArrayList<String>();
members.add("slarti");
members.add("dent");
group.setMembers(members);
createGroup(group);
deleteGroup(group.getName());
}
/**
* Method description
*
*/
@Test
public void modify()
{
Group group = new Group();
group.setName("group-d");
group.setDescription("group d");
createGroup(group);
group = getGroup(group.getName());
group.setDescription("GROUP D");
WebResource wr = createResource(client, "groups/group-d");
ClientResponse response = wr.put(ClientResponse.class, group);
assertNotNull(response);
assertEquals(204, response.getStatus());
response.close();
Group other = getGroup("group-d");
assertEquals(group.getName(), other.getName());
assertEquals(group.getDescription(), other.getDescription());
assertNotNull(other.getLastModified());
deleteGroup(other.getName());
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*/
@Test
public void getAll()
{
Group group = new Group();
group.setName("group-c");
createGroup(group);
WebResource wr = createResource(client, "groups");
ClientResponse response = wr.get(ClientResponse.class);
Collection<Group> groups =
response.getEntity(new GenericType<Collection<Group>>() {}
);
response.close();
assertNotNull(groups);
assertFalse(groups.isEmpty());
Group groupC = null;
for (Group g : groups)
{
if (g.getName().equals("group-c"))
{
groupC = g;
}
}
assertNotNull(groupC);
assertNotNull(groupC.getCreationDate());
assertNotNull(groupC.getType());
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param group
*/
private void createGroup(Group group)
{
WebResource wr = createResource(client, "groups");
ClientResponse response = wr.post(ClientResponse.class, group);
assertNotNull(response);
assertEquals(201, response.getStatus());
response.close();
Group other = getGroup(group.getName());
assertNotNull(other);
assertNotNull(other.getType());
assertEquals(group.getName(), other.getName());
assertEquals(group.getDescription(), other.getDescription());
assertArrayEquals(other.getMembers().toArray(new String[0]),
group.getMembers().toArray(new String[0]));
assertNotNull(other.getCreationDate());
}
/**
* Method description
*
*
* @param name
*/
private void deleteGroup(String name)
{
WebResource wr = createResource(client, "groups/".concat(name));
ClientResponse response = wr.delete(ClientResponse.class);
assertNotNull(response);
assertEquals(204, response.getStatus());
response.close();
wr = createResource(client, "groups/".concat(name));
response = wr.get(ClientResponse.class);
assertNotNull(response);
assertEquals(404, response.getStatus());
response.close();
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param groupname
*
* @return
*/
private Group getGroup(String groupname)
{
WebResource wr = createResource(client, "groups/".concat(groupname));
ClientResponse response = wr.get(ClientResponse.class);
assertNotNull(response);
Group group = response.getEntity(Group.class);
response.close();
assertNotNull(group);
assertEquals(groupname, group.getName());
return group;
}
}

View File

@@ -1,185 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import sonia.scm.group.Group;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
/**
*
* @author Sebastian Sdorra
*/
@RunWith(Parameterized.class)
public class GroupPermissionITCase extends AbstractPermissionITCaseBase<Group>
{
/**
* Constructs ...
*
*
* @param credentials
*/
public GroupPermissionITCase(Credentials credentials)
{
super(credentials);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*/
@AfterClass
public static void cleanup()
{
Client client = createClient();
authenticateAdmin(client);
createResource(client, "groups/test-group").delete();
client.destroy();
}
/**
* Method description
*
*/
@BeforeClass
public static void createTestGroup()
{
Group testGroup = new Group("xml", "test-group");
Client client = createClient();
authenticateAdmin(client);
WebResource wr = createResource(client, "groups");
ClientResponse response = wr.post(ClientResponse.class, testGroup);
assertNotNull(response);
assertEquals(201, response.getStatus());
response.close();
logoutClient(client);
client.destroy();
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
protected String getBasePath()
{
return "groups";
}
/**
* Method description
*
*
* @return
*/
@Override
protected Group getCreateItem()
{
return new Group("xml", "create-test-group");
}
/**
* Method description
*
*
* @return
*/
@Override
protected String getDeletePath()
{
return "groups/test-group";
}
/**
* Method description
*
*
* @return
*/
@Override
protected String getGetPath()
{
return "groups/test-group";
}
/**
* Method description
*
*
* @return
*/
@Override
protected Group getModifyItem()
{
return new Group("xml", "test-group", "dent", "zaphod", "trillian");
}
/**
* Method description
*
*
* @return
*/
@Override
protected String getModifyPath()
{
return "groups/test-group";
}
}

View File

@@ -35,24 +35,25 @@ package sonia.scm.it;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import org.junit.After; import org.junit.After;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.Matchers.*; import javax.ws.rs.core.EntityTag;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import java.util.Date; import java.util.Date;
import javax.ws.rs.core.EntityTag; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static sonia.scm.it.IntegrationTestUtil.createAdminClient;
import static sonia.scm.it.IntegrationTestUtil.createResource;
//~--- JDK imports ------------------------------------------------------------
/** /**
* *
@@ -188,8 +189,8 @@ public abstract class HttpCacheITCaseBase<T>
*/ */
private ClientResponse getCollectionResponse() private ClientResponse getCollectionResponse()
{ {
Client client = createAdminClient(); ScmClient client = createAdminClient();
WebResource resource = createResource(client, getCollectionUrlPart()); WebResource.Builder resource = createResource(client, getCollectionUrlPart());
ClientResponse response = resource.get(ClientResponse.class); ClientResponse response = resource.get(ClientResponse.class);
assertEquals(200, response.getStatus()); assertEquals(200, response.getStatus());

View File

@@ -35,33 +35,33 @@ package sonia.scm.it;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.Resources;
import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.client.apache.ApacheHttpClient; import com.sun.jersey.client.apache.ApacheHttpClient;
import com.sun.jersey.client.apache.config.ApacheHttpClientConfig; import com.sun.jersey.client.apache.config.ApacheHttpClientConfig;
import com.sun.jersey.client.apache.config.DefaultApacheHttpClientConfig; import com.sun.jersey.client.apache.config.DefaultApacheHttpClientConfig;
import com.sun.jersey.core.util.MultivaluedMapImpl; import de.otto.edison.hal.HalRepresentation;
import sonia.scm.ScmState;
import sonia.scm.Type;
import sonia.scm.api.rest.JSONContextResolver; import sonia.scm.api.rest.JSONContextResolver;
import sonia.scm.api.rest.ObjectMapperProvider; import sonia.scm.api.rest.ObjectMapperProvider;
import sonia.scm.repository.Person; import sonia.scm.repository.Person;
import sonia.scm.repository.client.api.ClientCommand; import sonia.scm.repository.client.api.ClientCommand;
import sonia.scm.repository.client.api.RepositoryClient; import sonia.scm.repository.client.api.RepositoryClient;
import sonia.scm.user.User;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
import javax.ws.rs.core.MultivaluedMap;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.UUID; import java.util.UUID;
import static org.junit.Assert.*;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
/** /**
@@ -83,7 +83,7 @@ public final class IntegrationTestUtil
public static final String BASE_URL = "http://localhost:8081/scm/"; public static final String BASE_URL = "http://localhost:8081/scm/";
/** scm-manager base url for the rest api */ /** scm-manager base url for the rest api */
public static final String REST_BASE_URL = BASE_URL.concat("api/rest/"); public static final String REST_BASE_URL = BASE_URL.concat("api/rest/v2/");
//~--- constructors --------------------------------------------------------- //~--- constructors ---------------------------------------------------------
@@ -95,72 +95,10 @@ public final class IntegrationTestUtil
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param client
* @param username
* @param password
*
* @return
*/
public static ClientResponse authenticate(Client client, String username, String password) {
WebResource wr = client.resource(createResourceUrl("auth/access_token"));
MultivaluedMap<String, String> formData = new MultivaluedMapImpl();
formData.add("username", username); public static ScmClient createAdminClient()
formData.add("password", password);
formData.add("cookie", "true");
formData.add("grant_type", "password");
return wr.type("application/x-www-form-urlencoded").post(ClientResponse.class, formData);
}
/**
* Method description
*
*
* @param client
*
* @return
*/
public static ScmState authenticateAdmin(Client client)
{ {
ClientResponse cr = authenticate(client, ADMIN_USERNAME, ADMIN_PASSWORD); return new ScmClient("scmadmin", "scmadmin");
ScmState state = cr.getEntity(ScmState.class);
cr.close();
assertNotNull(state);
assertTrue(state.isSuccess());
User user = state.getUser();
assertNotNull(user);
assertEquals("scmadmin", user.getName());
assertTrue(user.isAdmin());
Collection<Type> types = state.getRepositoryTypes();
assertNotNull(types);
assertFalse(types.isEmpty());
return state;
}
/**
* Method description
*
*
* @return
*/
public static Client createAdminClient()
{
Client client = createClient();
authenticateAdmin(client);
return client;
} }
/** /**
@@ -178,6 +116,15 @@ public final class IntegrationTestUtil
return ApacheHttpClient.create(config); return ApacheHttpClient.create(config);
} }
public static String serialize(Object o) {
ObjectMapper mapper = new ObjectMapperProvider().get();
try {
return mapper.writeValueAsString(o);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
/** /**
* Commit and push changes. * Commit and push changes.
* *
@@ -236,18 +183,21 @@ public final class IntegrationTestUtil
return params; return params;
} }
/** public static URI getLink(HalRepresentation object, String linkName) {
* Method description return URI.create(object.getLinks().getLinkBy("delete").get().getHref());
* }
*
* @param client public static WebResource.Builder createResource(ScmClient client, String url) {
* @param url return createResource(client, createResourceUrl(url));
* }
* @return public static WebResource.Builder createResource(ScmClient client, URI url) {
*/ return client.resource(url.toString());
public static WebResource createResource(Client client, String url) }
{
return client.resource(createResourceUrl(url)); public static ClientResponse post(ScmClient client, String path, String mediaType, Object o) {
return createResource(client, path)
.type(mediaType)
.post(ClientResponse.class, serialize(o));
} }
/** /**
@@ -258,9 +208,9 @@ public final class IntegrationTestUtil
* *
* @return * @return
*/ */
public static String createResourceUrl(String url) public static URI createResourceUrl(String url)
{ {
return REST_BASE_URL.concat(url); return URI.create(REST_BASE_URL).resolve(url);
} }
/** /**
@@ -269,30 +219,20 @@ public final class IntegrationTestUtil
* *
* @return * @return
*/ */
public static File createTempDirectory() public static File createTempDirectory() {
{ File directory = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString());
File directory = new File(System.getProperty("java.io.tmpdir"),
UUID.randomUUID().toString());
IOUtil.mkdirs(directory); IOUtil.mkdirs(directory);
return directory; return directory;
} }
/** public static String readJson(String jsonFileName) {
* Method description URL url = Resources.getResource(jsonFileName);
* try {
* return Resources.toString(url, Charset.forName("UTF-8"));
* @param client } catch (IOException e) {
*/ throw new RuntimeException("could not read json file " + jsonFileName, e);
public static void logoutClient(Client client) }
{
WebResource wr = createResource(client, "auth/logout");
ClientResponse response = wr.get(ClientResponse.class);
assertNotNull(response);
assertEquals(200, response.getStatus());
response.close();
client.destroy();
} }
} }

View File

@@ -35,27 +35,32 @@ package sonia.scm.it;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import sonia.scm.api.v2.resources.ConfigDto;
import sonia.scm.api.v2.resources.RepositoryDto;
import sonia.scm.web.VndMediaType;
import sonia.scm.config.ScmConfiguration; import javax.ws.rs.core.MediaType;
import sonia.scm.repository.Repository; import java.net.URI;
import sonia.scm.repository.RepositoryTestData;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static sonia.scm.it.IntegrationTestUtil.*; import static sonia.scm.it.IntegrationTestUtil.createAdminClient;
import static sonia.scm.it.RepositoryITUtil.*; import static sonia.scm.it.IntegrationTestUtil.createResource;
import static sonia.scm.it.IntegrationTestUtil.getLink;
import static sonia.scm.it.IntegrationTestUtil.readJson;
import static sonia.scm.it.IntegrationTestUtil.serialize;
import static sonia.scm.it.RepositoryITUtil.createRepository;
import static sonia.scm.it.RepositoryITUtil.deleteRepository;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
/** /**
* *
@@ -83,11 +88,9 @@ public class RepositoryArchiveITCase extends RepositoryTypeITCaseBase
* *
*/ */
@Before @Before
public void createTestRepository() public void createTestRepository() {
{
repository = RepositoryTestData.createHeartOfGold(type);
client = createAdminClient(); client = createAdminClient();
repository = createRepository(client, repository); repository = createRepository(client, readJson("repository-" + type + ".json"));
} }
/** /**
@@ -101,10 +104,8 @@ public class RepositoryArchiveITCase extends RepositoryTypeITCaseBase
if (repository != null) if (repository != null)
{ {
deleteRepository(client, repository.getId()); deleteRepository(client, repository);
} }
logoutClient(client);
} }
/** /**
@@ -112,20 +113,19 @@ public class RepositoryArchiveITCase extends RepositoryTypeITCaseBase
* *
*/ */
@Test @Test
public void testDeleteAllowed() public void testDeleteAllowed() {
{
setArchiveMode(true); setArchiveMode(true);
WebResource resource = createResource(client,
"repositories/".concat(repository.getId()));
repository.setArchived(true); repository.setArchived(true);
ClientResponse response = resource.put(ClientResponse.class, repository); ClientResponse response = createResource(client,
"repositories/" + repository.getNamespace() + "/" + repository.getName())
.type(VndMediaType.REPOSITORY).put(ClientResponse.class, serialize(repository));
assertNotNull(response); assertNotNull(response);
assertEquals(204, response.getStatus()); assertEquals(204, response.getStatus());
response = resource.delete(ClientResponse.class); response = createResource(client,
"repositories/" + repository.getNamespace() + "/" + repository.getName()).delete(ClientResponse.class);
assertNotNull(response); assertNotNull(response);
assertEquals(204, response.getStatus()); assertEquals(204, response.getStatus());
repository = null; repository = null;
@@ -140,12 +140,12 @@ public class RepositoryArchiveITCase extends RepositoryTypeITCaseBase
{ {
setArchiveMode(true); setArchiveMode(true);
WebResource resource = createResource(client, URI deleteUrl = getLink(repository, "delete");
"repositories/".concat(repository.getId())); ClientResponse response = createResource(client, deleteUrl).delete(ClientResponse.class);
ClientResponse response = resource.delete(ClientResponse.class);
assertNotNull(response); assertNotNull(response);
assertEquals(412, response.getStatus()); assertEquals(412, response.getStatus());
response.close();
} }
//~--- set methods ---------------------------------------------------------- //~--- set methods ----------------------------------------------------------
@@ -158,25 +158,25 @@ public class RepositoryArchiveITCase extends RepositoryTypeITCaseBase
*/ */
private void setArchiveMode(boolean archive) private void setArchiveMode(boolean archive)
{ {
WebResource resource = createResource(client, "config"); WebResource.Builder resource = createResource(client, "config").type(MediaType.APPLICATION_JSON);
ScmConfiguration config = resource.get(ScmConfiguration.class); ConfigDto config = resource.get(ConfigDto.class);
assertNotNull(config); assertNotNull(config);
config.setEnableRepositoryArchive(archive); config.setEnableRepositoryArchive(archive);
ClientResponse resp = resource.post(ClientResponse.class, config); ClientResponse resp = createResource(client, "config").type(VndMediaType.CONFIG).put(ClientResponse.class, config);
assertNotNull(resp); assertNotNull(resp);
assertEquals(201, resp.getStatus()); assertEquals(204, resp.getStatus());
} }
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */ /** Field description */
private Client client; private ScmClient client;
/** Field description */ /** Field description */
private Repository repository; private RepositoryDto repository;
/** Field description */ /** Field description */
private String type; private String type;

View File

@@ -37,31 +37,30 @@ package sonia.scm.it;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import sonia.scm.api.v2.resources.RepositoryDto;
import sonia.scm.repository.Repository; import sonia.scm.repository.client.api.RepositoryClient;
import sonia.scm.repository.client.api.RepositoryClientException;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
//~--- JDK imports ------------------------------------------------------------
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import sonia.scm.repository.client.api.RepositoryClient; import static org.junit.Assert.fail;
import sonia.scm.repository.client.api.RepositoryClientException; import static sonia.scm.it.IntegrationTestUtil.createTempDirectory;
//~--- JDK imports ------------------------------------------------------------
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@RunWith(Parameterized.class) @RunWith(Parameterized.class)
@Ignore("permissions not yet implemented -- see RepositoryITCaseBase#createTestRepository")
public class RepositoryExtendedITCase extends RepositoryITCaseBase public class RepositoryExtendedITCase extends RepositoryITCaseBase
{ {
@@ -76,9 +75,9 @@ public class RepositoryExtendedITCase extends RepositoryITCaseBase
* @param noperm * @param noperm
* @param password * @param password
*/ */
public RepositoryExtendedITCase(Repository repository, User owner, public RepositoryExtendedITCase(RepositoryDto repository, User owner,
User write, User read, User noperm, User write, User read, User noperm,
String password) String password, String ignore_testCaseName)
{ {
super(repository, owner, write, read, noperm, password); super(repository, owner, write, read, noperm, password);
} }

View File

@@ -31,9 +31,7 @@
package sonia.scm.it; package sonia.scm.it;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.sun.jersey.api.client.WebResource;
import org.junit.After; import org.junit.After;
import org.junit.Assume; import org.junit.Assume;
import org.junit.Before; import org.junit.Before;
@@ -43,26 +41,18 @@ import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters; import org.junit.runners.Parameterized.Parameters;
import sonia.scm.debug.DebugHookData; import sonia.scm.api.v2.resources.RepositoryDto;
import sonia.scm.repository.Changeset; import sonia.scm.repository.Changeset;
import sonia.scm.repository.Person; import sonia.scm.repository.Person;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.repository.client.api.ClientCommand; import sonia.scm.repository.client.api.ClientCommand;
import sonia.scm.repository.client.api.RepositoryClient; import sonia.scm.repository.client.api.RepositoryClient;
import sonia.scm.repository.client.api.RepositoryClientFactory; import sonia.scm.repository.client.api.RepositoryClientFactory;
import sonia.scm.util.IOUtil;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import static org.hamcrest.Matchers.allOf; import static sonia.scm.it.IntegrationTestUtil.readJson;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static sonia.scm.it.IntegrationTestUtil.createResource;
import static sonia.scm.it.RepositoryITUtil.createRepository; import static sonia.scm.it.RepositoryITUtil.createRepository;
import static sonia.scm.it.RepositoryITUtil.deleteRepository; import static sonia.scm.it.RepositoryITUtil.deleteRepository;
@@ -83,7 +73,7 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
public TemporaryFolder tempFolder = new TemporaryFolder(); public TemporaryFolder tempFolder = new TemporaryFolder();
private final String repositoryType; private final String repositoryType;
private Repository repository; private RepositoryDto repository;
private File workingCopy; private File workingCopy;
private RepositoryClient repositoryClient; private RepositoryClient repositoryClient;
@@ -105,8 +95,7 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
@Before @Before
public void setUpTestRepository() throws IOException public void setUpTestRepository() throws IOException
{ {
repository = RepositoryTestData.createHeartOfGold(repositoryType); repository = createRepository(client, readJson("repository-" + repositoryType + ".json"));
repository = createRepository(client, repository);
workingCopy = tempFolder.newFolder(); workingCopy = tempFolder.newFolder();
repositoryClient = createRepositoryClient(); repositoryClient = createRepositoryClient();
} }
@@ -117,7 +106,9 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
@After @After
public void removeTestRepository() public void removeTestRepository()
{ {
deleteRepository(client, repository.getId()); if (repository != null) {
deleteRepository(client, repository);
}
} }
/** /**
@@ -138,10 +129,10 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
Thread.sleep(WAIT_TIME); Thread.sleep(WAIT_TIME);
// check debug servlet for pushed commit // check debug servlet for pushed commit
WebResource wr = createResource(client, "debug/" + repository.getId() + "/post-receive/last"); // WebResource wr = createResource(client, "debug/" + repository.getId() + "/post-receive/last");
DebugHookData data = wr.get(DebugHookData.class); // DebugHookData data = wr.get(DebugHookData.class);
assertNotNull(data); // assertNotNull(data);
assertThat(data.getChangesets(), contains(changeset.getId())); // assertThat(data.getChangesets(), contains(changeset.getId()));
} }
/** /**
@@ -173,15 +164,15 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
Thread.sleep(WAIT_TIME); Thread.sleep(WAIT_TIME);
// check debug servlet that only one commit is present // check debug servlet that only one commit is present
WebResource wr = createResource(client, "debug/" + repository.getId() + "/post-receive/last"); // WebResource wr = createResource(client, "debug/" + repository.getId() + "/post-receive/last");
DebugHookData data = wr.get(DebugHookData.class); // DebugHookData data = wr.get(DebugHookData.class);
assertNotNull(data); // assertNotNull(data);
assertThat(data.getChangesets(), allOf( // assertThat(data.getChangesets(), allOf(
contains(b.getId()), // contains(b.getId()),
not( // not(
contains(a.getId()) // contains(a.getId())
) // )
)); // ));
} }
private Changeset commit(String message) throws IOException { private Changeset commit(String message) throws IOException {
@@ -197,7 +188,7 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
private RepositoryClient createRepositoryClient() throws IOException private RepositoryClient createRepositoryClient() throws IOException
{ {
return REPOSITORY_CLIENT_FACTORY.create(repositoryType, return REPOSITORY_CLIENT_FACTORY.create(repositoryType,
IntegrationTestUtil.BASE_URL + repositoryType + "/" + repository.getName(), IntegrationTestUtil.BASE_URL + repositoryType + "/" + repository.getNamespace() + "/" + repository.getName(),
IntegrationTestUtil.ADMIN_USERNAME, IntegrationTestUtil.ADMIN_PASSWORD, workingCopy IntegrationTestUtil.ADMIN_USERNAME, IntegrationTestUtil.ADMIN_PASSWORD, workingCopy
); );
} }
@@ -208,16 +199,10 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
* *
* @return repository types test parameter * @return repository types test parameter
*/ */
@Parameters @Parameters(name = "{0}")
public static Collection<String[]> createParameters() public static Collection<String[]> createParameters()
{ {
Collection<String[]> params = Lists.newArrayList(); return IntegrationTestUtil.createRepositoryTypeParameters();
params.add(new String[] { "git" });
params.add(new String[] { "svn" });
if (IOUtil.search("hg") != null) {
params.add(new String[] { "hg" });
}
return params;
} }
} }

View File

@@ -34,23 +34,24 @@ package sonia.scm.it;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import org.junit.Ignore;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData; import sonia.scm.repository.RepositoryTestData;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static sonia.scm.it.IntegrationTestUtil.*; import static sonia.scm.it.IntegrationTestUtil.createAdminClient;
import static sonia.scm.it.IntegrationTestUtil.createResource;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@Ignore()
public class RepositoryHttpCacheITCase extends HttpCacheITCaseBase<Repository> public class RepositoryHttpCacheITCase extends HttpCacheITCaseBase<Repository>
{ {
@@ -64,8 +65,8 @@ public class RepositoryHttpCacheITCase extends HttpCacheITCaseBase<Repository>
protected Repository createSampleItem() protected Repository createSampleItem()
{ {
Repository repository = RepositoryTestData.createHeartOfGold("git"); Repository repository = RepositoryTestData.createHeartOfGold("git");
Client client = createAdminClient(); ScmClient client = createAdminClient();
WebResource resource = createResource(client, "repositories"); WebResource.Builder resource = createResource(client, "repositories");
ClientResponse response = resource.post(ClientResponse.class, repository); ClientResponse response = resource.post(ClientResponse.class, repository);
assertNotNull(response); assertNotNull(response);
@@ -74,8 +75,7 @@ public class RepositoryHttpCacheITCase extends HttpCacheITCaseBase<Repository>
String location = response.getHeaders().get("Location").get(0); String location = response.getHeaders().get("Location").get(0);
assertNotNull(location); assertNotNull(location);
resource = client.resource(location); response = client.resource(location).get(ClientResponse.class);
response = resource.get(ClientResponse.class);
assertNotNull(response); assertNotNull(response);
assertEquals(200, response.getStatus()); assertEquals(200, response.getStatus());
repository = response.getEntity(Repository.class); repository = response.getEntity(Repository.class);
@@ -94,8 +94,8 @@ public class RepositoryHttpCacheITCase extends HttpCacheITCaseBase<Repository>
@Override @Override
protected void destroy(Repository item) protected void destroy(Repository item)
{ {
Client client = createAdminClient(); ScmClient client = createAdminClient();
WebResource resource = createResource(client, WebResource.Builder resource = createResource(client,
"repositories/".concat(item.getId())); "repositories/".concat(item.getId()));
ClientResponse response = resource.delete(ClientResponse.class); ClientResponse response = resource.delete(ClientResponse.class);

View File

@@ -1,259 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.collect.Lists;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import static sonia.scm.it.IntegrationTestUtil.*;
import static sonia.scm.it.RepositoryITUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;
import java.util.Arrays;
import java.util.Collection;
import org.junit.After;
import sonia.scm.util.IOUtil;
/**
*
* @author Sebastian Sdorra
*/
@RunWith(Parameterized.class)
public class RepositoryITCase extends AbstractAdminITCaseBase
{
/**
* Constructs ...
*
*
* @param repositoryType
*/
public RepositoryITCase(String repositoryType)
{
this.repositoryType = repositoryType;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@After
public void cleanup()
{
Collection<Repository> repositories =
createResource(client,
"repositories").get(new GenericType<Collection<Repository>>() {}
);
if (repositories != null)
{
for (Repository r : repositories)
{
createResource(client, "repositories/" + r.getId()).delete();
}
}
client.destroy();
}
/**
* Method description
*
*
* @return
*/
@Parameters
public static Collection<String[]> createParameters()
{
Collection<String[]> params = Lists.newArrayList();
params.add(new String[] { "git" });
params.add(new String[] { "svn" });
if (IOUtil.search("hg") != null)
{
params.add(new String[] { "hg" });
}
return params;
}
/**
* Method description
*
>>>>>>> merge rev
*/
@Test
public void create()
{
Repository repository =
RepositoryTestData.createHeartOfGold(repositoryType);
createRepository(client, repository);
}
/**
* Method description
*
*/
@Test
public void delete()
{
Repository repository =
RepositoryTestData.createHappyVerticalPeopleTransporter(repositoryType);
repository = createRepository(client, repository);
deleteRepository(client, repository.getId());
}
/**
* Method description
*
*/
@Test
public void doubleCreate()
{
Repository repository = RepositoryTestData.create42Puzzle(repositoryType);
repository = createRepository(client, repository);
WebResource wr = createResource(client, "repositories");
ClientResponse response = wr.post(ClientResponse.class, repository);
assertNotNull(response);
assertThat(response.getStatus(), not(lessThanOrEqualTo(400)));
}
/**
* Method description
*
*/
@Test
public void modify()
{
Repository repository =
RepositoryTestData.createHappyVerticalPeopleTransporter(repositoryType);
repository = createRepository(client, repository);
repository.setPermissions(Arrays.asList(new Permission("dent",
PermissionType.READ), new Permission("slarti", PermissionType.WRITE)));
WebResource wr = createResource(client,
"repositories/".concat(repository.getId()));
ClientResponse response = wr.put(ClientResponse.class, repository);
assertNotNull(response);
assertEquals(204, response.getStatus());
response.close();
Repository other = getRepositoryById(client, repository.getId());
assertRepositoriesEquals(repository, other);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*/
@Test
public void getAll()
{
Repository repository =
RepositoryTestData.createHappyVerticalPeopleTransporter(repositoryType);
repository = createRepository(client, repository);
WebResource wr = createResource(client, "repositories");
ClientResponse response = wr.get(ClientResponse.class);
assertNotNull(response);
assertEquals(200, response.getStatus());
Collection<Repository> repositories =
response.getEntity(new GenericType<Collection<Repository>>() {}
);
response.close();
assertNotNull(repositories);
assertFalse(repositories.isEmpty());
Repository hvpt = null;
for (Repository other : repositories)
{
// fix equals check
other.getPermissions();
if (repository.equals(other))
{
hvpt = other;
break;
}
}
assertNotNull(hvpt);
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final String repositoryType;
}

View File

@@ -37,37 +37,30 @@ package sonia.scm.it;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.runners.Parameterized.Parameters; import org.junit.runners.Parameterized.Parameters;
import sonia.scm.api.v2.resources.RepositoryDto;
import sonia.scm.ScmState; import sonia.scm.repository.client.api.RepositoryClient;
import sonia.scm.Type; import sonia.scm.repository.client.api.RepositoryClientFactory;
import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.user.UserTestData; import sonia.scm.user.UserTestData;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
import static sonia.scm.it.RepositoryITUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.GenericType;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import sonia.scm.repository.client.api.RepositoryClient; import static sonia.scm.it.IntegrationTestUtil.ADMIN_PASSWORD;
import sonia.scm.repository.client.api.RepositoryClientFactory; import static sonia.scm.it.IntegrationTestUtil.ADMIN_USERNAME;
import static sonia.scm.it.IntegrationTestUtil.commit;
import static sonia.scm.it.IntegrationTestUtil.createAdminClient;
import static sonia.scm.it.IntegrationTestUtil.createRandomFile;
import static sonia.scm.it.IntegrationTestUtil.createResource;
import static sonia.scm.it.IntegrationTestUtil.createTempDirectory;
import static sonia.scm.it.IntegrationTestUtil.readJson;
import static sonia.scm.it.RepositoryITUtil.createUrl;
import static sonia.scm.it.UserITUtil.postUser;
//~--- JDK imports ------------------------------------------------------------
/** /**
* *
@@ -76,6 +69,15 @@ import sonia.scm.repository.client.api.RepositoryClientFactory;
public class RepositoryITCaseBase public class RepositoryITCaseBase
{ {
private static final Collection<RepositoryDto> CREATED_REPOSITORIES = new ArrayList<>();
protected User nopermUser;
protected User ownerUser;
protected String password;
protected User readUser;
protected RepositoryDto repository;
protected User writeUser;
/** /**
* Constructs ... * Constructs ...
* *
@@ -87,8 +89,8 @@ public class RepositoryITCaseBase
* @param noperm * @param noperm
* @param password * @param password
*/ */
public RepositoryITCaseBase(Repository repository, User owner, User write, public RepositoryITCaseBase(RepositoryDto repository, User owner, User write,
User read, User noperm, String password) User read, User noperm, String password)
{ {
this.repository = repository; this.repository = repository;
this.ownerUser = owner; this.ownerUser = owner;
@@ -127,24 +129,27 @@ public class RepositoryITCaseBase
* *
* @throws IOException * @throws IOException
*/ */
public static void addTestFiles(Repository repository, String username, public static void addTestFiles(RepositoryDto repository, String username,
String password) String password)
throws IOException
{ {
File directory = createTempDirectory(); File directory = createTempDirectory();
try try {
{
RepositoryClientFactory clientFactory = new RepositoryClientFactory(); RepositoryClientFactory clientFactory = new RepositoryClientFactory();
RepositoryClient client = clientFactory.create( RepositoryClient client = clientFactory.create(
repository.getType(), repository.createUrl(BASE_URL), username, password, directory repository.getType(), createUrl(repository),
username, password, directory
); );
addTestFiles(client); addTestFiles(client);
} } catch (IOException e) {
finally throw new RuntimeException(e);
{ } finally {
IOUtil.delete(directory); try {
IOUtil.delete(directory);
} catch (IOException e) {
e.printStackTrace();
}
} }
} }
@@ -155,27 +160,17 @@ public class RepositoryITCaseBase
@AfterClass @AfterClass
public static void cleanup() public static void cleanup()
{ {
Client client = createAdminClient(); ScmClient client = createAdminClient();
deleteUser(client, UserTestData.createTrillian()); deleteUser(client, UserTestData.createTrillian());
deleteUser(client, UserTestData.createZaphod()); deleteUser(client, UserTestData.createZaphod());
deleteUser(client, UserTestData.createMarvin()); deleteUser(client, UserTestData.createMarvin());
deleteUser(client, UserTestData.createPerfect()); deleteUser(client, UserTestData.createPerfect());
Collection<Repository> repositories = for (RepositoryDto r : CREATED_REPOSITORIES)
createResource(client, "repositories").get(
new GenericType<Collection<Repository>>() {}
);
if (repositories != null)
{ {
for (Repository r : repositories) createResource(client, "repositories/" + r.getNamespace() + "/" + r.getName()).delete();
{
createResource(client, "repositories/" + r.getId()).delete();
}
} }
client.destroy();
} }
/** /**
@@ -186,15 +181,9 @@ public class RepositoryITCaseBase
* *
* @throws IOException * @throws IOException
*/ */
@Parameters @Parameters(name = "{6}")
public static Collection<Object[]> createParameters() throws IOException public static Collection<Object[]> createParameters() throws IOException
{ {
Client client = createClient();
ScmState state = authenticateAdmin(client);
assertNotNull(state);
assertTrue(state.isSuccess());
Collection<Object[]> params = new ArrayList<>(); Collection<Object[]> params = new ArrayList<>();
User owner = UserTestData.createTrillian(); User owner = UserTestData.createTrillian();
@@ -211,11 +200,8 @@ public class RepositoryITCaseBase
User noperm = UserTestData.createPerfect(); User noperm = UserTestData.createPerfect();
createUser(noperm); createUser(noperm);
IntegrationTestUtil.createRepositoryTypeParameters().stream().map(array -> array[0])
for (Type t : state.getRepositoryTypes()) .forEach(t -> appendTestParameter(params, t, owner, write, read, noperm));
{
appendTestParemeter(params, t.getName(), owner, write, read, noperm);
}
return params; return params;
} }
@@ -232,22 +218,15 @@ public class RepositoryITCaseBase
* @param noperm * @param noperm
* *
* @throws IOException * @throws IOException
* @throws RepositoryClientException
*/ */
private static void appendTestParemeter(Collection<Object[]> params, private static void appendTestParameter(Collection<Object[]> params,
String type, User owner, User write, User read, User noperm) throws IOException String type, User owner, User write, User read, User noperm)
{ {
Repository repository = createTestRepository(null, type, owner, write, read); RepositoryDto repository = createTestRepository(type, owner, write, read);
params.add(new Object[] params.add(new Object[]
{ {
repository, owner, write, read, noperm, "secret" repository, owner, write, read, noperm, "secret", repository.getType() + "-" + owner.getId()
}); });
repository = createTestRepository("test", type, owner, write, read);
params.add(new Object[]
{
repository, owner, write, read, noperm, "secret"
});
} }
/** /**
@@ -255,7 +234,6 @@ public class RepositoryITCaseBase
* *
* *
* *
* @param prefix
* @param type * @param type
* @param owner * @param owner
* @param write * @param write
@@ -264,29 +242,23 @@ public class RepositoryITCaseBase
* @return * @return
* *
* @throws IOException * @throws IOException
* @throws RepositoryClientException
*/ */
private static Repository createTestRepository(String prefix, String type, private static RepositoryDto createTestRepository(String type,
User owner, User write, User read) throws IOException User owner, User write, User read)
{ {
Client client = createAdminClient(); ScmClient client = createAdminClient();
Repository repository = RepositoryTestData.createHeartOfGold(type);
if (Util.isNotEmpty(prefix)) // TODO Activate for tests when implemented
{ // repository.setPermissions(Arrays.asList(
repository.setName(prefix.concat("/").concat(repository.getName())); // new Permission(owner.getName(), PermissionType.OWNER),
} // new Permission(write.getName(), PermissionType.WRITE),
// new Permission(read.getName(), PermissionType.READ))
// );
String repositoryJson = readJson("repository-" + type + ".json");
RepositoryDto repository = RepositoryITUtil.createRepository(client, repositoryJson);
CREATED_REPOSITORIES.add(repository);
//J-
repository.setPermissions(Arrays.asList(
new Permission(owner.getName(), PermissionType.OWNER),
new Permission(write.getName(), PermissionType.WRITE),
new Permission(read.getName(), PermissionType.READ))
);
//J+
repository = createRepository(client, repository);
client.destroy();
addTestFiles(repository, ADMIN_USERNAME, ADMIN_PASSWORD); addTestFiles(repository, ADMIN_USERNAME, ADMIN_PASSWORD);
return repository; return repository;
@@ -300,11 +272,11 @@ public class RepositoryITCaseBase
*/ */
private static void createUser(User user) private static void createUser(User user)
{ {
Client client = createAdminClient(); ScmClient client = createAdminClient();
user.setPassword("secret"); user.setPassword("secret");
createResource(client, "users").post(user);
client.destroy(); postUser(client, user);
} }
/** /**
@@ -314,7 +286,7 @@ public class RepositoryITCaseBase
* @param client * @param client
* @param user * @param user
*/ */
private static void deleteUser(Client client, User user) private static void deleteUser(ScmClient client, User user)
{ {
createResource(client, "users/".concat(user.getName())).delete(); createResource(client, "users/".concat(user.getName())).delete();
} }
@@ -327,33 +299,13 @@ public class RepositoryITCaseBase
* @param directory * @param directory
* *
* @return * @return
* *
* @throws IOException * @throws IOException
*/ */
protected RepositoryClient createRepositoryClient(User user, File directory) throws IOException protected RepositoryClient createRepositoryClient(User user, File directory) throws IOException
{ {
RepositoryClientFactory clientFactory = new RepositoryClientFactory(); RepositoryClientFactory clientFactory = new RepositoryClientFactory();
return clientFactory.create(repository.getType(), repository.createUrl(BASE_URL), return clientFactory.create(repository.getType(), createUrl(repository),
user.getName(), password, directory); user.getName(), password, directory);
} }
//~--- fields ---------------------------------------------------------------
/** Field description */
protected User nopermUser;
/** Field description */
protected User ownerUser;
/** Field description */
protected String password;
/** Field description */
protected User readUser;
/** Field description */
protected Repository repository;
/** Field description */
protected User writeUser;
} }

View File

@@ -35,119 +35,83 @@ package sonia.scm.it;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import sonia.scm.repository.Repository; import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import sonia.scm.api.rest.ObjectMapperProvider;
import sonia.scm.api.v2.resources.RepositoryDto;
import sonia.scm.web.VndMediaType;
import static org.junit.Assert.*; import java.io.IOException;
import java.net.URI;
import static sonia.scm.it.IntegrationTestUtil.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static sonia.scm.it.IntegrationTestUtil.BASE_URL;
import static sonia.scm.it.IntegrationTestUtil.createResource;
import static sonia.scm.it.IntegrationTestUtil.getLink;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
/**
*
* @author Sebastian Sdorra
*/
public final class RepositoryITUtil public final class RepositoryITUtil
{ {
/**
* Constructs ...
*
*/
private RepositoryITUtil() {} private RepositoryITUtil() {}
//~--- methods -------------------------------------------------------------- public static RepositoryDto createRepository(ScmClient client, String repositoryJson) {
ClientResponse response =
/** createResource(client, "repositories")
* Method description .accept("*/*")
* .type(VndMediaType.REPOSITORY)
* @param repository .post(ClientResponse.class, repositoryJson);
* @param other
*/
public static void assertRepositoriesEquals(Repository repository, Repository other)
{
assertEquals(repository.getName(), other.getName());
assertEquals(repository.getDescription(), other.getDescription());
assertEquals(repository.getContact(), other.getContact());
assertEquals(repository.getPermissions(), other.getPermissions());
assertEquals(repository.getType(), other.getType());
}
/**
* Method description
*
* @param client
* @param repository
*
* @return
*/
public static Repository createRepository(Client client,
Repository repository)
{
WebResource wr = createResource(client, "repositories");
ClientResponse response = wr.post(ClientResponse.class, repository);
assertNotNull(response); assertNotNull(response);
assertEquals(201, response.getStatus()); assertEquals(201, response.getStatus());
String url = response.getHeaders().get("Location").get(0); URI url = URI.create(response.getHeaders().get("Location").get(0));
response.close(); response.close();
Repository other = getRepository(client, url); RepositoryDto other = getRepository(client, url);
assertNotNull(other); assertNotNull(other);
assertNotNull(other.getType()); assertNotNull(other.getType());
assertRepositoriesEquals(repository, other);
assertNotNull(other.getId());
assertNotNull(other.getCreationDate()); assertNotNull(other.getCreationDate());
return other; return other;
} }
/** public static void deleteRepository(ScmClient client, RepositoryDto repository)
* Method description
*
* @param client
* @param id
*/
public static void deleteRepository(Client client, String id)
{ {
WebResource wr = createResource(client, "repositories/".concat(id)); URI deleteUrl = getLink(repository, "delete");
ClientResponse response = wr.delete(ClientResponse.class); ClientResponse response = createResource(client, deleteUrl).delete(ClientResponse.class);
assertNotNull(response); assertNotNull(response);
assertEquals(204, response.getStatus()); assertEquals(204, response.getStatus());
response.close(); response.close();
wr = createResource(client, "repositories/".concat(id));
response = wr.get(ClientResponse.class); URI selfUrl = getLink(repository, "self");
response = createResource(client, selfUrl).get(ClientResponse.class);
assertNotNull(response); assertNotNull(response);
assertEquals(404, response.getStatus()); assertEquals(404, response.getStatus());
response.close(); response.close();
} }
//~--- get methods ---------------------------------------------------------- public static RepositoryDto getRepository(ScmClient client, URI url)
/**
* Method description
*
* @param client
* @param url
*
* @return
*/
public static Repository getRepository(Client client, String url)
{ {
WebResource wr = client.resource(url); WebResource.Builder wr = createResource(client, url);
ClientResponse response = wr.get(ClientResponse.class); ClientResponse response = wr.get(ClientResponse.class);
assertNotNull(response); assertNotNull(response);
assertEquals(200, response.getStatus());
Repository repository = response.getEntity(Repository.class); String json = response.getEntity(String.class);
RepositoryDto repository = null;
try {
repository = new ObjectMapperProvider().get().readerFor(RepositoryDto.class).readValue(json);
} catch (IOException e) {
fail("could not read json:\n" + json);
}
response.close(); response.close();
assertNotNull(repository); assertNotNull(repository);
@@ -155,26 +119,7 @@ public final class RepositoryITUtil
return repository; return repository;
} }
/** public static String createUrl(RepositoryDto repository) {
* Method description return BASE_URL + repository.getType() + "/" + repository.getNamespace() + "/" + repository.getName();
*
* @param client
* @param id
*
* @return
*/
public static Repository getRepositoryById(Client client, String id)
{
WebResource wr = createResource(client, "repositories/".concat(id));
ClientResponse response = wr.get(ClientResponse.class);
assertNotNull(response);
Repository repository = response.getEntity(Repository.class);
response.close();
assertNotNull(repository);
return repository;
} }
} }

View File

@@ -35,37 +35,39 @@ package sonia.scm.it;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import de.otto.edison.hal.HalRepresentation;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import sonia.scm.api.rest.ObjectMapperProvider;
import sonia.scm.api.v2.resources.RepositoryDto;
import sonia.scm.web.VndMediaType;
import sonia.scm.repository.Repository; import java.io.IOException;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static sonia.scm.it.IntegrationTestUtil.*; import static org.junit.Assert.assertTrue;
import static sonia.scm.it.IntegrationTestUtil.createAdminClient;
import static sonia.scm.it.IntegrationTestUtil.createResource;
import static sonia.scm.it.IntegrationTestUtil.serialize;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;
import java.util.Collection;
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@RunWith(Parameterized.class) @RunWith(Parameterized.class)
public class RepositorySimplePermissionITCase public class RepositorySimplePermissionITCase
extends AbstractPermissionITCaseBase<Repository> extends AbstractPermissionITCaseBase<RepositoryDto>
{ {
/** Field description */ /** Field description */
private static String REPOSITORY_UUID; private static String REPOSITORY_PATH;
//~--- constructors --------------------------------------------------------- //~--- constructors ---------------------------------------------------------
@@ -75,7 +77,7 @@ public class RepositorySimplePermissionITCase
* *
* @param credentials * @param credentials
*/ */
public RepositorySimplePermissionITCase(Credentials credentials) public RepositorySimplePermissionITCase(Credentials credentials, String ignore_testCaseName)
{ {
super(credentials); super(credentials);
} }
@@ -87,20 +89,17 @@ public class RepositorySimplePermissionITCase
* *
*/ */
@BeforeClass @BeforeClass
public static void createTestRepository() public static void createTestRepository() throws IOException {
{ RepositoryDto repository = new RepositoryDto();
Repository repository = new Repository();
repository.setName("test-repo"); repository.setName("test-repo");
repository.setType("git"); repository.setType("git");
repository.setPublicReadable(false); // repository.setPublicReadable(false);
Client client = createClient(); ScmClient client = createAdminClient();
authenticateAdmin(client); WebResource.Builder wr = createResource(client, "repositories");
ClientResponse response = wr.type(VndMediaType.REPOSITORY).post(ClientResponse.class, serialize(repository));
WebResource wr = createResource(client, "repositories");
ClientResponse response = wr.post(ClientResponse.class, repository);
assertNotNull(response); assertNotNull(response);
assertEquals(201, response.getStatus()); assertEquals(201, response.getStatus());
@@ -109,17 +108,13 @@ public class RepositorySimplePermissionITCase
assertNotNull(repositoryUrl); assertNotNull(repositoryUrl);
response.close(); response.close();
wr = client.resource(repositoryUrl); response = client.resource(repositoryUrl).get(ClientResponse.class);
response = wr.get(ClientResponse.class);
assertNotNull(response); assertNotNull(response);
assertEquals(200, response.getStatus()); assertEquals(200, response.getStatus());
repository = response.getEntity(Repository.class); repository = new ObjectMapperProvider().get().readValue(response.getEntity(String.class), RepositoryDto.class);
assertNotNull(repository); REPOSITORY_PATH = repository.getNamespace() + "/" + repository.getName();
REPOSITORY_UUID = repository.getId(); assertNotNull(REPOSITORY_PATH);
assertNotNull(REPOSITORY_UUID);
response.close(); response.close();
logoutClient(client);
client.destroy();
} }
/** /**
@@ -127,13 +122,9 @@ public class RepositorySimplePermissionITCase
* *
*/ */
@AfterClass @AfterClass
public static void removeTestRepoistory() public static void removeTestRepository()
{ {
Client client = createClient(); createResource(createAdminClient(), "repositories/" + REPOSITORY_PATH).delete();
authenticateAdmin(client);
createResource(client, "repositories/" + REPOSITORY_UUID).delete();
client.destroy();
} }
/** /**
@@ -150,12 +141,16 @@ public class RepositorySimplePermissionITCase
assertNotNull(response); assertNotNull(response);
assertEquals(200, response.getStatus()); assertEquals(200, response.getStatus());
Collection<Repository> repositories = HalRepresentation repositories =
response.getEntity(new GenericType<Collection<Repository>>() {} null;
); try {
repositories = new ObjectMapperProvider().get().readValue(response.getEntity(String.class), HalRepresentation.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
assertNotNull(repositories); assertNotNull(repositories);
assertTrue(repositories.isEmpty()); assertTrue(repositories.getEmbedded().getItemsBy("repositories").isEmpty());
response.close(); response.close();
} }
} }
@@ -198,9 +193,9 @@ public class RepositorySimplePermissionITCase
* @return * @return
*/ */
@Override @Override
protected Repository getCreateItem() protected RepositoryDto getCreateItem()
{ {
Repository repository = new Repository(); RepositoryDto repository = new RepositoryDto();
repository.setName("create-test-repo"); repository.setName("create-test-repo");
repository.setType("svn"); repository.setType("svn");
@@ -217,7 +212,7 @@ public class RepositorySimplePermissionITCase
@Override @Override
protected String getDeletePath() protected String getDeletePath()
{ {
return "repositories/".concat(REPOSITORY_UUID); return "repositories/".concat(REPOSITORY_PATH);
} }
/** /**
@@ -229,7 +224,7 @@ public class RepositorySimplePermissionITCase
@Override @Override
protected String getGetPath() protected String getGetPath()
{ {
return "repositories/".concat(REPOSITORY_UUID); return "repositories/".concat(REPOSITORY_PATH);
} }
/** /**
@@ -239,11 +234,12 @@ public class RepositorySimplePermissionITCase
* @return * @return
*/ */
@Override @Override
protected Repository getModifyItem() protected RepositoryDto getModifyItem()
{ {
Repository repository = new Repository(); RepositoryDto repository = new RepositoryDto();
repository.setName("test-repo"); repository.setName("test-repo");
repository.setNamespace("scmadmin");
repository.setType("git"); repository.setType("git");
repository.setDescription("Test Repository"); repository.setDescription("Test Repository");
@@ -259,6 +255,11 @@ public class RepositorySimplePermissionITCase
@Override @Override
protected String getModifyPath() protected String getModifyPath()
{ {
return "repositories/".concat(REPOSITORY_UUID); return "repositories/".concat(REPOSITORY_PATH);
}
@Override
protected String getMediaType() {
return VndMediaType.REPOSITORY;
} }
} }

View File

@@ -36,39 +36,13 @@ package sonia.scm.it;
import org.junit.runners.Parameterized.Parameters; import org.junit.runners.Parameterized.Parameters;
import sonia.scm.util.IOUtil; import java.util.Collection;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.util.ArrayList; public class RepositoryTypeITCaseBase {
import java.util.Collection; @Parameters(name = "{0}")
public static Collection<String[]> createParameters() {
/** return IntegrationTestUtil.createRepositoryTypeParameters();
*
* @author Sebastian Sdorra
*/
public class RepositoryTypeITCaseBase
{
/**
* Method description
*
*
* @return
*/
@Parameters
public static Collection<String[]> createParameters()
{
Collection<String[]> params = new ArrayList<String[]>();
params.add(new String[] { "git" });
params.add(new String[] { "svn" });
if (IOUtil.search("hg") != null)
{
params.add(new String[] { "hg" });
}
return params;
} }
} }

View File

@@ -0,0 +1,37 @@
package sonia.scm.it;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import java.util.Base64;
import static sonia.scm.it.IntegrationTestUtil.createClient;
public class ScmClient {
private final String user;
private final String password;
private final Client client;
public static ScmClient anonymous() {
return new ScmClient(null, null);
}
public ScmClient(String user, String password) {
this.user = user;
this.password = password;
this.client = createClient();
}
public WebResource.Builder resource(String url) {
if (user == null) {
return client.resource(url).getRequestBuilder();
} else {
return client.resource(url).header("Authorization", createAuthHeaderValue());
}
}
public String createAuthHeaderValue() {
return "Basic " + Base64.getEncoder().encodeToString((user +":"+ password).getBytes());
}
}

View File

@@ -1,297 +0,0 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of SCM-Manager; 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 REGENTS 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.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.it;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.AfterClass;
import org.junit.Test;
import sonia.scm.ScmState;
import sonia.scm.Type;
import sonia.scm.user.User;
import sonia.scm.user.UserTestData;
import static org.junit.Assert.*;
import static sonia.scm.it.IntegrationTestUtil.*;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;
import java.util.Collection;
import javax.ws.rs.core.MediaType;
/**
*
* @author Sebastian Sdorra
*/
public class UserITCase extends AbstractAdminITCaseBase
{
/**
* Method description
*
*/
@AfterClass
public static void cleanup()
{
Client client = createClient();
authenticateAdmin(client);
createResource(client, "users/slarti").delete();
client.destroy();
}
/**
* Method description
*
*/
@Test
public void create()
{
User slarti = UserTestData.createSlarti();
slarti.setPassword("slarti123");
createUser(slarti);
}
/**
* Method description
*
*/
@Test
public void delete()
{
User dent = UserTestData.createDent();
createUser(dent);
deleteUser(dent);
}
/**
* Method description
*
*/
@Test
public void modify()
{
User marvin = UserTestData.createMarvin();
createUser(marvin);
marvin = getUser(marvin.getName());
marvin.setDisplayName("Paranoid Android");
WebResource wr = createResource(client, "users/".concat(marvin.getName()));
ClientResponse response =
wr.type(MediaType.APPLICATION_XML).put(ClientResponse.class, marvin);
assertNotNull(response);
assertEquals(204, response.getStatus());
response.close();
User other = getUser(marvin.getName());
assertEquals(marvin.getDisplayName(), other.getDisplayName());
assertNotNull(other.getLastModified());
deleteUser(marvin);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*/
@Test
public void get()
{
User scmadmin = getUser("scmadmin");
testAdmin(scmadmin);
}
/**
* Method description
*
*/
@Test
public void getAll()
{
WebResource wr = createResource(client, "users");
ClientResponse response = wr.get(ClientResponse.class);
assertNotNull(response);
assertEquals(200, response.getStatus());
Collection<User> users =
response.getEntity(new GenericType<Collection<User>>() {}
);
response.close();
assertNotNull(users);
assertFalse(users.isEmpty());
User admin = null;
for (User user : users)
{
if (user.getName().equals("scmadmin"))
{
admin = user;
}
}
testAdmin(admin);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param client
*/
protected void adminLogin(Client client)
{
ClientResponse cr = authenticate(client, "scmadmin", "scmadmin");
ScmState state = cr.getEntity(ScmState.class);
cr.close();
assertNotNull(state);
assertTrue(state.isSuccess());
User user = state.getUser();
assertNotNull(user);
assertEquals("scmadmin", user.getName());
assertTrue(user.isAdmin());
Collection<Type> types = state.getRepositoryTypes();
assertNotNull(types);
assertFalse(types.isEmpty());
}
/**
* Method description
*
*
* @param user
*/
private void createUser(User user)
{
WebResource wr = createResource(client, "users");
ClientResponse response =
wr.type(MediaType.APPLICATION_XML).post(ClientResponse.class, user);
assertNotNull(response);
assertEquals(201, response.getStatus());
response.close();
User other = getUser(user.getName());
assertEquals(user.getName(), other.getName());
assertEquals(user.getDisplayName(), other.getDisplayName());
assertEquals(user.getMail(), other.getMail());
assertNotNull(other.getType());
assertNotNull(other.getCreationDate());
}
/**
* Method description
*
*
* @param user
*/
private void deleteUser(User user)
{
WebResource wr = createResource(client, "users/".concat(user.getName()));
ClientResponse response = wr.delete(ClientResponse.class);
assertNotNull(response);
assertEquals(204, response.getStatus());
response.close();
wr = createResource(client, "users/".concat(user.getName()));
response = wr.get(ClientResponse.class);
assertNotNull(response);
assertEquals(404, response.getStatus());
response.close();
}
/**
* Method description
*
*
* @param user
*/
private void testAdmin(User user)
{
assertNotNull(user);
assertEquals(user.getName(), "scmadmin");
assertTrue(user.isAdmin());
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param username
*
* @return
*/
private User getUser(String username)
{
WebResource wr = createResource(client, "users/".concat(username));
ClientResponse response = wr.get(ClientResponse.class);
assertNotNull(response);
assertEquals(200, response.getStatus());
User user = response.getEntity(User.class);
response.close();
assertNotNull(user);
return user;
}
}

View File

@@ -0,0 +1,13 @@
package sonia.scm.it;
import com.sun.jersey.api.client.ClientResponse;
import sonia.scm.user.User;
import sonia.scm.web.VndMediaType;
import static sonia.scm.it.IntegrationTestUtil.post;
public class UserITUtil {
public static ClientResponse postUser(ScmClient client, User user) {
return post(client, "users", VndMediaType.USER, user);
}
}

View File

@@ -35,11 +35,20 @@ package sonia.scm.it;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.sun.jersey.api.client.ClientResponse;
import de.otto.edison.hal.HalRepresentation;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import sonia.scm.api.rest.ObjectMapperProvider;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.user.UserTestData; import sonia.scm.user.UserTestData;
import sonia.scm.web.VndMediaType;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/** /**
* *
@@ -55,7 +64,7 @@ public class UserPermissionITCase extends AbstractPermissionITCaseBase<User>
* *
* @param credentials * @param credentials
*/ */
public UserPermissionITCase(Credentials credentials) public UserPermissionITCase(Credentials credentials, String ignore_testCaseName)
{ {
super(credentials); super(credentials);
} }
@@ -140,4 +149,31 @@ public class UserPermissionITCase extends AbstractPermissionITCaseBase<User>
{ {
return "users/scmadmin"; return "users/scmadmin";
} }
@Override
protected String getMediaType() {
return VndMediaType.USER;
}
@Override
protected void checkGetAllResponse(ClientResponse response)
{
if (!credentials.isAnonymous())
{
assertNotNull(response);
assertEquals(200, response.getStatus());
HalRepresentation repositories =
null;
try {
repositories = new ObjectMapperProvider().get().readValue(response.getEntity(String.class), HalRepresentation.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
assertNotNull(repositories);
assertTrue(repositories.getEmbedded().getItemsBy("users").isEmpty());
response.close();
}
}
} }

View File

@@ -0,0 +1,7 @@
{
"contact": "zaphod.beeblebrox@hitchhiker.com",
"description": "Heart of Gold is the first prototype ship to successfully utilise the revolutionary Infinite Improbability Drive",
"name": "HeartOfGold-git",
"archived": false,
"type": "git"
}

View File

@@ -0,0 +1,7 @@
{
"contact": "zaphod.beeblebrox@hitchhiker.com",
"description": "Heart of Gold is the first prototype ship to successfully utilise the revolutionary Infinite Improbability Drive",
"name": "HeartOfGold-hg",
"archived": false,
"type": "hg"
}

View File

@@ -0,0 +1,7 @@
{
"contact": "zaphod.beeblebrox@hitchhiker.com",
"description": "Heart of Gold is the first prototype ship to successfully utilise the revolutionary Infinite Improbability Drive",
"name": "HeartOfGold-svn",
"archived": false,
"type": "svn"
}