diff options
author | Joey Sullivan <joey.sullivan@amdocs.com> | 2017-09-27 23:02:31 +0000 |
---|---|---|
committer | Patrick Brady <pb071s@att.com> | 2017-09-27 23:54:32 +0000 |
commit | e5aad808db5203acec496eed43b5785fc0640d90 (patch) | |
tree | 79df5447f99d4ca34b34d522e70e83e8d87dba1d /appc-oam/appc-oam-bundle/src/test | |
parent | 78f459993575bcab672898610ec281674ccaebc3 (diff) |
serializing OAM async task
Change-Id: I0c98636c165a2cc5b9915a3950ab64744e6328c7
Issue-Id: APPC-244
Signed-off-by: Joey Sullivan <joey.sullivan@amdocs.com>
Diffstat (limited to 'appc-oam/appc-oam-bundle/src/test')
5 files changed, 653 insertions, 139 deletions
diff --git a/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseActionRunnableTest.java b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseActionRunnableTest.java index c5ad95e43..07500f441 100644 --- a/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseActionRunnableTest.java +++ b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseActionRunnableTest.java @@ -22,7 +22,6 @@ * ============LICENSE_END========================================================= */ - package org.openecomp.appc.oam.processor; import com.att.eelf.configuration.EELFLogger; @@ -31,7 +30,6 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.common.header.CommonHeader; -import org.openecomp.appc.configuration.Configuration; import org.openecomp.appc.i18n.Msg; import org.openecomp.appc.oam.AppcOam; import org.openecomp.appc.oam.OAMCommandStatus; @@ -46,7 +44,6 @@ import org.powermock.reflect.Whitebox; import java.util.Date; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyMap; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -102,7 +99,6 @@ public class BaseActionRunnableTest { private StateHelper mockStateHelper = mock(StateHelper.class); private OperationHelper mockOperHelper = mock(OperationHelper.class); private ConfigurationHelper mockConfigHelper = mock(ConfigurationHelper.class); - private Configuration mockConfig = mock(Configuration.class); private BundleHelper mockBundleHelper = mock(BundleHelper.class); @SuppressWarnings("ResultOfMethodCallIgnored") @@ -111,11 +107,8 @@ public class BaseActionRunnableTest { // to avoid operation on logger fail, mock up the logger EELFLogger mockLogger = mock(EELFLogger.class); - Mockito.doReturn(mockConfig).when(mockConfigHelper).getConfig(); - Mockito.doReturn(10).when(mockConfig).getIntegerProperty(any(), anyInt()); - testProcessor = spy( - new TestProcessor(mockLogger, mockConfigHelper, mockStateHelper, null, mockOperHelper)); + new TestProcessor(mockLogger, mockConfigHelper, mockStateHelper, null, mockOperHelper)); Whitebox.setInternalState(testProcessor, "bundleHelper", mockBundleHelper); testBaseAcionRunnable = spy(new TestAbc(testProcessor)); @@ -127,41 +120,41 @@ public class BaseActionRunnableTest { Whitebox.setInternalState(testBaseAcionRunnable, "timeoutMs", 0); Whitebox.setInternalState(testBaseAcionRunnable, "startTimeMs", 0); Whitebox.setInternalState(testBaseAcionRunnable, "doTimeoutChecking", false); + long expectedTimeout = 10000L; + Mockito.doReturn(expectedTimeout).when(mockConfigHelper).getOAMOperationTimeoutValue(any()); testBaseAcionRunnable.setTimeoutValues(); - Assert.assertEquals("Should set timeoutMs", 10 * 1000, testBaseAcionRunnable.timeoutMs); + Assert.assertEquals("Should set timeoutMs", expectedTimeout, testBaseAcionRunnable.timeoutMs); Assert.assertTrue("Should set start time MS", testBaseAcionRunnable.startTimeMs != 0); Assert.assertTrue("Should do check", testBaseAcionRunnable.doTimeoutChecking); Whitebox.setInternalState(testBaseAcionRunnable, "timeoutMs", 0); Whitebox.setInternalState(testBaseAcionRunnable, "startTimeMs", 0); Whitebox.setInternalState(testBaseAcionRunnable, "doTimeoutChecking", false); - int timeoutSeconds = 20; - Whitebox.setInternalState(testProcessor, "timeoutSeconds", timeoutSeconds); + expectedTimeout = 20000L; + Mockito.doReturn(expectedTimeout).when(mockConfigHelper).getOAMOperationTimeoutValue(any()); testBaseAcionRunnable.setTimeoutValues(); - Assert.assertEquals("Should set timeoutMs", timeoutSeconds * 1000, testBaseAcionRunnable.timeoutMs); + Assert.assertEquals("Should set timeoutMs", expectedTimeout, testBaseAcionRunnable.timeoutMs); Assert.assertTrue("Should set start time MS", testBaseAcionRunnable.startTimeMs != 0); Assert.assertTrue("Should do check", testBaseAcionRunnable.doTimeoutChecking); Whitebox.setInternalState(testBaseAcionRunnable, "timeoutMs", 0); Whitebox.setInternalState(testBaseAcionRunnable, "startTimeMs", 0); Whitebox.setInternalState(testBaseAcionRunnable, "doTimeoutChecking", false); - - timeoutSeconds = 0; - Whitebox.setInternalState(testProcessor, "timeoutSeconds", timeoutSeconds); - Mockito.doReturn(0).when(mockConfig).getIntegerProperty( - testBaseAcionRunnable.OAM_OPERATION_TIMEOUT_SECOND, testBaseAcionRunnable.DEFAULT_OAM_OPERATION_TIMEOUT); + expectedTimeout = 0L; + Mockito.doReturn(expectedTimeout).when(mockConfigHelper).getOAMOperationTimeoutValue(any()); testBaseAcionRunnable.setTimeoutValues(); - Assert.assertEquals("Should set timeoutMs", timeoutSeconds * 1000, testBaseAcionRunnable.timeoutMs); + Assert.assertEquals("Should set timeoutMs", expectedTimeout, testBaseAcionRunnable.timeoutMs); Assert.assertTrue("Should not set start time MS", testBaseAcionRunnable.startTimeMs == 0); Assert.assertFalse("Should not do check", testBaseAcionRunnable.doTimeoutChecking); } + @Test public void testRun() throws Exception { // test doAction failed Whitebox.setInternalState(testBaseAcionRunnable, "doActionResult", false); testBaseAcionRunnable.run(); Assert.assertFalse("isWaiting should still be false", - Whitebox.getInternalState(testBaseAcionRunnable, "isWaiting")); + Whitebox.getInternalState(testBaseAcionRunnable, "isWaiting")); // test doAction success Whitebox.setInternalState(testBaseAcionRunnable, "doActionResult", true); @@ -170,13 +163,13 @@ public class BaseActionRunnableTest { Mockito.doReturn(true).when(testBaseAcionRunnable).checkState(); testBaseAcionRunnable.run(); Assert.assertFalse("isWaiting should still be false", - Whitebox.getInternalState(testBaseAcionRunnable, "isWaiting")); + Whitebox.getInternalState(testBaseAcionRunnable, "isWaiting")); // with checkState return false Mockito.doReturn(false).when(testBaseAcionRunnable).checkState(); testBaseAcionRunnable.run(); Assert.assertTrue("isWaiting should still be true", - Whitebox.getInternalState(testBaseAcionRunnable, "isWaiting")); + Whitebox.getInternalState(testBaseAcionRunnable, "isWaiting")); // should stay testBaseAcionRunnable.run(); @@ -187,11 +180,11 @@ public class BaseActionRunnableTest { public void testSetAbortStatus() throws Exception { testBaseAcionRunnable.setAbortStatus(); Assert.assertEquals("Should return abort code", OAMCommandStatus.ABORT.getResponseCode(), - testBaseAcionRunnable.status.getCode().intValue()); + testBaseAcionRunnable.status.getCode().intValue()); Assert.assertTrue("Should set abort due to execution error message", - testBaseAcionRunnable.status.getMessage().endsWith( - String.format(testBaseAcionRunnable.ABORT_MESSAGE_FORMAT, - testRpc.name(), testBaseAcionRunnable.DUE_TO_EXECUTION_ERROR))); + testBaseAcionRunnable.status.getMessage().endsWith( + String.format(testBaseAcionRunnable.ABORT_MESSAGE_FORMAT, + testRpc.name(), testBaseAcionRunnable.DUE_TO_EXECUTION_ERROR))); } @Test @@ -261,10 +254,10 @@ public class BaseActionRunnableTest { Assert.assertTrue("Should be timeout", testBaseAcionRunnable.isTimeout(parentName)); Mockito.verify(testBaseAcionRunnable, times(1)).postAction(any()); Assert.assertEquals("Should return timeout code", OAMCommandStatus.TIMEOUT.getResponseCode(), - testBaseAcionRunnable.status.getCode().intValue()); + testBaseAcionRunnable.status.getCode().intValue()); Assert.assertTrue("Should set timeout message", - testBaseAcionRunnable.status.getMessage().endsWith( - String.format(testBaseAcionRunnable.TIMEOUT_MESSAGE_FORMAT, testRpc.name(), timeoutMs))); + testBaseAcionRunnable.status.getMessage().endsWith( + String.format(testBaseAcionRunnable.TIMEOUT_MESSAGE_FORMAT, testRpc.name(), timeoutMs))); } @SuppressWarnings("unchecked") @@ -277,9 +270,8 @@ public class BaseActionRunnableTest { long failedNumber = 1; Mockito.doReturn(failedNumber).when(mockBundleHelper).getFailedMetrics(anyMap()); Assert.assertTrue("should return true", testBaseAcionRunnable.hasBundleOperationFailure()); - Mockito.verify(testBaseAcionRunnable, - times(1)).setStatus(OAMCommandStatus.UNEXPECTED_ERROR, - String.format(testBaseAcionRunnable.BUNDLE_OPERATION_FAILED_FORMAT, failedNumber)); + Mockito.verify(testBaseAcionRunnable, times(1)).setStatus(OAMCommandStatus.UNEXPECTED_ERROR, + String.format(testBaseAcionRunnable.BUNDLE_OPERATION_FAILED_FORMAT, failedNumber)); Mockito.verify(testBaseAcionRunnable, times(1)).postAction(AppcOamStates.Error); } @@ -289,11 +281,11 @@ public class BaseActionRunnableTest { AppcOam.RPC newRpc = AppcOam.RPC.restart; testBaseAcionRunnable.abortRunnable(newRpc); Assert.assertEquals("Should return abort code", OAMCommandStatus.ABORT.getResponseCode(), - testBaseAcionRunnable.status.getCode().intValue()); + testBaseAcionRunnable.status.getCode().intValue()); Assert.assertTrue("Should set abort due to new request message", - testBaseAcionRunnable.status.getMessage().endsWith( - String.format(testBaseAcionRunnable.ABORT_MESSAGE_FORMAT, testRpc.name(), - String.format(testBaseAcionRunnable.NEW_RPC_OPERATION_REQUEST, newRpc.name())))); + testBaseAcionRunnable.status.getMessage().endsWith( + String.format(testBaseAcionRunnable.ABORT_MESSAGE_FORMAT, testRpc.name(), + String.format(testBaseAcionRunnable.NEW_RPC_OPERATION_REQUEST, newRpc.name())))); Mockito.verify(mockOperHelper, times(1)).sendNotificationMessage(any(), any(), any()); Mockito.verify(testBaseAcionRunnable, times(1)).resetLogProperties(false); Mockito.verify(testBaseAcionRunnable, times(1)).resetLogProperties(true); diff --git a/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseCommonTest.java b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseCommonTest.java index 3a9e76f27..3f51669f7 100644 --- a/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseCommonTest.java +++ b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseCommonTest.java @@ -163,11 +163,20 @@ public class BaseCommonTest { testBaseCommon.setInitialLogProperties(); testBaseCommon.resetLogProperties(false); - Mockito.verify(testBaseCommon, times(2)).setInitialLogProperties(); + 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(testBaseCommon, times(3)).setInitialLogProperties(); + 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/openecomp/appc/oam/processor/BaseProcessorTest.java b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseProcessorTest.java index 354053c8e..0109adf36 100644 --- a/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseProcessorTest.java +++ b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/processor/BaseProcessorTest.java @@ -22,7 +22,6 @@ * ============LICENSE_END========================================================= */ - package org.openecomp.appc.oam.processor; import com.att.eelf.configuration.EELFLogger; @@ -46,8 +45,6 @@ import org.openecomp.appc.oam.util.StateHelper; import org.openecomp.appc.statemachine.impl.readers.AppcOamStates; import org.powermock.reflect.Whitebox; -import java.util.concurrent.Future; - import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -97,7 +94,7 @@ public class BaseProcessorTest { Mockito.doReturn(mockCommonHeader).when(mockInput).getCommonHeader(); testBaseProcessor = spy( - new TestAbc(null, mockConfigHelper, mockStateHelper, mockTaskHelper, mockOperHelper)); + new TestAbc(null, mockConfigHelper, mockStateHelper, mockTaskHelper, mockOperHelper)); Whitebox.setInternalState(testBaseProcessor, "commonHeader", mockCommonHeader); @@ -112,7 +109,7 @@ public class BaseProcessorTest { 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()); + OAMCommandStatus.INVALID_PARAMETER.getResponseCode(), status.getCode().intValue()); } @Test @@ -122,7 +119,7 @@ public class BaseProcessorTest { Mockito.doReturn(mockCommonHeader).when(mockInput).getCommonHeader(); Status status = testBaseProcessor.processRequest(mockInput); Assert.assertEquals("Should return success", - OAMCommandStatus.ACCEPTED.getResponseCode(), status.getCode().intValue()); + OAMCommandStatus.ACCEPTED.getResponseCode(), status.getCode().intValue()); } @Test(expected = InvalidInputException.class) @@ -135,7 +132,7 @@ public class BaseProcessorTest { public void testPreProcessWithInvalidState() throws Exception { Mockito.doReturn(currentState).when(mockStateHelper).getCurrentOamState(); Mockito.doThrow(new InvalidStateException("test")) - .when(mockOperHelper).getNextState(testRpc.getAppcOperation(), currentState); + .when(mockOperHelper).getNextState(testRpc.getAppcOperation(), currentState); testBaseProcessor.preProcess(mockInput); } @@ -143,7 +140,7 @@ public class BaseProcessorTest { public void testPreProcessWithAppcException() throws Exception { Mockito.doReturn(currentState).when(mockStateHelper).getCurrentOamState(); Mockito.doThrow(new APPCException("test")) - .when(mockOperHelper).getNextState(testRpc.getAppcOperation(), currentState); + .when(mockOperHelper).getNextState(testRpc.getAppcOperation(), currentState); testBaseProcessor.preProcess(mockInput); } @@ -152,7 +149,7 @@ public class BaseProcessorTest { Mockito.doReturn(currentState).when(mockStateHelper).getCurrentOamState(); AppcOamStates nextState = AppcOamStates.Starting; Mockito.doReturn(nextState) - .when(mockOperHelper).getNextState(testRpc.getAppcOperation(), currentState); + .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); @@ -163,32 +160,14 @@ public class BaseProcessorTest { public void testScheduleAsyncTask() throws Exception { // test no runnable testBaseProcessor.scheduleAsyncTask(); - Mockito.verify(mockTaskHelper, times(0)).scheduleAsyncTask(any(), any()); + 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(); - Mockito.verify(mockTaskHelper, times(1)).scheduleAsyncTask(testRpc, mockRunnable); - } - - @Test - public void isSameAsyncTask() throws Exception { - Future<?> mockTask1 = mock(Future.class); - Whitebox.setInternalState(testBaseProcessor, "scheduledRunnable", mockTask1); - Mockito.doReturn(mockTask1).when(mockTaskHelper).getCurrentAsyncTask(); - Assert.assertTrue("Shoudl be the same", testBaseProcessor.isSameAsyncTask()); - - Future<?> mockTask2 = mock(Future.class); - Mockito.doReturn(mockTask2).when(mockTaskHelper).getCurrentAsyncTask(); - Assert.assertFalse("Shoudl not be the same", testBaseProcessor.isSameAsyncTask()); - } - - @Test - public void cancleAsyncTask() throws Exception { - Future<?> mockTask = mock(Future.class); - Whitebox.setInternalState(testBaseProcessor, "scheduledRunnable", mockTask); - testBaseProcessor.cancelAsyncTask(); - Mockito.verify(mockTaskHelper, times(1)).cancelAsyncTask(mockTask); + // 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/openecomp/appc/oam/util/AsyncTaskHelperTest.java b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/util/AsyncTaskHelperTest.java index 873b21795..f81938e30 100644 --- a/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/util/AsyncTaskHelperTest.java +++ b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/util/AsyncTaskHelperTest.java @@ -25,107 +25,641 @@ package org.openecomp.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.openecomp.appc.oam.AppcOam; -import org.openecomp.appc.oam.processor.BaseActionRunnable; -import org.powermock.reflect.Whitebox; +import org.openecomp.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.Arrays; +import java.util.LinkedList; import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; +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.mockito.Mockito.times; +import static org.powermock.api.mockito.PowerMockito.mockStatic; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({FrameworkUtil.class}) public class AsyncTaskHelperTest { private AsyncTaskHelper asyncTaskHelper; - private ScheduledExecutorService mockScheduler = mock(ScheduledExecutorService.class); - private BaseActionRunnable mockRunnable = mock(BaseActionRunnable.class); + + private long initialDelayMillis = 0; + private long delayMillis = 10; + @Before public void setUp() throws Exception { - asyncTaskHelper = new AsyncTaskHelper(null); - Whitebox.setInternalState(asyncTaskHelper, "scheduledExecutorService", mockScheduler); // to avoid operation on logger fail, mock up the logger EELFLogger mockLogger = mock(EELFLogger.class); - Whitebox.setInternalState(asyncTaskHelper, "logger", mockLogger); + + + 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); + + } - @Test - public void testClose() throws Exception { + + @After + public void shutdown(){ asyncTaskHelper.close(); - Mockito.verify(mockScheduler, times(1)).shutdown(); } + + /** + * 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 testGetCurrentAsyncTask() throws Exception { - Future<?> mockTask = mock(Future.class); - Whitebox.setInternalState(asyncTaskHelper, "backgroundOamTask", mockTask); - Assert.assertEquals("Should return mock task", mockTask, asyncTaskHelper.getCurrentAsyncTask()); + 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 testScheduleAsyncTaskWithMmod() throws Exception { - // test maintenance mode - ScheduledFuture<?> mockTask0 = mock(ScheduledFuture.class); - Whitebox.setInternalState(asyncTaskHelper, "backgroundOamTask", mockTask0); + 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()); - ScheduledFuture<?> mockTask1 = mock(ScheduledFuture.class); - Mockito.doReturn(mockTask1).when(mockScheduler).scheduleWithFixedDelay( - mockRunnable, asyncTaskHelper.MMODE_TASK_DELAY, - asyncTaskHelper.MMODE_TASK_DELAY, TimeUnit.MILLISECONDS); - asyncTaskHelper.scheduleAsyncTask(AppcOam.RPC.maintenance_mode, mockRunnable); - Mockito.verify(mockTask0, times(1)).cancel(true); - Assert.assertEquals(mockTask1, asyncTaskHelper.scheduleAsyncTask(AppcOam.RPC.maintenance_mode, mockRunnable)); - Assert.assertEquals("Should set backgroundOamTask", mockTask1, asyncTaskHelper.getCurrentAsyncTask()); } + + /** + * 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. + */ @Test - public void testScheduleAsyncTaskWithStart() throws Exception { - for (AppcOam.RPC rpc : Arrays.asList(AppcOam.RPC.start, AppcOam.RPC.stop, AppcOam.RPC.restart)) { - runTest(rpc); + 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; } + + + } - private void runTest(AppcOam.RPC rpc) { - ScheduledFuture<?> mockTask0 = mock(ScheduledFuture.class); - Whitebox.setInternalState(asyncTaskHelper, "backgroundOamTask", mockTask0); - BaseActionRunnable mockRunnable0 = mock(BaseActionRunnable.class); - Whitebox.setInternalState(asyncTaskHelper, "taskRunnable", mockRunnable0); - ScheduledFuture<?> mockTask2 = mock(ScheduledFuture.class); - Mockito.doReturn(mockTask2).when(mockScheduler).scheduleWithFixedDelay( - mockRunnable, asyncTaskHelper.COMMON_INITIAL_DELAY, - asyncTaskHelper.COMMON_INTERVAL, TimeUnit.MILLISECONDS); - asyncTaskHelper.scheduleAsyncTask(rpc, mockRunnable); - Mockito.verify(mockTask0, times(1)).cancel(true); - Mockito.verify(mockRunnable0, times(1)).abortRunnable(rpc); - Assert.assertEquals(mockTask2, asyncTaskHelper.scheduleAsyncTask(rpc, mockRunnable)); - Assert.assertEquals("Should set backgroundOamTask", mockTask2, asyncTaskHelper.getCurrentAsyncTask()); + /** + * 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 testCancelAsyncTask() throws Exception { - Future<?> mockTask = mock(Future.class); - Whitebox.setInternalState(asyncTaskHelper, "backgroundOamTask", mockTask); - asyncTaskHelper.cancelAsyncTask(mockTask); - Mockito.verify(mockTask, times(1)).cancel(false); - Assert.assertTrue("Should have reset backgroundOamTask", - asyncTaskHelper.getCurrentAsyncTask() == null); - - - Whitebox.setInternalState(asyncTaskHelper, "backgroundOamTask", mockTask); - Future<?> mockTask2 = mock(Future.class); - asyncTaskHelper.cancelAsyncTask(mockTask2); - Mockito.verify(mockTask2, times(1)).cancel(false); - Assert.assertEquals("Should not reset backgroundOamTask", - mockTask, asyncTaskHelper.getCurrentAsyncTask()); + 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; } } diff --git a/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/util/BundleHelperTest.java b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/util/BundleHelperTest.java index 2edc285f0..878d15f39 100644 --- a/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/util/BundleHelperTest.java +++ b/appc-oam/appc-oam-bundle/src/test/java/org/openecomp/appc/oam/util/BundleHelperTest.java @@ -80,7 +80,7 @@ public class BundleHelperTest { mapFromGetAppcLcmBundles.put("BundleString", mockBundle); PowerMockito.doReturn(mapFromGetAppcLcmBundles).when(bundleHelper, MemberMatcher.method( - BundleHelper.class, "getAppcLcmBundles")).withNoArguments(); + BundleHelper.class, "getAppcLcmBundles")).withNoArguments(); StateHelper mockStateHelper = mock(StateHelper.class); Whitebox.setInternalState(bundleHelper, "stateHelper", mockStateHelper); @@ -90,25 +90,25 @@ public class BundleHelperTest { // test start Mockito.doReturn(true).when(mockStateHelper).isSameState(appcOamStates); - boolean result = bundleHelper.bundleOperations(AppcOam.RPC.start, new HashMap<>(), mockTaskHelper); + boolean result = bundleHelper.bundleOperations(AppcOam.RPC.start, new HashMap<>(), mockTaskHelper,null); Assert.assertTrue("Should be completed", result); - Mockito.verify(mockTaskHelper, times(1)).submitBundleLcOperation(any()); + Mockito.verify(mockTaskHelper, times(1)).submitBaseSubCallable(any()); // test start aborted Mockito.doReturn(false).when(mockStateHelper).isSameState(appcOamStates); - result = bundleHelper.bundleOperations(AppcOam.RPC.start, new HashMap<>(), mockTaskHelper); + result = bundleHelper.bundleOperations(AppcOam.RPC.start, new HashMap<>(), mockTaskHelper,null); Assert.assertFalse("Should be abort", result); - Mockito.verify(mockTaskHelper, times(1)).submitBundleLcOperation(any()); + Mockito.verify(mockTaskHelper, times(1)).submitBaseSubCallable(any()); // test stop - result = bundleHelper.bundleOperations(AppcOam.RPC.stop, new HashMap<>(), mockTaskHelper); + result = bundleHelper.bundleOperations(AppcOam.RPC.stop, new HashMap<>(), mockTaskHelper,null); Assert.assertTrue("Should be completed", result); - Mockito.verify(mockTaskHelper, times(2)).submitBundleLcOperation(any()); + Mockito.verify(mockTaskHelper, times(2)).submitBaseSubCallable(any()); } @Test(expected = APPCException.class) public void testBundleOperationsRpcException() throws Exception { - bundleHelper.bundleOperations(AppcOam.RPC.maintenance_mode, new HashMap<>(), mockTaskHelper); + bundleHelper.bundleOperations(AppcOam.RPC.maintenance_mode, new HashMap<>(), mockTaskHelper,null); } @Test @@ -156,7 +156,7 @@ public class BundleHelperTest { Mockito.doReturn(null).when(fakeConf).getProperty(propKey); String[] propResult = bundleHelper.readPropsFromPropListName(propKey); Assert.assertArrayEquals("PropertyResult should be empty string array", - ArrayUtils.EMPTY_STRING_ARRAY, propResult); + ArrayUtils.EMPTY_STRING_ARRAY, propResult); // Property has one entry String propValue1 = "1234"; String propValue2 = "5678"; |