diff --git a/pom.xml b/pom.xml index de10428..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 @@ -146,6 +134,24 @@ lombok 1.16.4 + + + junit + junit + 4.12 + + + org.mockito + mockito-core + 1.10.19 + test + + + org.hamcrest + hamcrest-core + + + 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..2bc2e11 --- /dev/null +++ b/src/test/java/com/griddynamics/cd/nrp/internal/rest/ArtifactUpdatePlexusResourceTest.java @@ -0,0 +1,145 @@ +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.Mock; +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<>(); + ArtifactStoreHelper artifactStoreHelper = mock(ArtifactStoreHelper.class); + 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() { + 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 shouldReturnCorrectResourceUri() throws Exception { + assertEquals(artifactUpdatePlexusResource.getResourceUri(), REQUEST_URI); + } + + @Test + 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 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 shouldConfigureXStreamCorrectly() 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 ifNoProxyIsConfiguredShouldReturnNoProxiesForThisArtifact() 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 ifProxyForArtifactIsConfiguredShouldReturnArtifactIsResolved() 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()); + } + + private M2Repository provideMockM2Repository(String id, String remoteURL) { + M2Repository repository = mock(M2Repository.class); + when(repository.getRemoteUrl()).thenReturn(remoteURL); + when(repository.getId()).thenReturn(id); + when(repository.getArtifactStoreHelper()).thenReturn(artifactStoreHelper); + return repository; + } + + @Test + public void if2Of3RepositoriesShouldSendOnlyToMatchningRepositories() throws Exception { + // Init mocks + + 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 + 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..e470eb9 --- /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 if2ArtifactsSubmittedAnd2PeersConfiguredShouldSend2artifactsTo2Peers() 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..40c3aac --- /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 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()); + 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 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()); + 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 + + +