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/NexusServer.java b/src/main/java/com/griddynamics/cd/nrp/internal/model/config/NexusServer.java index 4d78ae0..b683ff4 100644 --- a/src/main/java/com/griddynamics/cd/nrp/internal/model/config/NexusServer.java +++ b/src/main/java/com/griddynamics/cd/nrp/internal/model/config/NexusServer.java @@ -15,7 +15,9 @@ */ package com.griddynamics.cd.nrp.internal.model.config; -import lombok.*; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; 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 52cf9bf..57b1131 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 @@ -16,25 +16,21 @@ package com.griddynamics.cd.nrp.internal.uploading.impl; import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; -import com.griddynamics.cd.nrp.internal.model.internal.ArtifactMetaInfoQueueDump; import com.griddynamics.cd.nrp.internal.model.api.RestResponse; import com.griddynamics.cd.nrp.internal.model.config.NexusServer; +import com.griddynamics.cd.nrp.internal.model.internal.ArtifactMetaInfoQueueDump; 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; import com.sun.jersey.api.client.async.ITypeListener; -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.sonatype.sisu.goodies.common.ComponentSupport; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriBuilder; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import java.io.File; @@ -50,25 +46,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); - this.jerseyHttpClientExecutor = new ThreadPoolExecutor( - configurationsManager.getConfiguration().getRequestsSendingThreadsCount(), - configurationsManager.getConfiguration().getRequestsSendingThreadsCount(), - 30, - TimeUnit.SECONDS, - new LinkedBlockingQueue( - configurationsManager.getConfiguration().getRequestsQueueSize()) - ); initBackgroundWorkers(configurationsManager); } @@ -95,12 +87,8 @@ public void run() { } private FileBlockingQueue initFileBlockingQueue(ConfigurationsManager configurationsManager) { - BlockingQueue blockingQueue = - new LinkedBlockingQueue<>(configurationsManager. - getConfiguration().getRequestsQueueSize()); String blockingQueueDumpFileName = configurationsManager.getConfiguration().getQueueDumpFileName(); - FileBlockingQueue retVal = new FileBlockingQueue(blockingQueue, - blockingQueueDumpFileName); + FileBlockingQueue retVal = fileBlockingQueueFactory.getFileBlockingQueue(); try { File blockingQueueInputFile = new File(blockingQueueDumpFileName); if (blockingQueueInputFile.exists()) { @@ -133,7 +121,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 @@ -166,40 +156,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(); - 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..f02a657 --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/JerseyClientFactory.java @@ -0,0 +1,49 @@ +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(); + 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 + + +