/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.component.workflow.execution.internal;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import org.easymock.Capture;
import org.easymock.CaptureType;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import de.rcenvironment.core.component.execution.api.ComponentState;
import de.rcenvironment.core.component.workflow.execution.api.WorkflowExecutionContext;
import de.rcenvironment.core.component.workflow.model.api.Connection;
import de.rcenvironment.core.component.workflow.model.api.WorkflowDescription;
import de.rcenvironment.core.component.workflow.model.api.WorkflowNode;
import de.rcenvironment.core.notification.DistributedNotificationService;
/**
* Test cases for {@link WorkflowExecutionControllerImpl}.
*
* @author Doreen Seider
*/
public class WorkflowExecutionControllerImplTest {
private static final String COMP_EXE_ID_1 = "comp-exe-id-1";
private WorkflowExecutionContext wfCtxMock;
private ComponentStatesChangedEntirelyVerifier compStatesChangedVerifierMock;
private ComponentLostWatcher compLostWatcherMock;
private WorkflowStateMachine wfStateMachineMock;
private DistributedNotificationService notificationServiceMock;
/**
* Creates mock instances with default behavior used by {@link WorkflowExecutionControllerImpl}. Behavior will be overwritten in
* particular test cases.
*/
@Before
public void setUp() {
WorkflowDescription wfDescMock = EasyMock.createStrictMock(WorkflowDescription.class);
EasyMock.expect(wfDescMock.getWorkflowNodes()).andStubReturn(new ArrayList<WorkflowNode>());
EasyMock.expect(wfDescMock.removeWorkflowNodesAndRelatedConnectionsWithoutNotify(new ArrayList<WorkflowNode>()))
.andStubReturn(new ArrayList<Connection>());
EasyMock.expect(wfDescMock.clone()).andStubReturn(wfDescMock);
EasyMock.replay(wfDescMock);
wfCtxMock = EasyMock.createStrictMock(WorkflowExecutionContext.class);
EasyMock.expect(wfCtxMock.getInstanceName()).andStubReturn("wf instance name");
EasyMock.expect(wfCtxMock.getExecutionIdentifier()).andStubReturn("wf-exe-id");
EasyMock.expect(wfCtxMock.getWorkflowDescription()).andStubReturn(wfDescMock);
EasyMock.replay(wfCtxMock);
compStatesChangedVerifierMock = EasyMock.createStrictMock(ComponentStatesChangedEntirelyVerifier.class);
compStatesChangedVerifierMock.addListener(EasyMock.anyObject(ComponentStatesChangedEntirelyListener.class));
EasyMock.replay(compStatesChangedVerifierMock);
compLostWatcherMock = EasyMock.createStrictMock(ComponentLostWatcher.class);
EasyMock.replay(compLostWatcherMock);
WorkflowExecutionStorageBridge wfExeStorageBridgeMock = EasyMock.createStrictMock(WorkflowExecutionStorageBridge.class);
EasyMock.replay(wfExeStorageBridgeMock);
wfStateMachineMock = EasyMock.createStrictMock(WorkflowStateMachine.class);
EasyMock.replay(wfStateMachineMock);
WorkflowExecutionRelatedInstancesFactory wfExeInstancesFacMock =
EasyMock.createStrictMock(WorkflowExecutionRelatedInstancesFactory.class);
EasyMock
.expect(wfExeInstancesFacMock.createComponentConsoleLogFileWriter(EasyMock.anyObject(WorkflowExecutionStorageBridge.class)))
.andStubReturn(null);
EasyMock.expect(wfExeInstancesFacMock.createComponentStatesEntirelyChangedVerifier(0))
.andStubReturn(compStatesChangedVerifierMock);
EasyMock.expect(wfExeInstancesFacMock.createComponentLostWatcher(wfCtxMock, compStatesChangedVerifierMock))
.andStubReturn(compLostWatcherMock);
EasyMock.expect(wfExeInstancesFacMock.createWorkflowExecutionStorageBridge(wfCtxMock))
.andStubReturn(wfExeStorageBridgeMock);
EasyMock.expect(wfExeInstancesFacMock.createWorkflowStateMachine(EasyMock.anyObject(WorkflowStateMachineContext.class)))
.andStubReturn(wfStateMachineMock);
EasyMock.replay(wfExeInstancesFacMock);
notificationServiceMock = EasyMock.createStrictMock(DistributedNotificationService.class);
EasyMock.replay(notificationServiceMock);
@SuppressWarnings("deprecation")
WorkflowExecutionControllerImpl wfExeCtrlComp = new WorkflowExecutionControllerImpl();
wfExeCtrlComp.bindWorkflowExecutionRelatedInstancesFactory(wfExeInstancesFacMock);
wfExeCtrlComp.bindDistributedNotificationService(notificationServiceMock);
}
/**
* Tests if component heartbeat are forwarded properly.
*/
@Test
public void testComponentHeartbeatForwarding() {
EasyMock.reset(compLostWatcherMock);
compLostWatcherMock.announceComponentHeartbeat(COMP_EXE_ID_1);
EasyMock.replay(compLostWatcherMock);
WorkflowExecutionControllerImpl wfExeCtrl = new WorkflowExecutionControllerImpl(wfCtxMock);
wfExeCtrl.onComponentHeartbeatReceived(COMP_EXE_ID_1);
EasyMock.verify(compLostWatcherMock);
}
/**
* Tests if lifecycle methods delegates requests properly to the underlying {@link WorkflowStateMachine}.
*/
@Test
public void testLifeCycleRequestDelegation() {
WorkflowExecutionControllerImpl wfExeCtrl = new WorkflowExecutionControllerImpl(wfCtxMock);
Capture<WorkflowStateMachineEvent> wfStateMachineEveCapture = resetAndSetupWorkflowStateMachineMock();
wfExeCtrl.start();
verifyLifecycleRequestDelegation(wfStateMachineEveCapture, WorkflowStateMachineEventType.START_REQUESTED);
wfStateMachineEveCapture = resetAndSetupWorkflowStateMachineMock();
wfExeCtrl.pause();
verifyLifecycleRequestDelegation(wfStateMachineEveCapture, WorkflowStateMachineEventType.PAUSE_REQUESTED);
wfStateMachineEveCapture = resetAndSetupWorkflowStateMachineMock();
wfExeCtrl.resume();
verifyLifecycleRequestDelegation(wfStateMachineEveCapture, WorkflowStateMachineEventType.RESUME_REQUESTED);
wfStateMachineEveCapture = resetAndSetupWorkflowStateMachineMock();
wfExeCtrl.cancel();
verifyLifecycleRequestDelegation(wfStateMachineEveCapture, WorkflowStateMachineEventType.CANCEL_REQUESTED);
wfStateMachineEveCapture = resetAndSetupWorkflowStateMachineMock();
wfExeCtrl.dispose();
verifyLifecycleRequestDelegation(wfStateMachineEveCapture, WorkflowStateMachineEventType.DISPOSE_REQUESTED);
}
private Capture<WorkflowStateMachineEvent> resetAndSetupWorkflowStateMachineMock() {
EasyMock.reset(wfStateMachineMock);
Capture<WorkflowStateMachineEvent> wfStateMachineEveCapture = new Capture<>();
wfStateMachineMock.postEvent(EasyMock.capture(wfStateMachineEveCapture));
EasyMock.replay(wfStateMachineMock);
return wfStateMachineEveCapture;
}
private void verifyLifecycleRequestDelegation(Capture<WorkflowStateMachineEvent> wfStateMachineEveCapture,
WorkflowStateMachineEventType expectedType) {
EasyMock.verify(wfStateMachineMock);
assertTrue(wfStateMachineEveCapture.hasCaptured());
assertEquals(expectedType, wfStateMachineEveCapture.getValue().getType());
}
/**
* Tests if component state change announcements are processed properly.
* @throws InterruptedException on unexpected error
*/
@Test
public void testComponentStateChangeProcessingInCaseOfNoFailure() throws InterruptedException {
testComponentStateChangeProcessing(ComponentState.CANCELED);
}
/**
* Tests if component state change announcements are processed properly in case of {@link ComponentState#FAILED}.
* @throws InterruptedException on unexpected error
*/
@Test
public void testComponentStateChangeProcessingOnFailure() throws InterruptedException {
EasyMock.reset(wfStateMachineMock);
Capture<WorkflowStateMachineEvent> wfStateMachineEveCapture = new Capture<>();
wfStateMachineMock.postEvent(EasyMock.capture(wfStateMachineEveCapture));
EasyMock.replay(wfStateMachineMock);
testComponentStateChangeProcessing(ComponentState.FAILED);
EasyMock.verify(wfStateMachineMock);
assertTrue(wfStateMachineEveCapture.hasCaptured());
assertEquals(WorkflowStateMachineEventType.CANCEL_AFTER_FAILED_REQUESTED, wfStateMachineEveCapture.getValue().getType());
}
private void testComponentStateChangeProcessing(ComponentState compState) throws InterruptedException {
final String executionCountOnReset = "3";
EasyMock.reset(notificationServiceMock);
Capture<String> notificationBodyCapture = new Capture<>(CaptureType.ALL);
Capture<String> notificationIdCapture = new Capture<>(CaptureType.ALL);
notificationServiceMock.send(EasyMock.capture(notificationIdCapture), EasyMock.capture(notificationBodyCapture));
EasyMock.expectLastCall().times(2);
EasyMock.replay(notificationServiceMock);
EasyMock.reset(compStatesChangedVerifierMock);
compStatesChangedVerifierMock.addListener(EasyMock.anyObject(ComponentStatesChangedEntirelyListener.class));
Capture<String> compExeIdCapture = new Capture<>();
Capture<ComponentState> compStateCapture = new Capture<>();
compStatesChangedVerifierMock.announceComponentState(EasyMock.capture(compExeIdCapture), EasyMock.capture(compStateCapture));
EasyMock.replay(compStatesChangedVerifierMock);
WorkflowExecutionControllerImpl wfExeCtrl = new WorkflowExecutionControllerImpl(wfCtxMock);
wfExeCtrl.onComponentStateChanged(COMP_EXE_ID_1, compState, 5, executionCountOnReset, null, null);
final int waitForAsyncSendingMsec = 200;
Thread.sleep(waitForAsyncSendingMsec);
EasyMock.verify(notificationServiceMock);
assertTrue(notificationIdCapture.hasCaptured());
assertEquals(2, notificationIdCapture.getValues().size());
assertTrue(notificationIdCapture.getValues().get(0).contains(COMP_EXE_ID_1));
assertTrue(notificationIdCapture.getValues().get(1).contains(COMP_EXE_ID_1));
assertEquals(2, notificationBodyCapture.getValues().size());
assertEquals(compState.name(), notificationBodyCapture.getValues().get(0));
assertEquals(executionCountOnReset, notificationBodyCapture.getValues().get(1));
EasyMock.verify(compStatesChangedVerifierMock);
assertTrue(compExeIdCapture.hasCaptured());
assertEquals(COMP_EXE_ID_1, compExeIdCapture.getValue());
}
}