This commit is contained in:
Mohamed Karray
2018-09-19 16:29:50 +02:00
131 changed files with 1862 additions and 1819 deletions

View File

@@ -1,5 +1,6 @@
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState;
@@ -92,7 +93,7 @@ public class BranchRootResourceTest extends RepositoryTestBase {
changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
BranchCollectionToDtoMapper branchCollectionToDtoMapper = new BranchCollectionToDtoMapper(branchToDtoMapper, resourceLinks);
branchRootResource = new BranchRootResource(serviceFactory, branchToDtoMapper, branchCollectionToDtoMapper, changesetCollectionToDtoMapper);
super.branchRootResource = MockProvider.of(branchRootResource);
super.branchRootResource = Providers.of(branchRootResource);
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
when(serviceFactory.create(any(Repository.class))).thenReturn(service);

View File

@@ -1,6 +1,7 @@
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState;
@@ -79,7 +80,7 @@ public class ChangesetRootResourceTest extends RepositoryTestBase {
public void prepareEnvironment() throws Exception {
changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
changesetRootResource = new ChangesetRootResource(serviceFactory, changesetCollectionToDtoMapper, changesetToChangesetDtoMapper);
super.changesetRootResource = MockProvider.of(changesetRootResource);
super.changesetRootResource = Providers.of(changesetRootResource);
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService);
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService);

View File

@@ -1,6 +1,7 @@
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState;
@@ -63,7 +64,7 @@ public class DiffResourceTest extends RepositoryTestBase {
@Before
public void prepareEnvironment() throws Exception {
diffRootResource = new DiffRootResource(serviceFactory);
super.diffRootResource = MockProvider.of(diffRootResource);
super.diffRootResource = Providers.of(diffRootResource);
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
when(serviceFactory.create(any(Repository.class))).thenReturn(service);

View File

@@ -1,5 +1,6 @@
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState;
@@ -81,7 +82,7 @@ public class FileHistoryResourceTest extends RepositoryTestBase {
public void prepareEnvironment() throws Exception {
fileHistoryCollectionToDtoMapper = new FileHistoryCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
fileHistoryRootResource = new FileHistoryRootResource(serviceFactory, fileHistoryCollectionToDtoMapper);
super.fileHistoryRootResource = MockProvider.of(fileHistoryRootResource);
super.fileHistoryRootResource = Providers.of(fileHistoryRootResource);
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
when(serviceFactory.create(any(Repository.class))).thenReturn(service);

View File

@@ -11,7 +11,6 @@ import org.junit.Test;
import sonia.scm.PageResult;
import sonia.scm.group.Group;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
@@ -28,9 +27,9 @@ import static sonia.scm.PageResult.createPage;
public class GroupCollectionToDtoMapperTest {
private final UriInfo uriInfo = mock(UriInfo.class);
private final UriInfoStore uriInfoStore = new UriInfoStore();
private final ResourceLinks resourceLinks = new ResourceLinks(uriInfoStore);
private final ScmPathInfo uriInfo = mock(ScmPathInfo.class);
private final ScmPathInfoStore scmPathInfoStore = new ScmPathInfoStore();
private final ResourceLinks resourceLinks = new ResourceLinks(scmPathInfoStore);
private final GroupToGroupDtoMapper groupToDtoMapper = mock(GroupToGroupDtoMapper.class);
private final Subject subject = mock(Subject.class);
private final ThreadState subjectThreadState = new SubjectThreadState(subject);
@@ -41,10 +40,10 @@ public class GroupCollectionToDtoMapperTest {
@Before
public void init() throws URISyntaxException {
uriInfoStore.set(uriInfo);
scmPathInfoStore.set(uriInfo);
URI baseUri = new URI("http://example.com/base/");
expectedBaseUri = baseUri.resolve(GroupRootResource.GROUPS_PATH_V2 + "/");
when(uriInfo.getBaseUri()).thenReturn(baseUri);
when(uriInfo.getApiRestUri()).thenReturn(baseUri);
subjectThreadState.bind();
ThreadContext.bind(subject);
}

View File

@@ -3,6 +3,7 @@ package sonia.scm.api.v2.resources;
import com.github.sdorra.shiro.ShiroRule;
import com.github.sdorra.shiro.SubjectAware;
import com.google.common.io.Resources;
import com.google.inject.util.Providers;
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
@@ -73,7 +74,7 @@ public class GroupRootResourceTest {
GroupCollectionToDtoMapper groupCollectionToDtoMapper = new GroupCollectionToDtoMapper(groupToDtoMapper, resourceLinks);
GroupCollectionResource groupCollectionResource = new GroupCollectionResource(groupManager, dtoToGroupMapper, groupCollectionToDtoMapper, resourceLinks);
GroupResource groupResource = new GroupResource(groupManager, groupToDtoMapper, dtoToGroupMapper);
GroupRootResource groupRootResource = new GroupRootResource(MockProvider.of(groupCollectionResource), MockProvider.of(groupResource));
GroupRootResource groupRootResource = new GroupRootResource(Providers.of(groupCollectionResource), Providers.of(groupResource));
dispatcher = createDispatcher(groupRootResource);
dispatcher.getProviderFactory().registerProviderInstance(new JSONContextResolver(new ObjectMapperProvider().get()));

View File

@@ -4,7 +4,6 @@ import org.junit.Before;
import org.junit.Test;
import javax.ws.rs.Path;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.net.URISyntaxException;
@@ -37,7 +36,7 @@ public class LinkBuilderTest {
}
}
private UriInfo uriInfo = mock(UriInfo.class);
private ScmPathInfo uriInfo = mock(ScmPathInfo.class);
@Test
public void shouldBuildSimplePath() {
@@ -94,6 +93,6 @@ public class LinkBuilderTest {
@Before
public void setBaseUri() throws URISyntaxException {
when(uriInfo.getBaseUri()).thenReturn(new URI("http://example.com/"));
when(uriInfo.getApiRestUri()).thenReturn(new URI("http://example.com/"));
}
}

View File

@@ -17,7 +17,6 @@ import sonia.scm.user.UserManager;
import sonia.scm.web.VndMediaType;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.net.URISyntaxException;
@@ -45,9 +44,9 @@ public class MeResourceTest {
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(URI.create("/"));
@Mock
private UriInfo uriInfo;
private ScmPathInfo uriInfo;
@Mock
private UriInfoStore uriInfoStore;
private ScmPathInfoStore scmPathInfoStore;
@Mock
private UserManager userManager;
@@ -73,9 +72,9 @@ public class MeResourceTest {
when(userManager.getDefaultType()).thenReturn("xml");
userToDtoMapper.setResourceLinks(resourceLinks);
MeResource meResource = new MeResource(userToDtoMapper, userManager, passwordService);
when(uriInfo.getApiRestUri()).thenReturn(URI.create("/"));
when(scmPathInfoStore.get()).thenReturn(uriInfo);
dispatcher = createDispatcher(meResource);
when(uriInfo.getBaseUri()).thenReturn(URI.create("/"));
when(uriInfoStore.get()).thenReturn(uriInfo);
}
@Test

View File

@@ -1,22 +0,0 @@
package sonia.scm.api.v2.resources;
import javax.inject.Provider;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* A mockito implementation of CDI {@link javax.inject.Provider}.
*/
class MockProvider {
private MockProvider() {}
static <I> Provider<I> of(I instance) {
@SuppressWarnings("unchecked") // Can't make mockito return typed provider
Provider<I> provider = mock(Provider.class);
when(provider.get()).thenReturn(instance);
return provider;
}
}

View File

@@ -0,0 +1,23 @@
package sonia.scm.api.v2.resources;
import sonia.scm.repository.api.ScmProtocol;
class MockScmProtocol implements ScmProtocol {
private final String type;
private final String protocol;
public MockScmProtocol(String type, String protocol) {
this.type = type;
this.protocol = protocol;
}
@Override
public String getType() {
return type;
}
@Override
public String getUrl() {
return protocol;
}
}

View File

@@ -1,5 +1,6 @@
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState;
@@ -71,7 +72,7 @@ public class ModificationsResourceTest extends RepositoryTestBase {
@Before
public void prepareEnvironment() throws Exception {
modificationsRootResource = new ModificationsRootResource(serviceFactory, modificationsToDtoMapper);
super.modificationsRootResource = MockProvider.of(modificationsRootResource);
super.modificationsRootResource = Providers.of(modificationsRootResource);
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService);
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService);

View File

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.sdorra.shiro.ShiroRule;
import com.github.sdorra.shiro.SubjectAware;
import com.google.common.collect.ImmutableList;
import com.google.inject.util.Providers;
import de.otto.edison.hal.HalRepresentation;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
@@ -137,7 +138,7 @@ public class PermissionRootResourceTest extends RepositoryTestBase {
initMocks(this);
permissionCollectionToDtoMapper = new PermissionCollectionToDtoMapper(permissionToPermissionDtoMapper, resourceLinks);
permissionRootResource = new PermissionRootResource(permissionDtoToPermissionMapper, permissionToPermissionDtoMapper, permissionCollectionToDtoMapper, resourceLinks, repositoryManager);
super.permissionRootResource = MockProvider.of(permissionRootResource);
super.permissionRootResource = Providers.of(permissionRootResource);
dispatcher = createDispatcher(getRepositoryRootResource());
subjectThreadState.bind();
ThreadContext.bind(subject);

View File

@@ -3,13 +3,13 @@ package sonia.scm.api.v2.resources;
import com.github.sdorra.shiro.ShiroRule;
import com.github.sdorra.shiro.SubjectAware;
import com.google.common.io.Resources;
import com.google.inject.util.Providers;
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
@@ -20,6 +20,7 @@ import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryIsNotArchivedException;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.web.VndMediaType;
@@ -30,6 +31,7 @@ import java.net.URISyntaxException;
import java.net.URL;
import static java.util.Collections.singletonList;
import static java.util.stream.Stream.of;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
@@ -64,8 +66,14 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
@Mock
private RepositoryManager repositoryManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@Mock
private RepositoryServiceFactory serviceFactory;
@Mock
private RepositoryService service;
@Mock
private ScmPathInfoStore scmPathInfoStore;
@Mock
private ScmPathInfo uriInfo;
private final URI baseUri = URI.create("/");
@@ -83,8 +91,11 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
super.dtoToRepositoryMapper = dtoToRepositoryMapper;
super.manager = repositoryManager;
RepositoryCollectionToDtoMapper repositoryCollectionToDtoMapper = new RepositoryCollectionToDtoMapper(repositoryToDtoMapper, resourceLinks);
super.repositoryCollectionResource = MockProvider.of(new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks));
super.repositoryCollectionResource = Providers.of(new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks));
dispatcher = createDispatcher(getRepositoryRootResource());
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
when(scmPathInfoStore.get()).thenReturn(uriInfo);
when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y"));
}
@Test
@@ -268,6 +279,20 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
assertFalse(modifiedRepositoryCaptor.getValue().getPermissions().isEmpty());
}
@Test
public void shouldCreateArrayOfProtocolUrls() throws Exception {
mockRepository("space", "repo");
when(service.getSupportedProtocols()).thenReturn(of(new MockScmProtocol("http", "http://"), new MockScmProtocol("ssh", "ssh://")));
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(SC_OK, response.getStatus());
assertTrue(response.getContentAsString().contains("\"protocol\":[{\"href\":\"http://\",\"name\":\"http\"},{\"href\":\"ssh://\",\"name\":\"ssh\"}]"));
}
private PageResult<Repository> createSingletonPageResult(Repository repository) {
return new PageResult<>(singletonList(repository), 0);
}

View File

@@ -1,5 +1,6 @@
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
import sonia.scm.repository.RepositoryManager;
import javax.inject.Provider;
@@ -23,7 +24,7 @@ public abstract class RepositoryTestBase {
RepositoryRootResource getRepositoryRootResource() {
return new RepositoryRootResource(MockProvider.of(new RepositoryResource(
return new RepositoryRootResource(Providers.of(new RepositoryResource(
repositoryToDtoMapper,
dtoToRepositoryMapper,
manager,

View File

@@ -7,7 +7,6 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Answers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import sonia.scm.repository.HealthCheckFailure;
@@ -15,13 +14,17 @@ import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.api.Command;
import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.repository.api.ScmProtocol;
import java.net.URI;
import static java.util.Collections.singletonList;
import static java.util.stream.Stream.of;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
@@ -39,8 +42,14 @@ public class RepositoryToRepositoryDtoMapperTest {
private final URI baseUri = URI.create("http://example.com/base/");
@SuppressWarnings("unused") // Is injected
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@Mock
private RepositoryServiceFactory serviceFactory;
@Mock
private RepositoryService repositoryService;
@Mock
private ScmPathInfoStore scmPathInfoStore;
@Mock
private ScmPathInfo uriInfo;
@InjectMocks
private RepositoryToRepositoryDtoMapperImpl mapper;
@@ -48,7 +57,11 @@ public class RepositoryToRepositoryDtoMapperTest {
@Before
public void init() {
initMocks(this);
when(serviceFactory.create(any(Repository.class)).isSupported(any(Command.class))).thenReturn(true);
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService);
when(repositoryService.isSupported(any(Command.class))).thenReturn(true);
when(repositoryService.getSupportedProtocols()).thenReturn(of());
when(scmPathInfoStore.get()).thenReturn(uriInfo);
when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y"));
}
@After
@@ -129,14 +142,14 @@ public class RepositoryToRepositoryDtoMapperTest {
@Test
public void shouldNotCreateTagsLink_ifNotSupported() {
when(serviceFactory.create(any(Repository.class)).isSupported(Command.TAGS)).thenReturn(false);
when(repositoryService.isSupported(Command.TAGS)).thenReturn(false);
RepositoryDto dto = mapper.map(createTestRepository());
assertFalse(dto.getLinks().getLinkBy("tags").isPresent());
}
@Test
public void shouldNotCreateBranchesLink_ifNotSupported() {
when(serviceFactory.create(any(Repository.class)).isSupported(Command.BRANCHES)).thenReturn(false);
when(repositoryService.isSupported(Command.BRANCHES)).thenReturn(false);
RepositoryDto dto = mapper.map(createTestRepository());
assertFalse(dto.getLinks().getLinkBy("branches").isPresent());
}
@@ -165,6 +178,43 @@ public class RepositoryToRepositoryDtoMapperTest {
dto.getLinks().getLinkBy("permissions").get().getHref());
}
@Test
public void shouldCreateCorrectProtocolLinks() {
when(repositoryService.getSupportedProtocols()).thenReturn(
of(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol"))
);
RepositoryDto dto = mapper.map(createTestRepository());
assertTrue("should contain http link", dto.getLinks().stream().anyMatch(l -> l.getName().equals("http") && l.getHref().equals("http://scm")));
assertTrue("should contain other link", dto.getLinks().stream().anyMatch(l -> l.getName().equals("other") && l.getHref().equals("some://protocol")));
}
@Test
@SubjectAware(username = "community")
public void shouldCreateProtocolLinksForPullPermission() {
when(repositoryService.getSupportedProtocols()).thenReturn(
of(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol"))
);
RepositoryDto dto = mapper.map(createTestRepository());
assertEquals(2, dto.getLinks().getLinksBy("protocol").size());
}
@Test
@SubjectAware(username = "unpriv")
public void shouldNotCreateProtocolLinksWithoutPullPermission() {
when(repositoryService.getSupportedProtocols()).thenReturn(
of(mockProtocol("http", "http://scm"), mockProtocol("other", "some://protocol"))
);
RepositoryDto dto = mapper.map(createTestRepository());
assertTrue(dto.getLinks().getLinksBy("protocol").isEmpty());
}
private ScmProtocol mockProtocol(String type, String protocol) {
return new MockScmProtocol(type, protocol);
}
private Repository createTestRepository() {
Repository repository = new Repository();
repository.setNamespace("testspace");
@@ -179,4 +229,5 @@ public class RepositoryToRepositoryDtoMapperTest {
return repository;
}
}

View File

@@ -2,6 +2,7 @@ package sonia.scm.api.v2.resources;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.util.Providers;
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockDispatcherFactory;
import org.jboss.resteasy.mock.MockHttpRequest;
@@ -22,8 +23,10 @@ import java.util.List;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.Silent.class)
@@ -52,7 +55,7 @@ public class RepositoryTypeRootResourceTest {
RepositoryTypeCollectionToDtoMapper collectionMapper = new RepositoryTypeCollectionToDtoMapper(mapper, resourceLinks);
RepositoryTypeCollectionResource collectionResource = new RepositoryTypeCollectionResource(repositoryManager, collectionMapper);
RepositoryTypeResource resource = new RepositoryTypeResource(repositoryManager, mapper);
RepositoryTypeRootResource rootResource = new RepositoryTypeRootResource(MockProvider.of(collectionResource), MockProvider.of(resource));
RepositoryTypeRootResource rootResource = new RepositoryTypeRootResource(Providers.of(collectionResource), Providers.of(resource));
dispatcher.getRegistry().addSingletonResource(rootResource);
}

View File

@@ -1,6 +1,5 @@
package sonia.scm.api.v2.resources;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import static org.mockito.Mockito.mock;
@@ -10,8 +9,8 @@ public class ResourceLinksMock {
public static ResourceLinks createMock(URI baseUri) {
ResourceLinks resourceLinks = mock(ResourceLinks.class);
UriInfo uriInfo = mock(UriInfo.class);
when(uriInfo.getBaseUri()).thenReturn(baseUri);
ScmPathInfo uriInfo = mock(ScmPathInfo.class);
when(uriInfo.getApiRestUri()).thenReturn(baseUri);
ResourceLinks.UserLinks userLinks = new ResourceLinks.UserLinks(uriInfo);
when(resourceLinks.user()).thenReturn(userLinks);

View File

@@ -6,7 +6,6 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import sonia.scm.repository.NamespaceAndName;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import static org.junit.Assert.assertEquals;
@@ -18,9 +17,9 @@ public class ResourceLinksTest {
private static final String BASE_URL = "http://example.com/";
@Mock
private UriInfoStore uriInfoStore;
private ScmPathInfoStore scmPathInfoStore;
@Mock
private UriInfo uriInfo;
private ScmPathInfo uriInfo;
@InjectMocks
private ResourceLinks resourceLinks;
@@ -177,7 +176,7 @@ public class ResourceLinksTest {
@Before
public void initUriInfo() {
initMocks(this);
when(uriInfoStore.get()).thenReturn(uriInfo);
when(uriInfo.getBaseUri()).thenReturn(URI.create(BASE_URL));
when(scmPathInfoStore.get()).thenReturn(uriInfo);
when(uriInfo.getApiRestUri()).thenReturn(URI.create(BASE_URL));
}
}

View File

@@ -0,0 +1,35 @@
package sonia.scm.api.v2.resources;
import org.junit.Test;
import java.net.URI;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ScmPathInfoStoreTest {
@Test
public void shouldReturnSetInfo() {
URI someUri = URI.create("/anything");
ScmPathInfo uriInfo = mock(ScmPathInfo.class);
ScmPathInfoStore scmPathInfoStore = new ScmPathInfoStore();
when(uriInfo.getApiRestUri()).thenReturn(someUri);
scmPathInfoStore.set(uriInfo);
assertSame(someUri, scmPathInfoStore.get().getApiRestUri());
}
@Test(expected = IllegalStateException.class)
public void shouldFailIfSetTwice() {
ScmPathInfo uriInfo = mock(ScmPathInfo.class);
ScmPathInfoStore scmPathInfoStore = new ScmPathInfoStore();
scmPathInfoStore.set(uriInfo);
scmPathInfoStore.set(uriInfo);
}
}

View File

@@ -1,5 +1,6 @@
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
@@ -63,7 +64,7 @@ public class SourceRootResourceTest extends RepositoryTestBase {
when(fileObjectToFileObjectDtoMapper.map(any(FileObject.class), any(NamespaceAndName.class), anyString())).thenReturn(dto);
SourceRootResource sourceRootResource = new SourceRootResource(serviceFactory, browserResultToBrowserResultDtoMapper);
super.sourceRootResource = MockProvider.of(sourceRootResource);
super.sourceRootResource = Providers.of(sourceRootResource);
dispatcher = createDispatcher(getRepositoryRootResource());
}

View File

@@ -1,5 +1,6 @@
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState;
@@ -71,7 +72,7 @@ public class TagRootResourceTest extends RepositoryTestBase {
public void prepareEnvironment() throws Exception {
tagCollectionToDtoMapper = new TagCollectionToDtoMapper(resourceLinks, tagToTagDtoMapper);
tagRootResource = new TagRootResource(serviceFactory, tagCollectionToDtoMapper, tagToTagDtoMapper);
super.tagRootResource = MockProvider.of(tagRootResource);
super.tagRootResource = Providers.of(tagRootResource);
dispatcher = createDispatcher(getRepositoryRootResource());
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService);
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService);

View File

@@ -1,30 +0,0 @@
package sonia.scm.api.v2.resources;
import org.junit.Test;
import javax.ws.rs.core.UriInfo;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.mock;
public class UriInfoStoreTest {
@Test
public void shouldReturnSetInfo() {
UriInfo uriInfo = mock(UriInfo.class);
UriInfoStore uriInfoStore = new UriInfoStore();
uriInfoStore.set(uriInfo);
assertSame(uriInfo, uriInfoStore.get());
}
@Test(expected = IllegalStateException.class)
public void shouldFailIfSetTwice() {
UriInfo uriInfo = mock(UriInfo.class);
UriInfoStore uriInfoStore = new UriInfoStore();
uriInfoStore.set(uriInfo);
uriInfoStore.set(uriInfo);
}
}

View File

@@ -3,6 +3,7 @@ package sonia.scm.api.v2.resources;
import com.github.sdorra.shiro.ShiroRule;
import com.github.sdorra.shiro.SubjectAware;
import com.google.common.io.Resources;
import com.google.inject.util.Providers;
import org.apache.shiro.authc.credential.PasswordService;
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockHttpRequest;
@@ -78,8 +79,8 @@ public class UserRootResourceTest {
UserCollectionResource userCollectionResource = new UserCollectionResource(userManager, dtoToUserMapper,
userCollectionToDtoMapper, resourceLinks, passwordService);
UserResource userResource = new UserResource(dtoToUserMapper, userToDtoMapper, userManager, passwordService);
UserRootResource userRootResource = new UserRootResource(MockProvider.of(userCollectionResource),
MockProvider.of(userResource));
UserRootResource userRootResource = new UserRootResource(Providers.of(userCollectionResource),
Providers.of(userResource));
dispatcher = createDispatcher(userRootResource);
}

View File

@@ -36,33 +36,38 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
import com.google.common.base.Charsets;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.UniformInterfaceException;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import sonia.scm.api.rest.ObjectMapperProvider;
import sonia.scm.api.v2.resources.RepositoryDto;
import sonia.scm.api.v2.resources.UserDto;
import sonia.scm.api.v2.resources.UserToUserDtoMapperImpl;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.user.User;
import sonia.scm.user.UserTestData;
import sonia.scm.util.HttpUtil;
import sonia.scm.web.VndMediaType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.IOException;
import java.net.URI;
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.createResource;
import static sonia.scm.it.IntegrationTestUtil.readJson;
import static sonia.scm.it.RepositoryITUtil.createRepository;
import static sonia.scm.it.RepositoryITUtil.deleteRepository;
@@ -111,7 +116,6 @@ public class GitLfsITCase {
}
@Test
@Ignore("permissions not yet implemented")
public void testLfsAPIWithOwnerPermissions() throws IOException {
uploadAndDownloadAsUser(PermissionType.OWNER);
}
@@ -122,9 +126,11 @@ public class GitLfsITCase {
createUser(trillian);
try {
// TODO enable when permissions are implemented in v2
// repository.getPermissions().add(new Permission(trillian.getId(), permissionType));
// modifyRepository(repository);
String permissionsUrl = repository.getLinks().getLinkBy("permissions").get().getHref();
IntegrationTestUtil.createResource(adminClient, URI.create(permissionsUrl))
.accept("*/*")
.type(VndMediaType.PERMISSION)
.post(ClientResponse.class, "{\"name\": \""+ trillian.getId() +"\", \"type\":\"WRITE\"}");
ScmClient client = new ScmClient(trillian.getId(), "secret123");
@@ -135,25 +141,27 @@ public class GitLfsITCase {
}
@Test
@Ignore("permissions not yet implemented")
public void testLfsAPIWithWritePermissions() throws IOException {
uploadAndDownloadAsUser(PermissionType.WRITE);
}
private void createUser(User user) {
adminClient.resource(REST_BASE_URL + "users.json").post(user);
}
private void modifyRepository(Repository repository) {
adminClient.resource(REST_BASE_URL + "repositories/" + repository.getId() + ".json").put(repository);
UserDto dto = new UserToUserDtoMapperImpl(){
@Override
protected void appendLinks(User user, UserDto target) {}
}.map(user);
dto.setPassword(user.getPassword());
createResource(adminClient, "users")
.accept("*/*")
.type(VndMediaType.USER)
.post(ClientResponse.class, dto);
}
private void removeUser(User user) {
adminClient.resource(REST_BASE_URL + "users/" + user.getId() + ".json").delete();
adminClient.resource(REST_BASE_URL + "users/" + user.getId()).delete();
}
@Test
@Ignore("permissions not yet implemented")
public void testLfsAPIWithoutWritePermissions() throws IOException {
User trillian = UserTestData.createTrillian();
trillian.setPassword("secret123");
@@ -164,9 +172,11 @@ public class GitLfsITCase {
try {
// TODO enable when permissions are implemented in v2
// repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ));
// modifyRepository(repository);
String permissionsUrl = repository.getLinks().getLinkBy("permissions").get().getHref();
IntegrationTestUtil.createResource(adminClient, URI.create(permissionsUrl))
.accept("*/*")
.type(VndMediaType.PERMISSION)
.post(ClientResponse.class, "{\"name\": \""+ trillian.getId() +"\", \"type\":\"READ\"}");
ScmClient client = new ScmClient(trillian.getId(), "secret123");
uploadAndDownload(client);
@@ -176,7 +186,6 @@ public class GitLfsITCase {
}
@Test
@Ignore("permissions not yet implemented")
public void testLfsDownloadWithReadPermissions() throws IOException {
User trillian = UserTestData.createTrillian();
trillian.setPassword("secret123");
@@ -184,9 +193,11 @@ public class GitLfsITCase {
try {
// TODO enable when permissions are implemented in v2
// repository.getPermissions().add(new Permission(trillian.getId(), PermissionType.READ));
// modifyRepository(repository);
String permissionsUrl = repository.getLinks().getLinkBy("permissions").get().getHref();
IntegrationTestUtil.createResource(adminClient, URI.create(permissionsUrl))
.accept("*/*")
.type(VndMediaType.PERMISSION)
.post(ClientResponse.class, "{\"name\": \""+ trillian.getId() +"\", \"type\":\"READ\"}");
// upload data as admin
String data = UUID.randomUUID().toString();
@@ -221,7 +232,7 @@ public class GitLfsITCase {
LfsResponseBody response = request(client, request);
String uploadURL = response.objects[0].actions.upload.href;
client.resource(uploadURL).put(data);
client.resource(uploadURL).header(HttpUtil.HEADER_USERAGENT, "git-lfs/z").put(data);
return lfsObject;
}
@@ -233,14 +244,14 @@ public class GitLfsITCase {
String json = client
.resource(batchUrl)
.accept("application/vnd.git-lfs+json")
.header(HttpUtil.HEADER_USERAGENT, "git-lfs/z")
.header("Content-Type", "application/vnd.git-lfs+json")
.post(String.class, requestAsString);
return new ObjectMapperProvider().get().readValue(json, LfsResponseBody.class);
}
private String createBatchUrl() {
String url = BASE_URL + "git/" + repository.getNamespace() + "/" + repository.getName();
return url + "/info/lfs/objects/batch";
return String.format("%srepo/%s/%s/info/lfs/objects/batch", BASE_URL, repository.getNamespace(), repository.getName());
}
private byte[] download(ScmClient client, LfsObject lfsObject) throws IOException {
@@ -248,7 +259,7 @@ public class GitLfsITCase {
LfsResponseBody response = request(client, request);
String downloadUrl = response.objects[0].actions.download.href;
return client.resource(downloadUrl).get(byte[].class);
return client.resource(downloadUrl).header(HttpUtil.HEADER_USERAGENT, "git-lfs/z").get(byte[].class);
}
private LfsObject createLfsObject(byte[] data) {

View File

@@ -100,7 +100,7 @@ public class GitRepositoryPathMatcherITCase {
// tests end
private String createUrl() {
return BASE_URL + "git/" + repository.getNamespace() + "/" + repository.getName();
return BASE_URL + "repo/" + repository.getNamespace() + "/" + repository.getName();
}
private void cloneAndPush( String url ) throws IOException {

View File

@@ -172,7 +172,7 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
Thread.sleep(WAIT_TIME);
// check debug servlet that only one commit is present
WebResource.Builder wr = createResource(client, "../debug/" + repository.getNamespace() + "/" + repository.getName() + "/post-receive/last");
WebResource.Builder wr = createResource(client, String.format("../debug/%s/%s/post-receive/last", repository.getNamespace(), repository.getName()));
DebugHookData data = wr.get(DebugHookData.class);
assertNotNull(data);
assertThat(data.getChangesets(), allOf(
@@ -195,8 +195,8 @@ public class RepositoryHookITCase extends AbstractAdminITCaseBase
private RepositoryClient createRepositoryClient() throws IOException
{
return REPOSITORY_CLIENT_FACTORY.create(repositoryType,
IntegrationTestUtil.BASE_URL + repositoryType + "/" + repository.getNamespace() + "/" + repository.getName(),
return REPOSITORY_CLIENT_FACTORY.create(repositoryType,
String.format("%srepo/%s/%s", IntegrationTestUtil.BASE_URL, repository.getNamespace(), repository.getName()),
IntegrationTestUtil.ADMIN_USERNAME, IntegrationTestUtil.ADMIN_PASSWORD, workingCopy
);
}

View File

@@ -54,7 +54,6 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import sonia.scm.SCMContextProvider;
import sonia.scm.Type;
import sonia.scm.cache.GuavaCacheManager;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.security.AuthorizationCollector;
@@ -120,7 +119,6 @@ public class DefaultRepositoryManagerPerfTest {
keyGenerator,
repositoryDAO,
handlerSet,
repositoryMatcher,
namespaceStrategy
);

View File

@@ -61,7 +61,6 @@ import sonia.scm.store.ConfigurationStoreFactory;
import sonia.scm.store.JAXBConfigurationStoreFactory;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
@@ -383,69 +382,6 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
assertEquals("default_namespace", repository.getNamespace());
}
@Test
public void getRepositoryFromRequestUri_withoutLeadingSlash() throws AlreadyExistsException {
RepositoryManager m = createManager();
m.init(contextProvider);
createUriTestRepositories(m);
assertEquals("scm-test", m.getFromUri("hg/namespace/scm-test").getName());
assertEquals("namespace", m.getFromUri("hg/namespace/scm-test").getNamespace());
}
@Test
public void getRepositoryFromRequestUri_withLeadingSlash() throws AlreadyExistsException {
RepositoryManager m = createManager();
m.init(contextProvider);
createUriTestRepositories(m);
assertEquals("scm-test", m.getFromUri("/hg/namespace/scm-test").getName());
assertEquals("namespace", m.getFromUri("/hg/namespace/scm-test").getNamespace());
}
@Test
public void getRepositoryFromRequestUri_withPartialName() throws AlreadyExistsException {
RepositoryManager m = createManager();
m.init(contextProvider);
createUriTestRepositories(m);
assertEquals("scm", m.getFromUri("hg/namespace/scm").getName());
assertEquals("namespace", m.getFromUri("hg/namespace/scm").getNamespace());
}
@Test
public void getRepositoryFromRequestUri_withTrailingFilePath() throws AlreadyExistsException {
RepositoryManager m = createManager();
m.init(contextProvider);
createUriTestRepositories(m);
assertEquals("test-1", m.getFromUri("/git/namespace/test-1/ka/some/path").getName());
}
@Test
public void getRepositoryFromRequestUri_forNotExistingRepositoryName() throws AlreadyExistsException {
RepositoryManager m = createManager();
m.init(contextProvider);
createUriTestRepositories(m);
assertNull(m.getFromUri("/git/namespace/test-3/ka/some/path"));
}
@Test
public void getRepositoryFromRequestUri_forWrongNamespace() throws AlreadyExistsException {
RepositoryManager m = createManager();
m.init(contextProvider);
createUriTestRepositories(m);
assertNull(m.getFromUri("/git/other/other/test-2"));
}
@Test
public void shouldSetNamespace() throws AlreadyExistsException {
Repository repository = new Repository(null, "hg", null, "scm");
@@ -504,7 +440,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
when(namespaceStrategy.createNamespace(Mockito.any(Repository.class))).thenAnswer(invocation -> mockedNamespace);
return new DefaultRepositoryManager(configuration, contextProvider,
keyGenerator, repositoryDAO, handlerSet, createRepositoryMatcher(), namespaceStrategy);
keyGenerator, repositoryDAO, handlerSet, namespaceStrategy);
}
private void createRepository(RepositoryManager m, Repository repository) throws AlreadyExistsException {
@@ -530,10 +466,6 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
assertEquals(repo.getLastModified(), other.getLastModified());
}
private RepositoryMatcher createRepositoryMatcher() {
return new RepositoryMatcher(Collections.<RepositoryPathMatcher>emptySet());
}
private Repository createRepository(Repository repository) throws AlreadyExistsException {
manager.create(repository);
assertNotNull(repository.getId());

View File

@@ -0,0 +1,114 @@
package sonia.scm.web.protocol;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import sonia.scm.PushStateDispatcher;
import sonia.scm.repository.DefaultRepositoryProvider;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryNotFoundException;
import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.repository.spi.HttpScmProtocol;
import sonia.scm.web.UserAgent;
import sonia.scm.web.UserAgentParser;
import javax.inject.Provider;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
public class HttpProtocolServletTest {
@Mock
private RepositoryServiceFactory serviceFactory;
@Mock
private HttpServletRequest httpServletRequest;
@Mock
private PushStateDispatcher dispatcher;
@Mock
private UserAgentParser userAgentParser;
@Mock
private Provider<HttpServletRequest> requestProvider;
@InjectMocks
private HttpProtocolServlet servlet;
@Mock
private RepositoryService repositoryService;
@Mock
private UserAgent userAgent;
@Mock
private HttpServletRequest request;
@Mock
private HttpServletResponse response;
@Mock
private HttpScmProtocol protocol;
@Before
public void init() throws RepositoryNotFoundException {
initMocks(this);
when(userAgentParser.parse(request)).thenReturn(userAgent);
when(userAgent.isBrowser()).thenReturn(false);
NamespaceAndName existingRepo = new NamespaceAndName("space", "repo");
when(serviceFactory.create(not(eq(existingRepo)))).thenThrow(RepositoryNotFoundException.class);
when(serviceFactory.create(existingRepo)).thenReturn(repositoryService);
when(requestProvider.get()).thenReturn(httpServletRequest);
}
@Test
public void shouldDispatchBrowserRequests() throws ServletException, IOException {
when(userAgent.isBrowser()).thenReturn(true);
when(request.getRequestURI()).thenReturn("uri");
servlet.service(request, response);
verify(dispatcher).dispatch(request, response, "uri");
}
@Test
public void shouldHandleBadPaths() throws IOException, ServletException {
when(request.getPathInfo()).thenReturn("/illegal");
servlet.service(request, response);
verify(response).setStatus(400);
}
@Test
public void shouldHandleNotExistingRepository() throws IOException, ServletException {
when(request.getPathInfo()).thenReturn("/not/exists");
servlet.service(request, response);
verify(response).setStatus(404);
}
@Test
public void shouldDelegateToProvider() throws RepositoryNotFoundException, IOException, ServletException {
when(request.getPathInfo()).thenReturn("/space/name");
NamespaceAndName namespaceAndName = new NamespaceAndName("space", "name");
doReturn(repositoryService).when(serviceFactory).create(namespaceAndName);
Repository repository = new Repository();
when(repositoryService.getRepository()).thenReturn(repository);
when(repositoryService.getProtocol(HttpScmProtocol.class)).thenReturn(protocol);
servlet.service(request, response);
verify(httpServletRequest).setAttribute(DefaultRepositoryProvider.ATTRIBUTE_NAME, repository);
verify(protocol).serve(request, response, null);
verify(repositoryService).close();
}
}

View File

@@ -0,0 +1,68 @@
package sonia.scm.web.protocol;
import org.junit.jupiter.api.DynamicNode;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import sonia.scm.repository.NamespaceAndName;
import java.util.Optional;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
public class NamespaceAndNameFromPathExtractorTest {
@TestFactory
Stream<DynamicNode> shouldExtractCorrectNamespaceAndName() {
return Stream.of(
"/space/repo",
"/space/repo/",
"/space/repo/here",
"/space/repo/here/there",
"space/repo",
"space/repo/",
"space/repo/here/there"
).map(this::createCorrectTest);
}
@TestFactory
Stream<DynamicNode> shouldHandleTrailingDotSomethings() {
return Stream.of(
"/space/repo.git",
"/space/repo.and.more",
"/space/repo."
).map(this::createCorrectTest);
}
private DynamicTest createCorrectTest(String path) {
return dynamicTest(
"should extract correct namespace and name for path " + path,
() -> {
Optional<NamespaceAndName> namespaceAndName = NamespaceAndNameFromPathExtractor.fromUri(path);
assertThat(namespaceAndName.get()).isEqualTo(new NamespaceAndName("space", "repo"));
}
);
}
@TestFactory
Stream<DynamicNode> shouldHandleMissingParts() {
return Stream.of(
"",
"/",
"/space",
"/space/"
).map(this::createFailureTest);
}
private DynamicTest createFailureTest(String path) {
return dynamicTest(
"should not fail for wrong path " + path,
() -> {
Optional<NamespaceAndName> namespaceAndName = NamespaceAndNameFromPathExtractor.fromUri(path);
assertThat(namespaceAndName.isPresent()).isFalse();
}
);
}
}