aboutsummaryrefslogtreecommitdiffstats
path: root/appc-asdc-listener
diff options
context:
space:
mode:
Diffstat (limited to 'appc-asdc-listener')
-rw-r--r--appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcConfig.java316
-rw-r--r--appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcListener.java192
-rw-r--r--appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/AsdcCallbackTest.java (renamed from appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/TestAsdcListener.java)3
-rw-r--r--appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/AsdcListenerTest.java158
4 files changed, 459 insertions, 210 deletions
diff --git a/appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcConfig.java b/appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcConfig.java
index 448a7f365..d0d5319f9 100644
--- a/appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcConfig.java
+++ b/appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcConfig.java
@@ -29,161 +29,169 @@ import com.att.eelf.configuration.EELFManager;
import org.openecomp.sdc.api.consumer.IConfiguration;
import java.net.URI;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
public class AsdcConfig implements IConfiguration {
- private String host;
- private String consumer;
- private String consumerId;
- private String env;
- private String keystorePath;
- private String keystorePass;
- private int pollingInterval; // Time between listening sessions
- private int pollingTimeout; // Time to listen for (dmaap timeout url param)/1000
- private List<String> types = new ArrayList<>();
- private String user;
- private String pass;
-
- private URI storeOp;
-
- Properties props;
-
- private final EELFLogger logger = EELFManager.getInstance().getLogger(AsdcConfig.class);
-
- public AsdcConfig(Properties props) throws Exception {
- this.props = props;
- init();
- }
-
- private void init() throws Exception {
- if (props != null) {
- // Keystore for ca cert
- keystorePath = props.getProperty("appc.asdc.keystore.path");
- keystorePass = props.getProperty("appc.asdc.keystore.pass");
-
- // ASDC host
- host = props.getProperty("appc.asdc.host");
- env = props.getProperty("appc.asdc.env");
- user = props.getProperty("appc.asdc.user");
- pass = props.getProperty("appc.asdc.pass");
-
- // DMaaP properties
- consumer = props.getProperty("appc.asdc.consumer");
- consumerId = props.getProperty("appc.asdc.consumer.id");
-
- pollingInterval = Integer.valueOf(props.getProperty("interval", "60"));
-
- // Client uses cambriaClient-0.2.4 which throws non relevant (wrong)
- // exceptions with times > 30s
- pollingTimeout = Integer.valueOf(props.getProperty("timeout", "25"));
-
- // Anything less than 60 and we risk 429 Too Many Requests
- if (pollingInterval < 60) {
- pollingInterval = 60;
- }
-
- if (pollingInterval > pollingInterval) {
- logger.warn(String.format(
- "Message acknowledgement may be delayed by %ds in the ADSC listener. [Listening Time: %s, Poll Period: %s]",
- pollingInterval - pollingTimeout, pollingTimeout, pollingInterval));
- }
-
- logParams();
-
- // Download type
- types.add("APPC_CONFIG");
- types.add("VF_LICENSE");
- types.add("TOSCA_CSAR");
- /*
- This types seems redundant, as it looks from the code that they are not being used anywhere
- */
-
- storeOp = new URI(props.getProperty("appc.asdc.provider.url"));
- }
- }
-
- @Override
- public boolean activateServerTLSAuth() {
- return false;
- }
-
- //@Override
- public boolean isFilterInEmptyResources() {
- return false;
- }
-
- @Override
- public String getAsdcAddress() {
- return host;
- }
-
- @Override
- public String getConsumerGroup() {
- return consumer;
- }
-
- @Override
- public String getConsumerID() {
- return consumerId;
- }
-
- @Override
- public String getEnvironmentName() {
- return env;
- }
-
- @Override
- public String getKeyStorePassword() {
- return keystorePass;
- }
-
- @Override
- public String getKeyStorePath() {
- return keystorePath;
- }
-
- @Override
- public String getPassword() {
- return pass;
- }
-
- @Override
- public int getPollingInterval() {
- return pollingInterval;
- }
-
- @Override
- public int getPollingTimeout() {
- return pollingTimeout;
- }
-
- @Override
- public List<String> getRelevantArtifactTypes() {
- return types;
- }
-
- @Override
- public String getUser() {
- return user;
- }
-
- public URI getStoreOpURI() {
- return storeOp;
- }
-
- /**
- * Logs the relevant parameters
- */
- public void logParams() {
- Map<String, String> params = new HashMap<String, String>();
- params.put("ASDC Host", getAsdcAddress());
- params.put("ASDC Environment", getEnvironmentName());
- params.put("Consumer Name", getConsumerGroup());
- params.put("Consumer ID", getConsumerID());
- params.put("Poll Active Wait", String.valueOf(getPollingInterval()));
- params.put("Poll Timeout", String.valueOf(getPollingTimeout()));
-
- logger.info(String.format("ASDC Params: %s", params));
- }
+ private String host;
+ private String consumer;
+ private String consumerId;
+ private String env;
+ private String keystorePath;
+ private String keystorePass;
+ /** Polling internal is time between listening sessions */
+ private int pollingInterval;
+ /** Polling timeout is the time to listen for (dmaap timeout url param)/1000 */
+ private int pollingTimeout;
+ private List<String> types = new ArrayList<>();
+ private String user;
+ private String pass;
+
+ private URI storeOp;
+
+ private Properties props;
+
+ private final EELFLogger logger = EELFManager.getInstance().getLogger(AsdcConfig.class);
+
+ AsdcConfig(Properties props) throws Exception {
+ this.props = props;
+ init();
+ }
+
+ private void init() throws Exception {
+ if (props == null) {
+ logger.error("SdcConfig init is skipped due to properties is null");
+ return;
+ }
+
+ // Keystore for ca cert
+ keystorePath = props.getProperty("appc.asdc.keystore.path");
+ keystorePass = props.getProperty("appc.asdc.keystore.pass");
+
+ // ASDC host
+ host = props.getProperty("appc.asdc.host");
+ env = props.getProperty("appc.asdc.env");
+ user = props.getProperty("appc.asdc.user");
+ pass = props.getProperty("appc.asdc.pass");
+
+ // DMaaP properties
+ consumer = props.getProperty("appc.asdc.consumer");
+ consumerId = props.getProperty("appc.asdc.consumer.id");
+
+ pollingInterval = Integer.valueOf(props.getProperty("interval", "60"));
+
+ // Client uses cambriaClient-0.2.4 which throws non relevant (wrong)
+ // exceptions with times > 30s
+ pollingTimeout = Integer.valueOf(props.getProperty("timeout", "25"));
+
+ // Anything less than 60 and we risk 429 Too Many Requests
+ if (pollingInterval < 60) {
+ pollingInterval = 60;
+ }
+
+ if (pollingInterval > pollingTimeout) {
+ logger.warn(String.format(
+ "Message acknowledgement may be delayed by %ds in the ADSC listener. [Listening Time: %s, Poll Period: %s]",
+ pollingInterval - pollingTimeout, pollingTimeout, pollingInterval));
+ }
+
+ logParams();
+
+ // Download type
+ /*
+ This types seems redundant, as it looks from the code that they are not being used anywhere
+ */
+ types.add("APPC_CONFIG");
+ types.add("VF_LICENSE");
+ types.add("TOSCA_CSAR");
+
+ storeOp = new URI(props.getProperty("appc.asdc.provider.url"));
+ }
+
+ @Override
+ public boolean activateServerTLSAuth() {
+ return false;
+ }
+
+ public boolean isFilterInEmptyResources() {
+ return false;
+ }
+
+ @Override
+ public String getAsdcAddress() {
+ return host;
+ }
+
+ @Override
+ public String getConsumerGroup() {
+ return consumer;
+ }
+
+ @Override
+ public String getConsumerID() {
+ return consumerId;
+ }
+
+ @Override
+ public String getEnvironmentName() {
+ return env;
+ }
+
+ @Override
+ public String getKeyStorePassword() {
+ return keystorePass;
+ }
+
+ @Override
+ public String getKeyStorePath() {
+ return keystorePath;
+ }
+
+ @Override
+ public String getPassword() {
+ return pass;
+ }
+
+ @Override
+ public int getPollingInterval() {
+ return pollingInterval;
+ }
+
+ @Override
+ public int getPollingTimeout() {
+ return pollingTimeout;
+ }
+
+ @Override
+ public List<String> getRelevantArtifactTypes() {
+ return types;
+ }
+
+ @Override
+ public String getUser() {
+ return user;
+ }
+
+ URI getStoreOpURI() {
+ return storeOp;
+ }
+
+ /**
+ * Logs the relevant parameters
+ */
+ private void logParams() {
+ Map<String, String> params = new HashMap<>();
+ params.put("ASDC Host", getAsdcAddress());
+ params.put("ASDC Environment", getEnvironmentName());
+ params.put("Consumer Name", getConsumerGroup());
+ params.put("Consumer ID", getConsumerID());
+ params.put("Poll Active Wait", String.valueOf(getPollingInterval()));
+ params.put("Poll Timeout", String.valueOf(getPollingTimeout()));
+
+ logger.info(String.format("ASDC Params: %s", params));
+ }
}
diff --git a/appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcListener.java b/appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcListener.java
index d9755ef46..a580e4077 100644
--- a/appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcListener.java
+++ b/appc-asdc-listener/appc-asdc-listener-bundle/src/main/java/org/openecomp/appc/sdc/listener/AsdcListener.java
@@ -23,6 +23,13 @@
*/
package org.openecomp.appc.sdc.listener;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.openecomp.appc.configuration.Configuration;
+import org.openecomp.appc.configuration.ConfigurationFactory;
+import org.openecomp.sdc.api.IDistributionClient;
+import org.openecomp.sdc.api.results.IDistributionClientResult;
import org.openecomp.sdc.impl.DistributionClientFactory;
import org.openecomp.sdc.utils.DistributionActionResultEnum;
@@ -33,16 +40,13 @@ import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import org.openecomp.appc.configuration.Configuration;
-import org.openecomp.appc.configuration.ConfigurationFactory;
-import org.openecomp.sdc.api.IDistributionClient;
-import org.openecomp.sdc.api.results.IDistributionClientResult;
-import org.openecomp.sdc.impl.DistributionClientFactory;
-import org.openecomp.sdc.utils.DistributionActionResultEnum;
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
-
+/**
+ * SDC listener handles bundle start and stop through start and stop method. <p>
+ * Register connection with SDC server based on properties file configuration when start,
+ * and disconnect with SDC server when stop.
+ */
public class AsdcListener {
+ private final EELFLogger logger = EELFManager.getInstance().getLogger(AsdcListener.class);
/**
* The bundle context
@@ -52,83 +56,163 @@ public class AsdcListener {
private AsdcConfig config;
private CountDownLatch latch;
-
- private final EELFLogger logger = EELFManager.getInstance().getLogger(AsdcListener.class);
+ private Thread startThread = null;
@SuppressWarnings("unused")
public void start() throws Exception {
- logger.info("Starting bundle ASDC Listener");
+ // Add timestamp to the log to differentiate the jmeter run testing calls.
+ final long timeStamp = System.currentTimeMillis();
+ logger.info(String.format("[%d] Starting SDC Listener", timeStamp));
+
Configuration configuration = ConfigurationFactory.getConfiguration();
Properties props = configuration.getProperties();
-
config = new AsdcConfig(props);
+ logger.debug(String.format("[%d] created SDC config", timeStamp));
client = DistributionClientFactory.createDistributionClient();
+ logger.debug(String.format("[%d] created SDC client", timeStamp));
+
callback = new AsdcCallback(config.getStoreOpURI(), client);
+ logger.debug(String.format("[%d] created SDC callback", timeStamp));
latch = new CountDownLatch(1);
- new Thread(new Runnable() {
- @Override
- public void run() {
- initialRegistration(config);
-
- IDistributionClientResult result = client.init(config, callback);
-
- if (result.getDistributionActionResult() == DistributionActionResultEnum.SUCCESS) {
- client.start();
- } else {
- logger.error(String.format("Could not register ASDC client. %s - %s", result.getDistributionActionResult(),
- result.getDistributionMessageResult()));
- }
-
- latch.countDown();
- }
- }).start();
+ startThread = new Thread(new StartRunnable(timeStamp));
+ startThread.setName(String.format("[%d] sdcListener start", timeStamp));
+ logger.debug(String.format("[%d] created SDC initialization thread", timeStamp));
+ startThread.start();
}
@SuppressWarnings("unused")
public void stop() throws InterruptedException {
- logger.info("Stopping ASDC Listener");
- latch.await(10, TimeUnit.SECONDS);
+ // Add timestamp to the log to differentiate the jmeter run testing calls.
+ final long timeStamp = System.currentTimeMillis();
+ logger.info(String.format("[%d] Stopping ASDC Listener", timeStamp));
+
+ stopStartThread(timeStamp);
+
+ if (latch != null) {
+ logger.debug(String.format("[%d] waiting ASDC latch count to 0 for 10 seconds", timeStamp));
+ latch.await(10, TimeUnit.SECONDS);
+ latch = null;
+ }
if (callback != null) {
+ logger.debug(String.format("[%d] stopping ASDC callback", timeStamp));
callback.stop();
+ callback = null;
}
if (client != null) {
+ logger.debug(String.format("[%d] stopping ASDC client", timeStamp));
client.stop();
+ client = null;
}
- logger.info("ASDC Listener stopped successfully");
+ logger.info(String.format("[%d] ASDC Listener stopped successfully", timeStamp));
}
- private boolean initialRegistration(AsdcConfig config) {
- try {
- final String jsonTemplate = "{\"consumerName\": \"%s\",\"consumerSalt\": \"%s\",\"consumerPassword\":\"%s\"}";
- String saltedPassStr = org.openecomp.tlv.sdc.security.Passwords.hashPassword(config.getPassword());
- if (saltedPassStr == null || !saltedPassStr.contains(":")) {
- return false;
+ void stopStartThread(long timeStamp) throws InterruptedException {
+ if (startThread == null) {
+ return;
+ }
+
+ if (startThread.getState() == Thread.State.TERMINATED) {
+ logger.debug(String.format("[%d] ASDC thread(%s) is already terminated.",
+ timeStamp, startThread.getName()));
+ } else {
+ logger.debug(String.format("[%d] ASDC thread(%s) is to be interrupted with state(%s)",
+ timeStamp, startThread.getName(), startThread.getState().toString()));
+
+ startThread.interrupt();
+
+ logger.debug(String.format("[%d] ASDC thread(%s) has been interrupted(%s) with state(%s)",
+ timeStamp, startThread.getName(), startThread.isInterrupted(),
+ startThread.getState().toString()));
+ }
+ startThread = null;
+ }
+
+ /**
+ * Runnable implementation for actual initialization during ASDC listener start
+ */
+ class StartRunnable implements Runnable {
+ private final long timeStamp;
+
+ StartRunnable(long theTimeStamp) {
+ timeStamp = theTimeStamp;
+ }
+
+ /**
+ * This run method calls ASDC client for init and start which are synchronized calls along with stop.
+ * To interrupt this thread at stop time, we added thread interrupted checking in each step
+ * for earlier interruption.
+ */
+ @Override
+ public void run() {
+ if (!initialRegistration()) {
+ logger.warn(String.format("[%d] ASDC thread initial registration failed.", timeStamp));
+ }
+
+ if (isThreadInterrupted("after initial registration")) {
+ return;
+ }
+
+ IDistributionClientResult result = client.init(config, callback);
+
+ if (isThreadInterrupted("after client init")) {
+ return;
}
- String[] saltedPass = saltedPassStr.split(":");
- String json = String.format(jsonTemplate, config.getUser(), saltedPass[0], saltedPass[1]);
+ if (result.getDistributionActionResult() == DistributionActionResultEnum.SUCCESS) {
+ client.start();
+ } else {
+ logger.error(String.format("[%d] Could not register ASDC client. %s - %s",
+ timeStamp, result.getDistributionActionResult(), result.getDistributionMessageResult()));
+ }
+
+ latch.countDown();
+ }
- Map<String, String> headers = new HashMap<>();
- // TODO - Replace the header below to sdc's requirements. What should the new value be
- headers.put("USER_ID", "test");
+ private boolean initialRegistration() {
+ try {
+ final String jsonTemplate =
+ "{\"consumerName\": \"%s\",\"consumerSalt\": \"%s\",\"consumerPassword\":\"%s\"}";
+ String saltedPassStr = org.openecomp.tlv.sdc.security.Passwords.hashPassword(config.getPassword());
+ if (saltedPassStr == null || !saltedPassStr.contains(":")) {
+ return false;
+ }
- // TODO - How to format the url. Always same endpoint or ports?
- String host = config.getAsdcAddress();
- URL url = new URL(
- String.format("http%s://%s/sdc2/rest/v1/consumers", host.contains("443") ? "s" : "", host));
+ String[] saltedPass = saltedPassStr.split(":");
+ String json = String.format(jsonTemplate, config.getUser(), saltedPass[0], saltedPass[1]);
- logger.info(String.format("Attempting to register user %s on %s with salted pass of %s", config.getUser(),
- url, saltedPass[1]));
+ Map<String, String> headers = new HashMap<>();
+ // TODO - Replace the header below to sdc's requirements. What should the new value be
+ headers.put("USER_ID", "test");
- ProviderResponse result = ProviderOperations.post(url, json, headers);
- return result.getStatus() == 200;
- } catch (Exception e) {
- logger.error("Error performing initial registration with ASDC server. User may not be able to connect", e);
+ // TODO - How to format the url. Always same endpoint or ports?
+ String host = config.getAsdcAddress();
+ URL url = new URL(String.format("http%s://%s/sdc2/rest/v1/consumers",
+ host.contains("443") ? "s" : "", host));
+
+ logger.info(String.format("Attempting to register user %s on %s with salted pass of %s",
+ config.getUser(), url, saltedPass[1]));
+
+ ProviderOperations providerOperations = new ProviderOperations();
+ ProviderResponse result = providerOperations.post(url, json, headers);
+ return result.getStatus() == 200;
+ } catch (Exception e) {
+ logger.error(
+ "Error performing initial registration with ASDC server. User may not be able to connect",
+ e);
+ return false;
+ }
+ }
+
+ private boolean isThreadInterrupted(String details) {
+ if (Thread.currentThread().isInterrupted()) {
+ logger.info(String.format("[%d] ASDC thread interrupted %s.", timeStamp, details));
+ return true;
+ }
return false;
}
}
diff --git a/appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/TestAsdcListener.java b/appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/AsdcCallbackTest.java
index e6f913a6a..b4ee459f2 100644
--- a/appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/TestAsdcListener.java
+++ b/appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/AsdcCallbackTest.java
@@ -24,7 +24,6 @@
package org.openecomp.appc.sdc.listener;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -68,7 +67,7 @@ import java.util.List;
ArtifactStorageService.class,
ToscaCsarArtifactProcessor.class,
ArtifactProcessorFactory.class})
-public class TestAsdcListener {
+public class AsdcCallbackTest {
IDistributionClient client;
private EventSender eventSender;
diff --git a/appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/AsdcListenerTest.java b/appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/AsdcListenerTest.java
new file mode 100644
index 000000000..a821812ff
--- /dev/null
+++ b/appc-asdc-listener/appc-asdc-listener-bundle/src/test/java/org/openecomp/appc/sdc/listener/AsdcListenerTest.java
@@ -0,0 +1,158 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+package org.openecomp.appc.sdc.listener;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.openecomp.sdc.api.IDistributionClient;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(Thread.class)
+public class AsdcListenerTest {
+ private AsdcListener asdcListener;
+ private EELFLogger mockLogger = mock(EELFLogger.class);
+
+ @Before
+ public void setUp() throws Exception {
+ asdcListener = new AsdcListener();
+
+ // to avoid operation on logger fail, mock up the logger
+ Whitebox.setInternalState(asdcListener, "logger", mockLogger);
+ }
+
+ @Test
+ public void testStart() throws Exception {
+ asdcListener.start();
+ Assert.assertTrue("Should created startThread",
+ Whitebox.getInternalState(asdcListener, "startThread") != null);
+ }
+
+ @Test
+ public void testStop() throws Exception {
+ // test interrupt thread and other null case
+ MockThread mockThread = spy(new MockThread());
+ mockThread.setNewState(Thread.State.TIMED_WAITING);
+ Whitebox.setInternalState(asdcListener, "startThread", mockThread);
+
+ asdcListener.stop();
+ Mockito.verify(mockThread, times(1)).interrupt();
+ Assert.assertTrue("Should reset startThread",
+ Whitebox.getInternalState(asdcListener, "startThread") == null);
+
+ // test other non-null case and thread null case
+ IDistributionClient mockClient = mock(IDistributionClient.class);
+ Whitebox.setInternalState(asdcListener, "client", mockClient);
+ AsdcCallback mockCallback = mock(AsdcCallback.class);
+ Whitebox.setInternalState(asdcListener, "callback", mockCallback);
+ CountDownLatch mockLatch = mock(CountDownLatch.class);
+ Whitebox.setInternalState(asdcListener, "latch", mockLatch);
+
+ asdcListener.stop();
+
+ Mockito.verify(mockLatch, times(1)).await(10, TimeUnit.SECONDS);
+ Mockito.verify(mockCallback, times(1)).stop();
+ Mockito.verify(mockClient, times(1)).stop();
+ Assert.assertTrue("Should reset latch",
+ Whitebox.getInternalState(asdcListener, "latch") == null);
+ Assert.assertTrue("Should reset callback",
+ Whitebox.getInternalState(asdcListener, "callback") == null);
+ Assert.assertTrue("Should reset client",
+ Whitebox.getInternalState(asdcListener, "client") == null);
+ }
+
+ @Test
+ public void testStopStartThread() throws Exception {
+ // null case
+ asdcListener.stopStartThread(123);
+ Mockito.verify(mockLogger, times(0)).debug(String.valueOf(any()));
+
+ MockThread mockThread = spy(new MockThread());
+
+ // thread terminated case
+ Whitebox.setInternalState(asdcListener, "startThread", mockThread);
+ mockThread.setNewState(Thread.State.TERMINATED);
+ asdcListener.stopStartThread(123);
+ Mockito.verify(mockThread, times(0)).interrupt();
+ Mockito.verify(mockLogger, times(1)).debug(String.valueOf(any()));
+ Assert.assertTrue("Should reset startThread",
+ Whitebox.getInternalState(asdcListener, "startThread") == null);
+
+ // thread not termianted case
+ int timesCallThread = 0;
+ int timesCallLogger = 1;
+ for(Thread.State state : Thread.State.values()) {
+ if (state == Thread.State.TERMINATED) {
+ continue;
+ }
+ Whitebox.setInternalState(asdcListener, "startThread", mockThread);
+ mockThread.setNewState(state);
+ asdcListener.stopStartThread(123);
+ Mockito.verify(mockThread, times(++ timesCallThread)).interrupt();
+ Mockito.verify(mockLogger, times(timesCallLogger += 2)).debug(String.valueOf(any()));
+ Assert.assertTrue("Should reset startThread",
+ Whitebox.getInternalState(asdcListener, "startThread") == null);
+ }
+ }
+
+ /*
+ * I have used the following PowerMockito (due to Thread.getName() is a final method)
+ * try to mock up the thread behavior. But the mock Thread.getName() always returns null
+ * which works in intelliJ Junit test, but not Jenkins build:
+ * Thread mockThread = PowerMockito.mock(Thread.class);
+ * PowerMockito.doReturn(Thread.State.TERMINATED).when(mockThread).getState();
+ * PowerMockito.doReturn("testing").when(mockThread).getName();
+ * Hence, here goes the MockThread class to override Thread to my expected behavior.
+ */
+ class MockThread extends Thread {
+ private State state;
+
+ private MockThread() {
+ super.setName("testing");
+ }
+
+ void setNewState(State newState) {
+ state = newState;
+ }
+
+ @Override
+ public State getState() {
+ return state;
+ }
+ }
+} \ No newline at end of file