diff --git a/client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/ControllerConstants.java b/client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/ControllerConstants.java index 0b45e95676..1c862c0e95 100644 --- a/client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/ControllerConstants.java +++ b/client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/ControllerConstants.java @@ -32,6 +32,8 @@ public class ControllerConstants { public static final String REDIS_INSERTION = "/redisInsertion"; + public static final String DYNAMODB_INSERTION = "/dynamoDbInsertion"; + public static final String POST_SEARCH_ACTION = "/postSearchAction"; public static final String DERIVE_PARAMS = "/deriveParams"; diff --git a/client-java/controller/src/main/java/org/evomaster/client/java/controller/EmbeddedSutController.java b/client-java/controller/src/main/java/org/evomaster/client/java/controller/EmbeddedSutController.java index 1ae5bb73ef..e746661026 100644 --- a/client-java/controller/src/main/java/org/evomaster/client/java/controller/EmbeddedSutController.java +++ b/client-java/controller/src/main/java/org/evomaster/client/java/controller/EmbeddedSutController.java @@ -119,6 +119,11 @@ public final void setExecutingInitRedis(boolean executingInitRedis) { ExecutionTracer.setExecutingInitRedis(executingInitRedis); } + @Override + public final void setExecutingInitDynamoDb(boolean executingInitDynamoDb) { + ExecutionTracer.setExecutingInitDynamoDB(executingInitDynamoDb); + } + @Override public final void setExecutingAction(boolean executingAction){ ExecutionTracer.setExecutingAction(executingAction); diff --git a/client-java/controller/src/main/java/org/evomaster/client/java/controller/ExternalSutController.java b/client-java/controller/src/main/java/org/evomaster/client/java/controller/ExternalSutController.java index 5144521339..46352e50bc 100644 --- a/client-java/controller/src/main/java/org/evomaster/client/java/controller/ExternalSutController.java +++ b/client-java/controller/src/main/java/org/evomaster/client/java/controller/ExternalSutController.java @@ -530,6 +530,14 @@ public final void setExecutingInitRedis(boolean executingInitRedis) { ExecutionTracer.setExecutingInitRedis(executingInitRedis); } + @Override + public final void setExecutingInitDynamoDb(boolean executingInitDynamoDb) { + checkInstrumentation(); + serverController.setExecutingInitDynamoDb(executingInitDynamoDb); + // sync executingInitDynamoDb on the local ExecutionTracer + ExecutionTracer.setExecutingInitDynamoDB(executingInitDynamoDb); + } + @Override public final void setExecutingAction(boolean executingAction){ checkInstrumentation(); diff --git a/client-java/controller/src/main/java/org/evomaster/client/java/controller/SutHandler.java b/client-java/controller/src/main/java/org/evomaster/client/java/controller/SutHandler.java index 3a6c0a5749..378d4b0156 100644 --- a/client-java/controller/src/main/java/org/evomaster/client/java/controller/SutHandler.java +++ b/client-java/controller/src/main/java/org/evomaster/client/java/controller/SutHandler.java @@ -90,6 +90,14 @@ default void setupForGeneratedTest(){} RedisInsertionResultsDto execInsertionsIntoRedisDatabase(List insertions); + /** + * Executes DynamoDB initialization insertions. + * + * @param insertions items to insert + * @return insertion results + */ + DynamoDbInsertionResultsDto execInsertionsIntoDynamoDb(List insertions); + /** *

* return an instance of a client of an RPC service. diff --git a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/EMController.java b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/EMController.java index 5951d369d9..b922c31a6f 100644 --- a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/EMController.java +++ b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/EMController.java @@ -11,6 +11,7 @@ import org.evomaster.client.java.controller.api.dto.problem.rpc.ScheduleTaskInvocationsDto; import org.evomaster.client.java.controller.api.dto.problem.rpc.ScheduleTaskInvocationsResult; import org.evomaster.client.java.controller.mongo.MongoScriptRunner; +import org.evomaster.client.java.controller.dynamodb.DynamoDbCommandExecutor; import org.evomaster.client.java.controller.problem.*; import org.evomaster.client.java.controller.redis.RedisCommandExecutor; import org.evomaster.client.java.controller.redis.ReflectionBasedRedisClient; @@ -1065,4 +1066,47 @@ public Response executeRedisInsertion( sutController.setExecutingInitRedis(false); } } + + /** + * Executes DynamoDB initialization insertions. + * + * @param dto insertion commands + * @param httpServletRequest request metadata + * @return insertion results + */ + @Path(ControllerConstants.DYNAMODB_INSERTION) + @Consumes(Formats.JSON_V1) + @POST + public Response executeDynamoDbInsertion( + DynamoDbDatabaseCommandsDto dto, + @Context HttpServletRequest httpServletRequest) { + + assert trackRequestSource(httpServletRequest); + try { + sutController.setExecutingInitDynamoDb(true); + Object connection = noKillSwitch(sutController::getDynamoDbConnection); + if (connection == null) { + return Response.status(400) + .entity(WrappedResponseDto.withError("No active DynamoDB connection")).build(); + } + if (dto == null || dto.insertions == null || dto.insertions.isEmpty()) { + return Response.status(400) + .entity(WrappedResponseDto.withError("No input command")).build(); + } + if (dto.insertions.stream().anyMatch(i -> i == null || i.tableName == null + || i.tableName.isEmpty() || i.attributes == null || i.attributes.isEmpty())) { + return Response.status(400) + .entity(WrappedResponseDto.withError("Insertion with no table or attributes")).build(); + } + DynamoDbInsertionResultsDto results = DynamoDbCommandExecutor.executeInsert( + connection, dto.insertions); + return Response.status(200).entity(WrappedResponseDto.withData(results)).build(); + } catch (RuntimeException e) { + String msg = "Thrown exception: " + e.getMessage(); + SimpleLogger.error(msg, e); + return Response.status(500).entity(WrappedResponseDto.withError(msg)).build(); + } finally { + sutController.setExecutingInitDynamoDb(false); + } + } } diff --git a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/SutController.java b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/SutController.java index 053b1a8e8b..40348192b9 100644 --- a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/SutController.java +++ b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/SutController.java @@ -28,6 +28,8 @@ import org.evomaster.client.java.controller.internal.db.OpenSearchHandler; import org.evomaster.client.java.controller.internal.db.redis.RedisHandler; import org.evomaster.client.java.controller.internal.db.dynamodb.DynamoDbHandler; +import org.evomaster.client.java.controller.internal.db.dynamodb.DynamoDbCommandWithDistance; +import org.evomaster.client.java.controller.dynamodb.DynamoDbCommandExecutor; import org.evomaster.client.java.controller.redis.RedisCommandExecutor; import org.evomaster.client.java.controller.redis.ReflectionBasedRedisClient; import org.evomaster.client.java.sql.DbCleaner; @@ -314,6 +316,15 @@ public RedisInsertionResultsDto execInsertionsIntoRedisDatabase( return RedisCommandExecutor.executeInsert(connection, insertions); } + @Override + public DynamoDbInsertionResultsDto execInsertionsIntoDynamoDb(List insertions) { + Object connection = getDynamoDbConnection(); + if (connection == null) { + throw new IllegalStateException("No connection to DynamoDB"); + } + return DynamoDbCommandExecutor.executeInsert(connection, insertions); + } + public int getActionIndex(){ return actionIndex; } @@ -476,7 +487,7 @@ private boolean isRedisHeuristicsComputationAllowed() { } private boolean isDynamoDbHeuristicsComputationAllowed() { - return dynamoDbHandler.isCalculateHeuristics(); + return dynamoDbHandler.isCalculateHeuristics() || dynamoDbHandler.isExtractDynamoDbExecution(); } private void computeSQLHeuristics(ExtraHeuristicsDto dto, List additionalInfoList, boolean queryFromDatabase) { @@ -658,23 +669,26 @@ public final void computeRedisHeuristics(ExtraHeuristicsDto dto, List additionalInfoList) { - if (!dynamoDbHandler.isCalculateHeuristics()) { - return; - } if (!additionalInfoList.isEmpty()) { AdditionalInfo last = additionalInfoList.get(additionalInfoList.size() - 1); last.getDynamoDbInfoData().forEach(dynamoDbHandler::handle); } - dynamoDbHandler.getEvaluatedDynamoDbCommands().stream() - .map(evaluated -> new ExtraHeuristicEntryDto( - ExtraHeuristicEntryDto.Type.DYNAMODB, - ExtraHeuristicEntryDto.Objective.MINIMIZE_TO_ZERO, - evaluated.getHeuristicId(), - evaluated.getDistanceWithMetrics().getDistance(), - evaluated.getDistanceWithMetrics().getNumberOfEvaluatedItems(), - evaluated.getDistanceWithMetrics().isEvaluationFailure())) - .forEach(dto.heuristics::add); + List evaluated = dynamoDbHandler.getEvaluatedDynamoDbCommands(); + if (dynamoDbHandler.isCalculateHeuristics()) { + evaluated.stream() + .map(command -> new ExtraHeuristicEntryDto( + ExtraHeuristicEntryDto.Type.DYNAMODB, + ExtraHeuristicEntryDto.Objective.MINIMIZE_TO_ZERO, + command.getHeuristicId(), + command.getDistanceWithMetrics().getDistance(), + command.getDistanceWithMetrics().getNumberOfEvaluatedItems(), + command.getDistanceWithMetrics().isEvaluationFailure())) + .forEach(dto.heuristics::add); + } + if (dynamoDbHandler.isExtractDynamoDbExecution()) { + dto.dynamoDbExecutionsDto = dynamoDbHandler.getExecutionDto(); + } } /** @@ -1713,6 +1727,8 @@ public abstract List getTargetInfos(Collection ids, public abstract void setExecutingInitRedis(boolean executingInitRedis); + public abstract void setExecutingInitDynamoDb(boolean executingInitDynamoDb); + public abstract void setExecutingAction(boolean executingAction); diff --git a/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/SamplerVerifierTest.kt b/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/SamplerVerifierTest.kt index 1ca12df3a8..5235c469c7 100644 --- a/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/SamplerVerifierTest.kt +++ b/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/SamplerVerifierTest.kt @@ -529,6 +529,10 @@ class SamplerVerifierTest { return null } + override fun executeDynamoDbInsertions(dto: DynamoDbDatabaseCommandsDto): DynamoDbInsertionResultsDto? { + return null + } + override fun getSutInfo(): SutInfoDto? { return sutInfoDto } diff --git a/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/SamplerWithArazzoVerifierTest.kt b/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/SamplerWithArazzoVerifierTest.kt index 47128f31da..b4f9d886c6 100644 --- a/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/SamplerWithArazzoVerifierTest.kt +++ b/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/SamplerWithArazzoVerifierTest.kt @@ -190,6 +190,10 @@ class SamplerWithArazzoVerifierTest { return null } + override fun executeDynamoDbInsertions(dto: DynamoDbDatabaseCommandsDto): DynamoDbInsertionResultsDto? { + return null + } + override fun getSutInfo(): SutInfoDto? { return sutInfoDto } diff --git a/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/service/resource/ResourceTestBase.kt b/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/service/resource/ResourceTestBase.kt index 7ec54b006a..90b29b1088 100644 --- a/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/service/resource/ResourceTestBase.kt +++ b/core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/service/resource/ResourceTestBase.kt @@ -94,6 +94,9 @@ abstract class ResourceTestBase : ExtractTestBaseH2(), ResourceBasedTestInterfac return null } + override fun executeDynamoDbInsertions(dto: DynamoDbDatabaseCommandsDto): DynamoDbInsertionResultsDto? { + return null + } override fun executeDatabaseCommandAndGetQueryResults(dto: DatabaseCommandDto): QueryResultDto? { return SqlScriptRunner.execCommand(connection, dto.command).toDto() } diff --git a/core/src/main/kotlin/org/evomaster/core/database/sql/DatabaseExecutor.kt b/core/src/main/kotlin/org/evomaster/core/database/sql/DatabaseExecutor.kt index 74d25f3230..40ef8859bd 100644 --- a/core/src/main/kotlin/org/evomaster/core/database/sql/DatabaseExecutor.kt +++ b/core/src/main/kotlin/org/evomaster/core/database/sql/DatabaseExecutor.kt @@ -34,4 +34,10 @@ interface DatabaseExecutor { * Return the result of whether it success */ fun executeRedisDatabaseInsertions(dto: RedisDatabaseCommandsDto): RedisInsertionResultsDto? -} \ No newline at end of file + + /** + * Execute the given INSERT DynamoDB command (in DTO format). + * Return the result of whether it success + */ + fun executeDynamoDbInsertions(dto: DynamoDbDatabaseCommandsDto): DynamoDbInsertionResultsDto? +} diff --git a/core/src/main/kotlin/org/evomaster/core/problem/enterprise/EnterpriseChildTypeVerifier.kt b/core/src/main/kotlin/org/evomaster/core/problem/enterprise/EnterpriseChildTypeVerifier.kt index 1aea1976ba..47c175c872 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/enterprise/EnterpriseChildTypeVerifier.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/enterprise/EnterpriseChildTypeVerifier.kt @@ -3,6 +3,7 @@ package org.evomaster.core.problem.enterprise import org.evomaster.core.database.mongo.MongoDbAction import org.evomaster.core.problem.externalservice.HostnameResolutionAction import org.evomaster.core.database.redis.RedisDbAction +import org.evomaster.core.database.dynamodb.DynamoDbAction import org.evomaster.core.scheduletask.ScheduleTaskAction import org.evomaster.core.search.action.Action import org.evomaster.core.search.action.ActionComponent @@ -23,6 +24,7 @@ import org.evomaster.core.database.sql.SqlAction return SqlAction::class.java.isAssignableFrom(t) || MongoDbAction::class.java.isAssignableFrom(t) || RedisDbAction::class.java.isAssignableFrom(t) + || DynamoDbAction::class.java.isAssignableFrom(t) || HostnameResolutionAction::class.java.isAssignableFrom(t) || ScheduleTaskAction::class.java.isAssignableFrom(t) } diff --git a/core/src/main/kotlin/org/evomaster/core/problem/enterprise/EnterpriseIndividual.kt b/core/src/main/kotlin/org/evomaster/core/problem/enterprise/EnterpriseIndividual.kt index d87e31d63b..b6f72c6bf7 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/enterprise/EnterpriseIndividual.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/enterprise/EnterpriseIndividual.kt @@ -8,6 +8,7 @@ import org.evomaster.core.problem.api.ApiWsIndividual import org.evomaster.core.problem.externalservice.ApiExternalServiceAction import org.evomaster.core.problem.externalservice.HostnameResolutionAction import org.evomaster.core.database.redis.RedisDbAction +import org.evomaster.core.database.dynamodb.DynamoDbAction import org.evomaster.core.scheduletask.ScheduleTaskAction import org.evomaster.core.search.* import org.evomaster.core.search.action.* @@ -52,7 +53,7 @@ abstract class EnterpriseIndividual( /** * if no group definition is specified, then it is assumed that all action are for the MAIN group */ - groups : GroupsOfChildren = getEnterpriseTopGroups(children,children.size,0, 0, 0, 0, 0, 0), + groups : GroupsOfChildren = getEnterpriseTopGroups(children,children.size,0, 0, 0, 0, 0, 0, 0), ) : Individual( trackOperator, index, @@ -76,11 +77,12 @@ abstract class EnterpriseIndividual( sizeDNS: Int, sizeScheduleTasks: Int, sizeCleanUp: Int, + sizeDynamoDb: Int = 0, ) : GroupsOfChildren{ - if(children.size != sizeSQL + sizeMongo + sizeRedis + sizeDNS + sizeScheduleTasks + sizeMain + sizeCleanUp){ + if(children.size != sizeSQL + sizeMongo + sizeRedis + sizeDynamoDb + sizeDNS + sizeScheduleTasks + sizeMain + sizeCleanUp){ throw IllegalArgumentException("Group size mismatch. Expected a total of ${children.size}, but" + - " got main=$sizeMain, sql=$sizeSQL, mongo=$sizeMongo, redis=$sizeRedis, dns=$sizeDNS, scheduleTasks=$sizeScheduleTasks, sizeCleanUp=$sizeCleanUp") + " got main=$sizeMain, sql=$sizeSQL, mongo=$sizeMongo, redis=$sizeRedis, dynamodb=$sizeDynamoDb, dns=$sizeDNS, scheduleTasks=$sizeScheduleTasks, sizeCleanUp=$sizeCleanUp") } if(sizeSQL < 0){ throw IllegalArgumentException("Negative size for sizeSQL: $sizeSQL") @@ -91,6 +93,9 @@ abstract class EnterpriseIndividual( if(sizeRedis < 0){ throw IllegalArgumentException("Negative size for sizeRedis: $sizeMain") } + if(sizeDynamoDb < 0){ + throw IllegalArgumentException("Negative size for sizeDynamoDb: $sizeDynamoDb") + } if(sizeDNS < 0){ throw IllegalArgumentException("Negative size for sizeDNS: $sizeMain") } @@ -128,6 +133,12 @@ abstract class EnterpriseIndividual( if(sizeRedis==0) -1 else startIndexRedis , if(sizeRedis==0) -1 else endIndexRedis ) + val startIndexDynamoDb = children.indexOfFirst { a -> a is DynamoDbAction } + val endIndexDynamoDb = children.indexOfLast { a -> a is DynamoDbAction } + val dynamodb = ChildGroup(GroupsOfChildren.INITIALIZATION_DYNAMODB,{ e -> e is ActionComponent && e.flatten().all { a -> a is DynamoDbAction }}, + if (sizeDynamoDb == 0) -1 else startIndexDynamoDb, if (sizeDynamoDb == 0) -1 else endIndexDynamoDb + ) + val startIndexDns = children.indexOfFirst { a -> a is HostnameResolutionAction } val endIndexDns = children.indexOfLast { a -> a is HostnameResolutionAction } val dns = ChildGroup(GroupsOfChildren.INITIALIZATION_DNS,{e -> e is ActionComponent && e.flatten().all { a -> a is HostnameResolutionAction }}, @@ -140,7 +151,7 @@ abstract class EnterpriseIndividual( if(sizeScheduleTasks==0) -1 else startIndexScheduleTasks , if(sizeScheduleTasks==0) -1 else endIndexScheduleTasks ) - val initSize = sizeSQL+sizeMongo+sizeRedis+sizeDNS+sizeScheduleTasks + val initSize = sizeSQL+sizeMongo+sizeRedis+sizeDynamoDb+sizeDNS+sizeScheduleTasks val startIndexMain = initSize val endIndexMain = initSize + sizeMain - 1 @@ -150,7 +161,7 @@ abstract class EnterpriseIndividual( val cleanup = ChildGroup(GroupsOfChildren.CLEANUP, {e -> true}, if(sizeCleanUp == 0) -1 else endIndexMain+1, if(sizeCleanUp == 0) -1 else endIndexMain + sizeCleanUp) - return GroupsOfChildren(children, listOf(db, mongodb, redisdb, dns, schedule, main, cleanup)) + return GroupsOfChildren(children, listOf(db, mongodb, redisdb, dynamodb, dns, schedule, main, cleanup)) } } @@ -249,6 +260,7 @@ abstract class EnterpriseIndividual( .getAllInGroup(GroupsOfChildren.INITIALIZATION_SQL).flatMap { (it as ActionComponent).flatten() } + groupsView()!! .getAllInGroup(GroupsOfChildren.INITIALIZATION_MONGO).flatMap { (it as ActionComponent).flatten()}+ groupsView()!! .getAllInGroup(GroupsOfChildren.INITIALIZATION_REDIS).flatMap { (it as ActionComponent).flatten()}+ groupsView()!! + .getAllInGroup(GroupsOfChildren.INITIALIZATION_DYNAMODB).flatMap { (it as ActionComponent).flatten()}+ groupsView()!! .getAllInGroup(GroupsOfChildren.INITIALIZATION_DNS).flatMap { (it as ActionComponent).flatten()} + groupsView()!! .getAllInGroup(GroupsOfChildren.INITIALIZATION_SCHEDULE_TASK).flatMap { (it as ActionComponent).flatten() } // WARNING: this can still return DbAction, MongoDbAction and External ones... @@ -256,9 +268,10 @@ abstract class EnterpriseIndividual( ActionFilter.ONLY_SQL -> seeAllActions().filterIsInstance() ActionFilter.ONLY_MONGO -> seeAllActions().filterIsInstance() ActionFilter.ONLY_REDIS -> seeAllActions().filterIsInstance() + ActionFilter.ONLY_DYNAMODB -> seeAllActions().filterIsInstance() ActionFilter.NO_SQL -> seeAllActions().filter { it !is SqlAction } - ActionFilter.ONLY_DB -> seeAllActions().filter { it is SqlAction || it is MongoDbAction || it is RedisDbAction } - ActionFilter.NO_DB -> seeAllActions().filter { it !is SqlAction && it !is MongoDbAction && it !is RedisDbAction } + ActionFilter.ONLY_DB -> seeAllActions().filter { it is SqlAction || it is MongoDbAction || it is RedisDbAction || it is DynamoDbAction } + ActionFilter.NO_DB -> seeAllActions().filter { it !is SqlAction && it !is MongoDbAction && it !is RedisDbAction && it !is DynamoDbAction } ActionFilter.ONLY_EXTERNAL_SERVICE -> seeAllActions().filterIsInstance() ActionFilter.NO_EXTERNAL_SERVICE -> seeAllActions().filter { it !is ApiExternalServiceAction }.filter { it !is HostnameResolutionAction } ActionFilter.ONLY_DNS -> groupsView()!!.getAllInGroup(GroupsOfChildren.INITIALIZATION_DNS).flatMap { (it as ActionComponent).flatten()} @@ -327,6 +340,8 @@ abstract class EnterpriseIndividual( fun seeRedisDbActions() : List = seeActions(ActionFilter.ONLY_REDIS) as List + fun seeDynamoDbActions() : List = seeActions(ActionFilter.ONLY_DYNAMODB) as List + fun seeScheduleTaskActions() : List = seeActions(ActionFilter.ONLY_SCHEDULE_TASK) as List fun seeHostnameActions() : List = seeActions(ActionFilter.ONLY_DNS) as List @@ -396,6 +411,9 @@ abstract class EnterpriseIndividual( private fun getLastIndexOfRedisDbActionToAdd(): Int = groupsView()!!.endIndexForGroupInsertionInclusive(GroupsOfChildren.INITIALIZATION_REDIS) + private fun getLastIndexOfDynamoDbActionToAdd(): Int = + groupsView()!!.endIndexForGroupInsertionInclusive(GroupsOfChildren.INITIALIZATION_DYNAMODB) + private fun getLastIndexOfHostnameResolutionActionToAdd(): Int = groupsView()!!.endIndexForGroupInsertionInclusive(GroupsOfChildren.INITIALIZATION_DNS) @@ -411,6 +429,9 @@ abstract class EnterpriseIndividual( private fun getFirstIndexOfRedisDbActionToAdd(): Int = groupsView()!!.startIndexForGroupInsertionInclusive(GroupsOfChildren.INITIALIZATION_REDIS) + private fun getFirstIndexOfDynamoDbActionToAdd(): Int = + groupsView()!!.startIndexForGroupInsertionInclusive(GroupsOfChildren.INITIALIZATION_DYNAMODB) + private fun getFirstIndexOfHostnameResolutionActionToAdd(): Int = groupsView()!!.startIndexForGroupInsertionInclusive(GroupsOfChildren.INITIALIZATION_DNS) @@ -427,7 +448,7 @@ abstract class EnterpriseIndividual( */ fun addInitializingActions(actions: List): Int { - val invalid = actions.filter { it !is SqlAction && it !is MongoDbAction && it !is RedisDbAction && it !is HostnameResolutionAction } + val invalid = actions.filter { it !is SqlAction && it !is MongoDbAction && it !is RedisDbAction && it !is DynamoDbAction && it !is HostnameResolutionAction } if(invalid.isNotEmpty()){ throw IllegalArgumentException("Invalid ${invalid.size} environment actions of type:" + " ${invalid.map { it::class.java.simpleName }.toSet().joinToString(", ")}") @@ -438,6 +459,7 @@ abstract class EnterpriseIndividual( skipped += addInitializingDbActions(actions = actions.filterIsInstance()) addInitializingMongoDbActions(actions = actions.filterIsInstance()) addInitializingRedisDbActions(actions = actions.filterIsInstance()) + addInitializingDynamoDbActions(actions = actions.filterIsInstance()) addInitializingScheduleTaskActions(actions = actions.filterIsInstance()) //we don't need duplicates in hostname actions @@ -520,6 +542,14 @@ abstract class EnterpriseIndividual( } } + fun addInitializingDynamoDbActions(relativePosition: Int = -1, actions: List) { + if (relativePosition < 0) { + addChildrenToGroup(getLastIndexOfDynamoDbActionToAdd(), actions, GroupsOfChildren.INITIALIZATION_DYNAMODB) + } else { + addChildrenToGroup(getFirstIndexOfDynamoDbActionToAdd() + relativePosition, actions, GroupsOfChildren.INITIALIZATION_DYNAMODB) + } + } + fun addInitializingHostnameResolutionActions(relativePosition: Int=-1, actions: List) { if (relativePosition < 0) { addChildrenToGroup(getLastIndexOfHostnameResolutionActionToAdd(), actions, GroupsOfChildren.INITIALIZATION_DNS) diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/data/RestIndividual.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/data/RestIndividual.kt index f2719b78d9..b14a744d67 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/rest/data/RestIndividual.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/data/RestIndividual.kt @@ -14,6 +14,7 @@ import org.evomaster.core.problem.externalservice.HostnameResolutionAction import org.evomaster.core.problem.rest.resource.RestResourceCalls import org.evomaster.core.problem.rest.resource.SamplerSpecification import org.evomaster.core.database.redis.RedisDbAction +import org.evomaster.core.database.dynamodb.DynamoDbAction import org.evomaster.core.search.* import org.evomaster.core.search.action.ActionFilter.* import org.evomaster.core.search.action.EnvironmentAction @@ -43,8 +44,9 @@ class RestIndividual( dnsSize: Int = 0, scheduleSize : Int = 0, cleanupSize: Int = 0, + dynamoDbSize: Int = 0, groups : GroupsOfChildren = - getEnterpriseTopGroups(allActions, mainSize, sqlSize, mongoSize, redisSize, dnsSize, scheduleSize, cleanupSize), + getEnterpriseTopGroups(allActions, mainSize, sqlSize, mongoSize, redisSize, dnsSize, scheduleSize, cleanupSize, dynamoDbSize), ): ApiWsIndividual( sampleType, trackOperator, @@ -111,6 +113,7 @@ class RestIndividual( redisSize = groupsView()!!.sizeOfGroup(GroupsOfChildren.INITIALIZATION_REDIS), dnsSize = groupsView()!!.sizeOfGroup(GroupsOfChildren.INITIALIZATION_DNS), cleanupSize = groupsView()!!.sizeOfGroup(GroupsOfChildren.CLEANUP), + dynamoDbSize = groupsView()!!.sizeOfGroup(GroupsOfChildren.INITIALIZATION_DYNAMODB), ) } @@ -143,6 +146,8 @@ class RestIndividual( val redisDbActions = resources.flatMap { it.seeActions(ONLY_REDIS) } as List + val dynamoDbActions = resources.flatMap { it.seeActions(ONLY_DYNAMODB) } as List + val groups = resources.flatMap { it.seeEnterpriseActionGroup() } removeResourceCall(resources) @@ -151,6 +156,7 @@ class RestIndividual( addChildrenToGroup(sqlActions, GroupsOfChildren.INITIALIZATION_SQL) addChildrenToGroup(mongoDbActions, GroupsOfChildren.INITIALIZATION_MONGO) addChildrenToGroup(redisDbActions, GroupsOfChildren.INITIALIZATION_REDIS) + addChildrenToGroup(dynamoDbActions, GroupsOfChildren.INITIALIZATION_DYNAMODB) addChildrenToGroup(dnsActions, GroupsOfChildren.INITIALIZATION_DNS) @@ -169,7 +175,7 @@ class RestIndividual( /* if we move any environment action to the beginning of the individual, it might impact the fitness */ - return dnsActions.isNotEmpty() || sqlActions.isNotEmpty() || mongoDbActions.isNotEmpty() || redisDbActions.isNotEmpty() + return dnsActions.isNotEmpty() || sqlActions.isNotEmpty() || mongoDbActions.isNotEmpty() || redisDbActions.isNotEmpty() || dynamoDbActions.isNotEmpty() // re-generate local id // resetLocalIdRecursively() diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/resource/RestResourceCalls.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/resource/RestResourceCalls.kt index 667a8154c3..67379cf100 100755 --- a/core/src/main/kotlin/org/evomaster/core/problem/rest/resource/RestResourceCalls.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/resource/RestResourceCalls.kt @@ -1,6 +1,7 @@ package org.evomaster.core.problem.rest.resource import org.evomaster.core.Lazy +import org.evomaster.core.database.dynamodb.DynamoDbAction import org.evomaster.core.search.action.Action import org.evomaster.core.search.action.ActionComponent import org.evomaster.core.search.action.ActionFilter @@ -42,7 +43,11 @@ class RestResourceCalls( randomness: Randomness? = null ) : ActionTree( children, - { k -> SqlAction::class.java.isAssignableFrom(k) || MongoDbAction::class.java.isAssignableFrom(k) || EnterpriseActionGroup::class.java.isAssignableFrom(k) } + { k -> SqlAction::class.java.isAssignableFrom(k) || + MongoDbAction::class.java.isAssignableFrom(k) || + RedisDbAction::class.java.isAssignableFrom(k) || + DynamoDbAction::class.java.isAssignableFrom(k) || + EnterpriseActionGroup::class.java.isAssignableFrom(k) } ) { constructor( @@ -93,6 +98,11 @@ class RestResourceCalls( return children.flatMap { it.flatten() }.filterIsInstance() } + private val dynamoDbActions: List + get() { + return children.flatMap { it.flatten() }.filterIsInstance() + } + private val dnsActions: List get() { return children.flatMap { it.flatView() }.filterIsInstance() @@ -197,7 +207,7 @@ class RestResourceCalls( fun seeActions(filter: ActionFilter): List { return when (filter) { ActionFilter.ALL -> sqlActions.plus(externalServiceActions).plus(mainActions) // FIXME: Is this correct? - ActionFilter.INIT -> sqlActions.plus(mongoDbActions).plus(redisDbActions).plus(dnsActions) + ActionFilter.INIT -> sqlActions.plus(mongoDbActions).plus(redisDbActions).plus(dynamoDbActions).plus(dnsActions) ActionFilter.ONLY_SQL -> sqlActions ActionFilter.NO_INIT, ActionFilter.NO_SQL, ActionFilter.NO_DB -> externalServiceActions.plus(mainActions) ActionFilter.MAIN_EXECUTABLE -> mainActions @@ -205,8 +215,9 @@ class RestResourceCalls( ActionFilter.NO_EXTERNAL_SERVICE -> sqlActions.plus(mainActions) ActionFilter.ONLY_MONGO -> mongoDbActions ActionFilter.ONLY_REDIS -> redisDbActions + ActionFilter.ONLY_DYNAMODB -> dynamoDbActions ActionFilter.ONLY_DNS -> dnsActions - ActionFilter.ONLY_DB -> sqlActions.plus(mongoDbActions).plus(redisDbActions) + ActionFilter.ONLY_DB -> sqlActions.plus(mongoDbActions).plus(redisDbActions).plus(dynamoDbActions) ActionFilter.ONLY_SCHEDULE_TASK -> throw IllegalStateException("schedule task is not support in resource-based solution for REST Problem") } } diff --git a/core/src/main/kotlin/org/evomaster/core/remote/service/RemoteControllerImplementation.kt b/core/src/main/kotlin/org/evomaster/core/remote/service/RemoteControllerImplementation.kt index 018cfb5288..06e025ad1c 100644 --- a/core/src/main/kotlin/org/evomaster/core/remote/service/RemoteControllerImplementation.kt +++ b/core/src/main/kotlin/org/evomaster/core/remote/service/RemoteControllerImplementation.kt @@ -532,6 +532,19 @@ class RemoteControllerImplementation() : RemoteController{ return executeRedisDatabaseCommandAndGetResults(dto, object : GenericType>() {}) } + override fun executeDynamoDbInsertions(dto: DynamoDbDatabaseCommandsDto): DynamoDbInsertionResultsDto? { + val response = makeHttpCall { + getWebTarget() + .path(ControllerConstants.DYNAMODB_INSERTION) + .request() + .post(Entity.entity(dto, MediaType.APPLICATION_JSON_TYPE)) + } + return getDtoFromResponse( + response, + object : GenericType>() {} + )?.data + } + private fun executeDatabaseCommandAndGetResults(dto: DatabaseCommandDto, type: GenericType>): T?{ val response = makeHttpCall { diff --git a/core/src/main/kotlin/org/evomaster/core/search/GroupsOfChildren.kt b/core/src/main/kotlin/org/evomaster/core/search/GroupsOfChildren.kt index b6df94bd4d..1392fb5789 100644 --- a/core/src/main/kotlin/org/evomaster/core/search/GroupsOfChildren.kt +++ b/core/src/main/kotlin/org/evomaster/core/search/GroupsOfChildren.kt @@ -29,6 +29,8 @@ class GroupsOfChildren( const val INITIALIZATION_REDIS = "INITIALIZATION_REDIS" + const val INITIALIZATION_DYNAMODB = "INITIALIZATION_DYNAMODB" + const val INITIALIZATION_DNS = "INITIALIZATION_DNS" const val EXTERNAL_SERVICES = "EXTERNAL_SERVICES" diff --git a/core/src/main/kotlin/org/evomaster/core/search/action/ActionFilter.kt b/core/src/main/kotlin/org/evomaster/core/search/action/ActionFilter.kt index 353c781d6b..02fce68a4d 100644 --- a/core/src/main/kotlin/org/evomaster/core/search/action/ActionFilter.kt +++ b/core/src/main/kotlin/org/evomaster/core/search/action/ActionFilter.kt @@ -36,6 +36,9 @@ enum class ActionFilter { */ ONLY_REDIS, + /** actions which are DynamoDB-related actions */ + ONLY_DYNAMODB, + /** * actions which are not SQL-related actions */ diff --git a/core/src/test/kotlin/org/evomaster/core/output/service/FakeController.kt b/core/src/test/kotlin/org/evomaster/core/output/service/FakeController.kt index 9b5daeeda3..cdc9597ece 100644 --- a/core/src/test/kotlin/org/evomaster/core/output/service/FakeController.kt +++ b/core/src/test/kotlin/org/evomaster/core/output/service/FakeController.kt @@ -28,6 +28,10 @@ class FakeController : SutHandler { return null } + override fun execInsertionsIntoDynamoDb(insertions: List?): DynamoDbInsertionResultsDto? { + return null + } + override fun getDbSpecifications(): MutableList? { return null } diff --git a/core/src/test/kotlin/org/evomaster/core/problem/external/service/DummyController.kt b/core/src/test/kotlin/org/evomaster/core/problem/external/service/DummyController.kt index 1825ed3b40..6bb5e8ac12 100644 --- a/core/src/test/kotlin/org/evomaster/core/problem/external/service/DummyController.kt +++ b/core/src/test/kotlin/org/evomaster/core/problem/external/service/DummyController.kt @@ -87,6 +87,10 @@ class DummyController: RemoteController { TODO("Not yet implemented") } + override fun executeDynamoDbInsertions(dto: DynamoDbDatabaseCommandsDto): DynamoDbInsertionResultsDto? { + TODO("Not yet implemented") + } + override fun invokeScheduleTasksAndGetResults(dtos: ScheduleTaskInvocationsDto): ScheduleTaskInvocationsResult? { TODO("Not yet implemented") } diff --git a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualTestBase.kt b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualTestBase.kt index 49e9a7b429..9786eb55a4 100644 --- a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualTestBase.kt +++ b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualTestBase.kt @@ -682,6 +682,10 @@ abstract class RestIndividualTestBase { return null } + override fun executeDynamoDbInsertions(dto: DynamoDbDatabaseCommandsDto): DynamoDbInsertionResultsDto? { + return null + } + override fun invokeScheduleTasksAndGetResults(dtos: ScheduleTaskInvocationsDto): ScheduleTaskInvocationsResult? { return null } diff --git a/core/src/test/kotlin/org/evomaster/core/problem/rest/resource/ResourceNodeWithDbTest.kt b/core/src/test/kotlin/org/evomaster/core/problem/rest/resource/ResourceNodeWithDbTest.kt index e1fa01eee1..e1ef1c2af6 100644 --- a/core/src/test/kotlin/org/evomaster/core/problem/rest/resource/ResourceNodeWithDbTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/problem/rest/resource/ResourceNodeWithDbTest.kt @@ -282,6 +282,10 @@ class ResourceNodeWithDbTest { return null } + override fun executeDynamoDbInsertions(dto: DynamoDbDatabaseCommandsDto): DynamoDbInsertionResultsDto? { + return null + } + override fun executeDatabaseCommandAndGetQueryResults(dto: DatabaseCommandDto): QueryResultDto? { return SqlScriptRunner.execCommand(connection, dto.command).toDto() } diff --git a/core/src/test/kotlin/org/evomaster/core/sql/SqlInsertBuilderTest.kt b/core/src/test/kotlin/org/evomaster/core/sql/SqlInsertBuilderTest.kt index dbcc952460..f939a118e5 100644 --- a/core/src/test/kotlin/org/evomaster/core/sql/SqlInsertBuilderTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/sql/SqlInsertBuilderTest.kt @@ -424,6 +424,10 @@ class SqlInsertBuilderTest { return null } + override fun executeDynamoDbInsertions(dto: DynamoDbDatabaseCommandsDto): DynamoDbInsertionResultsDto? { + return null + } + override fun executeDatabaseCommandAndGetQueryResults(dto: DatabaseCommandDto): QueryResultDto? { return SqlScriptRunner.execCommand(connection, dto.command).toDto() }