From 1fd5f43c21a6c541f2d68dc104aa1775cd7c3ea6 Mon Sep 17 00:00:00 2001 From: Philip Garrett Date: Fri, 20 Dec 2024 22:39:53 -0300 Subject: [PATCH] Boolean and String gene unwrapped for test case naming --- .../RestActionTestCaseNamingStrategy.kt | 24 ++++++------- .../evomaster/core/problem/rest/RestPath.kt | 4 +-- .../naming/TestCaseDisambiguationTest.kt | 36 +++++++++++++++++-- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/core/src/main/kotlin/org/evomaster/core/output/naming/RestActionTestCaseNamingStrategy.kt b/core/src/main/kotlin/org/evomaster/core/output/naming/RestActionTestCaseNamingStrategy.kt index d6df69966f..9d8ac0c6e7 100644 --- a/core/src/main/kotlin/org/evomaster/core/output/naming/RestActionTestCaseNamingStrategy.kt +++ b/core/src/main/kotlin/org/evomaster/core/output/naming/RestActionTestCaseNamingStrategy.kt @@ -85,7 +85,7 @@ open class RestActionTestCaseNamingStrategy( * When two or more individuals share a name, no disambiguation is performed. * Otherwise, we would just be increasing test case name length without having actually disambiguated. */ - private fun collectSolvedNames(ambiguitySolversPerIndividual: MutableMap, MutableList<(Action) -> List>>): Map, String> { + private fun collectSolvedNames(ambiguitySolversPerIndividual: Map, MutableList<(Action) -> List>>): Map, String> { return ambiguitySolversPerIndividual .map { it.key to expandName(it.key, mutableListOf(), it.value) } .groupBy({ it.second }, { it.first }) @@ -151,7 +151,8 @@ open class RestActionTestCaseNamingStrategy( return duplicatedIndividuals .groupBy { val restAction = it.evaluatedMainActions().last().action as RestCallAction - restAction.path.getOnlyQuery(restAction.parameters) + restAction.path.getOnlyUsableQueries(restAction.parameters) + .filter { queryParam -> queryParam.getGeneForQuery().staticCheckIfImpactPhenotype() } } .filter { it.value.isNotEmpty() && it.key.isNotEmpty()} .flatMap { it.value } @@ -165,7 +166,7 @@ open class RestActionTestCaseNamingStrategy( val restAction = action as RestCallAction val result = mutableListOf() - val queryParams = restAction.path.getOnlyQuery(restAction.parameters) + val queryParams = restAction.path.getOnlyUsableQueries(restAction.parameters) .filter { it.getGeneForQuery().staticCheckIfImpactPhenotype() } result.add(with) result.add(if (queryParams.size > 1) "${queryParam}s" else queryParam) @@ -206,31 +207,26 @@ open class RestActionTestCaseNamingStrategy( // TODO: need to check if the BooleanGene is not enclosed in an OptionalGene private fun getBooleanQueryParams(queryParams: List): List { return queryParams.filter { - val wrappedGene = getWrappedGene(it) - wrappedGene is BooleanGene && wrappedGene.value + val booleanGene = it.getGeneForQuery().getWrappedGene(BooleanGene::class.java) + booleanGene != null && booleanGene.staticCheckIfImpactPhenotype() && booleanGene.value } } // TODO: need to check if the NumberGene is not enclosed in an OptionalGene private fun getNegativeNumberQueryParams(queryParams: List): List { return queryParams.filter { - val wrappedGene = getWrappedGene(it) - wrappedGene is NumberGene<*> && wrappedGene.value.toLong() < 0 + val numberGene = it.getGeneForQuery().getWrappedGene(NumberGene::class.java) + numberGene != null && numberGene.staticCheckIfImpactPhenotype() && numberGene.value.toLong() < 0 } } - // TODO: need to check if the StringGene is not enclosed in an OptionalGene private fun getEmptyStringQueryParams(queryParams: List): List { return queryParams.filter { - val wrappedGene = getWrappedGene(it) - wrappedGene is StringGene && wrappedGene.getValueAsRawString().trim().isEmpty() + val stringGene = it.getGeneForQuery().getWrappedGene(StringGene::class.java) + stringGene != null && stringGene.staticCheckIfImpactPhenotype() && stringGene.getValueAsRawString().trim().isEmpty() } } - private fun getWrappedGene(queryParam: QueryParam): Gene? { - return queryParam.getGeneForQuery().getWrappedGene(OptionalGene::class.java)?.gene - } - private fun isGetCall(evaluatedAction: EvaluatedAction): Boolean { return (evaluatedAction.action as RestCallAction).verb == HttpVerb.GET } diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/RestPath.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/RestPath.kt index f06c7882e5..dfe6ef381d 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/rest/RestPath.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/RestPath.kt @@ -297,14 +297,14 @@ class RestPath(path: String) { return params.filter(usableQueryParamsFunction()).size } - fun getOnlyQuery(params: List): List { + fun getOnlyUsableQueries(params: List): List { return params .filter(usableQueryParamsFunction()) .filterIsInstance() } fun resolveOnlyQuery(params: List): List { - return getOnlyQuery(params) + return getOnlyUsableQueries(params) .map { q -> val name = encode(q.name) diff --git a/core/src/test/kotlin/org/evomaster/core/output/naming/TestCaseDisambiguationTest.kt b/core/src/test/kotlin/org/evomaster/core/output/naming/TestCaseDisambiguationTest.kt index 3f8b6c50b2..8d1048a76f 100644 --- a/core/src/test/kotlin/org/evomaster/core/output/naming/TestCaseDisambiguationTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/output/naming/TestCaseDisambiguationTest.kt @@ -266,12 +266,44 @@ class TestCaseDisambiguationTest { assertEquals("test_1_getOnLanguagesWithQueryParamsNegativeLimitEmptyNameReturnsEmpty", testCases[1].name) } + @Test + fun unwrappedNegativeNumberQueryParamIsAdded() { + val simpleIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages")) + val negativeQPIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages", parameters = mutableListOf(getIntegerQueryParam("limit", false)))) + ensureGeneValue(negativeQPIndividual, "limit", "-1") + + val solution = Solution(mutableListOf(simpleIndividual, negativeQPIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) + + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME) + + val testCases = namingStrategy.getTestCases() + assertEquals(2, testCases.size) + assertEquals("test_0_getOnLanguagesReturnsEmpty", testCases[0].name) + assertEquals("test_1_getOnLanguagesWithQueryParamNegativeLimitReturnsEmpty", testCases[1].name) + } + + @Test + fun unwrappedEmptyStringQueryParamIsAdded() { + val simpleIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages")) + val emptyQPIndividual = getEvaluatedIndividualWith(getRestCallAction("/languages", parameters = mutableListOf(getStringQueryParam("name", false)))) + ensureGeneValue(emptyQPIndividual, "name", "") + + val solution = Solution(mutableListOf(simpleIndividual, emptyQPIndividual), "suitePrefix", "suiteSuffix", Termination.NONE, emptyList(), emptyList()) + + val namingStrategy = RestActionTestCaseNamingStrategy(solution, javaFormatter, QUERY_PARAMS_IN_NAME) + + val testCases = namingStrategy.getTestCases() + assertEquals(2, testCases.size) + assertEquals("test_0_getOnLanguagesReturnsEmpty", testCases[0].name) + assertEquals("test_1_getOnLanguagesWithQueryParamEmptyNameReturnsEmpty", testCases[1].name) + } + private fun getPathParam(paramName: String): Param { return PathParam(paramName, CustomMutationRateGene(paramName, StringGene(paramName), 1.0)) } - private fun getStringQueryParam(paramName: String): Param { - return getQueryParam(paramName, StringGene(paramName)) + private fun getStringQueryParam(paramName: String, wrapped: Boolean = true): Param { + return getQueryParam(paramName, StringGene(paramName), wrapped) } private fun getBooleanQueryParam(paramName: String): Param {