diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/data/RestPath.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/data/RestPath.kt index 8331f87ca2..4e1439b4e6 100644 --- a/core/src/main/kotlin/org/evomaster/core/problem/rest/data/RestPath.kt +++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/data/RestPath.kt @@ -413,7 +413,7 @@ class RestPath(path: String) { why not using URI also for Query part??? it seems unclear how to properly build it as a single string... */ - val entry = URI(null, null, path.toString(), null, null).rawPath + val entry = URI(null, null, path.toString(), null, null).toASCIIString() data.add(Pair(entry, false)) path.setLength(0) // clear it data.add(Pair(variable, true)) @@ -446,7 +446,7 @@ class RestPath(path: String) { } if(path.isNotEmpty()){ - val entry = URI(null, null, path.toString(), null, null).rawPath + val entry = URI(null, null, path.toString(), null, null).toASCIIString() data.add(Pair(entry, false)) } diff --git a/core/src/test/kotlin/org/evomaster/core/output/TestCaseWriterTest.kt b/core/src/test/kotlin/org/evomaster/core/output/TestCaseWriterTest.kt index d2454da456..86fb37fc90 100644 --- a/core/src/test/kotlin/org/evomaster/core/output/TestCaseWriterTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/output/TestCaseWriterTest.kt @@ -16,6 +16,7 @@ import org.evomaster.core.output.service.RestTestCaseWriter import org.evomaster.core.problem.enterprise.SampleType import org.evomaster.core.problem.rest.data.* import org.evomaster.core.problem.rest.param.BodyParam +import org.evomaster.core.problem.rest.param.PathParam import org.evomaster.core.search.EvaluatedIndividual import org.evomaster.core.search.FitnessValue import org.evomaster.core.search.gene.* @@ -28,6 +29,7 @@ import org.evomaster.core.search.gene.collection.EnumGene import org.evomaster.core.search.gene.numeric.IntegerGene import org.evomaster.core.search.gene.string.StringGene import org.evomaster.core.search.gene.utils.GeneUtils +import org.evomaster.core.search.gene.wrapper.CustomMutationRateGene import org.evomaster.core.search.gene.wrapper.OptionalGene import org.evomaster.core.sql.schema.TableId import org.junit.jupiter.api.Assertions.* @@ -1679,4 +1681,30 @@ public void test() throws Exception { assertFalse(lines.toString().contains(".body()")) } + + @Test + fun testNonAsciiInPathParamIsEncoded() { + // non-ASCII characters in path parameter values must be percent-encoded in generated test output. + val format = OutputFormat.KOTLIN_JUNIT_5 + + val pathParam = PathParam("key", CustomMutationRateGene("key", StringGene("key", "聚"), 1.0)) + val action = RestCallAction("1", HttpVerb.GET, RestPath("/api/{key}"), mutableListOf(pathParam)) + val individual = RestIndividual(mutableListOf(action), SampleType.RANDOM) + TestUtils.doInitializeIndividualForTesting(individual) + + val result = RestCallResult(action.getLocalId()) + result.setTimedout(false) + result.setStatusCode(200) + val ei = EvaluatedIndividual(FitnessValue(0.0), individual, listOf(result)) + + val writer = RestTestCaseWriter(getConfig(format), PartialOracles()) + val lines = writer.convertToCompilableTestCode(TestCase(test = ei, name = "test"), "baseUrlOfSut") + val output = lines.toString() + + assertFalse(output.contains("聚"), + "Non-ASCII character must not appear raw in generated test output, got:\n$output") + + assertTrue(output.contains("%E8%81%9A"), + "Non-ASCII character must be percent-encoded as %E8%81%9A in generated test output, got:\n$output") + } } diff --git a/core/src/test/kotlin/org/evomaster/core/problem/rest/RestPathTest.kt b/core/src/test/kotlin/org/evomaster/core/problem/rest/RestPathTest.kt index 7ddf3d809b..4ed357800f 100644 --- a/core/src/test/kotlin/org/evomaster/core/problem/rest/RestPathTest.kt +++ b/core/src/test/kotlin/org/evomaster/core/problem/rest/RestPathTest.kt @@ -605,4 +605,19 @@ internal class RestPathTest{ assertEquals(y, resolvedY) } + @Test + fun testPathParamWithNonAscii() { + // Non-ASCII characters (e.g. from AnyCharacterRxGene sampling the full + // Unicode range) must also be percent-encoded in path parameters. These + // are not encoded by URI(null, null, s, null, null) in path parameters, + // causing them to appear raw in the generated URL. + val key = PathParam("key", CustomMutationRateGene("d_", StringGene("key", "key-聚"), 1.0)) + + val resolved = RestPath("/api/{key}").resolve(listOf(key)) + + assertFalse(resolved.contains("聚"), + "Resolved path must not contain a raw non-ASCII character, got: $resolved") + assertTrue(resolved.contains("%E8%81%9A"), + "Resolved path must percent-encode non-ASCII characters, got: $resolved") + } } \ No newline at end of file