/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.component.execution.internal; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.UUID; import org.easymock.Capture; import org.easymock.CaptureType; import org.easymock.EasyMock; import org.junit.Test; import de.rcenvironment.core.component.api.LoopComponentConstants; import de.rcenvironment.core.component.execution.api.ComponentExecutionContext; import de.rcenvironment.core.component.execution.api.ComponentExecutionException; import de.rcenvironment.core.component.execution.api.WorkflowGraphHop; import de.rcenvironment.core.component.execution.internal.ComponentExecutionScheduler.State; import de.rcenvironment.core.component.execution.internal.InternalTDImpl.InternalTDType; import de.rcenvironment.core.component.model.api.ComponentDescription; import de.rcenvironment.core.component.model.api.ComponentInterface; import de.rcenvironment.core.component.model.configuration.api.ConfigurationDescription; import de.rcenvironment.core.component.model.endpoint.api.EndpointDatum; import de.rcenvironment.core.component.model.endpoint.api.EndpointDatumRecipient; import de.rcenvironment.core.component.model.endpoint.api.EndpointDatumRecipientFactory; import de.rcenvironment.core.component.model.endpoint.api.EndpointDefinition; import de.rcenvironment.core.component.model.endpoint.api.EndpointGroupDefinition; import de.rcenvironment.core.component.testutils.ComponentExecutionContextMock; import de.rcenvironment.core.component.testutils.EndpointDatumDefaultStub; import de.rcenvironment.core.datamodel.api.DataType; import de.rcenvironment.core.datamodel.api.EndpointCharacter; import de.rcenvironment.core.datamodel.api.TypedDatum; import de.rcenvironment.core.datamodel.testutils.NotAValueTDStub; import de.rcenvironment.core.datamodel.testutils.TypedDatumServiceDefaultStub; import de.rcenvironment.core.datamodel.types.api.NotAValueTD; /** * Test cases for the {@link ComponentExecutionScheduler}. * * @author Doreen Seider */ public class ComponentExecutionSchedulerTest { private static final String EXPECTED = " expected"; private static final String INPUT_1 = "input_1"; private static final String INPUT_2 = "input_2"; private static final String INPUT_3 = "input_3"; private static final String INPUT_4 = "input_4"; private static final String INPUT_5 = "input_5"; private static final String INPUT_6 = "input_6"; private static final String INPUT_7 = "input_7"; private static final String OR_GROUP = "orGroup"; private static final String AND_GROUP = "andGroup"; private static final boolean CONNECTED = true; private static final boolean NOT_CONNECTED = false; /** * Set up: one input (single, required); one value and 'finish value' received. Expected: Scheduling state become * {@link State#PROCESS_INPUT_DATA} and {@link State#FINISHED}. * * @throws Exception on unexpected error */ @Test public void testSingleRequiredInputForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.WorkflowFinish))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.FINISHED, compExeScheduler.getSchedulingState()); } /** * Set up: one input (single, required); two values received, which are queued. Expected: Failure event posted to * {@link ComponentStateMachine}. * * @throws Exception on unexpected error */ @Test public void testSingleRequiredInputForFailure() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateAndSchedulingFailureEventPosted(capturedEvent); } /** * Set up: one input (queue, required); multiple values and 'finish value' received. Expected: Scheduling state become multiple times * {@link State#PROCESS_INPUT_DATA} and finally {@link State#FINISHED}. * * @throws Exception on unexpected error */ @Test public void testQueuedInputForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.WorkflowFinish))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(1)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(2)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.FINISHED, compExeScheduler.getSchedulingState()); } /** * Set up: one input (constant, required); one value and 'finish value' received. Expected: Scheduling state become * {@link State#PROCESS_INPUT_DATA} and {@link State#FINISHED}. * * @throws Exception on unexpected error */ @Test public void testConstantInputForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.WorkflowFinish))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.FINISHED, compExeScheduler.getSchedulingState()); } /** * Set up: one input (constant, required); two values received. Expected: Failure event posted to {@link ComponentStateMachine}. * * @throws Exception on unexpected error */ @Test public void testConstantInputForFailure() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateAndSchedulingFailureEventPosted(capturedEvent); } /** * Setup: different kind of inputs; multiple values received. Expected: Appropriate scheduling. * * @throws Exception on unexpected error */ @Test public void testMultipleInputsForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required, CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required, CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_3, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required, CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_4, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required, CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_5, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.RequiredIfConnected, NOT_CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_6, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.NotRequired, CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_7, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.NotRequired, NOT_CONNECTED)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsToSend1 = new ArrayList<>(); endpointDatumsToSend1.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); endpointDatumsToSend1.add(new EndpointDatumMock(INPUT_3, new TypedDatumMock(DataType.Float))); endpointDatumsToSend1.add(new EndpointDatumMock(INPUT_4, new TypedDatumMock(DataType.Float))); endpointDatumsToSend1.add(new EndpointDatumMock(INPUT_3, new TypedDatumMock(DataType.Float))); endpointDatumsToSend1.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsToSend1); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsToSend1.get(0), endpointDatumsToSend1.get(1), endpointDatumsToSend1.get(2), endpointDatumsToSend1.get(4)); List<EndpointDatum> endpointDatumsToSend2 = new ArrayList<>(); endpointDatumsToSend2.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); endpointDatumsToSend2.add(new EndpointDatumMock(INPUT_4, new TypedDatumMock(DataType.Float))); endpointDatumsToSend2.add(new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.WorkflowFinish))); endpointDatumsToSend2.add(new EndpointDatumMock(INPUT_6, new TypedDatumMock(DataType.Float))); endpointDatumsToSend2.add(new EndpointDatumMock(INPUT_2, new InternalTDImpl(InternalTDType.WorkflowFinish))); endpointDatumsToSend2.add(new EndpointDatumMock(INPUT_3, new InternalTDImpl(InternalTDType.WorkflowFinish))); endpointDatumsToSend2.add(new EndpointDatumMock(INPUT_4, new InternalTDImpl(InternalTDType.WorkflowFinish))); endpointDatumsToSend2.add(new EndpointDatumMock(INPUT_6, new InternalTDImpl(InternalTDType.WorkflowFinish))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsToSend2); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsToSend1.get(4), endpointDatumsToSend1.get(3), endpointDatumsToSend2.get(0), endpointDatumsToSend2.get(1)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.FINISHED, compExeScheduler.getSchedulingState()); } /** * Setup: different kind of inputs; multiple values received. Expected: Appropriate scheduling. * * @throws Exception on unexpected error */ @Test public void testHandlingIfInputValuesAreLeftAfterFinished() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.WorkflowFinish))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new InternalTDImpl(InternalTDType.WorkflowFinish))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0), endpointDatumsSent.get(1)); assertSchedulingFailureEventPosted(capturedEvent); } /** * Setup: different kind of inputs; multiple values received. Expected: Appropriate scheduling. * * @throws Exception on unexpected error */ @Test public void testHandlingIfInputsAreRequiredButNotConnected() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required, NOT_CONNECTED)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(); ExecutionSpecificComponentExecutionContextMock compExeCtxMock = new ExecutionSpecificComponentExecutionContextMock(inputMockInfos); ComponentExecutionScheduler compExeScheduler = new ComponentExecutionScheduler(createCompExeRelatedInstancesStub(compExeCtxMock, createComponentStateMachineMock(capturedEvent))); try { compExeScheduler.initialize(compExeCtxMock); fail(ComponentExecutionException.class.getSimpleName() + EXPECTED); } catch (ComponentExecutionException e) { assertTrue(e.getMessage().contains("not connected")); assertTrue(true); } } /** * Set up: two inputs (constant, single; both required); one value each; one value to input of type single; reset value to one of them, * one value to single, one value to constant. * * Expected: {@link State#PROCESS_INPUT_DATA} 1) after both of the inputs have received values for the first time, 2) after value at * input of type single was received, 3) after both of the inputs have received values after reset was performed * * @throws Exception on unexpected error */ @Test public void testResetComponentForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); String executionId = UUID.randomUUID().toString(); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent, executionId); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); Queue<WorkflowGraphHop> resetCycleHops = new LinkedList<>(); WorkflowGraphHop workflowGraphHopMock = EasyMock.createStrictMock(WorkflowGraphHop.class); EasyMock.expect(workflowGraphHopMock.getHopExecutionIdentifier()).andReturn(executionId).anyTimes(); EasyMock.replay(workflowGraphHopMock); resetCycleHops.add(workflowGraphHopMock); InternalTDImpl resetTD = new InternalTDImpl(InternalTDType.NestedLoopReset, resetCycleHops); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, resetTD)); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0), endpointDatumsSent.get(1)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0), endpointDatumsSent.get(2)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.RESET, compExeScheduler.getSchedulingState()); assertEquals(resetTD, compExeScheduler.getResetDatum()); compExeScheduler.enable(); endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); } /** * Set up: two inputs (constant, single; both required); reset value to one of them; reset value has wrong recepient's execution * identifier. * * Expected: Failure due to wrong execution identifier * * @throws Exception on unexpected error */ @Test public void testResetComponentForFailure() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); Queue<WorkflowGraphHop> resetCycleHops = new LinkedList<>(); WorkflowGraphHop workflowGraphHopMock = EasyMock.createStrictMock(WorkflowGraphHop.class); EasyMock.expect(workflowGraphHopMock.getHopExecutionIdentifier()).andReturn(UUID.randomUUID().toString()).anyTimes(); EasyMock.replay(workflowGraphHopMock); resetCycleHops.add(workflowGraphHopMock); InternalTDImpl resetTD = new InternalTDImpl(InternalTDType.NestedLoopReset, resetCycleHops); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, resetTD)); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertSchedulingFailureEventPosted(capturedEvent); } /** * Set up: two inputs (constant, queue; both required); reset to outputs sent; reset value received at one of the inputs. * * Expected: {@link State#LOOP_RESET} 1) after both of the reset values were received * * @throws Exception on unexpected error */ @Test public void testResetLoopForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required, AND_GROUP, CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required, AND_GROUP, CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_3, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required, OR_GROUP, CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_4, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required, OR_GROUP, CONNECTED)); List<InputGroupMockInformation> inputGroupMockInfos = new ArrayList<>(); inputGroupMockInfos.add(new InputGroupMockInformation(OR_GROUP, EndpointGroupDefinition.LogicOperation.Or)); inputGroupMockInfos.add(new InputGroupMockInformation(AND_GROUP, EndpointGroupDefinition.LogicOperation.And, OR_GROUP)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); String executionId = UUID.randomUUID().toString(); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, inputGroupMockInfos, capturedEvent, executionId); sendAndCheckSendingDataToLoopDriverComponent(compExeScheduler, capturedEvent); compExeScheduler.fetchEndpointDatums(); List<String> identifiers = new ArrayList<>(); identifiers.add(UUID.randomUUID().toString()); identifiers.add(UUID.randomUUID().toString()); assertFalse(compExeScheduler.isLoopResetRequested()); compExeScheduler.addResetDataIdSent(identifiers.get(0)); compExeScheduler.addResetDataIdSent(identifiers.get(1)); assertTrue(compExeScheduler.isLoopResetRequested()); Queue<WorkflowGraphHop> resetCycleHops = new LinkedList<>(); WorkflowGraphHop workflowGraphHopMock = EasyMock.createStrictMock(WorkflowGraphHop.class); EasyMock.expect(workflowGraphHopMock.getHopExecutionIdentifier()).andReturn(executionId).anyTimes(); EasyMock.replay(workflowGraphHopMock); resetCycleHops.add(workflowGraphHopMock); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); for (String id : identifiers) { InternalTDImpl resetTD = new InternalTDImpl(InternalTDType.NestedLoopReset, id, resetCycleHops); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, resetTD)); } sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.LOOP_RESET, compExeScheduler.getSchedulingState()); compExeScheduler.enable(); sendAndCheckSendingDataToLoopDriverComponent(compExeScheduler, capturedEvent); } private void sendAndCheckSendingDataToLoopDriverComponent(ComponentExecutionScheduler compExeScheduler, Capture<ComponentStateMachineEvent> capturedEvent) throws InterruptedException, ComponentExecutionException { List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_3, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_4, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_4, new TypedDatumMock(DataType.Float))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0), endpointDatumsSent.get(2)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(1), endpointDatumsSent.get(2)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(3)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(4)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(5)); } /** * Set up: two inputs (constant, queue; both required); reset to outputs sent; reset value received at one of the inputs, second value * has wrong identifier. * * Expected: Failure due to wrong reset value identifier received * * @throws Exception on unexpected error */ @Test public void testResetLoopForFailure() throws Exception { } /** * Set up: two inputs (constant, single; both required); failure value received at one of the inputs. * * Expected: {@link State#FAILURE_FORWARD} 1) after failure values were received * * @throws Exception on unexpected error */ @Test public void testFailureValueAtComponentForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); String executionId = UUID.randomUUID().toString(); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent, executionId); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); Queue<WorkflowGraphHop> hopsToTraverse = new LinkedList<>(); WorkflowGraphHop workflowGraphHopMock = EasyMock.createStrictMock(WorkflowGraphHop.class); EasyMock.expect(workflowGraphHopMock.getHopExecutionIdentifier()).andReturn(executionId).anyTimes(); EasyMock.replay(workflowGraphHopMock); hopsToTraverse.add(workflowGraphHopMock); InternalTDImpl failureTD1 = new InternalTDImpl(InternalTDType.FailureInLoop, hopsToTraverse); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, failureTD1)); InternalTDImpl failureTD2 = new InternalTDImpl(InternalTDType.FailureInLoop, hopsToTraverse); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, failureTD2)); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.FAILURE_FORWARD, compExeScheduler.getSchedulingState()); assertEquals(failureTD1, compExeScheduler.getFailureDatum()); compExeScheduler.enable(); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.FAILURE_FORWARD, compExeScheduler.getSchedulingState()); assertEquals(failureTD2, compExeScheduler.getFailureDatum()); } /** * Set up: two inputs (constant, single; both required); failure value received at one of the inputs. * * Expected: {@link State#FAILURE_FORWARD} 1) after failure values were received * * @throws Exception on unexpected error */ @Test public void testFailureValueAtLoopDriverForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); String executionId = UUID.randomUUID().toString(); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent, executionId); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); Queue<WorkflowGraphHop> hopsToTraverse = new LinkedList<>(); InternalTDImpl failureTD1 = new InternalTDImpl(InternalTDType.FailureInLoop, "id-1", hopsToTraverse, "11"); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, failureTD1)); InternalTDImpl failureTD2 = new InternalTDImpl(InternalTDType.FailureInLoop, "id-2", hopsToTraverse, "21"); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, failureTD2)); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA_WITH_NOT_A_VALUE_DATA, compExeScheduler.getSchedulingState()); Map<String, EndpointDatum> endpointDatumsReturned = compExeScheduler.fetchEndpointDatums(); assertEquals(2, endpointDatumsReturned.size()); assertTrue(endpointDatumsReturned.get(INPUT_1).getValue() instanceof NotAValueTD); assertEquals("id-1", ((NotAValueTD) endpointDatumsReturned.get(INPUT_1).getValue()).getIdentifier()); assertTrue(endpointDatumsReturned.get(INPUT_2).getValue() instanceof NotAValueTD); assertEquals("id-2", ((NotAValueTD) endpointDatumsReturned.get(INPUT_2).getValue()).getIdentifier()); } /** * Set up: two inputs (constant, queue; both required); same parent group for both of them; three values. * * Expected: {@link State#PROCESS_INPUT_DATA} 1) after each value received * * @throws Exception on unexpected error */ @Test public void testOrGroupForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Constant, EndpointDefinition.InputExecutionContraint.Required, OR_GROUP, CONNECTED)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required, OR_GROUP, CONNECTED)); List<InputGroupMockInformation> inputGroupMockInfos = new ArrayList<>(); inputGroupMockInfos.add(new InputGroupMockInformation(OR_GROUP, EndpointGroupDefinition.LogicOperation.Or)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, inputGroupMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_2, new TypedDatumMock(DataType.Float))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(1)); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(2)); } /** * Set up: one input (queue; required); 'not a value' datum received. * * Expected: {@link State#PROCESS_INPUT_DATA_WITH_NOT_A_VALUE_DATA} after value was received * * @throws Exception on unexpected error */ @Test public void testNotAValueDataForSuccess() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new NotAValueTDStub())); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA_WITH_NOT_A_VALUE_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0)); } /** * Set up: one input (queue; required); 'not a value' datum received, which was sent or which was received before. * * Expected: Failure because 'not a value' was received again or twice * * @throws Exception on unexpected error */ @Test public void testNotAValueDataForFailure() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); String id = UUID.randomUUID().toString(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new NotAValueTDStub(id))); compExeScheduler.addNotAValueDatumSent(id); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertSchedulingFailureEventPosted(capturedEvent); capturedEvent.reset(); compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); endpointDatumsSent.clear(); id = UUID.randomUUID().toString(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new NotAValueTDStub(id))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new NotAValueTDStub(id))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA_WITH_NOT_A_VALUE_DATA, compExeScheduler.getSchedulingState()); checkEndpointDatumsSetSchedulerActiveAgain(compExeScheduler, compExeScheduler.fetchEndpointDatums(), endpointDatumsSent.get(0)); assertSchedulingFailureEventPosted(capturedEvent); } /** * Set up: one input (queue; required); datum received: 1) NotAValue 2) Internal 3) whose data type is not compatible with input's data * type. * * Expected: 1, 2: not failure; 3: failure * * @throws Exception on unexpected error */ @Test public void testDataTypeCheck() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Queue, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent .add(new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.FailureInLoop, new LinkedList<WorkflowGraphHop>(), "1"))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new NotAValueTDStub("id"))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.PROCESS_INPUT_DATA_WITH_NOT_A_VALUE_DATA, compExeScheduler.getSchedulingState()); endpointDatumsSent.clear(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Matrix))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertSchedulingFailureEventPosted(capturedEvent); } /** * Tests if the {@link ComponentExecutionScheduler} only post events to the {@link ComponentStateMachine} if set to active. * * @throws Exception on unexpected error */ @Test public void testIdleMode() throws Exception { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent); compExeScheduler.disable(); List<EndpointDatum> endpointDatumsSent = new ArrayList<>(); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new TypedDatumMock(DataType.Float))); endpointDatumsSent.add(new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.WorkflowFinish))); sendValuesToExecutionScheduler(compExeScheduler, endpointDatumsSent); assertNoNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.IDLING, compExeScheduler.getSchedulingState()); compExeScheduler.disable(); assertFalse(capturedEvent.hasCaptured()); compExeScheduler.enable(); assertNewSchedulingStateEventPosted(capturedEvent); } /** * Tests if the {@link ComponentExecutionScheduler} considers exclusively inputs with character of {@link EndpointCharacter#SAME_LOOP} * for finish detection if not outer loop input exists and the component is not a loop driver. * * @throws ComponentExecutionException on unexpected error */ @Test public void testFinishNoLoopDriverWithoutOuterLoopInputs() throws ComponentExecutionException { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required, EndpointCharacter.SAME_LOOP)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required, EndpointCharacter.SAME_LOOP)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent, false, false); EndpointDatum endpointDatum1 = new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.WorkflowFinish)); compExeScheduler.validateAndQueueEndpointDatum(endpointDatum1); assertNoNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.IDLING, compExeScheduler.getSchedulingState()); EndpointDatum endpointDatum2 = new EndpointDatumMock(INPUT_2, new InternalTDImpl(InternalTDType.WorkflowFinish)); compExeScheduler.validateAndQueueEndpointDatum(endpointDatum2); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.FINISHED, compExeScheduler.getSchedulingState()); assertFalse(compExeScheduler.isEnabled()); } /** * Tests if the {@link ComponentExecutionScheduler} considers exclusively inputs with character of {@link EndpointCharacter#SAME_LOOP} * for finish detection if component is a loop driver having outer loop inputs. * * @throws ComponentExecutionException on unexpected error */ @Test public void testFinishLoopDriverWithOuterLoopInputs() throws ComponentExecutionException { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required, EndpointCharacter.OUTER_LOOP)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required, EndpointCharacter.SAME_LOOP)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent, true, false); EndpointDatum endpointDatum1 = new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.WorkflowFinish)); compExeScheduler.validateAndQueueEndpointDatum(endpointDatum1); assertNoNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.IDLING, compExeScheduler.getSchedulingState()); EndpointDatum endpointDatum2 = new EndpointDatumMock(INPUT_2, new InternalTDImpl(InternalTDType.WorkflowFinish)); compExeScheduler.validateAndQueueEndpointDatum(endpointDatum2); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.FINISHED, compExeScheduler.getSchedulingState()); assertFalse(compExeScheduler.isEnabled()); } /** * Tests if the {@link ComponentExecutionScheduler} considers exclusively inputs with character of {@link EndpointCharacter#OUTER_LOOP} * for finish detection if at least one exists and the component is no loop driver. * * @throws ComponentExecutionException on unexpected error */ @Test public void testFinishNonDriverWithOuterLoopInputs() throws ComponentExecutionException { testFinishConsiderOuterLoopInputs(false); } /** * Tests if the {@link ComponentExecutionScheduler} considers exclusively inputs with character of {@link EndpointCharacter#OUTER_LOOP} * for finish detection if component is a nested loop driver. * * @throws ComponentExecutionException on unexpected error */ @Test public void testFinishNestedLoopDriver() throws ComponentExecutionException { testFinishConsiderOuterLoopInputs(true); } private void testFinishConsiderOuterLoopInputs(boolean isNestedLoopDriver) throws ComponentExecutionException { List<InputMockInformation> inputMockInfos = new ArrayList<>(); inputMockInfos.add(new InputMockInformation(INPUT_1, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required, EndpointCharacter.OUTER_LOOP)); inputMockInfos.add(new InputMockInformation(INPUT_2, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required, EndpointCharacter.OUTER_LOOP)); inputMockInfos.add(new InputMockInformation(INPUT_3, EndpointDefinition.InputDatumHandling.Single, EndpointDefinition.InputExecutionContraint.Required, EndpointCharacter.SAME_LOOP)); Capture<ComponentStateMachineEvent> capturedEvent = new Capture<>(CaptureType.ALL); ComponentExecutionScheduler compExeScheduler = setUpExecutionScheduler(inputMockInfos, capturedEvent, isNestedLoopDriver, isNestedLoopDriver); EndpointDatum endpointDatum1 = new EndpointDatumMock(INPUT_1, new InternalTDImpl(InternalTDType.WorkflowFinish)); compExeScheduler.validateAndQueueEndpointDatum(endpointDatum1); assertNoNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.IDLING, compExeScheduler.getSchedulingState()); EndpointDatum endpointDatum3 = new EndpointDatumMock(INPUT_3, new InternalTDImpl(InternalTDType.WorkflowFinish)); compExeScheduler.validateAndQueueEndpointDatum(endpointDatum3); assertNoNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.IDLING, compExeScheduler.getSchedulingState()); EndpointDatum endpointDatum2 = new EndpointDatumMock(INPUT_2, new InternalTDImpl(InternalTDType.WorkflowFinish)); compExeScheduler.validateAndQueueEndpointDatum(endpointDatum2); assertNewSchedulingStateEventPosted(capturedEvent); assertEquals(State.FINISHED, compExeScheduler.getSchedulingState()); assertFalse(compExeScheduler.isEnabled()); } private ComponentExecutionScheduler setUpExecutionScheduler(List<InputMockInformation> inputMockInfos, Capture<ComponentStateMachineEvent> capturedEvent) throws ComponentExecutionException { return setUpExecutionScheduler(inputMockInfos, capturedEvent, UUID.randomUUID().toString()); } private ComponentExecutionScheduler setUpExecutionScheduler(List<InputMockInformation> inputMockInfos, Capture<ComponentStateMachineEvent> capturedEvent, boolean isLoopDriver, boolean isNestedLoopDriver) throws ComponentExecutionException { return setUpExecutionScheduler(inputMockInfos, capturedEvent, UUID.randomUUID().toString(), isLoopDriver, isNestedLoopDriver); } private ComponentExecutionScheduler setUpExecutionScheduler(List<InputMockInformation> inputMockInfos, List<InputGroupMockInformation> inputGroupMockInfos, Capture<ComponentStateMachineEvent> capturedEvent) throws ComponentExecutionException { return setUpExecutionScheduler(inputMockInfos, inputGroupMockInfos, capturedEvent, UUID.randomUUID().toString()); } private ComponentExecutionScheduler setUpExecutionScheduler(List<InputMockInformation> inputMockInfos, Capture<ComponentStateMachineEvent> capturedEvent, String executionId, boolean isLoopDriver, boolean isNestedLoopDriver) throws ComponentExecutionException { return setUpExecutionScheduler(inputMockInfos, new ArrayList<InputGroupMockInformation>(), capturedEvent, executionId, isLoopDriver, isNestedLoopDriver); } private ComponentExecutionScheduler setUpExecutionScheduler(List<InputMockInformation> inputMockInfos, Capture<ComponentStateMachineEvent> capturedEvent, String executionId) throws ComponentExecutionException { return setUpExecutionScheduler(inputMockInfos, new ArrayList<InputGroupMockInformation>(), capturedEvent, executionId); } private ComponentExecutionScheduler setUpExecutionScheduler(List<InputMockInformation> inputMockInfos, List<InputGroupMockInformation> inputGroupMockInfos, Capture<ComponentStateMachineEvent> capturedEvent, String executionId) throws ComponentExecutionException { ExecutionSpecificComponentExecutionContextMock compExeCtxMock = new ExecutionSpecificComponentExecutionContextMock(executionId, inputMockInfos, inputGroupMockInfos); ComponentExecutionScheduler compExeScheduler = new ComponentExecutionScheduler( createCompExeRelatedInstancesStub(compExeCtxMock, createComponentStateMachineMock(capturedEvent))); compExeScheduler.bindTypedDatumService(new TypedDatumServiceDefaultStub()); compExeScheduler.initialize(compExeCtxMock); compExeScheduler.enable(); return compExeScheduler; } private ComponentExecutionScheduler setUpExecutionScheduler(List<InputMockInformation> inputMockInfos, List<InputGroupMockInformation> inputGroupMockInfos, Capture<ComponentStateMachineEvent> capturedEvent, String executionId, boolean isLoopDriver, boolean isNestedLoopDriver) throws ComponentExecutionException { ExecutionSpecificComponentExecutionContextMock compExeCtxMock = new ExecutionSpecificComponentExecutionContextMock( executionId, inputMockInfos, inputGroupMockInfos, isLoopDriver, isNestedLoopDriver); ComponentExecutionScheduler compExeScheduler = new ComponentExecutionScheduler( createCompExeRelatedInstancesStub(compExeCtxMock, createComponentStateMachineMock(capturedEvent))); compExeScheduler.bindTypedDatumService(new TypedDatumServiceDefaultStub()); compExeScheduler.initialize(compExeCtxMock); compExeScheduler.enable(); return compExeScheduler; } private ComponentStateMachine createComponentStateMachineMock(Capture<ComponentStateMachineEvent> capturedEvent) { ComponentStateMachine stateMachineMock = EasyMock.createStrictMock(ComponentStateMachine.class); stateMachineMock.postEvent(EasyMock.capture(capturedEvent)); EasyMock.expectLastCall().asStub(); EasyMock.replay(stateMachineMock); return stateMachineMock; } private ComponentExecutionRelatedInstances createCompExeRelatedInstancesStub(ComponentExecutionContext compExeCtx, ComponentStateMachine compStateMachine) { ComponentExecutionRelatedInstances compExeRelatedInstances = new ComponentExecutionRelatedInstances(); compExeRelatedInstances.compExeCtx = compExeCtx; compExeRelatedInstances.compStateMachine = compStateMachine; return compExeRelatedInstances; } private void sendValuesToExecutionScheduler(ComponentExecutionScheduler compExeScheduler, final List<EndpointDatum> endpointDatumsSent) { for (EndpointDatum endpointDatum : endpointDatumsSent) { compExeScheduler.validateAndQueueEndpointDatum(endpointDatum); } } private void checkEndpointDatumsSetSchedulerActiveAgain(ComponentExecutionScheduler compExeScheduler, Map<String, EndpointDatum> endpointDatumsReturned, EndpointDatum... endpointDatumsExpected) { assertEquals(Arrays.asList(endpointDatumsExpected).size(), endpointDatumsReturned.size()); for (EndpointDatum endpointDatum : endpointDatumsExpected) { assertTrue(endpointDatumsReturned.containsKey(endpointDatum.getInputName())); assertTrue(endpointDatumsReturned.containsValue(endpointDatum)); } compExeScheduler.enable(); } private void assertNoNewSchedulingStateEventPosted(Capture<ComponentStateMachineEvent> capturedEvent) { assertFalse(capturedEvent.hasCaptured()); } private void assertNewSchedulingStateAndSchedulingFailureEventPosted(Capture<ComponentStateMachineEvent> capturedEvent) { assertTrue(capturedEvent.hasCaptured()); assertEquals(2, capturedEvent.getValues().size()); assertEquals(ComponentStateMachineEventType.NEW_SCHEDULING_STATE, capturedEvent.getValues().get(0).getType()); assertEquals(ComponentStateMachineEventType.SCHEDULING_FAILED, capturedEvent.getValues().get(1).getType()); capturedEvent.reset(); } private void assertNewSchedulingStateEventPosted(Capture<ComponentStateMachineEvent> capturedEvent) { assertTrue(capturedEvent.hasCaptured()); assertEquals(ComponentStateMachineEventType.NEW_SCHEDULING_STATE, capturedEvent.getValue().getType()); capturedEvent.reset(); } private void assertSchedulingFailureEventPosted(Capture<ComponentStateMachineEvent> capturedEvent) { assertTrue(capturedEvent.hasCaptured()); assertEquals(ComponentStateMachineEventType.SCHEDULING_FAILED, capturedEvent.getValue().getType()); capturedEvent.reset(); } /** * Mock for arbitrary {@link TypedDatum} objects. * * @author Doreen Seider */ private final class TypedDatumMock implements TypedDatum { private final DataType dataType; private TypedDatumMock(DataType dataType) { this.dataType = dataType; } @Override public DataType getDataType() { return dataType; } } /** * Mock for {@link EndpointDatum} object, which mocks only scheduling-related methods. * * @author Doreen Seider */ private final class EndpointDatumMock extends EndpointDatumDefaultStub { private final String inputName; private final TypedDatum value; private EndpointDatumMock(String inputName, TypedDatum value) { this.inputName = inputName; this.value = value; } @Override public String getInputName() { return inputName; } @Override public TypedDatum getValue() { return value; } @Override public EndpointDatumRecipient getEndpointDatumRecipient() { return EndpointDatumRecipientFactory.createEndpointDatumRecipient(inputName, null, null, null); } } /** * Mock for {@link ComponentExecutionContext} objects, which mocks only scheduling-related methods. * * @author Doreen Seider */ private final class ExecutionSpecificComponentExecutionContextMock extends ComponentExecutionContextMock { private static final long serialVersionUID = 6234658796478889718L; private final List<InputMockInformation> inputMockInformations; private final List<InputGroupMockInformation> inputGroupMockInformations; private final boolean isLoopDriver; private final boolean isNestedLoopDriver; private ExecutionSpecificComponentExecutionContextMock(List<InputMockInformation> inputMockInformations) { this(inputMockInformations, new ArrayList<InputGroupMockInformation>()); } private ExecutionSpecificComponentExecutionContextMock(String executionId, List<InputMockInformation> inputMockInformations, List<InputGroupMockInformation> inputGroupMockInformations, boolean isLoopDriver, boolean isNestedLoopDriver) { super(executionId); this.inputMockInformations = inputMockInformations; this.inputGroupMockInformations = inputGroupMockInformations; this.isLoopDriver = isLoopDriver; this.isNestedLoopDriver = isNestedLoopDriver; } private ExecutionSpecificComponentExecutionContextMock(String executionId, List<InputMockInformation> inputMockInformations, List<InputGroupMockInformation> inputGroupMockInformations) { this(executionId, inputMockInformations, inputGroupMockInformations, false, false); } private ExecutionSpecificComponentExecutionContextMock(List<InputMockInformation> inputMockInformations, List<InputGroupMockInformation> inputGroupMockInformations) { super(); this.inputMockInformations = inputMockInformations; this.inputGroupMockInformations = inputGroupMockInformations; this.isLoopDriver = false; this.isNestedLoopDriver = false; } @Override public ComponentDescription getComponentDescription() { ComponentDescription componentDescriptionMock = EasyMock.createStrictMock(ComponentDescription.class); ComponentInterface compInterfaceMock = EasyMock.createStrictMock(ComponentInterface.class); EasyMock.expect(compInterfaceMock.getIsLoopDriver()).andStubReturn(isLoopDriver); EasyMock.replay(compInterfaceMock); EasyMock.expect(componentDescriptionMock.getComponentInterface()).andStubReturn(compInterfaceMock); ConfigurationDescription configDescMock = EasyMock.createStrictMock(ConfigurationDescription.class); EasyMock.expect(configDescMock.getConfigurationValue(LoopComponentConstants.CONFIG_KEY_IS_NESTED_LOOP)) .andStubReturn(String.valueOf(isNestedLoopDriver)); EasyMock.replay(configDescMock); EasyMock.expect(componentDescriptionMock.getConfigurationDescription()).andStubReturn(configDescMock); EasyMock.expect(componentDescriptionMock.getInputDescriptionsManager()) .andStubReturn(InputDescriptionManagerMockFactory.createInputDescriptionManagerMock(inputMockInformations, inputGroupMockInformations)); EasyMock.replay(componentDescriptionMock); return componentDescriptionMock; } } }