From 84ea15974166da136e4528ffa386bc2dbda8f660 Mon Sep 17 00:00:00 2001 From: Konstantin Schaper Date: Wed, 25 Nov 2020 12:08:51 +0100 Subject: [PATCH] add unit test for rest endpoints --- .../scm/api/v2/resources/TagRootResource.java | 2 + .../api/v2/resources/TagRootResourceTest.java | 135 +++++++++++++++++- 2 files changed, 134 insertions(+), 3 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/TagRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/TagRootResource.java index b46656a02d..0f5cb2c450 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/TagRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/TagRootResource.java @@ -239,6 +239,8 @@ public class TagRootResource { } return Response.noContent().build(); + } catch (IOException e) { + return Response.serverError().build(); } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java index 726cbc89e4..7655dd7c9b 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java @@ -24,8 +24,8 @@ package sonia.scm.api.v2.resources; -import com.google.inject.util.Providers; import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.util.ThreadContext; @@ -46,17 +46,24 @@ import sonia.scm.repository.Tag; import sonia.scm.repository.Tags; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.repository.api.TagCommandBuilder; import sonia.scm.repository.api.TagsCommandBuilder; import sonia.scm.web.RestDispatcher; import sonia.scm.web.VndMediaType; +import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @Slf4j @@ -79,6 +86,12 @@ public class TagRootResourceTest extends RepositoryTestBase { @Mock private TagsCommandBuilder tagsCommandBuilder; + @Mock + private TagCommandBuilder tagCommandBuilder; + @Mock + private TagCommandBuilder.TagCreateCommandBuilder tagCreateCommandBuilder; + @Mock + private TagCommandBuilder.TagDeleteCommandBuilder tagDeleteCommandBuilder; private TagCollectionToDtoMapper tagCollectionToDtoMapper; @InjectMocks @@ -89,17 +102,21 @@ public class TagRootResourceTest extends RepositoryTestBase { @Before - public void prepareEnvironment() throws Exception { + public void prepareEnvironment() { tagCollectionToDtoMapper = new TagCollectionToDtoMapper(resourceLinks, tagToTagDtoMapper); - tagRootResource = new TagRootResource(serviceFactory, tagCollectionToDtoMapper, tagToTagDtoMapper); + tagRootResource = new TagRootResource(serviceFactory, tagCollectionToDtoMapper, tagToTagDtoMapper, resourceLinks); dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService); when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService); when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); when(repositoryService.getTagsCommand()).thenReturn(tagsCommandBuilder); + when(repositoryService.getTagCommand()).thenReturn(tagCommandBuilder); subjectThreadState.bind(); ThreadContext.bind(subject); when(subject.isPermitted(any(String.class))).thenReturn(true); + when(tagCreateCommandBuilder.setName(any())).thenReturn(tagCreateCommandBuilder); + when(tagCreateCommandBuilder.setRevision(any())).thenReturn(tagCreateCommandBuilder); + when(tagDeleteCommandBuilder.setName(any())).thenReturn(tagDeleteCommandBuilder); } @After @@ -211,4 +228,116 @@ public class TagRootResourceTest extends RepositoryTestBase { assertTrue(response.getContentAsString().contains(String.format("\"name\":\"%s\"", tag2))); assertTrue(response.getContentAsString().contains(String.format("\"revision\":\"%s\"", revision2))); } + + @Test + public void shouldCreateTag() throws URISyntaxException, IOException { + Tags tags = new Tags(); + tags.setTags(Lists.emptyList()); + when(tagsCommandBuilder.getTags()).thenReturn(tags); + when(tagCommandBuilder.create()).thenReturn(tagCreateCommandBuilder); + when(tagCreateCommandBuilder.execute()).thenReturn(new Tag("newtag", "592d797cd36432e591416e8b2b98154f4f163411")); + MockHttpRequest request = MockHttpRequest + .post(TAG_URL) + .content("{\"name\": \"newtag\",\"revision\":\"592d797cd36432e591416e8b2b98154f4f163411\"}".getBytes()) + .contentType(VndMediaType.TAG_REQUEST); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(201, response.getStatus()); + assertEquals( + URI.create("/v2/repositories/space/repo/tags/newtag"), + response.getOutputHeaders().getFirst("Location")); + } + + @Test + public void shouldNotCreateTagIfNotPermitted() throws IOException, URISyntaxException { + doThrow(AuthorizationException.class).when(subject).checkPermission("repository:push:repoId"); + Tags tags = new Tags(); + tags.setTags(Lists.emptyList()); + when(tagsCommandBuilder.getTags()).thenReturn(tags); + when(tagCommandBuilder.create()).thenReturn(tagCreateCommandBuilder); + when(tagCreateCommandBuilder.execute()).thenReturn(new Tag("newtag", "592d797cd36432e591416e8b2b98154f4f163411")); + MockHttpRequest request = MockHttpRequest + .post(TAG_URL) + .content("{\"name\": \"newtag\",\"revision\":\"592d797cd36432e591416e8b2b98154f4f163411\"}".getBytes()) + .contentType(VndMediaType.TAG_REQUEST); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(403, response.getStatus()); + verify(tagCommandBuilder, never()).create(); + } + + @Test + public void shouldThrowExceptionIfTagAlreadyExists() throws URISyntaxException, IOException { + Tags tags = new Tags(); + tags.setTags(Collections.singletonList(new Tag("newtag", "592d797cd36432e591416e8b2b98154f4f163411"))); + when(tagsCommandBuilder.getTags()).thenReturn(tags); + when(tagCommandBuilder.create()).thenReturn(tagCreateCommandBuilder); + when(tagCreateCommandBuilder.execute()).thenReturn(new Tag("newtag", "592d797cd36432e591416e8b2b98154f4f163411")); + MockHttpRequest request = MockHttpRequest + .post(TAG_URL) + .content("{\"name\": \"newtag\",\"revision\":\"592d797cd36432e591416e8b2b98154f4f163411\"}".getBytes()) + .contentType(VndMediaType.TAG_REQUEST); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(409, response.getStatus()); + verify(tagCommandBuilder, never()).create(); + } + + @Test + public void shouldDeleteTag() throws IOException, URISyntaxException { + Tags tags = new Tags(); + tags.setTags(Collections.singletonList(new Tag("newtag", "592d797cd36432e591416e8b2b98154f4f163411"))); + when(tagsCommandBuilder.getTags()).thenReturn(tags); + when(tagCommandBuilder.delete()).thenReturn(tagDeleteCommandBuilder); + + MockHttpRequest request = MockHttpRequest + .delete(TAG_URL + "newtag"); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(204, response.getStatus()); + verify(tagCommandBuilder).delete(); + } + + @Test + public void shouldReturn204EvenIfTagDoesntExist() throws IOException, URISyntaxException { + Tags tags = new Tags(); + tags.setTags(Collections.emptyList()); + when(tagsCommandBuilder.getTags()).thenReturn(tags); + when(tagCommandBuilder.delete()).thenReturn(tagDeleteCommandBuilder); + + MockHttpRequest request = MockHttpRequest + .delete(TAG_URL + "newtag"); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(204, response.getStatus()); + verify(tagCommandBuilder, never()).delete(); + } + + @Test + public void shouldNotDeleteTagIfNotPermitted() throws IOException, URISyntaxException { + doThrow(AuthorizationException.class).when(subject).checkPermission("repository:modify:repoId"); + Tags tags = new Tags(); + tags.setTags(Collections.singletonList(new Tag("newtag", "592d797cd36432e591416e8b2b98154f4f163411"))); + when(tagsCommandBuilder.getTags()).thenReturn(tags); + when(tagCommandBuilder.delete()).thenReturn(tagDeleteCommandBuilder); + + MockHttpRequest request = MockHttpRequest + .delete(TAG_URL + "newtag"); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(403, response.getStatus()); + verify(tagCommandBuilder, never()).delete(); + } }