From 67b018aba0332e0bd277d2659fb7d9d93c77daad Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Mon, 16 Sep 2024 19:11:14 -0300 Subject: [PATCH 01/26] Integrate Solver with ApiWsStructureMutator --- .../api/service/ApiWsStructureMutator.kt | 47 ++++++++++++++++--- .../evomaster/core/sql/SqlInsertBuilder.kt | 2 +- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt index e805b16fa8..69a6ec8836 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt @@ -25,6 +25,7 @@ import org.evomaster.core.search.gene.sql.SqlPrimaryKeyGene import org.evomaster.core.search.impact.impactinfocollection.ImpactsOfIndividual import org.evomaster.core.search.service.mutator.MutatedGeneSpecification import org.evomaster.core.search.service.mutator.StructureMutator +import org.evomaster.core.solver.SMTLibZ3DbConstraintSolver import org.slf4j.Logger import org.slf4j.LoggerFactory import kotlin.math.max @@ -292,6 +293,41 @@ abstract class ApiWsStructureMutator : StructureMutator() { mutatedGenes: MutatedGeneSpecification?, sampler: ApiWsSampler ): MutableList>? { + if (config.generateSqlDataWithSearch) { + return handleSearch(ind, sampler, mutatedGenes, fw) + } + + if (config.generateSqlDataWithDSE) { + return handleDSE(sampler, fw) + } + + return mutableListOf() + } + + private fun handleDSE(sampler: ApiWsSampler, fw: Map>): MutableList> { + // TODO: Use one solver, instead of creating one each time? + val resourcesFolder = "/tmp"; + val schemaDto = sampler.sqlInsertBuilder?.schemaDto + ?: throw IllegalStateException("No DB schema is available") + val solver = SMTLibZ3DbConstraintSolver(schemaDto, resourcesFolder) + + val newActions = mutableListOf>() + for ((_, queries) in fw) { + for (query in queries) { + val newActionsForQuery = solver.solve(query) + newActions.addAll(mutableListOf(newActionsForQuery)) + } + } + + return newActions + } + + private fun handleSearch( + ind: T, + sampler: ApiWsSampler, + mutatedGenes: MutatedGeneSpecification?, + fw: Map> + ): MutableList>? { /* because there might exist representExistingData in db actions which are in between rest actions, we use seeDbActions() instead of seeInitializingActions() here @@ -319,7 +355,9 @@ abstract class ApiWsStructureMutator : StructureMutator() { ind.addInitializingDbActions(0, existing) //record newly added existing sql data - mutatedGenes?.addedExistingDataInInitialization?.getOrPut(ImpactsOfIndividual.SQL_ACTION_KEY, { mutableListOf() })?.addAll(0, existing) + mutatedGenes?.addedExistingDataInInitialization?.getOrPut( + ImpactsOfIndividual.SQL_ACTION_KEY, + { mutableListOf() })?.addAll(0, existing) if (log.isTraceEnabled) log.trace("{} existingSqlData are added", existing) @@ -333,7 +371,7 @@ abstract class ApiWsStructureMutator : StructureMutator() { val addedSqlInsertions = if (mutatedGenes != null) mutableListOf>() else null - while (!missing.isEmpty()) { + while (missing.isNotEmpty()) { val first = missing.entries.first() @@ -363,11 +401,6 @@ abstract class ApiWsStructureMutator : StructureMutator() { */ missing = findMissing(fw, ind.seeInitializingActions().filterIsInstance()) } - - if (config.generateSqlDataWithDSE) { - //TODO DSE could be plugged in here - } - return addedSqlInsertions } diff --git a/core/src/main/kotlin/org/evomaster/core/sql/SqlInsertBuilder.kt b/core/src/main/kotlin/org/evomaster/core/sql/SqlInsertBuilder.kt index e383acfee6..4f1062db8a 100644 --- a/core/src/main/kotlin/org/evomaster/core/sql/SqlInsertBuilder.kt +++ b/core/src/main/kotlin/org/evomaster/core/sql/SqlInsertBuilder.kt @@ -17,7 +17,7 @@ import org.evomaster.core.logging.LoggingUtil class SqlInsertBuilder( - schemaDto: DbSchemaDto, + public val schemaDto: DbSchemaDto, private val dbExecutor: DatabaseExecutor? = null ) { From 0bf9750c2af2a3f56f16af049349945173653c7b Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Sun, 6 Oct 2024 16:23:31 -0300 Subject: [PATCH 02/26] Create test to execute Z3Solver --- .gitignore | 2 + .../database/execution/SqlExecutionsDto.java | 12 +- .../client/java/sql/internal/SqlHandler.java | 5 + .../api/service/ApiWsStructureMutator.kt | 23 ++- .../org/evomaster/core/search/FitnessValue.kt | 17 +- .../core/solver/SMTLibZ3DbConstraintSolver.kt | 4 +- .../evomaster/core/solver/SmtLibGenerator.kt | 4 +- e2e-tests/spring-rest-h2-z3solver/pom.xml | 192 ++++++++++++++++++ .../h2/z3solver/SwaggerConfiguration.java | 32 +++ .../rest/h2/z3solver/Z3SolverApplication.java | 16 ++ .../rest/h2/z3solver/Z3SolverTypesRest.java | 50 +++++ .../rest/h2/z3solver/SpringController.java | 83 ++++++++ .../rest/h2/z3solver/Z3SolverController.java | 105 ++++++++++ .../spring/h2/z3solver/SpringTestBase.java | 12 ++ .../spring/h2/z3solver/Z3SolverEMTest.java | 46 +++++ .../test-classes/META-INF/main.kotlin_module | Bin 0 -> 24 bytes .../target/tmp/smt2_1728173160781.smt2 | 6 + .../target/tmp/smt2_1728173246572.smt2 | 6 + .../target/tmp/smt2_1728173289994.smt2 | 6 + .../target/tmp/smt2_1728173329155.smt2 | 6 + .../target/tmp/smt2_1728173425124.smt2 | 6 + .../target/tmp/smt2_1728173459579.smt2 | 6 + .../target/tmp/smt2_1728173476186.smt2 | 6 + .../target/tmp/smt2_1728173501556.smt2 | 6 + .../target/tmp/smt2_1728173591454.smt2 | 6 + .../target/tmp/smt2_1728173869812.smt2 | 6 + .../target/tmp/smt2_1728231295071.smt2 | 6 + .../target/tmp/smt2_1728231594731.smt2 | 6 + .../target/tmp/smt2_1728231656914.smt2 | 6 + .../target/tmp/smt2_1728231728587.smt2 | 6 + .../target/tmp/smt2_1728231868575.smt2 | 6 + .../target/tmp/smt2_1728231873748.smt2 | 6 + .../target/tmp/smt2_1728231901619.smt2 | 6 + .../target/tmp/smt2_1728231927658.smt2 | 6 + .../target/tmp/smt2_1728231938421.smt2 | 6 + .../target/tmp/smt2_1728231962167.smt2 | 6 + .../target/tmp/smt2_1728231997213.smt2 | 6 + .../target/tmp/smt2_1728232111216.smt2 | 6 + .../target/tmp/smt2_1728232142937.smt2 | 6 + .../target/tmp/smt2_1728232153363.smt2 | 6 + .../target/tmp/smt2_1728232195966.smt2 | 6 + .../target/tmp/smt2_1728232209591.smt2 | 6 + .../target/tmp/smt2_1728232250393.smt2 | 6 + .../target/tmp/smt2_1728232273824.smt2 | 6 + .../target/tmp/smt2_1728232355799.smt2 | 6 + .../target/tmp/smt2_1728232378497.smt2 | 6 + .../target/tmp/smt2_1728232410272.smt2 | 6 + .../target/tmp/smt2_1728232448122.smt2 | 6 + .../target/tmp/smt2_1728232487155.smt2 | 6 + .../target/tmp/smt2_1728232821350.smt2 | 6 + .../target/tmp/smt2_1728232844041.smt2 | 6 + .../target/tmp/smt2_1728232923800.smt2 | 6 + .../target/tmp/smt2_1728232982915.smt2 | 6 + .../target/tmp/smt2_1728233029968.smt2 | 6 + .../target/tmp/smt2_1728233129184.smt2 | 6 + .../target/tmp/smt2_1728233129347.smt2 | 6 + .../target/tmp/smt2_1728233397647.smt2 | 6 + .../target/tmp/smt2_1728237189554.smt2 | 6 + .../target/tmp/smt2_1728237257557.smt2 | 6 + .../target/tmp/smt2_1728238235379.smt2 | 6 + .../target/tmp/smt2_1728239044342.smt2 | 6 + .../target/tmp/smt2_1728239153274.smt2 | 6 + .../target/tmp/smt2_1728239730052.smt2 | 6 + .../target/tmp/smt2_1728240339346.smt2 | 6 + .../target/tmp/smt2_1728241054871.smt2 | 6 + .../target/tmp/smt2_1728241384558.smt2 | 6 + .../target/tmp/smt2_1728241404507.smt2 | 6 + .../target/tmp/smt2_1728241426208.smt2 | 6 + .../target/tmp/smt2_1728241501798.smt2 | 6 + .../target/tmp/smt2_1728241535868.smt2 | 6 + .../target/tmp/smt2_1728241568774.smt2 | 6 + .../target/tmp/smt2_1728241762177.smt2 | 6 + .../target/tmp/smt2_1728241786780.smt2 | 6 + .../target/tmp/smt2_1728241830524.smt2 | 6 + .../target/tmp/smt2_1728241982798.smt2 | 6 + 75 files changed, 942 insertions(+), 15 deletions(-) create mode 100644 e2e-tests/spring-rest-h2-z3solver/pom.xml create mode 100644 e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/SwaggerConfiguration.java create mode 100644 e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverApplication.java create mode 100644 e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverTypesRest.java create mode 100644 e2e-tests/spring-rest-h2-z3solver/src/test/java/com/foo/spring/rest/h2/z3solver/SpringController.java create mode 100644 e2e-tests/spring-rest-h2-z3solver/src/test/java/com/foo/spring/rest/h2/z3solver/Z3SolverController.java create mode 100644 e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/SpringTestBase.java create mode 100644 e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/test-classes/META-INF/main.kotlin_module create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173160781.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173246572.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173289994.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173329155.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173425124.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173459579.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173476186.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173501556.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173591454.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173869812.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231295071.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231594731.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231656914.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231728587.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231868575.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231873748.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231901619.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231927658.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231938421.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231962167.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231997213.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232111216.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232142937.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232153363.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232195966.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232209591.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232250393.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232273824.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232355799.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232378497.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232410272.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232448122.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232487155.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232821350.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232844041.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232923800.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232982915.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728233029968.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728233129184.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728233129347.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728233397647.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728237189554.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728237257557.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728238235379.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728239044342.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728239153274.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728239730052.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728240339346.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241054871.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241384558.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241404507.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241426208.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241501798.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241535868.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241568774.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241762177.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241786780.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241830524.smt2 create mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241982798.smt2 diff --git a/.gitignore b/.gitignore index aa6f59cc54..40a5431c5e 100644 --- a/.gitignore +++ b/.gitignore @@ -166,3 +166,5 @@ Migrations/ /e2e-tests/spring-rest-bb/maven/target/ /target/ /wfc/target/ + +*.DS_Store \ No newline at end of file diff --git a/client-java/sql-dto/src/main/java/org/evomaster/client/java/controller/api/dto/database/execution/SqlExecutionsDto.java b/client-java/sql-dto/src/main/java/org/evomaster/client/java/controller/api/dto/database/execution/SqlExecutionsDto.java index 50cb7aaffb..6c26e67e6d 100644 --- a/client-java/sql-dto/src/main/java/org/evomaster/client/java/controller/api/dto/database/execution/SqlExecutionsDto.java +++ b/client-java/sql-dto/src/main/java/org/evomaster/client/java/controller/api/dto/database/execution/SqlExecutionsDto.java @@ -54,12 +54,22 @@ public class SqlExecutionsDto { * Every time there is a WHERE clause which "failed" (ie, resulted in false), * we keep track of which tables/columns where involved in determining the * result of the WHERE. - * * If there is no WHERE, but still no data was returned, we consider it * as a failed WHERE + * The key is the table name and the value is the set of columns involved in the WHERE */ public Map> failedWhere = new HashMap<>(); + /** + * Every time there is a WHERE clause which "failed" (ie, resulted in false), + * we keep track of which tables/columns where involved in determining the + * result of the WHERE. + * If there is no WHERE, but still no data was returned, we consider it + * as a failed WHERE + * The list includes the SQL queries that failed + */ + public List failedWhereQueries = new ArrayList<>(); + /** * The total Number of SQL commands (e.g., SELECT and UPDATE) executed */ diff --git a/client-java/sql/src/main/java/org/evomaster/client/java/sql/internal/SqlHandler.java b/client-java/sql/src/main/java/org/evomaster/client/java/sql/internal/SqlHandler.java index e2d3e0989b..240a1689b6 100644 --- a/client-java/sql/src/main/java/org/evomaster/client/java/sql/internal/SqlHandler.java +++ b/client-java/sql/src/main/java/org/evomaster/client/java/sql/internal/SqlHandler.java @@ -48,6 +48,7 @@ public class SqlHandler { private final Map> updatedData; private final Map> insertedData; private final Map> failedWhere; + private final List failedWhereQueries; private final List deletedData; private final List executedSqlCommands; @@ -79,6 +80,7 @@ public SqlHandler(TaintHandler taintHandler) { updatedData = new ConcurrentHashMap<>(); insertedData = new ConcurrentHashMap<>(); failedWhere = new ConcurrentHashMap<>(); + failedWhereQueries = new CopyOnWriteArrayList<>(); deletedData = new CopyOnWriteArrayList<>(); executedSqlCommands = new CopyOnWriteArrayList<>(); @@ -94,6 +96,7 @@ public void reset() { updatedData.clear(); insertedData.clear(); failedWhere.clear(); + failedWhereQueries.clear(); deletedData.clear(); executedSqlCommands.clear(); @@ -155,6 +158,7 @@ public SqlExecutionsDto getExecutionDto() { SqlExecutionsDto sqlExecutionsDto = new SqlExecutionsDto(); sqlExecutionsDto.queriedData.putAll(queriedData); sqlExecutionsDto.failedWhere.putAll(failedWhere); + sqlExecutionsDto.failedWhereQueries.addAll(failedWhereQueries); sqlExecutionsDto.insertedData.putAll(insertedData); sqlExecutionsDto.updatedData.putAll(updatedData); sqlExecutionsDto.deletedData.addAll(deletedData); @@ -239,6 +243,7 @@ private SqlDistanceWithMetrics computeDistance(String sqlCommand, if (dist.sqlDistance > 0) { mergeNewData(failedWhere, columns); + failedWhereQueries.add(sqlCommand); } return dist; diff --git a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt index 5e69ce9bd4..4e75a91668 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt @@ -269,7 +269,8 @@ abstract class ApiWsStructureMutator : StructureMutator() { val oldSqlActions = mutableListOf().plus(ind.seeInitializingActions()) - val addedSqlInsertions = handleFailedWhereSQL(ind, fw, mutatedGenes, sampler) + val failedWhereQueries = evaluatedIndividual.fitness.getViewOfAggregatedFailedWhereQueries() + val addedSqlInsertions = handleFailedWhereSQL(ind, fw, failedWhereQueries, mutatedGenes, sampler) ind.repairInitializationActions(randomness) // update impact based on added genes @@ -290,6 +291,10 @@ abstract class ApiWsStructureMutator : StructureMutator() { * Map of FAILED WHERE clauses. from table name key to column name values */ fw: Map>, + /** + * List queries with FAILED WHERE clauses + */ + failedWhereQueries: List, mutatedGenes: MutatedGeneSpecification?, sampler: ApiWsSampler ): MutableList>? { @@ -298,25 +303,23 @@ abstract class ApiWsStructureMutator : StructureMutator() { } if (config.generateSqlDataWithDSE) { - return handleDSE(sampler, fw) + return handleDSE(sampler, failedWhereQueries) } return mutableListOf() } - private fun handleDSE(sampler: ApiWsSampler, fw: Map>): MutableList> { + private fun handleDSE(sampler: ApiWsSampler, failedWhereQueries: List): MutableList> { // TODO: Use one solver, instead of creating one each time? - val resourcesFolder = "/tmp"; + val resourcesFolder = System.getProperty("user.dir") + "/target/tmp"; val schemaDto = sampler.sqlInsertBuilder?.schemaDto ?: throw IllegalStateException("No DB schema is available") - val solver = SMTLibZ3DbConstraintSolver(schemaDto, resourcesFolder) + val solver = SMTLibZ3DbConstraintSolver(schemaDto, resourcesFolder, 1) val newActions = mutableListOf>() - for ((_, queries) in fw) { - for (query in queries) { - val newActionsForQuery = solver.solve(query) - newActions.addAll(mutableListOf(newActionsForQuery)) - } + for (query in failedWhereQueries) { + val newActionsForQuery = solver.solve(query) + newActions.addAll(mutableListOf(newActionsForQuery)) } return newActions diff --git a/core/src/main/kotlin/org/evomaster/core/search/FitnessValue.kt b/core/src/main/kotlin/org/evomaster/core/search/FitnessValue.kt index ee737c8876..2d9fc0aacc 100644 --- a/core/src/main/kotlin/org/evomaster/core/search/FitnessValue.kt +++ b/core/src/main/kotlin/org/evomaster/core/search/FitnessValue.kt @@ -79,13 +79,19 @@ class FitnessValue( /** * When SUT does SQL commands using WHERE, keep track of when those "fails" (ie evaluate - * to false), in particular the tables and columns in them involved + * to false), in particular, the tables and columns in them involved */ private val aggregatedFailedWhere: MutableMap> = mutableMapOf() + /** + * When SUT does SQL commands using WHERE, keep track of when those "fails" (ie evaluate + * to false), in particular, the sql query involved + */ + private val aggregatedFailedWhereQueries: MutableList = mutableListOf() + /** * When SUT does MONGO commands using FIND, keep track of when those "fails" (ie evaluate - * to false), in particular the collection and fields in them involved + * to false), in particular, the collection and fields in them involved */ private val aggregatedFailedFind: MutableList = mutableListOf() @@ -140,6 +146,11 @@ class FitnessValue( databaseExecutions.values, {x -> x.failedWhere} )) + + aggregatedFailedWhereQueries.clear() + aggregatedFailedWhereQueries.addAll( + databaseExecutions.values.flatMap { a -> a.executionInfo }.map{ b -> b.sqlCommand } + ) } fun aggregateMongoDatabaseData(){ aggregatedFailedFind.clear() @@ -166,6 +177,8 @@ class FitnessValue( fun getViewOfAggregatedFailedWhere() = aggregatedFailedWhere + fun getViewOfAggregatedFailedWhereQueries() = aggregatedFailedWhereQueries + fun getViewOfAggregatedFailedFind() = aggregatedFailedFind fun doesCover(target: Int): Boolean { diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index a341626f8e..9b941229e8 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -278,7 +278,7 @@ class SMTLibZ3DbConstraintSolver( */ private fun storeToTmpFile(smtLib: SMTLib): String { val fileName = "smt2_${System.currentTimeMillis()}.smt2" - val filePath = this.resourcesFolder + fileName + val filePath = leadingBarResourcesFolder() + fileName try { Files.write(Paths.get(filePath), smtLib.toString().toByteArray(StandardCharsets.UTF_8)) @@ -287,4 +287,6 @@ class SMTLibZ3DbConstraintSolver( } return fileName } + + private fun leadingBarResourcesFolder() = if (resourcesFolder.endsWith("/")) resourcesFolder else "$resourcesFolder/" } diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SmtLibGenerator.kt b/core/src/main/kotlin/org/evomaster/core/solver/SmtLibGenerator.kt index 254fa32ace..85d641c809 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SmtLibGenerator.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SmtLibGenerator.kt @@ -497,7 +497,8 @@ class SmtLibGenerator(private val schema: DbSchemaDto, private val numberOfRows: private fun getConstructors(table: TableDto): List { return table.columns.map { c -> val smtType = TYPE_MAP[c.type.uppercase(Locale.getDefault())] - DeclareConstSMTNode(c.name, smtType!!) + ?: throw RuntimeException("Unsupported column type: ${c.type}") + DeclareConstSMTNode(c.name, smtType) } } @@ -509,6 +510,7 @@ class SmtLibGenerator(private val schema: DbSchemaDto, private val numberOfRows: "TIMESTAMP" to "Int", "FLOAT" to "Real", "DOUBLE" to "Real", + "DECIMAL" to "Real", "CHARACTER VARYING" to "String", "CHAR" to "String", "CHARACTER LARGE OBJECT" to "String", diff --git a/e2e-tests/spring-rest-h2-z3solver/pom.xml b/e2e-tests/spring-rest-h2-z3solver/pom.xml new file mode 100644 index 0000000000..abff24a451 --- /dev/null +++ b/e2e-tests/spring-rest-h2-z3solver/pom.xml @@ -0,0 +1,192 @@ + +4.0.0 + + + org.evomaster + evomaster-e2e-tests + 3.2.1-SNAPSHOT + + +spring-rest-h2-z3solver +jar + + + + + + + javax.validation + validation-api + 2.0.1.Final + + + + + javax.ws.rs + javax.ws.rs-api + + + org.evomaster + evomaster-e2e-tests-utils + test-jar + + + org.evomaster + evomaster-client-java-controller + + + org.evomaster + evomaster-core + test + + + org.evomaster + evomaster-client-java-instrumentation + test-jar + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-security + + + com.h2database + h2 + + + org.locationtech.jts + jts-core + 1.19.0 + + + + com.google.code.gson + gson + + + + io.springfox + springfox-swagger2 + + + io.swagger + * + + + + + io.springfox + springfox-spring-web + + + io.swagger + swagger-parser + + + + + org.jetbrains.kotlin + kotlin-stdlib + + + + io.rest-assured + rest-assured + + + org.hamcrest + hamcrest-all + + + org.junit.jupiter + junit-jupiter-engine + + + org.junit.platform + junit-platform-launcher + + + org.junit.jupiter + junit-jupiter-params + + + + + javax.xml.bind + jaxb-api + + + org.glassfish.jaxb + jaxb-runtime + + + + + edu.stanford.nlp + stanford-corenlp + ${nlp.version} + test + + + edu.stanford.nlp + stanford-corenlp + ${nlp.version} + models + test + + + + + com.github.tomakehurst + wiremock-jre8-standalone + test + + + com.alibaba + dns-cache-manipulator + + + org.apache.httpcomponents + httpclient + + + com.squareup.okhttp3 + okhttp + + + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + + skipE2E_V2 + + true + + + + + \ No newline at end of file diff --git a/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/SwaggerConfiguration.java b/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/SwaggerConfiguration.java new file mode 100644 index 0000000000..6fe131411d --- /dev/null +++ b/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/SwaggerConfiguration.java @@ -0,0 +1,32 @@ +package com.foo.spring.rest.h2.z3solver; + +import org.springframework.context.annotation.Bean; +import org.springframework.security.core.Authentication; +import org.springframework.web.context.request.WebRequest; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +import static springfox.documentation.builders.PathSelectors.regex; + +public class SwaggerConfiguration { + + @Bean + public Docket docketApi() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + .paths(regex("/api/.*")) + .build() + .ignoredParameterTypes(WebRequest.class, Authentication.class); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("API") + .description("Some description") + .version("1.0") + .build(); + } +} diff --git a/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverApplication.java b/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverApplication.java new file mode 100644 index 0000000000..32ec1c016c --- /dev/null +++ b/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverApplication.java @@ -0,0 +1,16 @@ +package com.foo.spring.rest.h2.z3solver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@EnableSwagger2 +@SpringBootApplication(exclude = SecurityAutoConfiguration.class) +public class Z3SolverApplication extends SwaggerConfiguration { + + public static void main(String[] args) { + SpringApplication.run(Z3SolverApplication.class, args); + } + +} diff --git a/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverTypesRest.java b/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverTypesRest.java new file mode 100644 index 0000000000..f7d15aa5e8 --- /dev/null +++ b/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverTypesRest.java @@ -0,0 +1,50 @@ +package com.foo.spring.rest.h2.z3solver; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.persistence.EntityManager; +import javax.persistence.Query; +import java.util.List; + +/** + * Created by agusaldasoro on 04-Oct-24. + */ +@RestController +@RequestMapping(path = "/api/h2/z3solver/") +public class Z3SolverTypesRest { + + @Autowired + private EntityManager em; + +// // This fails to load, as when the WHERE clause is empty, it fails to calculate the failedWhere +// @GetMapping("/products") +// public ResponseEntity getEmptyWhere() { +// Query query = em.createNativeQuery( +// "select (1) from products"); +// List data = query.getResultList(); +// +// if (data.isEmpty()) { +// return ResponseEntity.status(400).build(); +// } else { +// return ResponseEntity.status(200).build(); +// } +// } + + @GetMapping("/products-1") + public ResponseEntity getId1() { + Query query = em.createNativeQuery( + "select (1) from products where id = 1"); + List data = query.getResultList(); + + if (data.isEmpty()) { + return ResponseEntity.status(400).build(); + } else { + return ResponseEntity.status(200).build(); + } + } +} + diff --git a/e2e-tests/spring-rest-h2-z3solver/src/test/java/com/foo/spring/rest/h2/z3solver/SpringController.java b/e2e-tests/spring-rest-h2-z3solver/src/test/java/com/foo/spring/rest/h2/z3solver/SpringController.java new file mode 100644 index 0000000000..f2059c2a51 --- /dev/null +++ b/e2e-tests/spring-rest-h2-z3solver/src/test/java/com/foo/spring/rest/h2/z3solver/SpringController.java @@ -0,0 +1,83 @@ +package com.foo.spring.rest.h2.z3solver; + +import org.evomaster.client.java.controller.EmbeddedSutController; +import org.evomaster.client.java.controller.api.dto.SutInfoDto; +import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto; +import org.evomaster.client.java.controller.problem.ProblemInfo; +import org.evomaster.client.java.controller.problem.RestProblem; +import org.evomaster.client.java.sql.DbSpecification; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public abstract class SpringController extends EmbeddedSutController { + + protected ConfigurableApplicationContext ctx; + protected final Class applicationClass; + + protected SpringController(Class applicationClass) { + this.applicationClass = applicationClass; + super.setControllerPort(0); + } + + @Override + public String startSut() { + + ctx = SpringApplication.run(applicationClass, "--server.port=0"); + + return "http://localhost:" + getSutPort(); + } + + protected int getSutPort() { + return (Integer) ((Map) Objects.requireNonNull(ctx.getEnvironment() + .getPropertySources().get("server.ports")).getSource()) + .get("local.server.port"); + } + + @Override + public boolean isSutRunning() { + return ctx != null && ctx.isRunning(); + } + + @Override + public void stopSut() { + ctx.stop(); + ctx.close(); + } + + @Override + public String getPackagePrefixesToCover() { + return "com.foo."; + } + + @Override + public void resetStateOfSUT() { + // nothing to do + } + + @Override + public ProblemInfo getProblemInfo() { + return new RestProblem( + "http://localhost:" + getSutPort() + "/v2/api-docs", + null + ); + } + + @Override + public List getInfoForAuthentication() { + return null; + } + + @Override + public List getDbSpecifications() { + return null; + } + + @Override + public SutInfoDto.OutputFormat getPreferredOutputFormat() { + return SutInfoDto.OutputFormat.JAVA_JUNIT_5; + } +} diff --git a/e2e-tests/spring-rest-h2-z3solver/src/test/java/com/foo/spring/rest/h2/z3solver/Z3SolverController.java b/e2e-tests/spring-rest-h2-z3solver/src/test/java/com/foo/spring/rest/h2/z3solver/Z3SolverController.java new file mode 100644 index 0000000000..949c4d9bbb --- /dev/null +++ b/e2e-tests/spring-rest-h2-z3solver/src/test/java/com/foo/spring/rest/h2/z3solver/Z3SolverController.java @@ -0,0 +1,105 @@ +package com.foo.spring.rest.h2.z3solver; + +import kotlin.random.Random; +import org.evomaster.client.java.controller.InstrumentedSutStarter; +import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType; +import org.evomaster.client.java.sql.DbSpecification; +import org.hibernate.dialect.H2Dialect; +import org.springframework.boot.SpringApplication; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class Z3SolverController extends SpringController { + + private static final String CREATE_TABLES_SQL = "CREATE TABLE products (\n" + + " id INTEGER NOT NULL,\n" + + " name VARCHAR(255) NOT NULL,\n" + + " price DECIMAL(10,2) NOT NULL,\n" + + " PRIMARY KEY (id)\n" + + ");"; + + public Z3SolverController() { + this(Z3SolverApplication.class); + } + + public static void main(String[] args) { + Z3SolverController controller = new Z3SolverController(); + controller.setControllerPort(40100); + InstrumentedSutStarter starter = new InstrumentedSutStarter(controller); + starter.start(); + } + + static { + /* + * To avoid issues with non-determinism checks (in particular in the handling of taint-analysis), + * we must disable the cache in H2 + */ + System.setProperty("h2.objectCache", "false"); + } + + protected Connection sqlConnection; + + protected Z3SolverController(Class applicationClass) { + super(applicationClass); + } + + @Override + public String startSut() { + + // lot of a problem if using same H2 instance. see: + // https://github.com/h2database/h2database/issues/227 + int rand = Random.Default.nextInt(); + + ctx = SpringApplication.run(applicationClass, "--server.port=0", + "--spring.datasource.url=jdbc:h2:mem:testdb_" + rand + ";DB_CLOSE_DELAY=-1;", + "--spring.jpa.database-platform=" + H2Dialect.class.getName(), + "--spring.datasource.username=sa", + "--spring.datasource.password", + "--spring.jpa.properties.hibernate.show_sql=true"); + + if (sqlConnection != null) { + try { + sqlConnection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + JdbcTemplate jdbc = ctx.getBean(JdbcTemplate.class); + + try { + sqlConnection = Objects.requireNonNull(jdbc.getDataSource()).getConnection(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + // execute create table + try { + createTables(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + return "http://localhost:" + getSutPort(); + } + + private void createTables() throws SQLException { + PreparedStatement stmt = sqlConnection.prepareStatement(CREATE_TABLES_SQL); + stmt.execute(); + } + + @Override + public void stopSut() { + super.stopSut(); + } + + @Override + public List getDbSpecifications() { + return Collections.singletonList(new DbSpecification(DatabaseType.H2, sqlConnection)); + } +} diff --git a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/SpringTestBase.java b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/SpringTestBase.java new file mode 100644 index 0000000000..315f93450c --- /dev/null +++ b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/SpringTestBase.java @@ -0,0 +1,12 @@ +package org.evomaster.e2etests.spring.h2.z3solver; + +import org.evomaster.client.java.controller.EmbeddedSutController; +import org.evomaster.e2etests.utils.RestTestBase; + +public class SpringTestBase extends RestTestBase { + + protected static void initClass(EmbeddedSutController controller) throws Exception { + + RestTestBase.initClass(controller); + } +} \ No newline at end of file diff --git a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java new file mode 100644 index 0000000000..6ea194ba4e --- /dev/null +++ b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java @@ -0,0 +1,46 @@ +package org.evomaster.e2etests.spring.h2.z3solver; + +import com.foo.spring.rest.h2.z3solver.Z3SolverController; +import org.evomaster.core.problem.rest.HttpVerb; +import org.evomaster.core.problem.rest.RestIndividual; +import org.evomaster.core.search.Solution; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class Z3SolverEMTest extends SpringTestBase { + + @BeforeAll + public static void initClass() throws Exception { + + SpringTestBase.initClass(new Z3SolverController()); + } + + @Test + public void testRunEM() throws Throwable { + + runTestHandlingFlakyAndCompilation( + "Z3SolverEM", + "com.foo.spring.rest.h2.z3solver.Z3SolverEvoMaster", + 2, + (args) -> { + args.add("--enableWeightBasedMutationRateSelectionForGene"); + args.add("false"); + args.add("--generateSqlDataWithSearch"); + args.add("false"); + args.add("--generateSqlDataWithDSE"); + args.add("true"); + + Solution solution = initAndRun(args); + + assertFalse(solution.getIndividuals().isEmpty()); + +// assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products", null); +// assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products", null); + + assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-1", null); + assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-1", null); + }); + } +} diff --git a/e2e-tests/spring-rest-h2-z3solver/target/test-classes/META-INF/main.kotlin_module b/e2e-tests/spring-rest-h2-z3solver/target/test-classes/META-INF/main.kotlin_module new file mode 100644 index 0000000000000000000000000000000000000000..3aa63618ce3a770e72020d4f312e3de7744d8bea GIT binary patch literal 24 YcmZQzU|?ooU| Date: Sun, 6 Oct 2024 16:29:37 -0300 Subject: [PATCH 03/26] Remove target folder --- .../spring/h2/z3solver/Z3SolverEMTest.java | 2 +- .../test-classes/META-INF/main.kotlin_module | Bin 24 -> 0 bytes .../target/tmp/smt2_1728173160781.smt2 | 6 ------ .../target/tmp/smt2_1728173246572.smt2 | 6 ------ .../target/tmp/smt2_1728173289994.smt2 | 6 ------ .../target/tmp/smt2_1728173329155.smt2 | 6 ------ .../target/tmp/smt2_1728173425124.smt2 | 6 ------ .../target/tmp/smt2_1728173459579.smt2 | 6 ------ .../target/tmp/smt2_1728173476186.smt2 | 6 ------ .../target/tmp/smt2_1728173501556.smt2 | 6 ------ .../target/tmp/smt2_1728173591454.smt2 | 6 ------ .../target/tmp/smt2_1728173869812.smt2 | 6 ------ .../target/tmp/smt2_1728231295071.smt2 | 6 ------ .../target/tmp/smt2_1728231594731.smt2 | 6 ------ .../target/tmp/smt2_1728231656914.smt2 | 6 ------ .../target/tmp/smt2_1728231728587.smt2 | 6 ------ .../target/tmp/smt2_1728231868575.smt2 | 6 ------ .../target/tmp/smt2_1728231873748.smt2 | 6 ------ .../target/tmp/smt2_1728231901619.smt2 | 6 ------ .../target/tmp/smt2_1728231927658.smt2 | 6 ------ .../target/tmp/smt2_1728231938421.smt2 | 6 ------ .../target/tmp/smt2_1728231962167.smt2 | 6 ------ .../target/tmp/smt2_1728231997213.smt2 | 6 ------ .../target/tmp/smt2_1728232111216.smt2 | 6 ------ .../target/tmp/smt2_1728232142937.smt2 | 6 ------ .../target/tmp/smt2_1728232153363.smt2 | 6 ------ .../target/tmp/smt2_1728232195966.smt2 | 6 ------ .../target/tmp/smt2_1728232209591.smt2 | 6 ------ .../target/tmp/smt2_1728232250393.smt2 | 6 ------ .../target/tmp/smt2_1728232273824.smt2 | 6 ------ .../target/tmp/smt2_1728232355799.smt2 | 6 ------ .../target/tmp/smt2_1728232378497.smt2 | 6 ------ .../target/tmp/smt2_1728232410272.smt2 | 6 ------ .../target/tmp/smt2_1728232448122.smt2 | 6 ------ .../target/tmp/smt2_1728232487155.smt2 | 6 ------ .../target/tmp/smt2_1728232821350.smt2 | 6 ------ .../target/tmp/smt2_1728232844041.smt2 | 6 ------ .../target/tmp/smt2_1728232923800.smt2 | 6 ------ .../target/tmp/smt2_1728232982915.smt2 | 6 ------ .../target/tmp/smt2_1728233029968.smt2 | 6 ------ .../target/tmp/smt2_1728233129184.smt2 | 6 ------ .../target/tmp/smt2_1728233129347.smt2 | 6 ------ .../target/tmp/smt2_1728233397647.smt2 | 6 ------ .../target/tmp/smt2_1728237189554.smt2 | 6 ------ .../target/tmp/smt2_1728237257557.smt2 | 6 ------ .../target/tmp/smt2_1728238235379.smt2 | 6 ------ .../target/tmp/smt2_1728239044342.smt2 | 6 ------ .../target/tmp/smt2_1728239153274.smt2 | 6 ------ .../target/tmp/smt2_1728239730052.smt2 | 6 ------ .../target/tmp/smt2_1728240339346.smt2 | 6 ------ .../target/tmp/smt2_1728241054871.smt2 | 6 ------ .../target/tmp/smt2_1728241384558.smt2 | 6 ------ .../target/tmp/smt2_1728241404507.smt2 | 6 ------ .../target/tmp/smt2_1728241426208.smt2 | 6 ------ .../target/tmp/smt2_1728241501798.smt2 | 6 ------ .../target/tmp/smt2_1728241535868.smt2 | 6 ------ .../target/tmp/smt2_1728241568774.smt2 | 6 ------ .../target/tmp/smt2_1728241762177.smt2 | 6 ------ .../target/tmp/smt2_1728241786780.smt2 | 6 ------ .../target/tmp/smt2_1728241830524.smt2 | 6 ------ .../target/tmp/smt2_1728241982798.smt2 | 6 ------ 61 files changed, 1 insertion(+), 355 deletions(-) delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/test-classes/META-INF/main.kotlin_module delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173160781.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173246572.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173289994.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173329155.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173425124.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173459579.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173476186.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173501556.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173591454.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728173869812.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231295071.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231594731.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231656914.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231728587.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231868575.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231873748.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231901619.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231927658.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231938421.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231962167.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728231997213.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232111216.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232142937.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232153363.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232195966.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232209591.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232250393.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232273824.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232355799.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232378497.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232410272.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232448122.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232487155.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232821350.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232844041.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232923800.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728232982915.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728233029968.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728233129184.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728233129347.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728233397647.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728237189554.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728237257557.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728238235379.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728239044342.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728239153274.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728239730052.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728240339346.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241054871.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241384558.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241404507.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241426208.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241501798.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241535868.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241568774.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241762177.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241786780.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241830524.smt2 delete mode 100644 e2e-tests/spring-rest-h2-z3solver/target/tmp/smt2_1728241982798.smt2 diff --git a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java index 6ea194ba4e..5137efc0ca 100644 --- a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java +++ b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java @@ -40,7 +40,7 @@ public void testRunEM() throws Throwable { // assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products", null); assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-1", null); - assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-1", null); +// assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-1", null); }); } } diff --git a/e2e-tests/spring-rest-h2-z3solver/target/test-classes/META-INF/main.kotlin_module b/e2e-tests/spring-rest-h2-z3solver/target/test-classes/META-INF/main.kotlin_module deleted file mode 100644 index 3aa63618ce3a770e72020d4f312e3de7744d8bea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 YcmZQzU|?ooU| Date: Sun, 6 Oct 2024 16:39:00 -0300 Subject: [PATCH 04/26] Add target to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 40a5431c5e..77f4800ff4 100644 --- a/.gitignore +++ b/.gitignore @@ -123,6 +123,7 @@ Migrations/ /e2e-tests/spring-rest-mysql-column-types/target/ /e2e-tests/spring-rest-postgres-column-types/target/ /e2e-tests/spring-rest-h2-column-types/target/ +/e2e-tests/spring-rest-h2-z3solver/target/ /test-old-libraries/target/ /e2e-tests/spring-web/target/ /e2e-tests/spring-rest-mongo/target/ From 641bbaf5109340234abf78adcc61e4af4ecf02b7 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Tue, 8 Oct 2024 21:15:12 -0300 Subject: [PATCH 05/26] Working test --- .../main/kotlin/org/evomaster/core/Main.kt | 1 + .../api/service/ApiWsStructureMutator.kt | 12 +++-- .../core/solver/DbConstraintSolver.kt | 3 +- .../core/solver/SMTLibZ3DbConstraintSolver.kt | 46 +++++++++---------- .../solver/SMTLibZ3DbConstraintSolverTest.kt | 12 ++--- .../spring/h2/z3solver/Z3SolverEMTest.java | 6 +-- 6 files changed, 39 insertions(+), 41 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/Main.kt b/core/src/main/kotlin/org/evomaster/core/Main.kt index 0730c374a9..c4785f8b37 100644 --- a/core/src/main/kotlin/org/evomaster/core/Main.kt +++ b/core/src/main/kotlin/org/evomaster/core/Main.kt @@ -2,6 +2,7 @@ package org.evomaster.core import com.google.inject.Injector import com.google.inject.Key +import com.google.inject.Provides import com.google.inject.TypeLiteral import com.netflix.governator.guice.LifecycleInjector import org.evomaster.client.java.controller.api.dto.ControllerInfoDto diff --git a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt index 4e75a91668..c5d2a8be15 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt @@ -47,6 +47,9 @@ abstract class ApiWsStructureMutator : StructureMutator() { @Inject protected lateinit var harvestResponseHandler: HarvestActualHttpWsResponseHandler + @Inject + protected lateinit var z3Solver: SMTLibZ3DbConstraintSolver + override fun addAndHarvestExternalServiceActions( individual: EvaluatedIndividual<*>, /** @@ -303,23 +306,22 @@ abstract class ApiWsStructureMutator : StructureMutator() { } if (config.generateSqlDataWithDSE) { - return handleDSE(sampler, failedWhereQueries) + return handleDSE(ind, sampler, failedWhereQueries) } return mutableListOf() } - private fun handleDSE(sampler: ApiWsSampler, failedWhereQueries: List): MutableList> { + private fun handleDSE(ind: T, sampler: ApiWsSampler, failedWhereQueries: List): MutableList> { // TODO: Use one solver, instead of creating one each time? - val resourcesFolder = System.getProperty("user.dir") + "/target/tmp"; val schemaDto = sampler.sqlInsertBuilder?.schemaDto ?: throw IllegalStateException("No DB schema is available") - val solver = SMTLibZ3DbConstraintSolver(schemaDto, resourcesFolder, 1) val newActions = mutableListOf>() for (query in failedWhereQueries) { - val newActionsForQuery = solver.solve(query) + val newActionsForQuery = z3Solver.solve(schemaDto, query) newActions.addAll(mutableListOf(newActionsForQuery)) + ind.addInitializingDbActions(actions = newActionsForQuery) } return newActions diff --git a/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt index 20ed170d42..977d565602 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt @@ -1,5 +1,6 @@ package org.evomaster.core.solver +import org.evomaster.client.java.controller.api.dto.database.schema.DbSchemaDto import org.evomaster.core.sql.SqlAction /** @@ -12,5 +13,5 @@ interface DbConstraintSolver : AutoCloseable { * Solves the given constraints and returns the Db Gene to insert in the database * @return a list of SQLAction with the inserts in the db for the given constraints */ - fun solve(sqlQuery: String): List + fun solve(schemaDto: DbSchemaDto, sqlQuery: String, numberOfRows: Int = 1): List } diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index 9b941229e8..6db664c7f3 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -33,13 +33,8 @@ import java.util.* * then executes Z3 to get values and returns the necessary list of SqlActions * to satisfy the query. */ -class SMTLibZ3DbConstraintSolver( - private val schemaDto: DbSchemaDto, // Database schema - private val resourcesFolder: String, // Folder for temporary resources - numberOfRows: Int = 2 // Number of rows to generate -) : DbConstraintSolver { - - private val generator: SmtLibGenerator = SmtLibGenerator(schemaDto, numberOfRows) +class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { + private val resourcesFolder = System.getProperty("user.dir") + "/target/tmp"; private val executor: Z3DockerExecutor = Z3DockerExecutor(resourcesFolder) /** @@ -56,13 +51,16 @@ class SMTLibZ3DbConstraintSolver( * @param sqlQuery The SQL query to solve. * @return A list of SQL actions that can be executed to satisfy the query. */ - override fun solve(sqlQuery: String): List { + override fun solve(schemaDto: DbSchemaDto, sqlQuery: String, numberOfRows: Int): List { + // TODO: Use memoized, if it's the same schema and query, return the same result and don't do any calculation + + val generator = SmtLibGenerator(schemaDto, numberOfRows) val queryStatement = parseStatement(sqlQuery) // Parse SQL query - val smtLib = this.generator.generateSMT(queryStatement) // Generate SMTLib problem + val smtLib = generator.generateSMT(queryStatement) // Generate SMTLib problem val fileName = storeToTmpFile(smtLib) // Store SMTLib to a temporary file val z3Response = executor.solveFromFile(fileName) // Solve using Z3 - return toSqlActionList(z3Response) // Convert Z3 response to SQL actions + return toSqlActionList(schemaDto, z3Response) // Convert Z3 response to SQL actions } /** @@ -85,7 +83,7 @@ class SMTLibZ3DbConstraintSolver( * @param z3Response The response from Z3. * @return A list of SQL actions. */ - private fun toSqlActionList(z3Response: Optional>): List { + private fun toSqlActionList(schemaDto: DbSchemaDto, z3Response: Optional>): List { if (!z3Response.isPresent) { return emptyList() // Return an empty list if no response } @@ -102,30 +100,28 @@ class SMTLibZ3DbConstraintSolver( // Create the list of genes with the values val genes = mutableListOf() for (columnName in columns.fields) { + var gene: Gene = IntegerGene(columnName, 0) when (val columnValue = columns.getField(columnName)) { is StringValue -> { - if (isBoolean(table, columnName)) { - val gene = BooleanGene(columnName, toBoolean(columnValue.value)) - genes.add(gene) + if (isBoolean(schemaDto, table, columnName)) { + gene = BooleanGene(columnName, toBoolean(columnValue.value)) } else { - val gene = StringGene(columnName, columnValue.value) - genes.add(gene) + gene = StringGene(columnName, columnValue.value) } } is LongValue -> { if (isTimestamp(table, columnName)) { - val gene = LongGene(columnName, columnValue.value.toLong()) - genes.add(gene) + gene = LongGene(columnName, columnValue.value.toLong()) } else { - val gene = IntegerGene(columnName, columnValue.value.toInt()) - genes.add(gene) + gene = IntegerGene(columnName, columnValue.value.toInt()) } } is RealValue -> { - val gene = DoubleGene(columnName, columnValue.value) - genes.add(gene) + gene = DoubleGene(columnName, columnValue.value) } } + gene.markAllAsInitialized() + genes.add(gene) } val sqlAction = SqlAction(table, table.columns, -1, genes.toList()) @@ -139,7 +135,7 @@ class SMTLibZ3DbConstraintSolver( return value.equals("True", ignoreCase = true) } - private fun isBoolean(table: Table, columnName: String?): Boolean { + private fun isBoolean(schemaDto: DbSchemaDto, table: Table, columnName: String?): Boolean { val col = schemaDto.tables.first { it.name == table.name }.columns.first { it.name == columnName } return col.type == "BOOLEAN" } @@ -171,7 +167,7 @@ class SMTLibZ3DbConstraintSolver( ?: throw RuntimeException("Table not found: $tableName") return Table( tableDto.name, - findColumns(tableDto), // Convert columns from DTO + findColumns(schema, tableDto), // Convert columns from DTO findForeignKeys(tableDto) // TODO: Implement this method ) } @@ -182,7 +178,7 @@ class SMTLibZ3DbConstraintSolver( * @param tableDto The table DTO containing column definitions. * @return A set of Column objects. */ - private fun findColumns(tableDto: TableDto): Set { + private fun findColumns(schemaDto: DbSchemaDto, tableDto: TableDto): Set { return tableDto.columns.map { columnDto -> toColumnFromDto(columnDto, schemaDto.databaseType) }.toSet() diff --git a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt index 9d47c46c0f..99a9273c40 100644 --- a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt @@ -2,6 +2,7 @@ package org.evomaster.core.solver import net.sf.jsqlparser.JSQLParserException import org.apache.commons.io.FileUtils +import org.evomaster.client.java.controller.api.dto.database.schema.DbSchemaDto import org.evomaster.client.java.sql.SchemaExtractor import org.evomaster.client.java.sql.SqlScriptRunner import org.evomaster.core.search.gene.Gene @@ -27,18 +28,16 @@ class SMTLibZ3DbConstraintSolverTest { companion object { private lateinit var solver: SMTLibZ3DbConstraintSolver private lateinit var connection: Connection - private lateinit var resourcesFolder: String + private lateinit var schemaDto: DbSchemaDto @JvmStatic @BeforeAll fun setup() { connection = DriverManager.getConnection("jdbc:h2:mem:constraint_test", "sa", "") SqlScriptRunner.execCommand(connection, "CREATE TABLE users(id bigint generated by default as identity primary key, name varchar(255), age int, points int);\n") - val schemaDto = SchemaExtractor.extract(connection) + schemaDto = SchemaExtractor.extract(connection) - resourcesFolder = tmpResourcesFolder() - createFolder(resourcesFolder) - solver = SMTLibZ3DbConstraintSolver(schemaDto, resourcesFolder) + solver = SMTLibZ3DbConstraintSolver() } @JvmStatic @@ -49,7 +48,6 @@ class SMTLibZ3DbConstraintSolverTest { if (this::solver.isInitialized) { solver.close() } - removeFolder(resourcesFolder) } private fun tmpResourcesFolder(): String { @@ -83,7 +81,7 @@ class SMTLibZ3DbConstraintSolverTest { @Throws(JSQLParserException::class) fun selectFromUsers() { - val newActions = solver.solve("SELECT * FROM Users;") + val newActions = solver.solve(schemaDto, "SELECT * FROM Users;", 2) assertEquals(2, newActions.size) diff --git a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java index 5137efc0ca..a62f333658 100644 --- a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java +++ b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java @@ -25,8 +25,8 @@ public void testRunEM() throws Throwable { "com.foo.spring.rest.h2.z3solver.Z3SolverEvoMaster", 2, (args) -> { - args.add("--enableWeightBasedMutationRateSelectionForGene"); - args.add("false"); + args.add("--heuristicsForSQL"); + args.add("true"); args.add("--generateSqlDataWithSearch"); args.add("false"); args.add("--generateSqlDataWithDSE"); @@ -40,7 +40,7 @@ public void testRunEM() throws Throwable { // assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products", null); assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-1", null); -// assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-1", null); + assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-1", null); }); } } From 885eb9e0825675297ec7b94c2aeb44d9c0fc2bbc Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Sun, 13 Oct 2024 22:52:54 -0300 Subject: [PATCH 06/26] Discard unncessary changes --- .../database/execution/SqlExecutionsDto.java | 10 ------- .../client/java/sql/internal/SqlHandler.java | 5 ---- .../main/kotlin/org/evomaster/core/Main.kt | 3 -- .../api/service/ApiWsStructureMutator.kt | 30 +++++++++---------- 4 files changed, 15 insertions(+), 33 deletions(-) diff --git a/client-java/sql-dto/src/main/java/org/evomaster/client/java/controller/api/dto/database/execution/SqlExecutionsDto.java b/client-java/sql-dto/src/main/java/org/evomaster/client/java/controller/api/dto/database/execution/SqlExecutionsDto.java index 6c26e67e6d..c64b8904e9 100644 --- a/client-java/sql-dto/src/main/java/org/evomaster/client/java/controller/api/dto/database/execution/SqlExecutionsDto.java +++ b/client-java/sql-dto/src/main/java/org/evomaster/client/java/controller/api/dto/database/execution/SqlExecutionsDto.java @@ -60,16 +60,6 @@ public class SqlExecutionsDto { */ public Map> failedWhere = new HashMap<>(); - /** - * Every time there is a WHERE clause which "failed" (ie, resulted in false), - * we keep track of which tables/columns where involved in determining the - * result of the WHERE. - * If there is no WHERE, but still no data was returned, we consider it - * as a failed WHERE - * The list includes the SQL queries that failed - */ - public List failedWhereQueries = new ArrayList<>(); - /** * The total Number of SQL commands (e.g., SELECT and UPDATE) executed */ diff --git a/client-java/sql/src/main/java/org/evomaster/client/java/sql/internal/SqlHandler.java b/client-java/sql/src/main/java/org/evomaster/client/java/sql/internal/SqlHandler.java index 240a1689b6..e2d3e0989b 100644 --- a/client-java/sql/src/main/java/org/evomaster/client/java/sql/internal/SqlHandler.java +++ b/client-java/sql/src/main/java/org/evomaster/client/java/sql/internal/SqlHandler.java @@ -48,7 +48,6 @@ public class SqlHandler { private final Map> updatedData; private final Map> insertedData; private final Map> failedWhere; - private final List failedWhereQueries; private final List deletedData; private final List executedSqlCommands; @@ -80,7 +79,6 @@ public SqlHandler(TaintHandler taintHandler) { updatedData = new ConcurrentHashMap<>(); insertedData = new ConcurrentHashMap<>(); failedWhere = new ConcurrentHashMap<>(); - failedWhereQueries = new CopyOnWriteArrayList<>(); deletedData = new CopyOnWriteArrayList<>(); executedSqlCommands = new CopyOnWriteArrayList<>(); @@ -96,7 +94,6 @@ public void reset() { updatedData.clear(); insertedData.clear(); failedWhere.clear(); - failedWhereQueries.clear(); deletedData.clear(); executedSqlCommands.clear(); @@ -158,7 +155,6 @@ public SqlExecutionsDto getExecutionDto() { SqlExecutionsDto sqlExecutionsDto = new SqlExecutionsDto(); sqlExecutionsDto.queriedData.putAll(queriedData); sqlExecutionsDto.failedWhere.putAll(failedWhere); - sqlExecutionsDto.failedWhereQueries.addAll(failedWhereQueries); sqlExecutionsDto.insertedData.putAll(insertedData); sqlExecutionsDto.updatedData.putAll(updatedData); sqlExecutionsDto.deletedData.addAll(deletedData); @@ -243,7 +239,6 @@ private SqlDistanceWithMetrics computeDistance(String sqlCommand, if (dist.sqlDistance > 0) { mergeNewData(failedWhere, columns); - failedWhereQueries.add(sqlCommand); } return dist; diff --git a/core/src/main/kotlin/org/evomaster/core/Main.kt b/core/src/main/kotlin/org/evomaster/core/Main.kt index c4785f8b37..c4a17c56aa 100644 --- a/core/src/main/kotlin/org/evomaster/core/Main.kt +++ b/core/src/main/kotlin/org/evomaster/core/Main.kt @@ -2,7 +2,6 @@ package org.evomaster.core import com.google.inject.Injector import com.google.inject.Key -import com.google.inject.Provides import com.google.inject.TypeLiteral import com.netflix.governator.guice.LifecycleInjector import org.evomaster.client.java.controller.api.dto.ControllerInfoDto @@ -13,8 +12,6 @@ import org.evomaster.core.AnsiColor.Companion.inRed import org.evomaster.core.AnsiColor.Companion.inYellow import org.evomaster.core.config.ConfigProblemException import org.evomaster.core.logging.LoggingUtil -import org.evomaster.core.output.OutputFormat -import org.evomaster.core.output.Termination import org.evomaster.core.output.TestSuiteSplitter import org.evomaster.core.output.clustering.SplitResult import org.evomaster.core.output.service.TestSuiteWriter diff --git a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt index c5d2a8be15..0dc051277f 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt @@ -47,6 +47,7 @@ abstract class ApiWsStructureMutator : StructureMutator() { @Inject protected lateinit var harvestResponseHandler: HarvestActualHttpWsResponseHandler + // TODO: This should only be initialized when config.generateSqlDataWithDSE is enabled @Inject protected lateinit var z3Solver: SMTLibZ3DbConstraintSolver @@ -312,21 +313,6 @@ abstract class ApiWsStructureMutator : StructureMutator() { return mutableListOf() } - private fun handleDSE(ind: T, sampler: ApiWsSampler, failedWhereQueries: List): MutableList> { - // TODO: Use one solver, instead of creating one each time? - val schemaDto = sampler.sqlInsertBuilder?.schemaDto - ?: throw IllegalStateException("No DB schema is available") - - val newActions = mutableListOf>() - for (query in failedWhereQueries) { - val newActionsForQuery = z3Solver.solve(schemaDto, query) - newActions.addAll(mutableListOf(newActionsForQuery)) - ind.addInitializingDbActions(actions = newActionsForQuery) - } - - return newActions - } - private fun handleSearch( ind: T, sampler: ApiWsSampler, @@ -409,6 +395,20 @@ abstract class ApiWsStructureMutator : StructureMutator() { return addedSqlInsertions } + private fun handleDSE(ind: T, sampler: ApiWsSampler, failedWhereQueries: List): MutableList> { + val schemaDto = sampler.sqlInsertBuilder?.schemaDto + ?: throw IllegalStateException("No DB schema is available") + + val newActions = mutableListOf>() + for (query in failedWhereQueries) { + val newActionsForQuery = z3Solver.solve(schemaDto, query) + newActions.addAll(mutableListOf(newActionsForQuery)) + ind.addInitializingDbActions(actions = newActionsForQuery) + } + + return newActions + } + private fun handleFailedFind( ind: T, ff: List, From dae59cb3bd6cc3fa4a69d3dafcdee16dc2ef2c38 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Sun, 13 Oct 2024 23:17:43 -0300 Subject: [PATCH 07/26] Format code --- .../core/solver/SMTLibZ3DbConstraintSolver.kt | 39 +++++++++++-------- .../solver/SMTLibZ3DbConstraintSolverTest.kt | 28 ------------- .../spring/h2/z3solver/Z3SolverEMTest.java | 5 ++- 3 files changed, 26 insertions(+), 46 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index 6db664c7f3..3b818229e8 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -3,6 +3,7 @@ package org.evomaster.core.solver import net.sf.jsqlparser.JSQLParserException import net.sf.jsqlparser.parser.CCJSqlParserUtil import net.sf.jsqlparser.statement.Statement +import org.apache.commons.io.FileUtils import org.evomaster.client.java.controller.api.dto.database.schema.ColumnDto import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType import org.evomaster.client.java.controller.api.dto.database.schema.DbSchemaDto @@ -21,6 +22,7 @@ import org.evomaster.core.sql.schema.Table import org.evomaster.solver.Z3DockerExecutor import org.evomaster.solver.smtlib.SMTLib import org.evomaster.solver.smtlib.value.* +import java.io.File import java.io.IOException import java.nio.charset.StandardCharsets import java.nio.file.Files @@ -42,6 +44,11 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { */ override fun close() { executor.close() + try { + FileUtils.cleanDirectory(File(resourcesFolder)) + } catch (e: IOException) { + throw RuntimeException("Error cleaning up resources folder", e) + } } /** @@ -55,12 +62,12 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { // TODO: Use memoized, if it's the same schema and query, return the same result and don't do any calculation val generator = SmtLibGenerator(schemaDto, numberOfRows) - val queryStatement = parseStatement(sqlQuery) // Parse SQL query - val smtLib = generator.generateSMT(queryStatement) // Generate SMTLib problem - val fileName = storeToTmpFile(smtLib) // Store SMTLib to a temporary file - val z3Response = executor.solveFromFile(fileName) // Solve using Z3 + val queryStatement = parseStatement(sqlQuery) + val smtLib = generator.generateSMT(queryStatement) + val fileName = storeToTmpFile(smtLib) + val z3Response = executor.solveFromFile(fileName) - return toSqlActionList(schemaDto, z3Response) // Convert Z3 response to SQL actions + return toSqlActionList(schemaDto, z3Response) } /** @@ -71,9 +78,9 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { */ private fun parseStatement(sqlQuery: String): Statement { return try { - CCJSqlParserUtil.parse(sqlQuery) // Parse query using JSQLParser + CCJSqlParserUtil.parse(sqlQuery) } catch (e: JSQLParserException) { - throw RuntimeException(e) // Rethrow exception if parsing fails + throw RuntimeException(e) } } @@ -85,13 +92,13 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { */ private fun toSqlActionList(schemaDto: DbSchemaDto, z3Response: Optional>): List { if (!z3Response.isPresent) { - return emptyList() // Return an empty list if no response + return emptyList() } val actions = mutableListOf() for (row in z3Response.get()) { - val tableName = getTableName(row.key) // Extract table name from the key + val tableName = getTableName(row.key) val columns = row.value as StructValue // Find table from schema and create SQL actions @@ -103,17 +110,17 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { var gene: Gene = IntegerGene(columnName, 0) when (val columnValue = columns.getField(columnName)) { is StringValue -> { - if (isBoolean(schemaDto, table, columnName)) { - gene = BooleanGene(columnName, toBoolean(columnValue.value)) + gene = if (isBoolean(schemaDto, table, columnName)) { + BooleanGene(columnName, toBoolean(columnValue.value)) } else { - gene = StringGene(columnName, columnValue.value) + StringGene(columnName, columnValue.value) } } is LongValue -> { - if (isTimestamp(table, columnName)) { - gene = LongGene(columnName, columnValue.value.toLong()) + gene = if (isTimestamp(table, columnName)) { + LongGene(columnName, columnValue.value.toLong()) } else { - gene = IntegerGene(columnName, columnValue.value.toInt()) + IntegerGene(columnName, columnValue.value.toInt()) } } is RealValue -> { @@ -267,7 +274,7 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { } /** - * Stores the SMTLib problem to a file in the resources folder. + * Stores the SMTLib problem to a file in the resources' folder. * * @param smtLib The SMTLib problem. * @return The filename of the stored SMTLib problem. diff --git a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt index 99a9273c40..198fec0a78 100644 --- a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt @@ -1,7 +1,6 @@ package org.evomaster.core.solver import net.sf.jsqlparser.JSQLParserException -import org.apache.commons.io.FileUtils import org.evomaster.client.java.controller.api.dto.database.schema.DbSchemaDto import org.evomaster.client.java.sql.SchemaExtractor import org.evomaster.client.java.sql.SqlScriptRunner @@ -13,14 +12,9 @@ import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test -import java.io.File -import java.io.IOException -import java.nio.file.Files -import java.nio.file.Paths import java.sql.Connection import java.sql.DriverManager import java.sql.SQLException -import java.time.Instant class SMTLibZ3DbConstraintSolverTest { @@ -49,28 +43,6 @@ class SMTLibZ3DbConstraintSolverTest { solver.close() } } - - private fun tmpResourcesFolder(): String { - val instant = Instant.now().epochSecond.toString() - val tmpFolderPath = "tmp-solver$instant/" - return System.getProperty("user.dir") + "/src/test/resources/" + tmpFolderPath - } - - private fun createFolder(folderPath: String) { - try { - Files.createDirectories(Paths.get(folderPath)) - } catch (e: IOException) { - throw RuntimeException("Error creating tmp folder '$folderPath'. ", e) - } - } - - private fun removeFolder(folderPath: String) { - try { - FileUtils.deleteDirectory(File(folderPath)) - } catch (e: IOException) { - throw RuntimeException("Error deleting tmp folder '$folderPath'. ", e) - } - } } /** diff --git a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java index a62f333658..7702bd2bce 100644 --- a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java +++ b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java @@ -36,8 +36,9 @@ public void testRunEM() throws Throwable { assertFalse(solution.getIndividuals().isEmpty()); -// assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products", null); -// assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products", null); + // TODO: Add support for queries with empty WHERE in the select + // assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products", null); + // assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products", null); assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-1", null); assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-1", null); From 8ba8ba896d663205cfdc5dde7d0b7b995157c0dd Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Mon, 14 Oct 2024 01:20:11 -0300 Subject: [PATCH 08/26] Add support for more than one --- .../api/service/ApiWsStructureMutator.kt | 2 ++ .../core/solver/SMTConditionVisitor.kt | 10 ++++-- .../core/solver/SMTLibZ3DbConstraintSolver.kt | 9 +++++- .../rest/h2/z3solver/Z3SolverTypesRest.java | 31 ++++++++++++++++++- .../spring/h2/z3solver/Z3SolverEMTest.java | 9 +++++- .../evomaster/solver/Z3DockerExecutor.java | 2 +- 6 files changed, 56 insertions(+), 7 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt index 0dc051277f..b989f6e495 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt @@ -48,6 +48,8 @@ abstract class ApiWsStructureMutator : StructureMutator() { protected lateinit var harvestResponseHandler: HarvestActualHttpWsResponseHandler // TODO: This should only be initialized when config.generateSqlDataWithDSE is enabled + // TODO: Also, z3solver.close() should be invoked + // when the application is shutting down to stop the Docker container and clean the tmp folder @Inject protected lateinit var z3Solver: SMTLibZ3DbConstraintSolver diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTConditionVisitor.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTConditionVisitor.kt index 62aecc50ae..21517c100e 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTConditionVisitor.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTConditionVisitor.kt @@ -91,9 +91,13 @@ class SMTConditionVisitor( return when { operand.contains(".") -> { // Handle column references with aliases val parts = operand.split(".") - val tableName = tableAliases[parts[0]] ?: defaultTableName - val columnName = parts[parts.lastIndex] - getColumnReference(tableName, columnName) + if (tableAliases.containsKey(parts[0])) { + val tableName = tableAliases[parts[0]] ?: defaultTableName + val columnName = parts[parts.lastIndex] + getColumnReference(tableName, columnName) + } else { + operand + } } isAColumn(operand) -> { // Handle direct column references getColumnReference(defaultTableName, operand) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index 3b818229e8..0351cf3f63 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -13,6 +13,7 @@ import org.evomaster.core.search.gene.Gene import org.evomaster.core.search.gene.numeric.DoubleGene import org.evomaster.core.search.gene.numeric.IntegerGene import org.evomaster.core.search.gene.numeric.LongGene +import org.evomaster.core.search.gene.sql.SqlPrimaryKeyGene import org.evomaster.core.search.gene.string.StringGene import org.evomaster.core.sql.SqlAction import org.evomaster.core.sql.schema.Column @@ -38,6 +39,7 @@ import java.util.* class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { private val resourcesFolder = System.getProperty("user.dir") + "/target/tmp"; private val executor: Z3DockerExecutor = Z3DockerExecutor(resourcesFolder) + private var idCounter: Long = 0L /** * Closes the Z3 Docker executor and cleans up temporary files. @@ -127,11 +129,16 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { gene = DoubleGene(columnName, columnValue.value) } } + val currentColumn = table.columns.firstOrNull(){ it.name == columnName} + if (currentColumn != null && currentColumn.primaryKey) { + gene = SqlPrimaryKeyGene(columnName, tableName, gene, 1) // Whats uniqueId? + } gene.markAllAsInitialized() genes.add(gene) } - val sqlAction = SqlAction(table, table.columns, -1, genes.toList()) + val sqlAction = SqlAction(table, table.columns, idCounter, genes.toList()) + idCounter++ actions.add(sqlAction) } diff --git a/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverTypesRest.java b/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverTypesRest.java index f7d15aa5e8..beb89f8216 100644 --- a/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverTypesRest.java +++ b/e2e-tests/spring-rest-h2-z3solver/src/main/java/com/foo/spring/rest/h2/z3solver/Z3SolverTypesRest.java @@ -3,6 +3,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -20,7 +21,7 @@ public class Z3SolverTypesRest { @Autowired private EntityManager em; -// // This fails to load, as when the WHERE clause is empty, it fails to calculate the failedWhere +// // TODO: Fix this. This fails to load, as when the WHERE clause is empty, it fails to calculate the failedWhere // @GetMapping("/products") // public ResponseEntity getEmptyWhere() { // Query query = em.createNativeQuery( @@ -40,6 +41,34 @@ public ResponseEntity getId1() { "select (1) from products where id = 1"); List data = query.getResultList(); + if (data.isEmpty()) { + return ResponseEntity.status(400).build(); + } else { + return ResponseEntity.status(200).build(); + } + } + +// @GetMapping("/products-2/{id}") +// public ResponseEntity getIdNamePrice(@PathVariable("id") Long id) { +// try { +// Query query = em.createNativeQuery("SELECT * FROM products WHERE id = $id" + id); +// List data = query.getResultList(); +// +// if (data.isEmpty()) { +// return ResponseEntity.status(400).build(); +// } else { +// return ResponseEntity.status(200).build(); +// } +// } catch (Exception e) { +// return ResponseEntity.status(400).build(); +// } +// } + + @GetMapping("/products-3") + public ResponseEntity getProductsWithName() { + Query query = em.createNativeQuery("SELECT (1) FROM products WHERE id = 2 AND name = 'Agus' AND price = 10.0"); + List data = query.getResultList(); + if (data.isEmpty()) { return ResponseEntity.status(400).build(); } else { diff --git a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java index 7702bd2bce..8dee21b877 100644 --- a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java +++ b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java @@ -23,7 +23,7 @@ public void testRunEM() throws Throwable { runTestHandlingFlakyAndCompilation( "Z3SolverEM", "com.foo.spring.rest.h2.z3solver.Z3SolverEvoMaster", - 2, + 50, (args) -> { args.add("--heuristicsForSQL"); args.add("true"); @@ -42,6 +42,13 @@ public void testRunEM() throws Throwable { assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-1", null); assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-1", null); + +// // TODO: This is currently not supported +// assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-2/{id}", null); +// assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-2/{id}", null); + + assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-3", null); + assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-3", null); }); } } diff --git a/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java b/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java index 04904622a5..15dc50ecc8 100644 --- a/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java +++ b/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java @@ -62,7 +62,7 @@ public Optional> solveFromFile(String fileName) { // Execute the Z3 solver on the specified file in the container Container.ExecResult result = z3Prover.execInContainer("z3", containerPath + fileName); if (result.getExitCode() != 0) { - throw new RuntimeException("Error executing Z3 solver"); + throw new RuntimeException("Error executing Z3 solver" + result.getStdout()); } String stdout = result.getStdout(); From 9cca01f157e03e014cc50d172ed8b40109a6ac2a Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Mon, 14 Oct 2024 01:28:07 -0300 Subject: [PATCH 09/26] fix gene id --- .../org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt | 3 ++- .../e2etests/spring/h2/z3solver/Z3SolverEMTest.java | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index 0351cf3f63..c38393e99c 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -131,7 +131,8 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { } val currentColumn = table.columns.firstOrNull(){ it.name == columnName} if (currentColumn != null && currentColumn.primaryKey) { - gene = SqlPrimaryKeyGene(columnName, tableName, gene, 1) // Whats uniqueId? + gene = SqlPrimaryKeyGene(columnName, tableName, gene, idCounter) + idCounter++ } gene.markAllAsInitialized() genes.add(gene) diff --git a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java index 8dee21b877..0e264a326c 100644 --- a/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java +++ b/e2e-tests/spring-rest-h2-z3solver/src/test/java/org/evomaster/e2etests/spring/h2/z3solver/Z3SolverEMTest.java @@ -43,9 +43,9 @@ public void testRunEM() throws Throwable { assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-1", null); assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-1", null); -// // TODO: This is currently not supported -// assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-2/{id}", null); -// assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-2/{id}", null); + // TODO: This is currently not supported + // assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-2/{id}", null); + // assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-2/{id}", null); assertHasAtLeastOne(solution, HttpVerb.GET, 400, "/api/h2/z3solver/products-3", null); assertHasAtLeastOne(solution, HttpVerb.GET, 200, "/api/h2/z3solver/products-3", null); From 80a102b2a84360bdf27f45e2b1e85e55a25ec7a2 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Mon, 14 Oct 2024 01:45:56 -0300 Subject: [PATCH 10/26] Fix tests --- .../core/solver/SMTLibZ3DbConstraintSolverTest.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt index 198fec0a78..1f714fea4f 100644 --- a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt @@ -6,6 +6,7 @@ import org.evomaster.client.java.sql.SchemaExtractor import org.evomaster.client.java.sql.SqlScriptRunner import org.evomaster.core.search.gene.Gene import org.evomaster.core.search.gene.numeric.IntegerGene +import org.evomaster.core.search.gene.sql.SqlPrimaryKeyGene import org.evomaster.core.search.gene.string.StringGene import org.evomaster.solver.smtlib.* import org.junit.jupiter.api.AfterAll @@ -64,8 +65,9 @@ class SMTLibZ3DbConstraintSolverTest { for (gene in genesInsert1) { when (gene.name) { "ID" -> { - assertTrue(gene is IntegerGene) - assertEquals(0, (gene as IntegerGene).value) + assertTrue(gene is SqlPrimaryKeyGene) + val child = gene.getViewOfChildren().first() + assertEquals(0, (child as IntegerGene).value) } "NAME" -> { assertTrue(gene is StringGene) @@ -92,8 +94,9 @@ class SMTLibZ3DbConstraintSolverTest { for (gene in genesInsert2) { when (gene.name) { "ID" -> { - assertTrue(gene is IntegerGene) - assertEquals(1, (gene as IntegerGene).value) + assertTrue(gene is SqlPrimaryKeyGene) + val child = gene.getViewOfChildren().first() + assertEquals(1, (child as IntegerGene).value) } "NAME" -> { assertTrue(gene is StringGene) From ca2826b736f368f4c5179db76bb5c6ec04eef7c6 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Fri, 22 Nov 2024 16:29:16 -0300 Subject: [PATCH 11/26] Fix injection --- .../kotlin/org/evomaster/core/BaseModule.kt | 6 +++-- .../core/solver/SMTLibZ3DbConstraintSolver.kt | 24 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/BaseModule.kt b/core/src/main/kotlin/org/evomaster/core/BaseModule.kt index 7493b786ed..d55426f312 100644 --- a/core/src/main/kotlin/org/evomaster/core/BaseModule.kt +++ b/core/src/main/kotlin/org/evomaster/core/BaseModule.kt @@ -14,8 +14,7 @@ import org.evomaster.core.search.service.mutator.MutationWeightControl import org.evomaster.core.search.service.mutator.genemutation.ArchiveGeneMutator import org.evomaster.core.search.tracer.ArchiveMutationTrackService import org.evomaster.core.search.tracer.TrackService - - +import org.evomaster.core.solver.SMTLibZ3DbConstraintSolver /** @@ -84,6 +83,9 @@ class BaseModule(val args: Array, val noTests: Boolean = false) : Abstra bind(ExecutionInfoReporter::class.java) .asEagerSingleton() + bind(SMTLibZ3DbConstraintSolver::class.java) + .asEagerSingleton() + //no longer needed if TestSuiteWriter is moved out? // if(noTests){ // bind(TestCaseWriter::class.java) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index c38393e99c..95add7c8f1 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -1,5 +1,6 @@ package org.evomaster.core.solver +import com.google.inject.Inject import net.sf.jsqlparser.JSQLParserException import net.sf.jsqlparser.parser.CCJSqlParserUtil import net.sf.jsqlparser.statement.Statement @@ -8,6 +9,7 @@ import org.evomaster.client.java.controller.api.dto.database.schema.ColumnDto import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType import org.evomaster.client.java.controller.api.dto.database.schema.DbSchemaDto import org.evomaster.client.java.controller.api.dto.database.schema.TableDto +import org.evomaster.core.EMConfig import org.evomaster.core.search.gene.BooleanGene import org.evomaster.core.search.gene.Gene import org.evomaster.core.search.gene.numeric.DoubleGene @@ -15,6 +17,7 @@ import org.evomaster.core.search.gene.numeric.IntegerGene import org.evomaster.core.search.gene.numeric.LongGene import org.evomaster.core.search.gene.sql.SqlPrimaryKeyGene import org.evomaster.core.search.gene.string.StringGene +import org.evomaster.core.search.service.SearchTimeController import org.evomaster.core.sql.SqlAction import org.evomaster.core.sql.schema.Column import org.evomaster.core.sql.schema.ColumnDataType @@ -29,6 +32,7 @@ import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Paths import java.util.* +import javax.annotation.PostConstruct /** * An SMT solver implementation using Z3 in a Docker container. @@ -37,11 +41,25 @@ import java.util.* * to satisfy the query. */ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { - private val resourcesFolder = System.getProperty("user.dir") + "/target/tmp"; - private val executor: Z3DockerExecutor = Z3DockerExecutor(resourcesFolder) + private val resourcesFolder = System.getProperty("user.dir") + "/target/tmp" + private lateinit var executor: Z3DockerExecutor private var idCounter: Long = 0L - /** + @Inject + private lateinit var config: EMConfig + + @Inject + private lateinit var time: SearchTimeController + + @PostConstruct + private fun postConstruct() { + if (config.generateSqlDataWithDSE) { + executor = Z3DockerExecutor(resourcesFolder); + } + } + + + /** * Closes the Z3 Docker executor and cleans up temporary files. */ override fun close() { From 490ba37d1a3eb68f735a82d477baf19a92377331 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Fri, 22 Nov 2024 17:07:37 -0300 Subject: [PATCH 12/26] Fix conflicts --- .../org/evomaster/core/solver/DbConstraintSolver.kt | 4 ++-- .../core/solver/SMTLibZ3DbConstraintSolver.kt | 10 +++++----- .../core/solver/SMTLibZ3DbConstraintSolverTest.kt | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt index 977d565602..9f4c1b19c5 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt @@ -1,6 +1,6 @@ package org.evomaster.core.solver -import org.evomaster.client.java.controller.api.dto.database.schema.DbSchemaDto +import org.evomaster.client.java.controller.api.dto.database.schema.DbInfoDto import org.evomaster.core.sql.SqlAction /** @@ -13,5 +13,5 @@ interface DbConstraintSolver : AutoCloseable { * Solves the given constraints and returns the Db Gene to insert in the database * @return a list of SQLAction with the inserts in the db for the given constraints */ - fun solve(schemaDto: DbSchemaDto, sqlQuery: String, numberOfRows: Int = 1): List + fun solve(schemaDto: DbInfoDto, sqlQuery: String, numberOfRows: Int = 1): List } diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index de1ce1ff9e..6cb571ed6f 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -59,7 +59,7 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { } - /** + /** * Closes the Z3 Docker executor and cleans up temporary files. */ override fun close() { @@ -78,7 +78,7 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { * @param sqlQuery The SQL query to solve. * @return A list of SQL actions that can be executed to satisfy the query. */ - override fun solve(schemaDto: DbSchemaDto, sqlQuery: String, numberOfRows: Int): List { + override fun solve(schemaDto: DbInfoDto, sqlQuery: String, numberOfRows: Int): List { // TODO: Use memoized, if it's the same schema and query, return the same result and don't do any calculation val generator = SmtLibGenerator(schemaDto, numberOfRows) @@ -110,7 +110,7 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { * @param z3Response The response from Z3. * @return A list of SQL actions. */ - private fun toSqlActionList(schemaDto: DbSchemaDto, z3Response: Optional>): List { + private fun toSqlActionList(schemaDto: DbInfoDto, z3Response: Optional>): List { if (!z3Response.isPresent) { return emptyList() } @@ -168,7 +168,7 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { return value.equals("True", ignoreCase = true) } - private fun isBoolean(schemaDto: DbSchemaDto, table: Table, columnName: String?): Boolean { + private fun isBoolean(schemaDto: DbInfoDto, table: Table, columnName: String?): Boolean { val col = schemaDto.tables.first { it.name == table.name }.columns.first { it.name == columnName } return col.type == "BOOLEAN" } @@ -211,7 +211,7 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { * @param tableDto The table DTO containing column definitions. * @return A set of Column objects. */ - private fun findColumns(schemaDto: DbSchemaDto, tableDto: TableDto): Set { + private fun findColumns(schemaDto: DbInfoDto, tableDto: TableDto): Set { return tableDto.columns.map { columnDto -> toColumnFromDto(columnDto, schemaDto.databaseType) }.toSet() diff --git a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt index cd20c3b5d1..ea18c8874f 100644 --- a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt @@ -1,8 +1,7 @@ package org.evomaster.core.solver import net.sf.jsqlparser.JSQLParserException -import org.evomaster.client.java.sql.SchemaExtractor -import org.apache.commons.io.FileUtils +import org.evomaster.client.java.controller.api.dto.database.schema.DbInfoDto import org.evomaster.client.java.sql.DbInfoExtractor import org.evomaster.client.java.sql.SqlScriptRunner import org.evomaster.core.search.gene.Gene From dcc29f78ec1c044cc48feb04a3e1fc72b1934909 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Sun, 24 Nov 2024 22:31:28 -0300 Subject: [PATCH 13/26] Fix build --- e2e-tests/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e-tests/pom.xml b/e2e-tests/pom.xml index 4186f6fc09..e1c7526539 100644 --- a/e2e-tests/pom.xml +++ b/e2e-tests/pom.xml @@ -26,6 +26,7 @@ spring-rest-postgres-column-types spring-rest-mysql-column-types spring-rest-h2-column-types + spring-rest-h2-z3solver spring-web spring-rest-mongo spring-rest-bb From 585368166e15be69b60812949525d16db9b60145 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Sun, 24 Nov 2024 22:43:53 -0300 Subject: [PATCH 14/26] fix test --- .../org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt | 5 ++++- .../evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index 6cb571ed6f..be3002deb8 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -54,10 +54,13 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { @PostConstruct private fun postConstruct() { if (config.generateSqlDataWithDSE) { - executor = Z3DockerExecutor(resourcesFolder); + initializeExecutor() } } + fun initializeExecutor() { + executor = Z3DockerExecutor(resourcesFolder) + } /** * Closes the Z3 Docker executor and cleans up temporary files. diff --git a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt index ea18c8874f..ebc8b0b0dc 100644 --- a/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolverTest.kt @@ -32,6 +32,7 @@ class SMTLibZ3DbConstraintSolverTest { SqlScriptRunner.execCommand(connection, "CREATE TABLE users(id bigint generated by default as identity primary key, name varchar(255), age int, points int);\n") schemaDto = DbInfoExtractor.extract(connection) solver = SMTLibZ3DbConstraintSolver() + solver.initializeExecutor() } @JvmStatic From 24854329be507c59ab4507acb587b2bd8109a543 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Sun, 24 Nov 2024 22:49:39 -0300 Subject: [PATCH 15/26] Fix version --- e2e-tests/spring-rest-h2-z3solver/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/spring-rest-h2-z3solver/pom.xml b/e2e-tests/spring-rest-h2-z3solver/pom.xml index abff24a451..3b885b05d3 100644 --- a/e2e-tests/spring-rest-h2-z3solver/pom.xml +++ b/e2e-tests/spring-rest-h2-z3solver/pom.xml @@ -5,7 +5,7 @@ org.evomaster evomaster-e2e-tests - 3.2.1-SNAPSHOT + 3.3.1-SNAPSHOT spring-rest-h2-z3solver From 953409ec2c8a87e4af1c84c05cb1583071687c69 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Sun, 24 Nov 2024 22:56:58 -0300 Subject: [PATCH 16/26] Update core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt --- .../core/problem/api/service/ApiWsStructureMutator.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt index b989f6e495..cf25c713d0 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt @@ -47,9 +47,7 @@ abstract class ApiWsStructureMutator : StructureMutator() { @Inject protected lateinit var harvestResponseHandler: HarvestActualHttpWsResponseHandler - // TODO: This should only be initialized when config.generateSqlDataWithDSE is enabled - // TODO: Also, z3solver.close() should be invoked - // when the application is shutting down to stop the Docker container and clean the tmp folder + // TODO: z3solver.close() should be invoked when the application is shutting down to stop the Docker container and clean the tmp folder @Inject protected lateinit var z3Solver: SMTLibZ3DbConstraintSolver From 874722c9ee19f2715518f9dd34218d12a5964b0c Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Thu, 19 Dec 2024 11:27:01 -0300 Subject: [PATCH 17/26] Test something --- .gitignore | 2 +- .../evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt | 7 +++---- .../main/java/org/evomaster/solver/Z3DockerExecutor.java | 4 +++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 87a538f5ef..22b50914a2 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +*.DS_Store /.idea/ .idea/ *.iml @@ -168,7 +169,6 @@ Migrations/ /target/ /wfc/target/ -*.DS_Store /e2e-tests/emb-json/target/ /process_data/ /e2e-tests/spring-rest-multidb/target/ diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index be3002deb8..8e0e5655e4 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -33,6 +33,7 @@ import java.nio.file.Files import java.nio.file.Paths import java.util.* import javax.annotation.PostConstruct +import javax.annotation.PreDestroy /** * An SMT solver implementation using Z3 in a Docker container. @@ -42,15 +43,12 @@ import javax.annotation.PostConstruct */ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { private val resourcesFolder = System.getProperty("user.dir") + "/target/tmp" - private lateinit var executor: Z3DockerExecutor + private lateinit var executor: Z3DockerExecutor private var idCounter: Long = 0L @Inject private lateinit var config: EMConfig - @Inject - private lateinit var time: SearchTimeController - @PostConstruct private fun postConstruct() { if (config.generateSqlDataWithDSE) { @@ -65,6 +63,7 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { /** * Closes the Z3 Docker executor and cleans up temporary files. */ + @PreDestroy override fun close() { executor.close() try { diff --git a/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java b/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java index 15dc50ecc8..ba91eb421f 100644 --- a/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java +++ b/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java @@ -84,6 +84,8 @@ public Optional> solveFromFile(String fileName) { */ @Override public void close() { - z3Prover.stop(); + if (z3Prover != null) { + z3Prover.stop(); + } } } From a6a5dfff3fb78b7e1d7c84cf473c23d0a9aaf7d7 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Thu, 19 Dec 2024 11:29:10 -0300 Subject: [PATCH 18/26] Update core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt --- .../evomaster/core/problem/api/service/ApiWsStructureMutator.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt index cf25c713d0..971375b788 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/api/service/ApiWsStructureMutator.kt @@ -47,7 +47,6 @@ abstract class ApiWsStructureMutator : StructureMutator() { @Inject protected lateinit var harvestResponseHandler: HarvestActualHttpWsResponseHandler - // TODO: z3solver.close() should be invoked when the application is shutting down to stop the Docker container and clean the tmp folder @Inject protected lateinit var z3Solver: SMTLibZ3DbConstraintSolver From c728bc925e7a2494383b1aced2a3992c1969ecc2 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Thu, 16 Jan 2025 01:45:48 -0300 Subject: [PATCH 19/26] Fix deps --- e2e-tests/spring-rest-h2-z3solver/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/spring-rest-h2-z3solver/pom.xml b/e2e-tests/spring-rest-h2-z3solver/pom.xml index 3b885b05d3..fce0920b9b 100644 --- a/e2e-tests/spring-rest-h2-z3solver/pom.xml +++ b/e2e-tests/spring-rest-h2-z3solver/pom.xml @@ -5,10 +5,10 @@ org.evomaster evomaster-e2e-tests - 3.3.1-SNAPSHOT + 3.4.1-SNAPSHOT -spring-rest-h2-z3solver +evomaster-e2e-tests-spring-rest-h2-z3solver jar From 81672ee8a83155c075d84080fb150f63c0e355ea Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Thu, 16 Jan 2025 10:19:03 -0300 Subject: [PATCH 20/26] Fix write to file error --- .../core/solver/SMTLibZ3DbConstraintSolver.kt | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index 8e0e5655e4..5864cf202b 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -17,7 +17,6 @@ import org.evomaster.core.search.gene.numeric.IntegerGene import org.evomaster.core.search.gene.numeric.LongGene import org.evomaster.core.search.gene.sql.SqlPrimaryKeyGene import org.evomaster.core.search.gene.string.StringGene -import org.evomaster.core.search.service.SearchTimeController import org.evomaster.core.sql.SqlAction import org.evomaster.core.sql.schema.Column import org.evomaster.core.sql.schema.ColumnDataType @@ -34,6 +33,8 @@ import java.nio.file.Paths import java.util.* import javax.annotation.PostConstruct import javax.annotation.PreDestroy +import kotlin.io.path.createDirectories +import kotlin.io.path.exists /** * An SMT solver implementation using Z3 in a Docker container. @@ -308,15 +309,35 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { * @return The filename of the stored SMTLib problem. */ private fun storeToTmpFile(smtLib: SMTLib): String { - val fileName = "smt2_${System.currentTimeMillis()}.smt2" - val filePath = leadingBarResourcesFolder() + fileName + val directoryPath = leadingBarResourcesFolder() + val fileNameBase = "smt2_${System.currentTimeMillis()}" + val fileExtension = ".smt2" try { - Files.write(Paths.get(filePath), smtLib.toString().toByteArray(StandardCharsets.UTF_8)) + // Create dir if it doesn't exist + val directory = Paths.get(directoryPath) + if (!directory.exists()) { + directory.createDirectories() + } + + // Generate a unique file name + var fileName = "$fileNameBase$fileExtension" + var filePath = directory.resolve(fileName) + if (filePath.exists()) { + // Add a random suffix to the file name if it already exists + val randomSuffix = (1000..9999).random() + fileName = "${fileNameBase}_$randomSuffix$fileExtension" + filePath = directory.resolve(fileName) + } + + // Write the SMTLib content to the file + Files.write(filePath, smtLib.toString().toByteArray(StandardCharsets.UTF_8)) + + return fileName } catch (e: IOException) { - throw RuntimeException("Error writing SMTLib to file", e) + println("Failed to write SMTLib to file: ${e.message}") + return "error_saving_file_${System.currentTimeMillis()}.smt2" } - return fileName } private fun leadingBarResourcesFolder() = if (resourcesFolder.endsWith("/")) resourcesFolder else "$resourcesFolder/" From 5879985e2aa6730e49e51ae6b9eaeb9a68897f64 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Fri, 17 Jan 2025 00:50:40 -0300 Subject: [PATCH 21/26] Add logs info --- solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java b/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java index ba91eb421f..eeb196eb93 100644 --- a/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java +++ b/solver/src/main/java/org/evomaster/solver/Z3DockerExecutor.java @@ -62,7 +62,7 @@ public Optional> solveFromFile(String fileName) { // Execute the Z3 solver on the specified file in the container Container.ExecResult result = z3Prover.execInContainer("z3", containerPath + fileName); if (result.getExitCode() != 0) { - throw new RuntimeException("Error executing Z3 solver" + result.getStdout()); + throw new RuntimeException("Error executing Z3 solver: \n" + result.getStdout() + "\n" + result.getStderr()); } String stdout = result.getStdout(); From b231482d006ec87f6d6da4128f8d178f47749aba Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Mon, 20 Jan 2025 00:33:34 -0300 Subject: [PATCH 22/26] Print error while saving file --- .../org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index 5864cf202b..934d7139db 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -335,8 +335,7 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { return fileName } catch (e: IOException) { - println("Failed to write SMTLib to file: ${e.message}") - return "error_saving_file_${System.currentTimeMillis()}.smt2" + throw RuntimeException("Failed to write SMTLib to file: ${e.message}") } } From 4eb8a31af23ad578895daa909d565a5098a16dc2 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Mon, 20 Jan 2025 10:30:33 -0300 Subject: [PATCH 23/26] Use another tmp folder --- .../org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index 934d7139db..d4c5f20b68 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -43,7 +43,8 @@ import kotlin.io.path.exists * to satisfy the query. */ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { - private val resourcesFolder = System.getProperty("user.dir") + "/target/tmp" + private val resourcesFolder = System.getProperty("java.io.tmpdir") + "/target/tmp" + private lateinit var executor: Z3DockerExecutor private var idCounter: Long = 0L From 616f22b8230ef4254680639535b7ee7d95fe79ff Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Mon, 20 Jan 2025 23:34:44 -0300 Subject: [PATCH 24/26] Add tests --- .../core/solver/SMTLibZ3DbConstraintSolver.kt | 4 +- .../org/evomaster/core/solver/FileTest.java | 103 ++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 core/src/test/kotlin/org/evomaster/core/solver/FileTest.java diff --git a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt index d4c5f20b68..f2a37eb99e 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt @@ -43,7 +43,9 @@ import kotlin.io.path.exists * to satisfy the query. */ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver { - private val resourcesFolder = System.getProperty("java.io.tmpdir") + "/target/tmp" + + // Create a temporary directory for tests + var resourcesFolder = Files.createTempDirectory("tmp").toString() private lateinit var executor: Z3DockerExecutor private var idCounter: Long = 0L diff --git a/core/src/test/kotlin/org/evomaster/core/solver/FileTest.java b/core/src/test/kotlin/org/evomaster/core/solver/FileTest.java new file mode 100644 index 0000000000..8f3a414de2 --- /dev/null +++ b/core/src/test/kotlin/org/evomaster/core/solver/FileTest.java @@ -0,0 +1,103 @@ +package org.evomaster.core.solver; + + + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.*; +import java.util.List; + +import static org.junit.Assert.*; + +public class FileTest { + + private Path tempDir; + private Path testFilePath; + + @Before + public void setUp() throws IOException { + // Create a temporary directory for tests + tempDir = Files.createTempDirectory("test-files"); + testFilePath = tempDir.resolve("example.txt"); + } + + @After + public void tearDown() throws IOException { + // Clean up after tests + if (Files.exists(testFilePath)) { + Files.delete(testFilePath); + } + if (Files.exists(tempDir)) { + Files.delete(tempDir); + } + } + + @Test + public void testWriteWithFileWriter() throws IOException { + FileWriter writer = new FileWriter(testFilePath.toFile()); + writer.write("Hello, FileWriter!"); + writer.close(); + + String content = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8); + assertEquals("Hello, FileWriter!", content); + } + + @Test + public void testWriteWithBufferedWriter() throws IOException { + BufferedWriter writer = new BufferedWriter(new FileWriter(testFilePath.toFile())); + writer.write("Hello, BufferedWriter!"); + writer.close(); + + String content = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8); + assertEquals("Hello, BufferedWriter!", content); + } + + @Test + public void testWriteWithPrintWriter() throws IOException { + PrintWriter writer = new PrintWriter(testFilePath.toFile()); + writer.println("Hello, PrintWriter!"); + writer.close(); + + String content = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8).trim(); + assertEquals("Hello, PrintWriter!", content); + } + + @Test + public void testWriteWithFilesWriteMethod() throws IOException { + String content = "Hello, Files.write!"; + Files.write(testFilePath, content.getBytes(StandardCharsets.UTF_8)); + + String fileContent = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8); + assertEquals(content, fileContent); + } + + @Test + public void testWriteWithOutputStream() throws IOException { + FileOutputStream outputStream = new FileOutputStream(testFilePath.toFile()); + outputStream.write("Hello, OutputStream!".getBytes(StandardCharsets.UTF_8)); + outputStream.close(); + + String content = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8); + assertEquals("Hello, OutputStream!", content); + } + + @Test + public void testAppendToFile() throws IOException { + // Write initial content + Files.write(testFilePath, "Initial content\n".getBytes(StandardCharsets.UTF_8)); + + // Append content + FileWriter writer = new FileWriter(testFilePath.toFile(), true); + writer.write("Appended content"); + writer.close(); + + List lines = Files.readAllLines(testFilePath, StandardCharsets.UTF_8); + assertEquals(2, lines.size()); + assertEquals("Initial content", lines.get(0)); + assertEquals("Appended content", lines.get(1)); + } +} From 826787cbe95bd21e4d2314409fb8503ef3c78b25 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Tue, 21 Jan 2025 13:30:05 -0300 Subject: [PATCH 25/26] Remove trial test --- .../org/evomaster/core/solver/FileTest.java | 103 ------------------ 1 file changed, 103 deletions(-) delete mode 100644 core/src/test/kotlin/org/evomaster/core/solver/FileTest.java diff --git a/core/src/test/kotlin/org/evomaster/core/solver/FileTest.java b/core/src/test/kotlin/org/evomaster/core/solver/FileTest.java deleted file mode 100644 index 8f3a414de2..0000000000 --- a/core/src/test/kotlin/org/evomaster/core/solver/FileTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.evomaster.core.solver; - - - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.nio.file.*; -import java.util.List; - -import static org.junit.Assert.*; - -public class FileTest { - - private Path tempDir; - private Path testFilePath; - - @Before - public void setUp() throws IOException { - // Create a temporary directory for tests - tempDir = Files.createTempDirectory("test-files"); - testFilePath = tempDir.resolve("example.txt"); - } - - @After - public void tearDown() throws IOException { - // Clean up after tests - if (Files.exists(testFilePath)) { - Files.delete(testFilePath); - } - if (Files.exists(tempDir)) { - Files.delete(tempDir); - } - } - - @Test - public void testWriteWithFileWriter() throws IOException { - FileWriter writer = new FileWriter(testFilePath.toFile()); - writer.write("Hello, FileWriter!"); - writer.close(); - - String content = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8); - assertEquals("Hello, FileWriter!", content); - } - - @Test - public void testWriteWithBufferedWriter() throws IOException { - BufferedWriter writer = new BufferedWriter(new FileWriter(testFilePath.toFile())); - writer.write("Hello, BufferedWriter!"); - writer.close(); - - String content = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8); - assertEquals("Hello, BufferedWriter!", content); - } - - @Test - public void testWriteWithPrintWriter() throws IOException { - PrintWriter writer = new PrintWriter(testFilePath.toFile()); - writer.println("Hello, PrintWriter!"); - writer.close(); - - String content = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8).trim(); - assertEquals("Hello, PrintWriter!", content); - } - - @Test - public void testWriteWithFilesWriteMethod() throws IOException { - String content = "Hello, Files.write!"; - Files.write(testFilePath, content.getBytes(StandardCharsets.UTF_8)); - - String fileContent = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8); - assertEquals(content, fileContent); - } - - @Test - public void testWriteWithOutputStream() throws IOException { - FileOutputStream outputStream = new FileOutputStream(testFilePath.toFile()); - outputStream.write("Hello, OutputStream!".getBytes(StandardCharsets.UTF_8)); - outputStream.close(); - - String content = new String(Files.readAllBytes(testFilePath), StandardCharsets.UTF_8); - assertEquals("Hello, OutputStream!", content); - } - - @Test - public void testAppendToFile() throws IOException { - // Write initial content - Files.write(testFilePath, "Initial content\n".getBytes(StandardCharsets.UTF_8)); - - // Append content - FileWriter writer = new FileWriter(testFilePath.toFile(), true); - writer.write("Appended content"); - writer.close(); - - List lines = Files.readAllLines(testFilePath, StandardCharsets.UTF_8); - assertEquals(2, lines.size()); - assertEquals("Initial content", lines.get(0)); - assertEquals("Appended content", lines.get(1)); - } -} From 72a72ceaff94f022c1ea97588daaa52040c499a6 Mon Sep 17 00:00:00 2001 From: Agustina Aldasoro Date: Fri, 24 Jan 2025 16:25:54 -0300 Subject: [PATCH 26/26] Add javadoc --- .../kotlin/org/evomaster/core/solver/DbConstraintSolver.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt b/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt index 9f4c1b19c5..2a3b2a9897 100644 --- a/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt +++ b/core/src/main/kotlin/org/evomaster/core/solver/DbConstraintSolver.kt @@ -11,6 +11,9 @@ interface DbConstraintSolver : AutoCloseable { /** * Solves the given constraints and returns the Db Gene to insert in the database + * @param schemaDto the schema of the database + * @param sqlQuery the query to solve + * @param numberOfRows the number of rows to insert in the db per table * @return a list of SQLAction with the inserts in the db for the given constraints */ fun solve(schemaDto: DbInfoDto, sqlQuery: String, numberOfRows: Int = 1): List