diff --git a/src/main/java/logic/dynamicdatageneration/TestcaseSimulator.java b/src/main/java/logic/dynamicdatageneration/TestcaseSimulator.java index a0ae992..ac64e91 100644 --- a/src/main/java/logic/dynamicdatageneration/TestcaseSimulator.java +++ b/src/main/java/logic/dynamicdatageneration/TestcaseSimulator.java @@ -7,6 +7,8 @@ import logic.dynamicdatageneration.testrun.TestData; import logic.model.Testcase; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.logging.Logger; @@ -36,40 +38,45 @@ public Optional simulateTestcase(Testcase testcase, Commands commands) TestData testDataCreated = new TestData(testcase.getFunctions(), commands); for (int actualRun = 1; actualRun <= maximalNumberOfTries; actualRun++) { - - resetApplication(); - executeFunctions(testcase, testDataCreated, actualRun); - var logList = executor.getAllNewLogs(0L); - LOGGER.info("Logs for Call of run " + actualRun + ":\n" + String.join("\n", logList)); - List specificTargetsToBeCovered = getAllTestTargets(testcase); - boolean allGeneralTestTargetsCovered = areAllTestTargetsCovered(testDataCreated, logList, testcase.getLogsOfTarget()); - boolean allSpecificTargetsCovered = areAllTestTargetsCovered(testDataCreated, logList, specificTargetsToBeCovered); - - if (allSpecificTargetsCovered) { - testcase.addTextToWriteOutput("Successfully covered in run " + actualRun + ":\n" + testDataCreated + "\n"); - testcase.setCovered(true); - testcase.setTestData(testDataCreated); - testcase.setSpecificTargetCovered(true); - testcase.setTestTargetData(testDataCreated); - testcase.setNumberOfRuns(actualRun); - return Optional.of(testDataCreated); - } else if (allGeneralTestTargetsCovered) { - testcase.addTextToWriteOutput("Successfully covered in run " + actualRun + ":\n" + testDataCreated + "\n"); - if (!testcase.isCovered()) { + try { + resetApplication(); + executeFunctions(testcase, testDataCreated, actualRun); + var logList = executor.getAllNewLogs(0L); + LOGGER.info("Logs for Call of run " + actualRun + ":\n" + String.join("\n", logList)); + List specificTargetsToBeCovered = getAllTestTargets(testcase); + boolean allGeneralTestTargetsCovered = areAllTestTargetsCovered(testDataCreated, logList, testcase.getLogsOfTarget()); + boolean allSpecificTargetsCovered = areAllTestTargetsCovered(testDataCreated, logList, specificTargetsToBeCovered); + + if (allSpecificTargetsCovered) { + testcase.addTextToWriteOutput("Successfully covered in run " + actualRun + ":\n" + testDataCreated + "\n"); testcase.setCovered(true); + testcase.setTestData(testDataCreated); + testcase.setSpecificTargetCovered(true); testcase.setTestTargetData(testDataCreated); testcase.setNumberOfRuns(actualRun); + return Optional.of(testDataCreated); + } else if (allGeneralTestTargetsCovered) { + testcase.addTextToWriteOutput("Successfully covered in run " + actualRun + ":\n" + testDataCreated + "\n"); + if (!testcase.isCovered()) { + testcase.setCovered(true); + testcase.setTestTargetData(testDataCreated); + testcase.setNumberOfRuns(actualRun); + } } + /* quite generic and has to be more specific */ + } catch (Exception e) { + String message = String.format("Error occurred in run%d: %s", actualRun, e.getMessage()); + System.err.println(message); + LOGGER.warning(message); } - } return Optional.empty(); } public void resetApplication() { if (resetFunctionName != null) { - executor.invokeFunction(resetFunctionName, "{}"); + executor.invokeFunction(resetFunctionName, "{}", new HashMap<>()); } executor.deleteOldLogs(); } @@ -114,7 +121,7 @@ private void executeFunctions(Testcase testcase, TestData testData, int actualRu LOGGER.info(invocation); testcase.addTextToWriteOutput(invocation); - String result = executor.invokeFunction(functionName, jsonData); + String result = executor.invokeFunction(functionName, jsonData, testData.getOutputValues()); testData.addResultToOutput(result); String resultFormatted = String.format("result: %s", result); @@ -132,7 +139,8 @@ private void executeFunctionsWithOldData(Testcase testcase, TestData testData) { String invocation = String.format("invoke function '%s' with json '%s'", functionName, jsonData); LOGGER.info(invocation); testcase.addTextToWriteOutput(invocation); - String result = executor.invokeFunction(functionName, jsonData); + String result = executor.invokeFunction(functionName, jsonData, testData.getOutputValues()); + testData.addResultToOutput(result); String resultFormatted = String.format("result: %s", result); LOGGER.info(resultFormatted); testcase.addTextToWriteOutput(resultFormatted); diff --git a/src/main/java/logic/dynamicdatageneration/executionplatforms/AWSInvoker.java b/src/main/java/logic/dynamicdatageneration/executionplatforms/AWSInvoker.java index fef27f6..7ae9920 100644 --- a/src/main/java/logic/dynamicdatageneration/executionplatforms/AWSInvoker.java +++ b/src/main/java/logic/dynamicdatageneration/executionplatforms/AWSInvoker.java @@ -11,6 +11,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Map; public class AWSInvoker implements Executor { protected AWSLambda amazonLambda; @@ -23,10 +24,14 @@ public AWSInvoker(String region) { @Override - public String invokeFunction(String functionName, String json) { + public String invokeFunction(String functionName, String json, Map> outputValues) { InvokeRequest invokeRequest = new InvokeRequest() .withFunctionName(functionName); json = json.replaceAll("'", "\""); + + json = setOutputsOfPreviousFunctions(json, outputValues); + + invokeRequest.setPayload(json); InvokeResult invokeResult = amazonLambda.invoke(invokeRequest); @@ -38,6 +43,24 @@ public String invokeFunction(String functionName, String json) { return new String(invokeResult.getPayload().array(), StandardCharsets.UTF_8); } + private String setOutputsOfPreviousFunctions(String json, Map> outputValues) { + while (json.contains("##PREVIOUSOUTPUT__")) { + String key = json.split("##PREVIOUSOUTPUT")[1].split("__")[1]; + var occurence = Integer.parseInt(json.split("##PREVIOUSOUTPUT")[1].split("__")[2]); + if (outputValues.containsKey(key) && outputValues.get(key).size()>occurence) { + String value = outputValues.get(key).get(occurence); + var jsonFirstPart= json.split("##PREVIOUSOUTPUT")[0]; + var jsonSecondPart= json.split("PREVIOUSOUTPUT##",2)[1]; + json = jsonFirstPart+value+jsonSecondPart; + } + else { + break; + } + + } + return json; + } + @Override public List getAllNewLogs(long startTime) { diff --git a/src/main/java/logic/dynamicdatageneration/executionplatforms/Executor.java b/src/main/java/logic/dynamicdatageneration/executionplatforms/Executor.java index 435793b..4515c84 100644 --- a/src/main/java/logic/dynamicdatageneration/executionplatforms/Executor.java +++ b/src/main/java/logic/dynamicdatageneration/executionplatforms/Executor.java @@ -1,9 +1,10 @@ package logic.dynamicdatageneration.executionplatforms; import java.util.List; +import java.util.Map; public interface Executor { - String invokeFunction(String functionName, String jsonData); + String invokeFunction(String functionName, String jsonData, Map> outputValues); List getAllNewLogs(long startTime); diff --git a/src/main/java/logic/dynamicdatageneration/testrun/FunctionWithInputData.java b/src/main/java/logic/dynamicdatageneration/testrun/FunctionWithInputData.java index 784863a..c84e8f2 100644 --- a/src/main/java/logic/dynamicdatageneration/testrun/FunctionWithInputData.java +++ b/src/main/java/logic/dynamicdatageneration/testrun/FunctionWithInputData.java @@ -107,18 +107,46 @@ public void changeData(TestData testData) { var inputValues = testData.getInputValues().get(inputData.getKey()); setRandomEntryOfListAsValue(inputData, inputValues); } else if (decisionRandomOutputAsValue < testData.getProbRandomOutputAsValue()) { - var inputValues = testData.getOutputValues().values().stream() - .flatMap(Collection::stream).collect(Collectors.toList()); - setRandomEntryOfListAsValue(inputData, inputValues); + var inputValues = testData.getOutputValues().entrySet().stream().map(entry -> { + var key = entry.getKey(); + var values = entry.getValue(); + List result = new ArrayList<>(); + for (int i = 0; i < values.size(); i++) { + var value = values.get(i); + result.add(new Pair(key, value, i)); + } + return result; + }).flatMap(List::stream).collect(Collectors.toList()); + setRandomEntryOfOutputAsValue(inputData, inputValues); } else if (decisionSimilarOutputAsValue < testData.getProbSimilarOutputAsValue()) { - var inputValues = testData.getOutputValues().get(inputData.getKey()); - setRandomEntryOfListAsValue(inputData, inputValues); + var inputValues = testData.getOutputValues().entrySet().stream() + .filter(entry -> entry.getKey().equals(inputData.getKey())) + .map(entry -> { + var key = entry.getKey(); + var values = entry.getValue(); + List result = new ArrayList<>(); + for (int i = 0; i < values.size(); i++) { + var value = values.get(i); + result.add(new Pair(key, value, i)); + } + return result; + }).flatMap(List::stream).collect(Collectors.toList()); + setRandomEntryOfOutputAsValue(inputData, inputValues); } } } } + private void setRandomEntryOfOutputAsValue(GeneralInput inputData, List inputValues) { + if (inputValues != null && inputValues.size() > 0) { + var item = getRandomItem2(inputValues); + var inputText = String.format("##PREVIOUSOUTPUT__%s__%s__PREVIOUSOUTPUT##", item.getKey(),item.getOccurence()); + inputData.setGeneratedValue(inputText); + } + + } + private void setRandomEntryOfListAsValue(GeneralInput inputData, List inputValues) { if (inputValues != null && inputValues.size() > 0) { var item = getRandomItem(inputValues); @@ -131,4 +159,34 @@ private T getRandomItem(List list) { int entryNumber = rn.nextInt(list.size()); return list.get(entryNumber); } + + private T getRandomItem2(List list) { + int entryNumber = rn.nextInt(list.size()); + return list.get(entryNumber); + } + + + private final class Pair { + private final String key; + private final String value; + private final int occurence; + + Pair(String key, String value, int occurence) { + this.key = key; + this.value = value; + this.occurence = occurence; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + public int getOccurence() { + return occurence; + } + } } \ No newline at end of file