/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.components.doe.execution; import static org.easymock.EasyMock.anyObject; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import java.util.HashMap; import java.util.Map; import org.easymock.EasyMock; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import de.rcenvironment.components.doe.common.DOEConstants; import de.rcenvironment.core.component.api.ComponentConstants; import de.rcenvironment.core.component.api.ComponentException; import de.rcenvironment.core.component.api.LoopComponentConstants; import de.rcenvironment.core.component.datamanagement.api.ComponentDataManagementService; import de.rcenvironment.core.component.execution.api.Component; import de.rcenvironment.core.component.execution.api.ComponentContext; import de.rcenvironment.core.component.testutils.ComponentContextMock; import de.rcenvironment.core.component.testutils.ComponentTestWrapper; 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.api.TypedDatumService; import de.rcenvironment.core.datamodel.types.api.BooleanTD; import de.rcenvironment.core.datamodel.types.api.FileReferenceTD; import de.rcenvironment.core.datamodel.types.api.FloatTD; import de.rcenvironment.core.toolkitbridge.transitional.ConcurrencyUtils; import de.rcenvironment.core.utils.common.StringUtils; import de.rcenvironment.core.utils.common.TempFileServiceAccess; import junit.framework.Assert; /** * Test class for the DOE execution. * * @author Sascha Zur * @author Doreen Seider */ public class DOEComponentTest { private static final String NUMBER_OF_OUTPUTS_FOR_CHOSEN_METHOD_TOO_FEW = "Number of outputs for chosen method too few"; private static final String MINIMAL_CUSTOM_TABLE = "[[\"1\"],[\"2\"]]"; private static final String FIVE = "5"; private static final String I = "i"; private static final String TWO = "2"; private static final String ZERO = "0"; private static final String TEN = "10"; private static final String MINUS_TEN = "-10"; private static final String ONE = "1"; private static final String MINUS_1 = "-1"; private static final String Y = "y"; private static final String X = "x"; private static final long EIGHT_HUNDRED_INT = 800; private static final int STATIC_OUTPUTS_COUNT = 2; /** * Exception rule. */ @Rule public ExpectedException exception = ExpectedException.none(); private ComponentTestWrapper component; private ComponentContextMock context; /** * JUnit setup method. * * @throws Exception e */ @Before public void setUp() throws Exception { context = new ComponentContextMock(); component = new ComponentTestWrapper(new DOEComponent(), context); final TypedDatumService typedDatumServiceMock = context.getService(TypedDatumService.class); TempFileServiceAccess.setupUnitTestEnvironment(); // create stub ComponentDataManagementService componentDataManagementServiceMock = EasyMock.createMock(ComponentDataManagementService.class); // define stub behavior FileReferenceTD dummyFileReference = typedDatumServiceMock.getFactory().createFileReference("", ""); EasyMock.expect(componentDataManagementServiceMock.createFileReferenceTDFromLocalFile(anyObject(ComponentContext.class), anyObject(File.class), anyObject(String.class))).andReturn(dummyFileReference); EasyMock.replay(componentDataManagementServiceMock); context.addService(ComponentDataManagementService.class, componentDataManagementServiceMock); } /** * JUnit tear down method. * * @throws Exception e */ @After public void tearDown() throws Exception {} /** * Test if the DOE can handle input(s). * * @throws ComponentException : */ @Test public void testWithOneInput() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); context.addSimulatedInput(I, "", DataType.Float, true, null); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(1)); component.start(); Assert.assertEquals(1, context.getCapturedOutput(X).size()); Assert.assertEquals(1, context.getCapturedOutput(Y).size()); final double[] expectedValuesX = { -1, 1, -1, 1 }; final double[] expectedValuesY = { -10, -10, 10, 10 }; checkOutput(new double[] { expectedValuesX[0] }, X); checkOutput(new double[] { expectedValuesY[0] }, Y); for (int i = 1; i < 4; i++) { component.processInputs(); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(1)); Assert.assertEquals(1, context.getCapturedOutput(X).size()); Assert.assertEquals(1, context.getCapturedOutput(Y).size()); checkOutput(new double[] { expectedValuesX[i] }, X); checkOutput(new double[] { expectedValuesY[i] }, Y); checkLoopDoneSent(false); } component.processInputs(); checkLoopDoneSent(true); checkClosedOutputs(2); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * Test if the DOE can handle invalid input(s) with behavior rerun. * * @throws ComponentException : */ @Test public void testWithOneInvalidInputRerun() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); context.addSimulatedInput(I, "", DataType.Float, true, null); final double[] expectedValuesX = { -1, -1, 1, -1, 1 }; final double[] expectedValuesY = { -10, -10, -10, 10, 10 }; component.start(); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createNotAValue()); Assert.assertEquals(1, context.getCapturedOutput(X).size()); Assert.assertEquals(1, context.getCapturedOutput(Y).size()); checkOutput(new double[] { expectedValuesX[0] }, X); checkOutput(new double[] { expectedValuesY[0] }, Y); for (int i = 1; i < 5; i++) { component.processInputs(); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(1)); Assert.assertEquals(1, context.getCapturedOutput(X).size()); Assert.assertEquals(1, context.getCapturedOutput(Y).size()); checkOutput(new double[] { expectedValuesX[i] }, X); checkOutput(new double[] { expectedValuesY[i] }, Y); checkLoopDoneSent(false); } component.processInputs(); checkLoopDoneSent(true); checkClosedOutputs(2); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * Test if the DOE can handle invalid input(s) with behavior abort. * * @throws ComponentException : */ @Test public void testWithOneInvalidInputAbort() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.Fail, null); addStaticOutputs(); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); context.addSimulatedInput(I, "", DataType.Float, true, null); component.start(); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createNotAValue()); Assert.assertEquals(1, context.getCapturedOutput(X).size()); Assert.assertEquals(1, context.getCapturedOutput(Y).size()); exception.expect(ComponentException.class); component.processInputs(); checkLoopDoneSent(false); component.processInputs(); checkLoopDoneSent(true); checkClosedOutputs(2); } /** * Test if the DOE can handle invalid input(s) with behavior rerun. * * @throws ComponentException : */ @Test public void testWithOneInvalidInputSkip() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.Discard, null); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); context.addSimulatedInput(I, "", DataType.Float, true, null); addStaticOutputs(); component.start(); Assert.assertEquals(1, context.getCapturedOutput(X).size()); Assert.assertEquals(1, context.getCapturedOutput(Y).size()); final double[] expectedValuesX = { -1, 1, -1, 1 }; checkOutput(new double[] { expectedValuesX[0] }, X); final double[] expectedValuesY = { -10, -10, 10, 10 }; checkOutput(new double[] { expectedValuesY[0] }, Y); for (int i = 1; i < 4; i++) { context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createNotAValue()); component.processInputs(); Assert.assertEquals(1, context.getCapturedOutput(X).size()); Assert.assertEquals(1, context.getCapturedOutput(Y).size()); checkOutput(new double[] { expectedValuesX[i] }, X); checkOutput(new double[] { expectedValuesY[i] }, Y); } component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * Test the full factorial algorithm for DOE with no inputs. * * @throws ComponentException : */ @Test public void testAlgorithmFullFactorialNoOutputs() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); exception.expect(ComponentException.class); exception.expectMessage(NUMBER_OF_OUTPUTS_FOR_CHOSEN_METHOD_TOO_FEW); component.start(); } /** * Test the full factorial algorithm for DOE with one inputs. * * @throws ComponentException : */ @Test public void testAlgorithmFullFactorialOneOutput() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); exception.expect(ComponentException.class); exception.expectMessage(NUMBER_OF_OUTPUTS_FOR_CHOSEN_METHOD_TOO_FEW); addNewOutput(X, MINUS_1, ONE); component.start(); } /** * Test the full factorial algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmFullFactorialLevelTooLow() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, ONE, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); exception.expect(ComponentException.class); exception.expectMessage("Level number for full factorial design too low"); component.start(); } /** * Test the full factorial algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmFullFactorial() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); addStaticOutputs(); component.start(); Assert.assertEquals(4, context.getCapturedOutput(X).size()); Assert.assertEquals(4, context.getCapturedOutput(Y).size()); final double[] expectedValuesX = { -1, 1, -1, 1 }; checkOutput(expectedValuesX, X); final double[] expectedValuesY = { -10, -10, 10, 10 }; checkOutput(expectedValuesY, Y); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * Test the full factorial algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmFullFactorialWithHistoryData() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); context.setConfigurationValue(ComponentConstants.CONFIG_KEY_STORE_DATA_ITEM, String.valueOf(true)); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); addStaticOutputs(); component.start(); Assert.assertEquals(4, context.getCapturedOutput(X).size()); Assert.assertEquals(4, context.getCapturedOutput(Y).size()); final double[] expectedValuesX = { -1, 1, -1, 1 }; checkOutput(expectedValuesX, X); final double[] expectedValuesY = { -10, -10, 10, 10 }; checkOutput(expectedValuesY, Y); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * * Test the LHC algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmLHCNoOutputs() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_LHC, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); exception.expect(ComponentException.class); exception.expectMessage(NUMBER_OF_OUTPUTS_FOR_CHOSEN_METHOD_TOO_FEW); component.start(); } /** * * Test the LHC algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmLHCOneOutput() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_LHC, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); exception.expect(ComponentException.class); exception.expectMessage(NUMBER_OF_OUTPUTS_FOR_CHOSEN_METHOD_TOO_FEW); component.start(); } /** * Test the LHC algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmLHCThreeRuns() throws ComponentException { addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); setDOEConfiguration(DOEConstants.DOE_ALGORITHM_LHC, ZERO, "3", ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); component.start(); Assert.assertEquals(3, context.getCapturedOutput(X).size()); Assert.assertEquals(3, context.getCapturedOutput(Y).size()); final double[] expectedValuesX = new double[] { 0.03362467007842257, -0.6016364814685322, 0.5554789329844331 }; checkOutput(expectedValuesX, X); final double[] expectedValuesY = new double[] { 2.941661196547428, 5.166359773569898, -9.14068566084149 }; checkOutput(expectedValuesY, Y); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * Test the LHC algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmLHCFiveRuns() throws ComponentException { addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); setDOEConfiguration(DOEConstants.DOE_ALGORITHM_LHC, ONE, FIVE, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); component.start(); Assert.assertEquals(5, context.getCapturedOutput(X).size()); Assert.assertEquals(5, context.getCapturedOutput(Y).size()); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * * Test the Monte Carlo algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmMonteCarloNoOutput() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_MONTE_CARLO, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); component.start(); } /** * Test the Monte Carlo algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmMonteCarloTwoRuns() throws ComponentException { addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); setDOEConfiguration(DOEConstants.DOE_ALGORITHM_MONTE_CARLO, ZERO, "3", ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); component.start(); Assert.assertEquals(3, context.getCapturedOutput(X).size()); Assert.assertEquals(3, context.getCapturedOutput(Y).size()); final double[] expectedValuesX = new double[] { 0.46193557475331404, 0.2748348507002165, 0.19509055559440358 }; checkOutput(expectedValuesX, X); final double[] expectedValuesY = new double[] { -5.189271686570283, 1.0087401023526787, -3.3356320104670045 }; checkOutput(expectedValuesY, Y); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * Test the Monte Carlo algorithm for DOE. * * @throws ComponentException : */ @Test public void testAlgorithmMonteCarloFiveRuns() throws ComponentException { addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); setDOEConfiguration(DOEConstants.DOE_ALGORITHM_MONTE_CARLO, ONE, FIVE, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); component.start(); Assert.assertEquals(5, context.getCapturedOutput(X).size()); Assert.assertEquals(5, context.getCapturedOutput(Y).size()); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * Test the custom table for DOE. * * @throws ComponentException : */ @Test public void testCustomTableNoTable() throws ComponentException { addNewOutput(X, MINUS_1, ONE); setDOEConfiguration(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE, ONE, FIVE, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, ""); exception.expect(ComponentException.class); exception.expectMessage("No table"); component.start(); } /** * Test the custom table for DOE. * * @throws ComponentException : */ @Test public void testCustomTableValidTable() throws ComponentException { addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); addStaticOutputs(); final String table = "[[\"1\", \"1\"],[\"2\", \"1\"]]"; setDOEConfiguration(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE, ONE, FIVE, ZERO, ONE, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, table); component.start(); Assert.assertEquals(2, context.getCapturedOutput(X).size()); Assert.assertEquals(2, context.getCapturedOutput(Y).size()); final double[] expectedValuesX = new double[] { 1, 2 }; checkOutput(expectedValuesX, X); final double[] expectedValuesY = new double[] { 1, 1 }; checkOutput(expectedValuesY, Y); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * Test the custom table for DOE. * * @throws ComponentException : */ @Test public void testCustomTableTooFewOutputs() throws ComponentException { addNewOutput(X, MINUS_1, ONE); addStaticOutputs(); final String table = "[[\"1\", \"1\"],[\"2\", \"1\"]]"; setDOEConfiguration(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE, ONE, FIVE, ZERO, ONE, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, table); component.start(); Assert.assertEquals(2, context.getCapturedOutput(X).size()); Assert.assertEquals(0, context.getCapturedOutput(Y).size()); final double[] expectedValuesX = new double[] { 1, 2 }; checkOutput(expectedValuesX, X); component.tearDown(Component.FinalComponentState.FINISHED); component.dispose(); } /** * Test the custom table for DOE. * * @throws ComponentException : */ @Test public void testCustomTableTooFewValues() throws ComponentException { addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_1, ONE); final String table = MINIMAL_CUSTOM_TABLE; setDOEConfiguration(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE, ONE, FIVE, ZERO, ONE, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, table); exception.expect(ComponentException.class); exception.expectMessage(StringUtils.format("Number of values per sample (%s) is lower than the number of outputs", 1, 2)); component.start(); } /** * Test the custom table for DOE. * * @throws ComponentException : */ @Test public void testCustomTableEndGreaterStart() throws ComponentException { addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_1, ONE); final String table = MINIMAL_CUSTOM_TABLE; setDOEConfiguration(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE, ONE, FIVE, ONE, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, table); exception.expect(ComponentException.class); component.start(); } /** * Test the custom table for DOE. * * @throws ComponentException : */ @Test public void testCustomTableStartLessZero() throws ComponentException { addNewOutput(X, MINUS_1, ONE); addStaticOutputs(); final String table = MINIMAL_CUSTOM_TABLE; setDOEConfiguration(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE, ONE, FIVE, MINUS_1, TWO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, table); component.start(); Assert.assertEquals(2, context.getCapturedOutput(X).size()); } /** * Test the custom table for DOE. * * @throws ComponentException : */ @Test public void testCustomTableMoreRunsThanValues() throws ComponentException { addNewOutput(X, MINUS_1, ONE); final String table = MINIMAL_CUSTOM_TABLE; setDOEConfiguration(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE, ONE, FIVE, FIVE, FIVE, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, table); exception.expect(ComponentException.class); exception.expectMessage(StringUtils.format("Start sample value (%s) is greater than the number of samples (%s)", 5, 2)); component.start(); } /** * Test the custom table for DOE. * * @throws ComponentException : */ @Test public void testCustomTableInvalidEntry() throws ComponentException { addNewOutput(X, MINUS_1, ONE); final String table = "[[\"1\"],[\"null\"]]"; setDOEConfiguration(DOEConstants.DOE_ALGORITHM_CUSTOM_TABLE, ONE, FIVE, ZERO, ONE, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, table); exception.expect(ComponentException.class); component.start(); } /** * Tests if values are forwarded as expected. * * @throws ComponentException on unexpected errors */ @Test public void testForwardingValue() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); context.addSimulatedInput(I, LoopComponentConstants.ENDPOINT_ID_TO_FORWARD, DataType.Float, true, null); context.addSimulatedOutput(I, LoopComponentConstants.ENDPOINT_ID_TO_FORWARD, DataType.Float, true, null); component.start(); Assert.assertEquals(1, context.getCapturedOutput(X).size()); Assert.assertEquals(1, context.getCapturedOutput(Y).size()); Assert.assertEquals(0, context.getCapturedOutput(I).size()); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(1.0)); component.processInputs(); Assert.assertEquals(1, context.getCapturedOutput(I).size()); Assert.assertEquals(1.0, ((FloatTD) context.getCapturedOutput(I).get(0)).getFloatValue(), 0); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(7.0)); component.processInputs(); Assert.assertEquals(1, context.getCapturedOutput(I).size()); Assert.assertEquals(7.0, ((FloatTD) context.getCapturedOutput(I).get(0)).getFloatValue(), 0); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(5.0)); component.processInputs(); Assert.assertEquals(1, context.getCapturedOutput(I).size()); Assert.assertEquals(5.0, ((FloatTD) context.getCapturedOutput(I).get(0)).getFloatValue(), 0); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(5.0)); component.processInputs(); Assert.assertEquals(0, context.getCapturedOutput(I).size()); checkLoopDoneSent(true); checkClosedOutputs(3); component.tearDownAndDispose(Component.FinalComponentState.FINISHED); } /** * Tests if values are forwarded as expected. * * @throws ComponentException on unexpected errors */ @Test public void testForwardingValueWithStartValues() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, TWO, ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); context.addSimulatedInput(I, LoopComponentConstants.ENDPOINT_ID_TO_FORWARD, DataType.Float, true, null); context.addSimulatedInput(I + LoopComponentConstants.ENDPOINT_STARTVALUE_SUFFIX, LoopComponentConstants.ENDPOINT_ID_START_TO_FORWARD, DataType.Float, true, null); context.addSimulatedOutput(I, LoopComponentConstants.ENDPOINT_ID_TO_FORWARD, DataType.Float, true, null); component.start(); Assert.assertEquals(0, context.getCapturedOutput(X).size()); Assert.assertEquals(0, context.getCapturedOutput(Y).size()); Assert.assertEquals(0, context.getCapturedOutput(I).size()); context.setInputValue(I + LoopComponentConstants.ENDPOINT_STARTVALUE_SUFFIX, context.getService(TypedDatumService.class).getFactory().createFloat(1.0)); component.processInputs(); Assert.assertEquals(1, context.getCapturedOutput(X).size()); Assert.assertEquals(1, context.getCapturedOutput(Y).size()); Assert.assertEquals(1, context.getCapturedOutput(I).size()); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(1.0)); component.processInputs(); Assert.assertEquals(1, context.getCapturedOutput(I).size()); Assert.assertEquals(1.0, ((FloatTD) context.getCapturedOutput(I).get(0)).getFloatValue(), 0); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(7.0)); component.processInputs(); Assert.assertEquals(1, context.getCapturedOutput(I).size()); Assert.assertEquals(7.0, ((FloatTD) context.getCapturedOutput(I).get(0)).getFloatValue(), 0); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(5.0)); component.processInputs(); Assert.assertEquals(1, context.getCapturedOutput(I).size()); Assert.assertEquals(5.0, ((FloatTD) context.getCapturedOutput(I).get(0)).getFloatValue(), 0); context.setInputValue(I, context.getService(TypedDatumService.class).getFactory().createFloat(5.0)); component.processInputs(); Assert.assertEquals(0, context.getCapturedOutput(I).size()); checkLoopDoneSent(true); checkClosedOutputs(3); component.tearDownAndDispose(Component.FinalComponentState.FINISHED); } /** * Test if the components cancels sending new design variables in case the component run (start) was canceled. * * @throws ComponentException on unexpected error. */ @Test(timeout = EIGHT_HUNDRED_INT) public void testCancelStart() throws ComponentException { setDOEConfiguration(DOEConstants.DOE_ALGORITHM_FULLFACT, ZERO, "200", ZERO, ZERO, LoopComponentConstants.LoopBehaviorInCaseOfFailure.RerunAndFail, null); addStaticOutputs(); addNewOutput(X, MINUS_1, ONE); addNewOutput(Y, MINUS_TEN, TEN); ConcurrencyUtils.getAsyncTaskService().execute(new Runnable() { @Override public void run() { try { final int hundred = 150; Thread.sleep(hundred); } catch (InterruptedException e) { return; // test timeout will apply as onStartInterrupted is not called } component.onStartInterrupted(null); } }); component.start(); final int outputCount = 40000; assertTrue(context.getCapturedOutput(X).size() < outputCount); assertTrue(context.getCapturedOutput(Y).size() < outputCount); assertTrue(context.getCapturedOutput(X).size() == context.getCapturedOutput(Y).size()); checkLoopDoneSent(true); component.tearDownAndDispose(Component.FinalComponentState.FINISHED); } private void addStaticOutputs() { context.addSimulatedOutput(LoopComponentConstants.ENDPOINT_NAME_LOOP_DONE, "", DataType.Boolean, false, new HashMap<String, String>()); context.addSimulatedOutput(DOEConstants.OUTPUT_NAME_NUMBER_OF_SAMPLES, "", DataType.Integer, false, new HashMap<String, String>(), EndpointCharacter.SAME_LOOP); } private void addNewOutput(String name, String lower, String upper) { Map<String, String> metaDatumX = new HashMap<>(); metaDatumX.put("lower", lower); metaDatumX.put("upper", upper); context.addSimulatedOutput(name, "", DataType.Float, true, metaDatumX); } private void checkOutput(double[] expectedValuesX, String outputName) { int i = 0; for (TypedDatum output : context.getCapturedOutput(outputName)) { Assert.assertEquals(expectedValuesX[i++], ((FloatTD) output).getFloatValue()); } Assert.assertEquals(expectedValuesX.length, i); } private void setDOEConfiguration(String method, String seed, String runNumber, String startSample, String endSample, LoopComponentConstants.LoopBehaviorInCaseOfFailure behaviour, String table) { context.setConfigurationValue(DOEConstants.KEY_METHOD, method); context.setConfigurationValue(DOEConstants.KEY_SEED_NUMBER, seed); context.setConfigurationValue(DOEConstants.KEY_RUN_NUMBER, runNumber); context.setConfigurationValue(DOEConstants.KEY_START_SAMPLE, startSample); context.setConfigurationValue(DOEConstants.KEY_END_SAMPLE, endSample); context.setConfigurationValue(LoopComponentConstants.CONFIG_KEY_LOOP_FAULT_TOLERANCE_NAV, behaviour.name()); context.setConfigurationValue(LoopComponentConstants.CONFIG_KEY_MAX_RERUN_BEFORE_FAIL_NAV, "1"); context.setConfigurationValue(DOEConstants.KEY_TABLE, table); } private void checkLoopDoneSent(boolean done) { if (done) { Assert.assertEquals(1, context.getCapturedOutput(LoopComponentConstants.ENDPOINT_NAME_LOOP_DONE).size()); Assert.assertEquals(true, ((BooleanTD) context .getCapturedOutput(LoopComponentConstants.ENDPOINT_NAME_LOOP_DONE).get(0)).getBooleanValue()); } } private void checkClosedOutputs(int dynInputCount) { assertEquals(STATIC_OUTPUTS_COUNT + dynInputCount, context.getCapturedOutputClosings().size()); } }