From 3358960fbed22ea7d952b196c67151a49f559e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Magry=C5=9B?= Date: Thu, 2 Jul 2015 13:55:51 +0200 Subject: [PATCH 1/3] Implement automated tests for plugin API HTTP Client Implement automated tests for plugin API HTTP resource Add Mockito and Power Mock dependency Implement automated tests for ConfigurationsManager. Implement additional tests for HTTP Client and HTTP resource Exclude artifacts forbidden by maven enforce plugin --- pom.xml | 25 +++ .../ReplicationPluginConfiguration.java | 10 +- .../impl/ArtifactUpdateApiClientImpl.java | 67 ++------ .../impl/ConfigurationsManagerImpl.java | 12 +- .../AsyncWebResourceBuilderFactory.java | 38 +++++ .../factories/FileBlockingQueueFactory.java | 32 ++++ .../impl/factories/JerseyClientFactory.java | 51 ++++++ .../ArtifactUpdatePlexusResourceTest.java | 157 ++++++++++++++++++ .../impl/ArtifactUpdateApiClientImplTest.java | 137 +++++++++++++++ .../impl/AwaitableFIleBlockingQueue.java | 30 ++++ .../impl/ConfigurationsManagerImplTest.java | 58 +++++++ src/test/resources/replication-plugin-2.xml | 15 ++ src/test/resources/replication-plugin.xml | 10 ++ 13 files changed, 576 insertions(+), 66 deletions(-) create mode 100644 src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/AsyncWebResourceBuilderFactory.java create mode 100644 src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/FileBlockingQueueFactory.java create mode 100644 src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/JerseyClientFactory.java create mode 100644 src/test/java/com/griddynamics/cd/nrp/internal/rest/ArtifactUpdatePlexusResourceTest.java create mode 100644 src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImplTest.java create mode 100644 src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/AwaitableFIleBlockingQueue.java create mode 100644 src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImplTest.java create mode 100644 src/test/resources/replication-plugin-2.xml create mode 100644 src/test/resources/replication-plugin.xml diff --git a/pom.xml b/pom.xml index de10428..9061665 100644 --- a/pom.xml +++ b/pom.xml @@ -146,6 +146,31 @@ lombok 1.16.4 + + + org.mockito + mockito-core + 1.10.19 + test + + + org.hamcrest + hamcrest-core + + + + + org.powermock + powermock-api-mockito + 1.6.2 + test + + + org.mockito + mockito-all + + + diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfiguration.java b/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfiguration.java index 47a4feb..9251883 100644 --- a/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfiguration.java +++ b/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfiguration.java @@ -24,7 +24,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; /** @@ -36,26 +36,24 @@ public class ReplicationPluginConfiguration { @XmlElement(name = "server") @XmlElementWrapper(name = "servers") - private final Set servers = new HashSet<>(); + private final Set servers = new LinkedHashSet<>(); @Getter @NonNull @XmlAttribute(name = "myUrl") private String myUrl; + @Getter @XmlAttribute(name = "requestsQueueSize") private Integer requestsQueueSize = 500; @XmlAttribute(name = "requestsSendingThreadsCount") private Integer requestsSendingThreadsCount = 1; @XmlAttribute(name = "queueDumpFileName") + @NonNull private String queueDumpFileName; public void addServer(NexusServer server) { servers.add(server); } - public Integer getRequestsQueueSize() { - return requestsQueueSize; - } - public String getQueueDumpFileName() { return queueDumpFileName; } diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImpl.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImpl.java index 95b8551..9f54965 100644 --- a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImpl.java +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImpl.java @@ -22,6 +22,8 @@ import com.griddynamics.cd.nrp.internal.model.config.NexusServer; import com.griddynamics.cd.nrp.internal.uploading.ArtifactUpdateApiClient; import com.griddynamics.cd.nrp.internal.uploading.ConfigurationsManager; +import com.griddynamics.cd.nrp.internal.uploading.impl.factories.AsyncWebResourceBuilderFactory; +import com.griddynamics.cd.nrp.internal.uploading.impl.factories.FileBlockingQueueFactory; import com.sun.jersey.api.client.AsyncWebResource; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.GenericType; @@ -66,25 +68,21 @@ public class ArtifactUpdateApiClientImpl extends ComponentSupport implements Art * Provides access to the plugin configurations */ private final ConfigurationsManager configurationsManager; - + private final FileBlockingQueueFactory fileBlockingQueueFactory; + private final AsyncWebResourceBuilderFactory asyncWebResourceBuilderFactory; /** * ExecutorService shares between clients. All treads are created in the same executor */ - private final ExecutorService jerseyHttpClientExecutor; private final FileBlockingQueue fileBlockingQueue; @Inject - public ArtifactUpdateApiClientImpl(ConfigurationsManager configurationsManager) { + public ArtifactUpdateApiClientImpl(ConfigurationsManager configurationsManager, + FileBlockingQueueFactory fileBlockingQueueFactory, + AsyncWebResourceBuilderFactory asyncWebResourceBuilderFactory) { this.configurationsManager = configurationsManager; + this.fileBlockingQueueFactory = fileBlockingQueueFactory; + this.asyncWebResourceBuilderFactory = asyncWebResourceBuilderFactory; this.fileBlockingQueue = initFileBlockingQueue(configurationsManager.getConfiguration()); - this.jerseyHttpClientExecutor = new ThreadPoolExecutor( - configurationsManager.getConfiguration().getRequestsSendingThreadsCount(), - configurationsManager.getConfiguration().getRequestsSendingThreadsCount(), - 30, - TimeUnit.SECONDS, - new LinkedBlockingQueue( - configurationsManager.getConfiguration().getRequestsQueueSize()) - ); initBackgroundWorkers(configurationsManager.getConfiguration()); } @@ -110,11 +108,8 @@ public void run() { } private FileBlockingQueue initFileBlockingQueue(ReplicationPluginConfiguration replicationPluginConfiguration) { - BlockingQueue blockingQueue = - new LinkedBlockingQueue<>(replicationPluginConfiguration.getRequestsQueueSize()); String queueFileName = replicationPluginConfiguration.getQueueDumpFileName(); - FileBlockingQueue retVal = new FileBlockingQueue(blockingQueue, - queueFileName); + FileBlockingQueue retVal = fileBlockingQueueFactory.getFileBlockingQueue(); try { File queueFile = new File(queueFileName); if (queueFile.exists()) { @@ -147,7 +142,9 @@ public void offerRequest(ArtifactMetaInfo artifactMetaInfo) { */ public void sendRequest(ArtifactMetaInfo metaInfo) { for (NexusServer server : configurationsManager.getConfiguration().getServers()) { - AsyncWebResource.Builder service = getService(server.getUrl(), server.getUser(), server.getPassword()); + AsyncWebResource.Builder service = + asyncWebResourceBuilderFactory.getAsyncWebResourceBuilder( + server.getUrl(), server.getUser(), server.getPassword()); try { service.post(new ITypeListener() { @Override @@ -180,42 +177,4 @@ public GenericType getGenericType() { } } - /** - * Returns jersey HTTP resource to access to the remote replication servers - * - * @param nexusUrl URL of the remote server - * @param login Username on the remote server - * @param password User's password - * @return Jersey HTTP client - */ - private AsyncWebResource.Builder getService(String nexusUrl, String login, String password) { - Client client = getClient(login, password); - client.setExecutorService(jerseyHttpClientExecutor); - AsyncWebResource webResource = client.asyncResource(UriBuilder.fromUri(nexusUrl).build()); - webResource = webResource.path("service").path("local").path("artifact").path("maven").path("update"); - return webResource.accept(MediaType.APPLICATION_XML_TYPE) - .type(MediaType.APPLICATION_XML_TYPE); - } - - /** - * Creates jersey HTTP client - * - * @param login Username on the remote server - * @param password User's password - * @return HTTP client - */ - private Client getClient(String login, String password) { - ClientConfig config = new DefaultClientConfig(); - config.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 1000); - config.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, 2000); - Client client = Client.create(config); - client.setExecutorService(jerseyHttpClientExecutor); - if (login != null && !login.isEmpty() && password != null) { - log.debug("Creating HTTP client with authorized HTTPBasicAuthFilter."); - client.addFilter(new HTTPBasicAuthFilter(login, password)); - } else { - log.debug("Creating HTTP client with anonymous HTTPBasicAuthFilter."); - } - return client; - } } diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImpl.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImpl.java index 5d4b4be..4dc835b 100644 --- a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImpl.java +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImpl.java @@ -66,7 +66,7 @@ public ConfigurationsManagerImpl(NexusConfiguration nexusConfiguration) { @PostConstruct public void init() { log.trace("Initializing plugin configurations"); - reloadConfigurations(); + reloadConfigurations(CONFIG_FILENAME); } /** @@ -78,7 +78,7 @@ public ReplicationPluginConfiguration getConfiguration() { if (config == null) { synchronized (this) { if (config == null) { - reloadConfigurations(); + reloadConfigurations(CONFIG_FILENAME); } } } @@ -89,8 +89,8 @@ public ReplicationPluginConfiguration getConfiguration() { * Reloads {@link ConfigurationsManagerImpl#config} * from XML plugin configurations file */ - public void reloadConfigurations() { - File file = getConfigurationFile(); + public void reloadConfigurations(String filename) { + File file = getConfigurationFile(filename); try { JAXBContext jaxbContext = JAXBContext.newInstance(ReplicationPluginConfiguration.class); @@ -104,7 +104,7 @@ public void reloadConfigurations() { /** * Returns plugin configurations XML file */ - private File getConfigurationFile() { - return new File(nexusConfiguration.getConfigurationDirectory(), CONFIG_FILENAME); + private File getConfigurationFile(String filename) { + return new File(nexusConfiguration.getConfigurationDirectory(), filename); } } diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/AsyncWebResourceBuilderFactory.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/AsyncWebResourceBuilderFactory.java new file mode 100644 index 0000000..aeec5ea --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/AsyncWebResourceBuilderFactory.java @@ -0,0 +1,38 @@ +package com.griddynamics.cd.nrp.internal.uploading.impl.factories; + +import com.sun.jersey.api.client.AsyncWebResource; +import com.sun.jersey.api.client.Client; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriBuilder; + +@Singleton +public class AsyncWebResourceBuilderFactory { + + private final JerseyClientFactory jerseyClientFactory; + + @Inject + public AsyncWebResourceBuilderFactory(JerseyClientFactory jerseyClientFactory) { + this.jerseyClientFactory = jerseyClientFactory; + } + + + /** + * Returns jersey HTTP resource to access to the remote replication servers + * + * @param nexusUrl URL of the remote server + * @param login Username on the remote server + * @param password User's password + * @return Jersey HTTP client + */ + public AsyncWebResource.Builder getAsyncWebResourceBuilder(String nexusUrl, String login, String password) { + Client client = jerseyClientFactory.getClient(login, password); + AsyncWebResource webResource = client.asyncResource(UriBuilder.fromUri(nexusUrl).build()); + webResource = webResource.path("service").path("local").path("artifact").path("maven").path("update"); + return webResource.accept(MediaType.APPLICATION_XML_TYPE) + .type(MediaType.APPLICATION_XML_TYPE); + } + +} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/FileBlockingQueueFactory.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/FileBlockingQueueFactory.java new file mode 100644 index 0000000..c76343a --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/FileBlockingQueueFactory.java @@ -0,0 +1,32 @@ +package com.griddynamics.cd.nrp.internal.uploading.impl.factories; + +import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; +import com.griddynamics.cd.nrp.internal.uploading.ConfigurationsManager; +import com.griddynamics.cd.nrp.internal.uploading.impl.FileBlockingQueue; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +@Singleton +public class FileBlockingQueueFactory { + + private final ConfigurationsManager configurationsManager; + + @Inject + public FileBlockingQueueFactory(ConfigurationsManager configurationsManager) { + this.configurationsManager = configurationsManager; + } + + public FileBlockingQueue getFileBlockingQueue() { + BlockingQueue blockingQueue = + new LinkedBlockingQueue<>(configurationsManager. + getConfiguration().getRequestsQueueSize()); + String blockingQueueDumpFileName = configurationsManager.getConfiguration().getQueueDumpFileName(); + + return new FileBlockingQueue(blockingQueue, + blockingQueueDumpFileName); + } + +} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/JerseyClientFactory.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/JerseyClientFactory.java new file mode 100644 index 0000000..df6b7c7 --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/JerseyClientFactory.java @@ -0,0 +1,51 @@ +package com.griddynamics.cd.nrp.internal.uploading.impl.factories; + +import com.griddynamics.cd.nrp.internal.uploading.ConfigurationsManager; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +@Singleton +public class JerseyClientFactory { + + private Logger log = LoggerFactory.getLogger(JerseyClientFactory.class); + + private final ExecutorService executorService; + + @Inject + public JerseyClientFactory(ConfigurationsManager configurationsManager) { + this.executorService = new ThreadPoolExecutor( + configurationsManager.getConfiguration().getRequestsSendingThreadsCount(), + configurationsManager.getConfiguration().getRequestsSendingThreadsCount(), + 30, + TimeUnit.SECONDS, + new LinkedBlockingQueue( + configurationsManager.getConfiguration().getRequestsQueueSize())); + } + + public Client getClient(String login, String password) { + ClientConfig config = new DefaultClientConfig(); + config.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 1000); + config.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, 2000); + Client client = Client.create(config); + client.setExecutorService(executorService); + if (login != null && !login.isEmpty() && password != null) { + log.debug("Creating HTTP client with authorized HTTPBasicAuthFilter."); + client.addFilter(new HTTPBasicAuthFilter(login, password)); + } else { + log.debug("Creating HTTP client with anonymous HTTPBasicAuthFilter."); + } + return client; + } + +} diff --git a/src/test/java/com/griddynamics/cd/nrp/internal/rest/ArtifactUpdatePlexusResourceTest.java b/src/test/java/com/griddynamics/cd/nrp/internal/rest/ArtifactUpdatePlexusResourceTest.java new file mode 100644 index 0000000..bf82a85 --- /dev/null +++ b/src/test/java/com/griddynamics/cd/nrp/internal/rest/ArtifactUpdatePlexusResourceTest.java @@ -0,0 +1,157 @@ +package com.griddynamics.cd.nrp.internal.rest; + +import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; +import com.griddynamics.cd.nrp.internal.model.api.RestResponse; +import com.thoughtworks.xstream.XStream; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.restlet.data.Request; +import org.restlet.resource.ResourceException; +import org.sonatype.nexus.proxy.maven.ArtifactStoreHelper; +import org.sonatype.nexus.proxy.maven.ArtifactStoreRequest; +import org.sonatype.nexus.proxy.maven.maven2.M2Repository; +import org.sonatype.nexus.proxy.registry.RepositoryRegistry; +import org.sonatype.nexus.proxy.repository.Repository; +import org.sonatype.plexus.rest.resource.PathProtectionDescriptor; + +import java.util.ArrayList; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class ArtifactUpdatePlexusResourceTest { + + private final String REQUEST_URI = "/artifact/maven/update"; + private final ArrayList repositories = new ArrayList<>(); + ArtifactStoreRequest artifactStoreRequestMock = mock(ArtifactStoreRequest.class); + + private ArtifactUpdatePlexusResource artifactUpdatePlexusResource; + private ArtifactMetaInfo artifactMetaInfo; + + @Before + public void setUp() throws Exception { + artifactUpdatePlexusResource = spy(new ArtifactUpdatePlexusResource() { + @Override + protected RepositoryRegistry getRepositoryRegistry() { +// ArtifactStoreHelper artifactStoreHelper = mock(ArtifactStoreHelper.class); +// ArrayList repositories = new ArrayList<>(); +// M2Repository repository = mock(M2Repository.class); +// when(repository.getRemoteUrl()).thenReturn("http://localhost:8081/nexus/content/repositories/snapshots/"); +// when(repository.getId()).thenReturn("replica-1"); +// when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); +// repositories.add(repository); + RepositoryRegistry repositoryRegistry = mock(RepositoryRegistry.class); + when(repositoryRegistry.getRepositories()).thenReturn(repositories); + return repositoryRegistry; + } + + @Override + protected ArtifactStoreRequest getResourceStoreRequest(Request request, boolean localOnly, boolean remoteOnly, String repositoryId, String g, String a, String v, String p, String c, String e) throws ResourceException { + return artifactStoreRequestMock; + } + }); + artifactMetaInfo = new ArtifactMetaInfo("http://localhost:8081/nexus", "com.griddynamics.cd", "nexus-replication-plugin", "1.0", "snapshots"); + artifactMetaInfo.setExtension("jar"); + } + + @After + public void tearDown() { + repositories.clear(); + } + + @Test + public void testGetResourceUri() throws Exception { + assertEquals(artifactUpdatePlexusResource.getResourceUri(), REQUEST_URI); + } + + @Test + public void testGetResourceProtection() throws Exception { + PathProtectionDescriptor resourceProtection = artifactUpdatePlexusResource.getResourceProtection(); + assertEquals("Incorrect request URI in security configuration", resourceProtection.getPathPattern(), REQUEST_URI); + assertEquals("Incorrect permissions for API", resourceProtection.getFilterExpression(), "authcBasic,perms[nexus:artifact]"); + } + + @Test + public void testGetPayloadInstance() throws Exception { + Object instance = artifactUpdatePlexusResource.getPayloadInstance(); + assertNotNull(REQUEST_URI + " resource should be configured to return ArtifactMetaInfo as request body DTO. Method returns null.", instance); + assertTrue(REQUEST_URI + " resource should be configured to return ArtifactMetaInfo as request body DTO. Method returns incorrect type.", instance instanceof ArtifactMetaInfo); + } + + @Test + public void testConfigureXStream() throws Exception { + XStream xstream = mock(XStream.class); + artifactUpdatePlexusResource.configureXStream(xstream); + Mockito.verify(xstream, Mockito.times(1)).processAnnotations(ArtifactMetaInfo.class); + Mockito.verify(xstream, Mockito.times(1)).processAnnotations(RestResponse.class); + } + + @Test + public void testPostForEmptyRepositoriesList() throws Exception { + // Mocks initialization + Request request = mock(Request.class); + + // Tested method invocation + RestResponse response = (RestResponse) artifactUpdatePlexusResource.post(null, request, null, artifactMetaInfo); + // Asserts + assertEquals("Method should return message that no proxies found", response.getMessage(), "No proxies for this artifact."); + assertFalse("Method should return error status because of no proxies found", response.isSuccess()); + } + + @Test + public void testPostForOneRepositoryList() throws Exception { + // Init mocks + ArtifactStoreHelper artifactStoreHelper = mock(ArtifactStoreHelper.class); + Request request = new Request(); + + M2Repository repository = mock(M2Repository.class); + when(repository.getRemoteUrl()).thenReturn("http://localhost:8081/nexus/content/repositories/snapshots/"); + when(repository.getId()).thenReturn("replica-1"); + when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); + repositories.add(repository); + // Tested method invocation + RestResponse response = (RestResponse) artifactUpdatePlexusResource.post(null, request, null, artifactMetaInfo); + // Asserts + Mockito.verify(artifactStoreHelper, Mockito.times(1)).retrieveArtifact(artifactStoreRequestMock); + Assert.assertEquals("Request should return that artifact is resolved", "Artifact is resolved.", response.getMessage()); + Assert.assertTrue("Request should be success.", response.isSuccess()); + } + + @Test + public void testPostForTwoMatchedRepositories() throws Exception { + // Init mocks + ArtifactStoreHelper artifactStoreHelper = mock(ArtifactStoreHelper.class); + + M2Repository repository = mock(M2Repository.class); + when(repository.getRemoteUrl()).thenReturn("http://localhost:8081/nexus/content/repositories/snapshots/"); + when(repository.getId()).thenReturn("replica-1"); + when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); + repositories.add(repository); + + repository = mock(M2Repository.class); + when(repository.getRemoteUrl()).thenReturn("http://localhost:8081/nexus/content/repositories/snapshots/"); + when(repository.getId()).thenReturn("replica-2"); + when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); + repositories.add(repository); + + repository = mock(M2Repository.class); + when(repository.getRemoteUrl()).thenReturn("http://localhost:8085/nexus/content/repositories/releases/"); + when(repository.getId()).thenReturn("replica-3"); + when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); + repositories.add(repository); + + Request request = new Request(); + // Tested method invocation + RestResponse response = (RestResponse) artifactUpdatePlexusResource.post(null, request, null, artifactMetaInfo); + // Asserts + Mockito.verify(artifactStoreHelper, Mockito.times(2)).retrieveArtifact(artifactStoreRequestMock); + Assert.assertEquals("Request should return that artifact is resolved", "Artifact is resolved.", response.getMessage()); + Assert.assertTrue("Request should be success.", response.isSuccess()); + } +} \ No newline at end of file diff --git a/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImplTest.java b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImplTest.java new file mode 100644 index 0000000..8e75af1 --- /dev/null +++ b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImplTest.java @@ -0,0 +1,137 @@ +package com.griddynamics.cd.nrp.internal.uploading.impl; + + +import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; +import com.griddynamics.cd.nrp.internal.model.config.NexusServer; +import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfiguration; +import com.griddynamics.cd.nrp.internal.uploading.ArtifactUpdateApiClient; +import com.griddynamics.cd.nrp.internal.uploading.ConfigurationsManager; +import com.griddynamics.cd.nrp.internal.uploading.impl.factories.AsyncWebResourceBuilderFactory; +import com.griddynamics.cd.nrp.internal.uploading.impl.factories.FileBlockingQueueFactory; +import com.sun.jersey.api.client.AsyncWebResource; +import com.sun.jersey.api.client.async.ITypeListener; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class ArtifactUpdateApiClientImplTest { + + private AwaitableFIleBlockingQueue awaitableFIleBlockingQueue; + @Mock + private ConfigurationsManager configurationsManagerMock; + @Mock + private FileBlockingQueueFactory fileBlockingQueueFactory; + @Mock + private AsyncWebResourceBuilderFactory asyncWebResourceBuilderFactoryMock; + @Mock + AsyncWebResource.Builder asyncWebResourceBuilderMock; + + private ArtifactUpdateApiClient underTest; + + @Before + public void setUp() { + NexusServer nexusServer = new NexusServer("http://mock:8082","admin","admin123"); + NexusServer nexusServer2 = new NexusServer("http://mock:8083", "admin2", "admin456"); + awaitableFIleBlockingQueue = new AwaitableFIleBlockingQueue( + new LinkedBlockingQueue(), "/tmp/queueDumpForTests", + 2 + ); + ReplicationPluginConfiguration replicationPluginConfiguration = + new ReplicationPluginConfiguration("http://mock:8081","/tmp/queueDumpForTests"); + replicationPluginConfiguration.addServer(nexusServer); + replicationPluginConfiguration.addServer(nexusServer2); + when(configurationsManagerMock.getConfiguration()).thenReturn(replicationPluginConfiguration); + when(fileBlockingQueueFactory.getFileBlockingQueue()).thenReturn(awaitableFIleBlockingQueue); + when(asyncWebResourceBuilderFactoryMock.getAsyncWebResourceBuilder( + anyString(), anyString(), anyString())). + thenReturn(asyncWebResourceBuilderMock); + underTest = new ArtifactUpdateApiClientImpl( + configurationsManagerMock, + fileBlockingQueueFactory, + asyncWebResourceBuilderFactoryMock); + } + + @After + public void tearDown() { + underTest = null; + } + + @Test + public void testOfferRequest() throws InterruptedException { + ArtifactMetaInfo artifactMetaInfo = new ArtifactMetaInfo( + "http://mock:8081", + "com.griddynamics", + "nexus-replication-status", + "1.0-SNAPSHOT", + "local-master-nexus" + ); + ArtifactMetaInfo artifactMetaInfo2 = new ArtifactMetaInfo( + "http://mock:8081", + "com.griddynamics", + "nexus-replication-status", + "2.0-SNAPSHOT", + "local-master-nexus" + ); + underTest.offerRequest(artifactMetaInfo); + underTest.offerRequest(artifactMetaInfo2); + awaitableFIleBlockingQueue.await(); + + ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor loginCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor passwordCaptor = ArgumentCaptor.forClass(String.class); + + verify(asyncWebResourceBuilderFactoryMock, times(4)). + getAsyncWebResourceBuilder(urlCaptor.capture(), loginCaptor.capture(), passwordCaptor.capture()); + + List allUrls = urlCaptor.getAllValues(); + List allLogins = loginCaptor.getAllValues(); + List allpasswowrds = passwordCaptor.getAllValues(); + + assertEquals(4, allUrls.size()); + assertEquals("http://mock:8082", allUrls.get(0)); + assertEquals("http://mock:8083", allUrls.get(1)); + assertEquals("http://mock:8082", allUrls.get(2)); + assertEquals("http://mock:8083", allUrls.get(3)); + + assertEquals(4, allLogins.size()); + assertEquals("admin", allLogins.get(0)); + assertEquals("admin2", allLogins.get(1)); + assertEquals("admin", allLogins.get(2)); + assertEquals("admin2", allLogins.get(3)); + + assertEquals(4, allpasswowrds.size()); + assertEquals("admin123", allpasswowrds.get(0)); + assertEquals("admin456", allpasswowrds.get(1)); + assertEquals("admin123", allpasswowrds.get(2)); + assertEquals("admin456", allpasswowrds.get(3)); + + ArgumentCaptor iTypeListenerArgumentCaptor = ArgumentCaptor.forClass(ITypeListener.class); + + ArgumentCaptor artifactMetaInfoArgumentCaptor = + ArgumentCaptor.forClass(ArtifactMetaInfo.class); + + verify(asyncWebResourceBuilderMock,times(4)).post( + iTypeListenerArgumentCaptor.capture(), + artifactMetaInfoArgumentCaptor.capture()); + + + assertEquals(artifactMetaInfo,artifactMetaInfoArgumentCaptor.getAllValues().get(0)); + assertEquals(artifactMetaInfo,artifactMetaInfoArgumentCaptor.getAllValues().get(1)); + assertEquals(artifactMetaInfo2,artifactMetaInfoArgumentCaptor.getAllValues().get(2)); + assertEquals(artifactMetaInfo2,artifactMetaInfoArgumentCaptor.getAllValues().get(3)); + + } + +} \ No newline at end of file diff --git a/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/AwaitableFIleBlockingQueue.java b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/AwaitableFIleBlockingQueue.java new file mode 100644 index 0000000..0241ea4 --- /dev/null +++ b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/AwaitableFIleBlockingQueue.java @@ -0,0 +1,30 @@ +package com.griddynamics.cd.nrp.internal.uploading.impl; + +import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; + +public class AwaitableFIleBlockingQueue extends FileBlockingQueue{ + + private final CountDownLatch countDownLatch; + + public AwaitableFIleBlockingQueue(BlockingQueue blockingQueue, + String blockingQueueDumpFileName, + int n) { + super(blockingQueue, blockingQueueDumpFileName); + this.countDownLatch = new CountDownLatch(n); + } + + @Override + public ArtifactMetaInfo take() throws InterruptedException { + ArtifactMetaInfo retVal = super.take(); + countDownLatch.countDown(); + return retVal; + } + + public void await() throws InterruptedException { + countDownLatch.await(); + } + +} diff --git a/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImplTest.java b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImplTest.java new file mode 100644 index 0000000..276348c --- /dev/null +++ b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImplTest.java @@ -0,0 +1,58 @@ +package com.griddynamics.cd.nrp.internal.uploading.impl; + +import com.griddynamics.cd.nrp.internal.model.config.NexusServer; +import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfiguration; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonatype.nexus.configuration.application.NexusConfiguration; + +import java.io.File; +import java.net.URL; +import java.util.Iterator; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class ConfigurationsManagerImplTest { + + private final String FIRST_CONFIGURATION_FILE = "replication-plugin.xml"; + private final String SECOND_CONFIGURATION_FILE = "replication-plugin-2.xml"; + + @Test + public void testGetConfiguration() throws Exception { + NexusConfiguration nexusConfiguration = mock(NexusConfiguration.class); + URL configFile = getClass().getClassLoader().getResource(FIRST_CONFIGURATION_FILE); + when(nexusConfiguration.getConfigurationDirectory()).thenReturn(new File(configFile.getFile()).getParentFile()); + ConfigurationsManagerImpl configurationsManager = spy(new ConfigurationsManagerImpl(nexusConfiguration)); + + ReplicationPluginConfiguration configuration = configurationsManager.getConfiguration(); + Assert.assertEquals("My url was written incorrectly", "http://localhost:8081/nexus", configuration.getMyUrl()); + Assert.assertEquals("Incorrect count of servers", 1, configuration.getServers().size()); + Iterator iterator = configuration.getServers().iterator(); + if (iterator.hasNext()) { + NexusServer nexusServer = iterator.next(); + Assert.assertEquals("Server url was written incorrectly", "http://localhost:8083/nexus", nexusServer.getUrl()); + Assert.assertEquals("User was written incorrectly", "admin", nexusServer.getUser()); + Assert.assertEquals("Password was written incorrectly", "admin123", nexusServer.getPassword()); + } + } + + @Test + public void testReloadConfigurations() throws Exception { + NexusConfiguration nexusConfiguration = mock(NexusConfiguration.class); + URL configFile = getClass().getClassLoader().getResource(FIRST_CONFIGURATION_FILE); + when(nexusConfiguration.getConfigurationDirectory()).thenReturn(new File(configFile.getFile()).getParentFile()); + ConfigurationsManagerImpl configurationsManager = spy(new ConfigurationsManagerImpl(nexusConfiguration)); + + ReplicationPluginConfiguration configuration = configurationsManager.getConfiguration(); + Assert.assertEquals("First file should contain one nexus server only", 1, configuration.getServers().size()); + + configurationsManager.reloadConfigurations(SECOND_CONFIGURATION_FILE); + configuration = configurationsManager.getConfiguration(); + Assert.assertEquals("Second file should contain two nexus servers", 2, configuration.getServers().size()); + } +} \ No newline at end of file diff --git a/src/test/resources/replication-plugin-2.xml b/src/test/resources/replication-plugin-2.xml new file mode 100644 index 0000000..4bfa8d6 --- /dev/null +++ b/src/test/resources/replication-plugin-2.xml @@ -0,0 +1,15 @@ + + + + + http://localhost:8083/nexus + admin + admin123 + + + http://localhost:8083/nexus2 + admin2 + admin123 + + + diff --git a/src/test/resources/replication-plugin.xml b/src/test/resources/replication-plugin.xml new file mode 100644 index 0000000..95d9854 --- /dev/null +++ b/src/test/resources/replication-plugin.xml @@ -0,0 +1,10 @@ + + + + + http://localhost:8083/nexus + admin + admin123 + + + From 088f1d8b6cd7380a2f81b45b2a2e2d5edeb67be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Magry=C5=9B?= Date: Thu, 9 Jul 2015 17:01:46 +0200 Subject: [PATCH 2/3] Code review changes. --- .../ArtifactUpdatePlexusResourceTest.java | 50 +++++++------------ .../impl/ArtifactUpdateApiClientImplTest.java | 2 +- .../impl/ConfigurationsManagerImplTest.java | 4 +- 3 files changed, 22 insertions(+), 34 deletions(-) diff --git a/src/test/java/com/griddynamics/cd/nrp/internal/rest/ArtifactUpdatePlexusResourceTest.java b/src/test/java/com/griddynamics/cd/nrp/internal/rest/ArtifactUpdatePlexusResourceTest.java index bf82a85..2bc2e11 100644 --- a/src/test/java/com/griddynamics/cd/nrp/internal/rest/ArtifactUpdatePlexusResourceTest.java +++ b/src/test/java/com/griddynamics/cd/nrp/internal/rest/ArtifactUpdatePlexusResourceTest.java @@ -8,6 +8,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import org.restlet.data.Request; @@ -29,6 +30,7 @@ public class ArtifactUpdatePlexusResourceTest { private final String REQUEST_URI = "/artifact/maven/update"; private final ArrayList repositories = new ArrayList<>(); + ArtifactStoreHelper artifactStoreHelper = mock(ArtifactStoreHelper.class); ArtifactStoreRequest artifactStoreRequestMock = mock(ArtifactStoreRequest.class); private ArtifactUpdatePlexusResource artifactUpdatePlexusResource; @@ -39,13 +41,6 @@ public void setUp() throws Exception { artifactUpdatePlexusResource = spy(new ArtifactUpdatePlexusResource() { @Override protected RepositoryRegistry getRepositoryRegistry() { -// ArtifactStoreHelper artifactStoreHelper = mock(ArtifactStoreHelper.class); -// ArrayList repositories = new ArrayList<>(); -// M2Repository repository = mock(M2Repository.class); -// when(repository.getRemoteUrl()).thenReturn("http://localhost:8081/nexus/content/repositories/snapshots/"); -// when(repository.getId()).thenReturn("replica-1"); -// when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); -// repositories.add(repository); RepositoryRegistry repositoryRegistry = mock(RepositoryRegistry.class); when(repositoryRegistry.getRepositories()).thenReturn(repositories); return repositoryRegistry; @@ -66,26 +61,26 @@ public void tearDown() { } @Test - public void testGetResourceUri() throws Exception { + public void shouldReturnCorrectResourceUri() throws Exception { assertEquals(artifactUpdatePlexusResource.getResourceUri(), REQUEST_URI); } @Test - public void testGetResourceProtection() throws Exception { + public void shouldReturnCorrectFilterExpression() throws Exception { PathProtectionDescriptor resourceProtection = artifactUpdatePlexusResource.getResourceProtection(); assertEquals("Incorrect request URI in security configuration", resourceProtection.getPathPattern(), REQUEST_URI); assertEquals("Incorrect permissions for API", resourceProtection.getFilterExpression(), "authcBasic,perms[nexus:artifact]"); } @Test - public void testGetPayloadInstance() throws Exception { + public void shouldReturnCorrectPayload() throws Exception { Object instance = artifactUpdatePlexusResource.getPayloadInstance(); assertNotNull(REQUEST_URI + " resource should be configured to return ArtifactMetaInfo as request body DTO. Method returns null.", instance); assertTrue(REQUEST_URI + " resource should be configured to return ArtifactMetaInfo as request body DTO. Method returns incorrect type.", instance instanceof ArtifactMetaInfo); } @Test - public void testConfigureXStream() throws Exception { + public void shouldConfigureXStreamCorrectly() throws Exception { XStream xstream = mock(XStream.class); artifactUpdatePlexusResource.configureXStream(xstream); Mockito.verify(xstream, Mockito.times(1)).processAnnotations(ArtifactMetaInfo.class); @@ -93,7 +88,7 @@ public void testConfigureXStream() throws Exception { } @Test - public void testPostForEmptyRepositoriesList() throws Exception { + public void ifNoProxyIsConfiguredShouldReturnNoProxiesForThisArtifact() throws Exception { // Mocks initialization Request request = mock(Request.class); @@ -105,7 +100,7 @@ public void testPostForEmptyRepositoriesList() throws Exception { } @Test - public void testPostForOneRepositoryList() throws Exception { + public void ifProxyForArtifactIsConfiguredShouldReturnArtifactIsResolved() throws Exception { // Init mocks ArtifactStoreHelper artifactStoreHelper = mock(ArtifactStoreHelper.class); Request request = new Request(); @@ -123,28 +118,21 @@ public void testPostForOneRepositoryList() throws Exception { Assert.assertTrue("Request should be success.", response.isSuccess()); } - @Test - public void testPostForTwoMatchedRepositories() throws Exception { - // Init mocks - ArtifactStoreHelper artifactStoreHelper = mock(ArtifactStoreHelper.class); - + private M2Repository provideMockM2Repository(String id, String remoteURL) { M2Repository repository = mock(M2Repository.class); - when(repository.getRemoteUrl()).thenReturn("http://localhost:8081/nexus/content/repositories/snapshots/"); - when(repository.getId()).thenReturn("replica-1"); + when(repository.getRemoteUrl()).thenReturn(remoteURL); + when(repository.getId()).thenReturn(id); when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); - repositories.add(repository); + return repository; + } - repository = mock(M2Repository.class); - when(repository.getRemoteUrl()).thenReturn("http://localhost:8081/nexus/content/repositories/snapshots/"); - when(repository.getId()).thenReturn("replica-2"); - when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); - repositories.add(repository); + @Test + public void if2Of3RepositoriesShouldSendOnlyToMatchningRepositories() throws Exception { + // Init mocks - repository = mock(M2Repository.class); - when(repository.getRemoteUrl()).thenReturn("http://localhost:8085/nexus/content/repositories/releases/"); - when(repository.getId()).thenReturn("replica-3"); - when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); - repositories.add(repository); + repositories.add(provideMockM2Repository("replica-1", "http://localhost:8081/nexus/content/repositories/snapshots/")); + repositories.add(provideMockM2Repository("replica-2", "http://localhost:8081/nexus/content/repositories/snapshots/")); + repositories.add(provideMockM2Repository("replica-3", "http://localhost:8085/nexus/content/repositories/snapshots/")); Request request = new Request(); // Tested method invocation diff --git a/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImplTest.java b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImplTest.java index 8e75af1..e470eb9 100644 --- a/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImplTest.java +++ b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImplTest.java @@ -69,7 +69,7 @@ public void tearDown() { } @Test - public void testOfferRequest() throws InterruptedException { + public void if2ArtifactsSubmittedAnd2PeersConfiguredShouldSend2artifactsTo2Peers() throws InterruptedException { ArtifactMetaInfo artifactMetaInfo = new ArtifactMetaInfo( "http://mock:8081", "com.griddynamics", diff --git a/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImplTest.java b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImplTest.java index 276348c..40c3aac 100644 --- a/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImplTest.java +++ b/src/test/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImplTest.java @@ -23,7 +23,7 @@ public class ConfigurationsManagerImplTest { private final String SECOND_CONFIGURATION_FILE = "replication-plugin-2.xml"; @Test - public void testGetConfiguration() throws Exception { + public void ifOneNexusServerSuppliedInCOnfigurationFileShouldLoadOneNexusServerWithItsAttributes() throws Exception { NexusConfiguration nexusConfiguration = mock(NexusConfiguration.class); URL configFile = getClass().getClassLoader().getResource(FIRST_CONFIGURATION_FILE); when(nexusConfiguration.getConfigurationDirectory()).thenReturn(new File(configFile.getFile()).getParentFile()); @@ -42,7 +42,7 @@ public void testGetConfiguration() throws Exception { } @Test - public void testReloadConfigurations() throws Exception { + public void if2NexusServersSuppliedInCOnfigurationFileShouldLoad2NexusServer() throws Exception { NexusConfiguration nexusConfiguration = mock(NexusConfiguration.class); URL configFile = getClass().getClassLoader().getResource(FIRST_CONFIGURATION_FILE); when(nexusConfiguration.getConfigurationDirectory()).thenReturn(new File(configFile.getFile()).getParentFile()); From 4bd9d887c290f97c2a5dbeca47865a97d7f36b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Magry=C5=9B?= Date: Fri, 10 Jul 2015 12:24:37 +0200 Subject: [PATCH 3/3] Get rid of PowerMock dependency. --- pom.xml | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/pom.xml b/pom.xml index 9061665..e789267 100644 --- a/pom.xml +++ b/pom.xml @@ -67,18 +67,6 @@ ${nexus.version} provided - - org.sonatype.nexus - nexus-plugin-testsupport - ${nexus.version} - test - - - javax.servlet - javax.servlet-api - - - org.sonatype.nexus nexus-rest-api @@ -147,6 +135,11 @@ 1.16.4 + + junit + junit + 4.12 + org.mockito mockito-core @@ -159,18 +152,6 @@ - - org.powermock - powermock-api-mockito - 1.6.2 - test - - - org.mockito - mockito-all - - -