summaryrefslogtreecommitdiffstats
path: root/appc-oam
diff options
context:
space:
mode:
Diffstat (limited to 'appc-oam')
-rw-r--r--appc-oam/appc-oam-bundle/pom.xml6
-rw-r--r--appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/AppcOamTest.java235
-rw-r--r--appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/processor/BaseCommonTest.java185
-rw-r--r--appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/processor/BaseProcessorTest.java175
-rw-r--r--appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/util/AsyncTaskHelperTest.java663
5 files changed, 1264 insertions, 0 deletions
diff --git a/appc-oam/appc-oam-bundle/pom.xml b/appc-oam/appc-oam-bundle/pom.xml
index fdc0c8ffd..a4cde77e1 100644
--- a/appc-oam/appc-oam-bundle/pom.xml
+++ b/appc-oam/appc-oam-bundle/pom.xml
@@ -166,6 +166,12 @@
<version>1.6.2</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>3.22.0-GA</version>
+ <scope>test</scope>
+ </dependency>
<!-- TEMP CODE -->
<dependency>
<groupId>org.json</groupId>
diff --git a/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/AppcOamTest.java b/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/AppcOamTest.java
new file mode 100644
index 000000000..c3aac5635
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/AppcOamTest.java
@@ -0,0 +1,235 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * Modifications (C) 2018 Ericsson
+ * =============================================================================
+ * 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.
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.appc.oam;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.appc.exceptions.APPCException;
+import org.onap.appc.i18n.Msg;
+import org.onap.appc.metricservice.MetricRegistry;
+import org.onap.appc.metricservice.MetricService;
+import org.onap.appc.metricservice.metric.Metric;
+import org.onap.appc.metricservice.metric.MetricType;
+import org.onap.appc.metricservice.metric.impl.DefaultPrimitiveCounter;
+import org.onap.appc.metricservice.metric.impl.DispatchingFuntionMetricImpl;
+import org.onap.appc.oam.processor.OamMmodeProcessor;
+import org.onap.appc.oam.processor.OamRestartProcessor;
+import org.onap.appc.oam.processor.OamStartProcessor;
+import org.onap.appc.oam.processor.OamStopProcessor;
+import org.onap.appc.oam.util.AsyncTaskHelper;
+import org.onap.appc.oam.util.ConfigurationHelper;
+import org.onap.appc.oam.util.OperationHelper;
+import org.onap.appc.oam.util.StateHelper;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.AppcState;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.GetAppcStateInput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.GetAppcStateOutput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.GetMetricsInput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.GetMetricsOutput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.MaintenanceModeInput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.MaintenanceModeOutput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.RestartInput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.RestartOutput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.StartInput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.StartOutput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.StopInput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.StopOutput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.common.header.CommonHeader;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.status.Status;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.powermock.reflect.Whitebox;
+import com.att.aft.dme2.internal.google.common.collect.Iterables;
+import com.att.eelf.configuration.EELFLogger;
+import com.google.common.collect.ImmutableMap;
+
+
+public class AppcOamTest {
+
+ private AppcOam appcOam;
+ private CommonHeader mockCommonHeader = mock(CommonHeader.class);
+ private Status mockStatus = mock(Status.class);
+ private OperationHelper mockOperationHelper = mock(OperationHelper.class);
+ private StateHelper mockStateHelper = mock(StateHelper.class);
+
+ @Before
+ public void setUp() throws Exception {
+ appcOam = spy(new AppcOam(null, null, null));
+
+ Whitebox.setInternalState(appcOam, "stateHelper", mockStateHelper);
+ Whitebox.setInternalState(appcOam, "operationHelper", mockOperationHelper);
+ }
+
+ @Test
+ public void testMaintenanceMode() throws Exception {
+ // mock processor creation
+ OamMmodeProcessor mockProcessor = mock(OamMmodeProcessor.class);
+ Mockito.doReturn(mockProcessor).when(appcOam).getOamMmodeProcessor(Mockito.any(EELFLogger.class),
+ Mockito.any(ConfigurationHelper.class), Mockito.any(StateHelper.class),
+ Mockito.any(AsyncTaskHelper.class), Mockito.any(OperationHelper.class));
+ // mock input
+ MaintenanceModeInput mockInput = mock(MaintenanceModeInput.class);
+ Mockito.doReturn(mockCommonHeader).when(mockInput).getCommonHeader();
+ // mock processor result
+ Mockito.doReturn(mockStatus).when(mockProcessor).processRequest(mockInput);
+
+ Future<RpcResult<MaintenanceModeOutput>> response = appcOam.maintenanceMode(mockInput);
+
+ Assert.assertEquals("Should have common header", mockCommonHeader,
+ response.get().getResult().getCommonHeader());
+ Assert.assertEquals("Should have status", mockStatus, response.get().getResult().getStatus());
+ }
+
+ @Test
+ public void testStart() throws Exception {
+ // mock processor creation
+ OamStartProcessor mockProcessor = mock(OamStartProcessor.class);
+ Mockito.doReturn(mockProcessor).when(appcOam).getOamStartProcessor(Mockito.any(EELFLogger.class),
+ Mockito.any(ConfigurationHelper.class), Mockito.any(StateHelper.class),
+ Mockito.any(AsyncTaskHelper.class), Mockito.any(OperationHelper.class));
+ // mock input
+ StartInput mockInput = mock(StartInput.class);
+ Mockito.doReturn(mockCommonHeader).when(mockInput).getCommonHeader();
+ // mock processor result
+ Mockito.doReturn(mockStatus).when(mockProcessor).processRequest(mockInput);
+
+ Future<RpcResult<StartOutput>> response = appcOam.start(mockInput);
+
+ Assert.assertEquals("Should have common header", mockCommonHeader,
+ response.get().getResult().getCommonHeader());
+ Assert.assertEquals("Should have status", mockStatus, response.get().getResult().getStatus());
+ }
+
+ @Test
+ public void testStop() throws Exception {
+ // mock processor creation
+ OamStopProcessor mockProcessor = mock(OamStopProcessor.class);
+ //Mockito.doNothing().when(mockProcessor).setInitialLogProperties();
+ Mockito.doReturn(mockProcessor).when(appcOam).getOamStopProcessor(Mockito.any(EELFLogger.class),
+ Mockito.any(ConfigurationHelper.class), Mockito.any(StateHelper.class),
+ Mockito.any(AsyncTaskHelper.class), Mockito.any(OperationHelper.class));
+ // mock input
+ StopInput mockInput = mock(StopInput.class);
+ Mockito.doReturn(mockCommonHeader).when(mockInput).getCommonHeader();
+ // mock processor result
+ Mockito.doReturn(mockStatus).when(mockProcessor).processRequest(mockInput);
+
+ Future<RpcResult<StopOutput>> response = appcOam.stop(mockInput);
+
+ Assert.assertEquals("Should have common header", mockCommonHeader,
+ response.get().getResult().getCommonHeader());
+ Assert.assertEquals("Should have status", mockStatus, response.get().getResult().getStatus());
+ }
+
+ @Test
+ public void testRestart() throws Exception {
+ // mock processor creation
+ OamRestartProcessor mockProcessor = mock(OamRestartProcessor.class);
+ Mockito.doReturn(mockProcessor).when(appcOam).getOamRestartProcessor(Mockito.any(EELFLogger.class),
+ Mockito.any(ConfigurationHelper.class), Mockito.any(StateHelper.class),
+ Mockito.any(AsyncTaskHelper.class), Mockito.any(OperationHelper.class));
+ // mock input
+ RestartInput mockInput = mock(RestartInput.class);
+ Mockito.doReturn(mockCommonHeader).when(mockInput).getCommonHeader();
+ // mock processor result
+ Mockito.doReturn(mockStatus).when(mockProcessor).processRequest(mockInput);
+
+ Future<RpcResult<RestartOutput>> response = appcOam.restart(mockInput);
+
+ Assert.assertEquals("Should have common header", mockCommonHeader,
+ response.get().getResult().getCommonHeader());
+ Assert.assertEquals("Should have status", mockStatus, response.get().getResult().getStatus());
+ }
+
+ @Test
+ public void testGetAppcState() throws Exception {
+ AppcState appcState = AppcState.Started;
+ Mockito.doReturn(appcState).when(mockStateHelper).getCurrentOamYangState();
+ GetAppcStateInput getAppcStateInput = mock(GetAppcStateInput.class);
+ Future<RpcResult<GetAppcStateOutput>> state = appcOam.getAppcState(getAppcStateInput);
+ Assert.assertEquals("Should return the same state",
+ appcState, state.get().getResult().getState());
+ }
+
+ @Test
+ public void testGetMetricsMetricDisabled() throws InterruptedException, ExecutionException {
+ Whitebox.setInternalState(appcOam, "isMetricEnabled", false);
+ GetMetricsInput getMetricsInput = mock(GetMetricsInput.class);
+ Future<RpcResult<GetMetricsOutput>> result = appcOam.getMetrics(getMetricsInput);
+ assertEquals("Metric Service not enabled", Iterables.get(result.get().getErrors(), 0).getMessage());
+ }
+
+ @Test
+ public void testGetMetricsNoMetricsService() throws InterruptedException, ExecutionException, APPCException {
+ Whitebox.setInternalState(appcOam, "isMetricEnabled", true);
+ Mockito.doThrow(new APPCException()).when(mockOperationHelper).getService(MetricService.class);
+ GetMetricsInput getMetricsInput = mock(GetMetricsInput.class);
+ Future<RpcResult<GetMetricsOutput>> result = appcOam.getMetrics(getMetricsInput);
+ assertEquals("Metric Service not found", Iterables.get(result.get().getErrors(), 0).getMessage());
+ }
+
+ @Test
+ public void testGetMetricsNoMetrics() throws InterruptedException, ExecutionException, APPCException {
+ Whitebox.setInternalState(appcOam, "isMetricEnabled", true);
+ MetricService mockMetricService = mock(MetricService.class);
+ Mockito.doReturn(mockMetricService).when(mockOperationHelper).getService(MetricService.class);
+ GetMetricsInput getMetricsInput = mock(GetMetricsInput.class);
+ Future<RpcResult<GetMetricsOutput>> result = appcOam.getMetrics(getMetricsInput);
+ assertEquals("No metrics Registered", Iterables.get(result.get().getErrors(), 0).getMessage());
+ }
+
+ @Test
+ public void testGetMetricsWithMetricRegistry() throws InterruptedException, ExecutionException, APPCException {
+ Whitebox.setInternalState(appcOam, "isMetricEnabled", true);
+ MetricService mockMetricService = mock(MetricService.class);
+ MetricRegistry mockMetricRegistry = mock(MetricRegistry.class);
+ Mockito.doReturn(mockMetricService).when(mockOperationHelper).getService(MetricService.class);
+ Mockito.doReturn(ImmutableMap.of("TEST REGISTRY NAME", mockMetricRegistry)).when(mockMetricService).getAllRegistry();
+ Metric metric = new DispatchingFuntionMetricImpl("TEST METRIC NAME", MetricType.COUNTER, 0, 0);
+ Mockito.doReturn(new Metric[] {metric}).when(mockMetricRegistry).metrics();
+ GetMetricsInput getMetricsInput = mock(GetMetricsInput.class);
+ Future<RpcResult<GetMetricsOutput>> result = appcOam.getMetrics(getMetricsInput);
+ assertEquals(1, result.get().getResult().getMetrics().size());
+ }
+
+ @Test
+ public void testClose() throws Exception {
+ ConfigurationHelper mockConfigurationHelper = mock(ConfigurationHelper.class);
+ Mockito.doReturn("TEST APP NAME").when(mockConfigurationHelper).getAppcName();
+ Whitebox.setInternalState(appcOam, "configurationHelper", mockConfigurationHelper);
+ EELFLogger mockLogger = Mockito.mock(EELFLogger.class);
+ Whitebox.setInternalState(appcOam, "logger", mockLogger);
+ appcOam.close();
+ Mockito.verify(mockLogger).info(Msg.COMPONENT_TERMINATED, "TEST APP NAME", "oam");
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/processor/BaseCommonTest.java b/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/processor/BaseCommonTest.java
new file mode 100644
index 000000000..60d9e3c92
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/processor/BaseCommonTest.java
@@ -0,0 +1,185 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * Modifications (C) 2018 Ericsson
+ * =============================================================================
+ * 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.
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.appc.oam.processor;
+
+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.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.common.header.CommonHeader;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.status.Status;
+import org.onap.appc.exceptions.InvalidInputException;
+import org.onap.appc.exceptions.InvalidStateException;
+import org.onap.appc.oam.AppcOam;
+import org.onap.appc.oam.OAMCommandStatus;
+import org.onap.appc.oam.util.ConfigurationHelper;
+import org.onap.appc.oam.util.OperationHelper;
+import org.onap.appc.oam.util.StateHelper;
+import org.onap.appc.statemachine.impl.readers.AppcOamStates;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.slf4j.MDC;
+import java.util.Map;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({BaseCommon.class, MDC.class})
+public class BaseCommonTest {
+ private class TestAbc extends BaseCommon {
+
+ /**
+ * Constructor
+ *
+ * @param eelfLogger for logging
+ * @param configurationHelperIn for property reading
+ * @param stateHelperIn for APP-C OAM state checking
+ * @param operationHelperIn for operational helper
+ */
+ TestAbc(EELFLogger eelfLogger,
+ ConfigurationHelper configurationHelperIn,
+ StateHelper stateHelperIn,
+ OperationHelper operationHelperIn) {
+ super(eelfLogger, configurationHelperIn, stateHelperIn, operationHelperIn);
+ }
+ }
+
+ private TestAbc testBaseCommon;
+ private ConfigurationHelper mockConfigHelper = mock(ConfigurationHelper.class);
+ private StateHelper mockStateHelper = mock(StateHelper.class);
+ private CommonHeader mockCommonHeader = mock(CommonHeader.class);
+
+ @Before
+ public void setUp() throws Exception {
+ testBaseCommon = spy(new TestAbc(null, mockConfigHelper, mockStateHelper, null));
+
+ Whitebox.setInternalState(testBaseCommon, "commonHeader", mockCommonHeader);
+ Whitebox.setInternalState(testBaseCommon, "rpc", AppcOam.RPC.maintenance_mode);
+
+ // to avoid operation on logger fail, mock up the logger
+ EELFLogger mockLogger = mock(EELFLogger.class);
+ Whitebox.setInternalState(testBaseCommon, "logger", mockLogger);
+ }
+
+ @Test
+ public void testSetStatus() throws Exception {
+ OAMCommandStatus oamCommandStatus = OAMCommandStatus.ACCEPTED;
+ testBaseCommon.setStatus(oamCommandStatus);
+ Status status = testBaseCommon.status;
+ Assert.assertEquals("Should have code", oamCommandStatus.getResponseCode(), status.getCode().intValue());
+ Assert.assertEquals("Should have message", oamCommandStatus.getResponseMessage(), status.getMessage());
+ }
+
+ @Test
+ public void testSetStatusWithParams() throws Exception {
+ String message = "testing";
+ OAMCommandStatus oamCommandStatus = OAMCommandStatus.REJECTED;
+ testBaseCommon.setStatus(oamCommandStatus, message);
+ Status status = testBaseCommon.status;
+ Assert.assertEquals("Should have code", oamCommandStatus.getResponseCode(), status.getCode().intValue());
+ Assert.assertTrue("Should have message", status.getMessage().endsWith(message));
+ }
+
+ @Test
+ public void testSetErrorStatus() throws Exception {
+ Mockito.doReturn("testName").when(mockConfigHelper).getAppcName();
+ Mockito.doReturn(AppcOamStates.Started).when(mockStateHelper).getCurrentOamState();
+ Mockito.doReturn("testRequestId").when(mockCommonHeader).getRequestId();
+ Mockito.doReturn("testOrigId").when(mockCommonHeader).getOriginatorId();
+ Mockito.doReturn("SOME HOST NAME").when(testBaseCommon).getHostInfo(Mockito.anyString());
+
+ String exceptionMessage = "testing";
+
+ OAMCommandStatus oamCommandStatus = OAMCommandStatus.INVALID_PARAMETER;
+ Throwable t = new InvalidInputException(exceptionMessage);
+ testBaseCommon.setErrorStatus(t);
+ Status status = testBaseCommon.status;
+ Assert.assertEquals("Should have code", oamCommandStatus.getResponseCode(), status.getCode().intValue());
+ Mockito.verify(testBaseCommon, times(1)).resetLogProperties(false);
+ Mockito.verify(testBaseCommon, times(1)).resetLogProperties(true);
+
+ oamCommandStatus = OAMCommandStatus.REJECTED;
+ t = new InvalidStateException(exceptionMessage);
+ testBaseCommon.setErrorStatus(t);
+ status = testBaseCommon.status;
+ Assert.assertEquals("Should have code", oamCommandStatus.getResponseCode(), status.getCode().intValue());
+ Mockito.verify(testBaseCommon, times(2)).resetLogProperties(false);
+ Mockito.verify(testBaseCommon, times(2)).resetLogProperties(true);
+
+ oamCommandStatus = OAMCommandStatus.UNEXPECTED_ERROR;
+ t = new NullPointerException(exceptionMessage);
+ testBaseCommon.setErrorStatus(t);
+ status = testBaseCommon.status;
+ Assert.assertEquals("Should have code", oamCommandStatus.getResponseCode(), status.getCode().intValue());
+ Mockito.verify(testBaseCommon, times(3)).resetLogProperties(false);
+ Mockito.verify(testBaseCommon, times(3)).resetLogProperties(true);
+ }
+
+ @Test
+ public void testSetInitialLogProperties() throws Exception {
+ mockStatic(MDC.class);
+ Mockito.doReturn("SOME HOST NAME").when(testBaseCommon).getHostInfo(Mockito.anyString());
+ testBaseCommon.setInitialLogProperties();
+ PowerMockito.verifyStatic(times(5));
+ }
+
+ @Test
+ public void testClearRequestLogProperties() throws Exception {
+ mockStatic(MDC.class);
+ testBaseCommon.clearRequestLogProperties();
+ PowerMockito.verifyStatic(times(5));
+ }
+
+ @Test
+ public void testResetLogProperties() throws Exception {
+ Mockito.doReturn("SOME HOST NAME").when(testBaseCommon).getHostInfo(Mockito.anyString());
+ testBaseCommon.setInitialLogProperties();
+
+ testBaseCommon.resetLogProperties(false);
+ Mockito.verify(mockCommonHeader, times(2)).getRequestId();
+ Mockito.verify(mockCommonHeader, times(2)).getOriginatorId();
+ Map<String, String> oldMdcMap = Whitebox.getInternalState(testBaseCommon, "oldMdcContent");
+ Assert.assertTrue("Should have 5 entries in persisted map", oldMdcMap.size() == 5);
+
+ testBaseCommon.resetLogProperties(false);
+ Mockito.verify(mockCommonHeader, times(3)).getRequestId();
+ Mockito.verify(mockCommonHeader, times(3)).getOriginatorId();
+
+ // test oldMdcMap is cleared
+ testBaseCommon.resetLogProperties(false);
+ Mockito.verify(mockCommonHeader, times(4)).getRequestId();
+ Mockito.verify(mockCommonHeader, times(4)).getOriginatorId();
+ oldMdcMap = Whitebox.getInternalState(testBaseCommon, "oldMdcContent");
+ Assert.assertTrue("Should have 5 entries in persisted map", oldMdcMap.size() == 5);
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/processor/BaseProcessorTest.java b/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/processor/BaseProcessorTest.java
new file mode 100644
index 000000000..55ae11b8d
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/processor/BaseProcessorTest.java
@@ -0,0 +1,175 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * Modifications (C) 2018 Ericsson
+ * =============================================================================
+ * 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.
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.appc.oam.processor;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.StartInput;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.common.header.CommonHeader;
+import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.status.Status;
+import org.onap.appc.exceptions.APPCException;
+import org.onap.appc.exceptions.InvalidInputException;
+import org.onap.appc.exceptions.InvalidStateException;
+import org.onap.appc.i18n.Msg;
+import org.onap.appc.oam.AppcOam;
+import org.onap.appc.oam.OAMCommandStatus;
+import org.onap.appc.oam.util.AsyncTaskHelper;
+import org.onap.appc.oam.util.ConfigurationHelper;
+import org.onap.appc.oam.util.OperationHelper;
+import org.onap.appc.oam.util.StateHelper;
+import org.onap.appc.statemachine.impl.readers.AppcOamStates;
+import org.powermock.reflect.Whitebox;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+
+@SuppressWarnings("ResultOfMethodCallIgnored")
+public class BaseProcessorTest {
+ private AppcOam.RPC testRpc = AppcOam.RPC.start;
+ private AppcOamStates currentState = AppcOamStates.Stopped;
+
+ private class TestAbc extends BaseProcessor {
+
+ /**
+ * Constructor
+ *
+ * @param eelfLogger for logging
+ * @param configurationHelperIn for property reading
+ * @param stateHelperIn for APP-C OAM state checking
+ * @param asyncTaskHelperIn for scheduling async task
+ * @param operationHelperIn for operational helper
+ */
+ TestAbc(EELFLogger eelfLogger,
+ ConfigurationHelper configurationHelperIn,
+ StateHelper stateHelperIn,
+ AsyncTaskHelper asyncTaskHelperIn,
+ OperationHelper operationHelperIn) {
+ super(eelfLogger, configurationHelperIn, stateHelperIn, asyncTaskHelperIn, operationHelperIn);
+
+ // must set rpc and auditMsg
+ rpc = testRpc;
+ auditMsg = Msg.OAM_OPERATION_STARTING;
+ }
+ }
+
+ private TestAbc testBaseProcessor;
+ private ConfigurationHelper mockConfigHelper = mock(ConfigurationHelper.class);
+ private StateHelper mockStateHelper = mock(StateHelper.class);
+ private AsyncTaskHelper mockTaskHelper = mock(AsyncTaskHelper.class);
+ private OperationHelper mockOperHelper = mock(OperationHelper.class);
+
+ private StartInput mockInput = mock(StartInput.class);
+ private CommonHeader mockCommonHeader = mock(CommonHeader.class);
+
+ @Before
+ public void setUp() throws Exception {
+ Mockito.doReturn(mockCommonHeader).when(mockOperHelper).getCommonHeader(mockInput);
+ Mockito.doReturn(mockCommonHeader).when(mockInput).getCommonHeader();
+
+ testBaseProcessor = spy(
+ new TestAbc(null, mockConfigHelper, mockStateHelper, mockTaskHelper, mockOperHelper));
+ Mockito.doReturn("SOME HOST NAME").when(testBaseProcessor).getHostInfo(Mockito.anyString());
+ Whitebox.setInternalState(testBaseProcessor, "commonHeader", mockCommonHeader);
+
+ // to avoid operation on logger fail, mock up the logger
+ EELFLogger mockLogger = mock(EELFLogger.class);
+ Whitebox.setInternalState(testBaseProcessor, "logger", mockLogger);
+ }
+
+ @Test
+ public void testProcessRequestError() throws Exception {
+ Mockito.doReturn(currentState).when(mockStateHelper).getCurrentOamState();
+ Mockito.doThrow(new InvalidInputException("test")).when(mockOperHelper).isInputValid(mockInput);
+ Status status = testBaseProcessor.processRequest(mockInput);
+ Assert.assertEquals("Should return reject",
+ OAMCommandStatus.INVALID_PARAMETER.getResponseCode(), status.getCode().intValue());
+ }
+
+ @Test
+ public void testProcessRequest() throws Exception {
+ Mockito.doReturn(currentState).when(mockStateHelper).getCurrentOamState();
+ Mockito.doReturn(AppcOamStates.Starting).when(mockOperHelper).getNextState(any(), any());
+ Mockito.doReturn(mockCommonHeader).when(mockInput).getCommonHeader();
+ Status status = testBaseProcessor.processRequest(mockInput);
+ Assert.assertEquals("Should return success",
+ OAMCommandStatus.ACCEPTED.getResponseCode(), status.getCode().intValue());
+ }
+
+ @Test(expected = InvalidInputException.class)
+ public void testPreProcessWithInvalidInput() throws Exception {
+ Mockito.doThrow(new InvalidInputException("test")).when(mockOperHelper).isInputValid(mockInput);
+ testBaseProcessor.preProcess(mockInput);
+ }
+
+ @Test(expected = InvalidStateException.class)
+ public void testPreProcessWithInvalidState() throws Exception {
+ Mockito.doReturn(currentState).when(mockStateHelper).getCurrentOamState();
+ Mockito.doThrow(new InvalidStateException("test"))
+ .when(mockOperHelper).getNextState(testRpc.getAppcOperation(), currentState);
+ testBaseProcessor.preProcess(mockInput);
+ }
+
+ @Test(expected = APPCException.class)
+ public void testPreProcessWithAppcException() throws Exception {
+ Mockito.doReturn(currentState).when(mockStateHelper).getCurrentOamState();
+ Mockito.doThrow(new APPCException("test"))
+ .when(mockOperHelper).getNextState(testRpc.getAppcOperation(), currentState);
+ testBaseProcessor.preProcess(mockInput);
+ }
+
+ @Test
+ public void testPreProcess() throws Exception {
+ Mockito.doReturn(currentState).when(mockStateHelper).getCurrentOamState();
+ AppcOamStates nextState = AppcOamStates.Starting;
+ Mockito.doReturn(nextState)
+ .when(mockOperHelper).getNextState(testRpc.getAppcOperation(), currentState);
+ testBaseProcessor.preProcess(mockInput);
+ Mockito.verify(mockOperHelper, times(1)).isInputValid(mockInput);
+ Mockito.verify(mockOperHelper, times(1)).getNextState(testRpc.getAppcOperation(), currentState);
+ Mockito.verify(mockStateHelper, times(1)).setState(nextState);
+ }
+
+ @Test
+ public void testScheduleAsyncTask() throws Exception {
+ // test no runnable
+ testBaseProcessor.scheduleAsyncTask();
+ Assert.assertTrue(Whitebox.getInternalState(testBaseProcessor, "runnable") == null);
+ Assert.assertTrue(Whitebox.getInternalState(testBaseProcessor, "scheduledRunnable") == null);
+
+ BaseActionRunnable mockRunnable = mock(BaseActionRunnable.class);
+ Whitebox.setInternalState(testBaseProcessor, "runnable", mockRunnable);
+ testBaseProcessor.scheduleAsyncTask();
+ // scheduledRunnable should still be null, there's no mock done
+ // as I have trouble to make mockTaskHelper.scheduleBaseRunnable to return a proper Future
+ Assert.assertTrue(Whitebox.getInternalState(testBaseProcessor, "scheduledRunnable") == null);
+ }
+
+}
diff --git a/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/util/AsyncTaskHelperTest.java b/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/util/AsyncTaskHelperTest.java
new file mode 100644
index 000000000..319b0c796
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/test/java/org/onap/appc/oam/util/AsyncTaskHelperTest.java
@@ -0,0 +1,663 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 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.
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.appc.oam.util;
+
+import com.att.eelf.configuration.EELFLogger;
+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.onap.appc.oam.AppcOam;
+import org.onap.appc.statemachine.impl.readers.AppcOamStates;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.LinkedList;
+import java.util.concurrent.Future;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({FrameworkUtil.class})
+public class AsyncTaskHelperTest {
+ private AsyncTaskHelper asyncTaskHelper;
+
+ private long initialDelayMillis = 0;
+ private long delayMillis = 10;
+
+
+ @Before
+ public void setUp() throws Exception {
+
+ // to avoid operation on logger fail, mock up the logger
+ EELFLogger mockLogger = mock(EELFLogger.class);
+
+
+ mockStatic(FrameworkUtil.class);
+ Bundle myBundle = mock(Bundle.class);
+ Mockito.doReturn("TestBundle").when(myBundle).getSymbolicName();
+ PowerMockito.when(FrameworkUtil.getBundle(any())).thenReturn(myBundle);
+
+ asyncTaskHelper = new AsyncTaskHelper(mockLogger);
+
+
+ }
+
+
+ @After
+ public void shutdown(){
+ asyncTaskHelper.close();
+ }
+
+
+ /**
+ * Test that Base Runnable
+ *
+ * Runs at a fix rate;
+ * Only one Base Runnable can be scheduled at time;
+ * Future.cancle stops the Base Runnable;
+ * That another Base Runnable can be scheduled once the previous isDone.
+ */
+ @Test
+ public void test_scheduleBaseRunnable_Base_isDone() throws Exception{
+
+
+
+ //loop is to test we can run consecutive Base Runnable
+ for(int testIteration = 0; testIteration < 3;testIteration++){
+ final ExecuteTest et = new ExecuteTest();
+
+ Future<?> future = asyncTaskHelper.scheduleBaseRunnable(
+ et::test
+ , s -> { }
+ ,initialDelayMillis
+ ,delayMillis
+ );
+
+ //make sure it is running at a fix rate
+ Assert.assertTrue("It should be iterating", et.waitForTestExec(5000));
+ Assert.assertFalse("It Should not be Done", future.isDone());
+ Assert.assertTrue("It should be iterating", et.waitForTestExec(5000));
+ Assert.assertFalse("It Should not be Done", future.isDone());
+
+
+ //make sure a seconds Runnable cannot be scheduled when one is already running
+ try {
+ asyncTaskHelper.scheduleBaseRunnable(et::test
+ , s -> {}
+ ,initialDelayMillis
+ ,delayMillis
+ );
+ Assert.fail("scheduling should have been prevented. ");
+ } catch (IllegalStateException e) {
+ //IllegalStateException means the second scheduling was not allowed.
+ }
+
+
+ //let it cancel itself
+ et.cancelSelfOnNextExecution(future);
+
+ //it should be done after it executes itself one more time.
+ Assert.assertTrue("it should be done", waitFor(future::isDone, 5000));
+ Assert.assertTrue("The test failed to execute", et.isExecuted);
+ }
+
+
+ }
+
+
+ /**
+ * Makes sure the Future.isDone one only returns true if its runnable is not currently executing and will not
+ * execute in the future. Default implementation of isDone() returns true immediately after the future is
+ * canceled -- Even if is there is still a thread actively executing the runnable
+ */
+ @Test
+ public void test_scheduleBaseRunnable_Base_isDone_Ignore_Interrupt() throws Exception{
+
+
+ final ExecuteTest et = new ExecuteTest();
+
+ //configure test to run long and ignore interrupt
+ et.isContinuous = true;
+ et.isIgnoreInterrupt = true;
+
+
+
+ Future<?> future = asyncTaskHelper.scheduleBaseRunnable(
+ et::test
+ , s->{}
+ ,initialDelayMillis
+ ,delayMillis
+ );
+
+ //make sure it is running
+ Assert.assertTrue("It should be running",waitFor(et::isExecuting,1000));
+ Assert.assertTrue("It should be running",et.waitForTestExec(1000));
+ Assert.assertFalse("It Should not be Done", future.isDone());
+
+ //cancel it and make sure it is still running
+ future.cancel(true);
+ Assert.assertTrue("It should be running",waitFor(et::isExecuting,1000));
+ Assert.assertTrue("It should be running",et.waitForTestExec(1000));
+ Assert.assertFalse("It Should not be Done", future.isDone());
+
+ //let the thread die and then make sure its done
+ et.isContinuous = false;
+ Assert.assertTrue("It should not be running",waitForNot(et::isExecuting,1000));
+ Assert.assertTrue("It Should be Done", future.isDone());
+
+ }
+
+
+
+
+ /**
+ * Make sure the base Future.isDone returns false until the sub callable has completed execution.
+ */
+ @Test
+ public void test_scheduleBaseRunnable_SubTask_isDone_Ignore_Interrupt() throws Exception{
+
+
+ final ExecuteTest baseET = new ExecuteTest();
+ final ExecuteTest subET = new ExecuteTest();
+
+ //configure sub test to run long and ignore interrupt
+ subET.isContinuous = true;
+ subET.isIgnoreInterrupt = true;
+
+
+ //schedule the Base test to run and make sure it is running.
+ Future<?> baseFuture = asyncTaskHelper.scheduleBaseRunnable(
+ baseET::test
+ ,s->{}
+ ,initialDelayMillis
+ ,delayMillis
+ );
+ Assert.assertTrue("baseET should be running",waitFor(baseET::isExecuted,1000));
+ Assert.assertFalse("baseET Should not be Done because it runs at a fix rate", baseFuture.isDone());
+
+
+ //schedule the sub task and make sure it is running
+ Future<?> subFuture = asyncTaskHelper.submitBaseSubCallable(subET::test);
+ Assert.assertTrue("subET should be running",waitFor(subET::isExecuting,1000));
+ Assert.assertTrue("subET should be running",subET.waitForTestExec(1000));
+ Assert.assertFalse("subET Should not be Done", subFuture.isDone());
+ Assert.assertFalse("baseET Should not be Done", baseFuture.isDone());
+
+ //cancel the base task and make sure isDone is still false
+ baseFuture.cancel(true);
+ Assert.assertTrue("subET should be running",waitFor(subET::isExecuting,1000));
+ Assert.assertTrue("subET should be running",subET.waitForTestExec(1000));
+ Assert.assertFalse("subET Should not be Done",subFuture.isDone());
+ Assert.assertFalse("baseET Should not be Done", baseFuture.isDone());
+
+
+ //let the sub task die and and make sure the base is now finally done
+ subET.isContinuous = false;
+ Assert.assertTrue("subET should not be running",waitForNot(subET::isExecuting,1000));
+ Assert.assertTrue("subET Should be Done", subFuture.isDone());
+ Assert.assertTrue("baseET Should be Done", baseFuture.isDone());
+
+ }
+
+
+ /**
+ * Make sure the base Future.isDone returns false until the 3 sub callable has completed execution.
+ * Each sub callable will be shutdown one at a time.
+ */
+ public void test_scheduleBaseRunnable_SubTasks_isDone() throws Exception {
+
+
+ //loop is to test we can run consecutive Base Runnable
+ for (int testIteration = 0; testIteration < 3; testIteration++) {
+ final ExecuteTest baseET = new ExecuteTest();
+ final LinkedList<Sub> subList = new LinkedList<>();
+ for (int i = 0; i < 3; i++) {
+ Sub sub = new Sub();
+ sub.et.isContinuous = true;
+ subList.add(sub);
+ }
+
+
+ //schedule the base runnable and make sure it is running
+ Future<?> baseFuture = asyncTaskHelper.scheduleBaseRunnable(
+ baseET::test
+ , s -> {
+ }
+ , initialDelayMillis
+ , delayMillis
+ );
+ Assert.assertTrue("baseET should be running", waitFor(baseET::isExecuted, 1000));
+ Assert.assertFalse("baseET Should not be Done because it runs at a fix rate", baseFuture.isDone());
+
+
+ //schedule the sub Callables and make sure these are running
+ subList.forEach(sub -> sub.future = asyncTaskHelper.submitBaseSubCallable(sub.et::test));
+ for (Sub sub : subList) {
+ Assert.assertTrue("subET should be running", waitFor(sub.et::isExecuting, 100));
+ Assert.assertTrue("subET should be running", sub.et.waitForTestExec(1000));
+ Assert.assertFalse("subET Should not be Done", sub.future.isDone());
+ }
+ Assert.assertFalse("baseET Should not be Done", baseFuture.isDone());
+
+
+ //On each iteration shut down a sub callable. Make sure it stops, the others are still running and the
+ // //base is still running.
+ while (!subList.isEmpty()) {
+
+ //stop one sub and make sure it stopped
+ {
+ Sub sub = subList.removeFirst();
+ Assert.assertTrue("subET should be running", waitFor(sub.et::isExecuting, 1000));
+ sub.et.isContinuous = false;
+ Assert.assertTrue("subET should not be running", waitForNot(sub.et::isExecuting,1000));
+ Assert.assertTrue("subET Should not be Done", sub.future.isDone());
+ }
+
+ //make sure the other are still running
+ for (Sub sub : subList) {
+ Assert.assertTrue("subET should be running", waitFor(sub.et::isExecuting, 1000));
+ Assert.assertTrue("subET should be running", sub.et.waitForTestExec(1000));
+ Assert.assertFalse("subET Should not be Done", sub.future.isDone());
+ }
+
+ //Make sure the Base is still running
+ Assert.assertFalse("baseET Should not be Done", baseFuture.isDone());
+ }
+
+ //let the base cancel itself and make sure it stops
+ baseET.cancelSelfOnNextExecution(baseFuture);
+ Assert.assertTrue("baseET should be done", waitFor(baseFuture::isDone, 1000));
+ }
+ }
+
+
+ /**
+ * Make sure SubCallable cannot be scheduled when there is not BaseRunnable
+ */
+ @Test(expected=IllegalStateException.class)
+ public void test_SubTasksScheduleFailWhenNoBase() throws Exception {
+ asyncTaskHelper.submitBaseSubCallable(()->null);
+ }
+
+
+
+ /**
+ * Make sure SubCallable cannot be scheduled when BaseRunnable is cancelled but is still actively running.
+ */
+ @Test(expected=IllegalStateException.class)
+ public void test_SubTasksScheduleFailWhenBaseCanceledBeforeisDone() throws Exception {
+
+ final ExecuteTest et = new ExecuteTest();
+ et.isContinuous = true;
+
+ Future<?> future = asyncTaskHelper.scheduleBaseRunnable(
+ et::test
+ , s -> { }
+ ,initialDelayMillis
+ ,delayMillis
+ );
+
+ Assert.assertTrue("It should be running",waitFor(et::isExecuting,1000));
+ future.cancel(false);
+ Assert.assertTrue("It should be running",waitFor(et::isExecuting,1000));
+
+ try {
+ asyncTaskHelper.submitBaseSubCallable(() -> null);
+ } finally {
+ et.isContinuous = false;
+ }
+
+
+
+ }
+
+
+ /**
+ * Make sure SubCallable cannot be scheduled after a BaseRunnable has completed
+ */
+ @Test(expected=IllegalStateException.class)
+ public void test_SubTasksScheduleFailAfterBaseDone() throws Exception {
+
+ final ExecuteTest et = new ExecuteTest();
+
+ Future<?> future = asyncTaskHelper.scheduleBaseRunnable(
+ et::test
+ , s -> { }
+ ,initialDelayMillis
+ ,delayMillis
+ );
+
+
+ future.cancel(false);
+ Assert.assertTrue("It should not be running",waitFor(future::isDone,1000));
+
+ try {
+ asyncTaskHelper.submitBaseSubCallable(() -> null);
+ } finally {
+ et.isContinuous = false;
+ }
+
+ }
+
+
+ /**
+ * Test {@link AsyncTaskHelper#cancelBaseActionRunnable(AppcOam.RPC, AppcOamStates, long, TimeUnit)}}
+ * Test cancel does not block when BaseRunnable is not scheduled
+ */
+ @Test
+ public void test_cancel_noBlockingWhenBaseRunnableNotScheduled() throws Exception{
+ //nothing is running so this should return immediately without TimeoutException
+ asyncTaskHelper.cancelBaseActionRunnable(AppcOam.RPC.stop , AppcOamStates.Started , 1, TimeUnit.MILLISECONDS);
+ }
+
+
+
+ /**
+ * Test {@link AsyncTaskHelper#cancelBaseActionRunnable(AppcOam.RPC, AppcOamStates, long, TimeUnit)}}
+ * Test cancel does blocks until BaseRunnable is done scheduled
+ */
+ @Test()
+ public void test_cancel_BlockingWhenBaseRunnableNotDone() throws Exception {
+
+
+ final ExecuteTest et = new ExecuteTest();
+ et.isContinuous = true;
+ et.isIgnoreInterrupt = true;
+ asyncTaskHelper.scheduleBaseRunnable(
+ et::test
+ , s -> {
+ }
+ , initialDelayMillis
+ , delayMillis
+ );
+
+ Assert.assertTrue("It should be running", waitFor(et::isExecuting, 1000));
+
+
+ //we should get a timeout
+ try {
+ asyncTaskHelper.cancelBaseActionRunnable(
+ AppcOam.RPC.stop,
+ AppcOamStates.Started,
+ 1,
+ TimeUnit.MILLISECONDS);
+ Assert.fail("Should have gotten TimeoutException");
+ } catch (TimeoutException e) {
+ //just ignore as it is expected
+ }
+
+
+ //release the test thread
+ et.isContinuous = false;
+
+
+ //we should not get a timeout
+ asyncTaskHelper.cancelBaseActionRunnable(
+ AppcOam.RPC.stop,
+ AppcOamStates.Started,
+ 1000,
+ TimeUnit.MILLISECONDS);
+
+ }
+
+
+
+ /**
+ * Test {@link AsyncTaskHelper#cancelBaseActionRunnable(AppcOam.RPC, AppcOamStates, long, TimeUnit)}}
+ * Test cancel does not block when BaseRunnable is not scheduled
+ */
+ @Test
+ public void test_BaseRunnableCancelCallback() throws Exception{
+
+ AtomicReference<AppcOam.RPC> cancelCallback = new AtomicReference<>(null);
+
+ final ExecuteTest et = new ExecuteTest();
+ et.isContinuous = true;
+ Future<?> future = asyncTaskHelper.scheduleBaseRunnable(
+ et::test
+ , cancelCallback::set
+ , initialDelayMillis
+ , delayMillis
+ );
+
+ Assert.assertTrue("It should be running", waitFor(et::isExecuting, 1000));
+ Assert.assertTrue("It should be running", waitForNot(future::isDone, 1000));
+
+
+ try {
+ asyncTaskHelper.cancelBaseActionRunnable(
+ AppcOam.RPC.stop,
+ AppcOamStates.Started,
+ 1,
+ TimeUnit.MILLISECONDS);
+ Assert.fail("Should have gotten TimeoutException");
+ } catch (TimeoutException e) {
+ //just ignore as it is expected
+ }
+
+
+ Assert.assertEquals("Unexpected rpc in call back",AppcOam.RPC.stop,cancelCallback.get());
+ }
+
+
+
+
+
+
+
+
+ /**
+ * @return true if the negation of the expected value is returned from the supplier within the specified
+ * amount of time
+ */
+ private static boolean waitForNot(Supplier<Boolean> s,long timeoutMillis)throws Exception{
+ return waitFor(()->!s.get(),timeoutMillis);
+ }
+
+
+ /**
+ * @return true if the expected value is returned from the supplier within the specified
+ * amount of time
+ */
+ private static boolean waitFor(Supplier<Boolean> s,long timeoutMillis) throws Exception {
+ long timeout = TimeUnit.MILLISECONDS.toMillis(timeoutMillis);
+ long expiryTime = System.currentTimeMillis() + timeout;
+ long elapsedTime;
+ while(!s.get()){
+ elapsedTime = expiryTime - System.currentTimeMillis();
+ if(elapsedTime < 1) {
+ break;
+ }
+ Thread.sleep(10);
+ }
+ return s.get();
+ }
+
+
+ /**
+ * This class is used control a thread executed in th {@link #test()}
+ */
+ @SuppressWarnings("unused")
+ private static class ExecuteTest {
+
+
+ /** A fail safe to insure this TEst does not run indefinitely */
+ private final long EXPIRY_TIME = System.currentTimeMillis() + 10000;
+
+
+
+ /** A thread sets this value to true when it has completed the execution the of executes {@link #test()} */
+ private volatile boolean isExecuted = false;
+
+ /**
+ * A thread sets this value to true when it is actively executing {@link #test()} and back to false when
+ * it is not
+ */
+ private volatile boolean isExecuting = false;
+
+ /**
+ * While this value is true, a thread will not be allowed to return from {@link #test()} It will simulate a
+ * long execution.
+ */
+ private volatile boolean isContinuous = false;
+
+ /**
+ * When this value is set to true, an ongoing simulation of a long execution of {@link #test()} cannot be force
+ * to abort via a {@link Thread#interrupt()}
+ */
+ private volatile boolean isIgnoreInterrupt = false;
+
+
+
+ /** Use to send a signal to the thread executing {@link #notifyTestExcuted(long)} */
+ private Semaphore inner = new Semaphore(0);
+
+ /** Use to send a signal to the thread executing {@link #waitForTestExec(long)} */
+ private Semaphore outer = new Semaphore(0);
+
+ /** The {@link Future} of the Thread executing {@link #test()}*/
+ private volatile Future<?> future;
+
+ /**
+ * When set the Thread executing {@link #test()} will cancel itself
+ * @param future - The {@link Future} of the Thread executing {@link #test()}
+ */
+ private void cancelSelfOnNextExecution(Future<?> future) {
+ this.future = future;
+ }
+
+
+ private boolean isExecuted() {
+ return isExecuted;
+ }
+
+ private boolean isExecuting() {
+ return isExecuting;
+ }
+
+
+ private boolean isContinuous() {
+ return isContinuous;
+ }
+
+
+ private boolean isIgnoreInterrupt() {
+ return isIgnoreInterrupt;
+ }
+
+
+
+ /**
+ * The thread executing this method if blocked from returning until the thread executing
+ * {@link #test()} invokes {@link #notifyTestExcuted(long)} or the specified time elapses
+ * @param timeoutMillis - the amount of time to wait for a execution iteration.
+ * @return true if the Thread is released because of an invocation of {@link #notifyTestExcuted(long)}
+ * @throws InterruptedException - If the Caller thread is interrupted.
+ */
+ private boolean waitForTestExec(long timeoutMillis) throws InterruptedException {
+ inner.release();
+ return outer.tryAcquire(timeoutMillis,TimeUnit.MILLISECONDS);
+ }
+
+
+ /**
+ * Test simulator
+ * @return Always returns true.
+ */
+ private Boolean test() {
+ isTestExpired();
+ System.out.println("started");
+ isExecuting = true;
+ try {
+ if (future != null) {
+ future.cancel(false);
+ }
+ if(!isContinuous){
+ notifyTestExcuted(1);
+ }
+
+ while(isContinuous){
+ notifyTestExcuted(100);
+ isTestExpired();
+ }
+
+ } finally {
+ isExecuting = false;
+ isExecuted = true;
+ }
+ return true;
+ }
+
+
+ /** @throws RuntimeException if the test has bee running too long */
+ private void isTestExpired(){
+ if(System.currentTimeMillis() > EXPIRY_TIME){
+ throw new RuntimeException("Something went wrong the test expired.");
+ }
+ }
+
+
+ /**
+ * The thread executing {@link #test()} if blocked from returning until another thread invokes
+ * {@link #waitForTestExec(long)} or the specified time elapses
+ * @param timeoutMillis - the amount of time to wait for a execution iteration.
+ * @return true if the Thread is released because of an invocation of {@link #waitForTestExec(long)}
+ */
+ private boolean notifyTestExcuted(long timeoutMillis){
+ try {
+ boolean acquire = inner.tryAcquire(timeoutMillis,TimeUnit.MILLISECONDS);
+ if(acquire){
+ outer.release();
+ System.out.println("release");
+ }
+ } catch (InterruptedException e) {
+ if(!isIgnoreInterrupt){
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+
+ static class Sub {
+ ExecuteTest et = new ExecuteTest();
+ Future<?> future = null;
+ }
+
+}