diff --git a/.gitignore b/.gitignore index efe2cd61d..6243070d1 100644 --- a/.gitignore +++ b/.gitignore @@ -329,6 +329,9 @@ scripts/dockerize/dockerfiles /jdk_25_maven/cs/rest/jasper/target/ /jdk_25_maven/em/external/rest/jasper/target/ /jdk_25_maven/em/embedded/rest/jasper/target/ +/jdk_21_maven/cs/rest/redis-sample/target/ +/jdk_21_maven/em/external/rest/redis-sample/target/ +/jdk_21_maven/em/embedded/rest/redis-sample/target/ /jdk_11_maven/em/embedded/rest/tracking-system/target/ /jdk_11_maven/em/external/rest/tracking-system/target/ /jdk_17_maven/em/embedded/rest/tiltaksgjennomforing/target/ diff --git a/README.md b/README.md index 8238051c0..60e1dc27b 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ How to setup authentication information, based on the current content of the ini Auth configuration files can found in the [auth](auth) folder. -### REST: Java/Kotlin (38) +### REST: Java/Kotlin (39) * **Bibliothek** (MIT), [jdk_17_gradle/cs/rest/bibliothek](jdk_17_gradle/cs/rest/bibliothek), from [https://github.com/PaperMC/bibliothek](https://github.com/PaperMC/bibliothek) @@ -135,6 +135,8 @@ Auth configuration files can found in the [auth](auth) folder. * **Quartz Manager** (Apache), [jdk_11_maven/cs/rest-gui/quartz-manager](jdk_11_maven/cs/rest-gui/quartz-manager), from [https://github.com/fabioformosa/quartz-manager](https://github.com/fabioformosa/quartz-manager) +* **Redis Sample** (not-known license), [jdk_21_maven/cs/rest/redis-sample](jdk_21_maven/cs/rest/redis-sample), from [https://github.com/hendisantika/spring-boot-redis-sample](https://github.com/hendisantika/spring-boot-redis-sample) + * **Reservations API** (not-known license), [jdk_11_gradle/cs/rest/reservations-api](jdk_11_gradle/cs/rest/reservations-api), from [https://github.com/cyrilgavala/reservations-api](https://github.com/cyrilgavala/reservations-api) * **Restcountries** (MPL), [jdk_8_maven/cs/rest/original/restcountries](jdk_8_maven/cs/rest/original/restcountries), from [https://github.com/apilayer/restcountries](https://github.com/apilayer/restcountries) diff --git a/dockerfiles/redis-sample.dockerfile b/dockerfiles/redis-sample.dockerfile new file mode 100644 index 000000000..e6429223a --- /dev/null +++ b/dockerfiles/redis-sample.dockerfile @@ -0,0 +1,17 @@ +FROM amazoncorretto:21-alpine-jdk + +COPY ./dist/redis-sample-sut.jar . +COPY ./dist/jacocoagent.jar . + + + +#ENV TOOL="undefined" +#ENV RUN="0" + +ENTRYPOINT \ + java \ +# unfortunately dumponexit is completely unreliable in Docker :( +# -javaagent:jacocoagent.jar=destfile=./jacoco/redis-sample__${TOOL}__${RUN}__jacoco.exec,append=false,dumponexit=true \ + -javaagent:jacocoagent.jar=output=tcpserver,address=*,port=6300,append=false,dumponexit=false \ + -jar redis-sample-sut.jar \ + --server.port=8080 --spring.data.redis.host=db --spring.data.redis.port=6379 --spring.data.redis.password=53cret --spring.autoconfigure.exclude=org.springframework.boot.security.autoconfigure.web.servlet.ServletWebSecurityAutoConfiguration --app.numberOfRatings=5000 --app.ratingStars=5 \ No newline at end of file diff --git a/dockerfiles/redis-sample.yaml b/dockerfiles/redis-sample.yaml new file mode 100644 index 000000000..9defd496a --- /dev/null +++ b/dockerfiles/redis-sample.yaml @@ -0,0 +1,32 @@ +services: + mitmproxy: + image: mitmproxy/mitmproxy:10.2.4 + user: "0:0" + environment: + MITM_LOG_DIR: /custom-logs + MITM_LOG_FILE: ${MITM_LOG_FILE:-minlog.csv} + command: > + mitmdump + --mode reverse:http://sut-redis-sample:8080 + --listen-host 0.0.0.0 + --listen-port 8080 + --set keep_host_header=true + -s /addons/minlog.py + volumes: + - ${HOST_LOG_DIR:-./mitm-logs}:/custom-logs + - ./addons:/addons:ro + ports: + - "${HOST_PORT:-8080}:8080" + depends_on: + - sut-redis-sample + sut-redis-sample: + build: + dockerfile: ./dockerfiles/redis-sample.dockerfile + context: .. + environment: + AUTH_PORT: ${AUTH_PORT:-8081} + ports: + - "${JACOCO_PORT:-6300}:6300" + db: + image: redis:7.4-alpine + command: redis-server --requirepass 53cret \ No newline at end of file diff --git a/experiments/wb-exp.py b/experiments/wb-exp.py index 572a119c2..f4afaa39a 100644 --- a/experiments/wb-exp.py +++ b/experiments/wb-exp.py @@ -201,6 +201,7 @@ def __init__(self, name, platform): Sut("ohsome-api", JDK_17), Sut("pay-publicapi",JDK_11), Sut("person-controller",JDK_21), + Sut("redis-sample", JDK_21), Sut("proxyprint", JDK_8), Sut("quartz-manager", JDK_11), Sut("reservations-api", JDK_11), diff --git a/jdk_21_maven/cs/rest/pom.xml b/jdk_21_maven/cs/rest/pom.xml index 3cb72b60b..ada40d03e 100644 --- a/jdk_21_maven/cs/rest/pom.xml +++ b/jdk_21_maven/cs/rest/pom.xml @@ -14,6 +14,7 @@ person-controller + redis-sample diff --git a/jdk_21_maven/cs/rest/redis-sample/pom.xml b/jdk_21_maven/cs/rest/redis-sample/pom.xml index c4330e501..62e35db3b 100644 --- a/jdk_21_maven/cs/rest/redis-sample/pom.xml +++ b/jdk_21_maven/cs/rest/redis-sample/pom.xml @@ -83,6 +83,13 @@ 2.2.4 test + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 3.1.0 + + @@ -107,6 +114,12 @@ org.springframework.boot spring-boot-maven-plugin + + + redis-sample + sut + org.projectlombok diff --git a/jdk_21_maven/cs/rest/redis-sample/src/main/java/id/my/hendisantika/springbootredissample/boot/CreateBooks.java b/jdk_21_maven/cs/rest/redis-sample/src/main/java/id/my/hendisantika/springbootredissample/boot/CreateBooks.java index 0d9808476..4430629c1 100644 --- a/jdk_21_maven/cs/rest/redis-sample/src/main/java/id/my/hendisantika/springbootredissample/boot/CreateBooks.java +++ b/jdk_21_maven/cs/rest/redis-sample/src/main/java/id/my/hendisantika/springbootredissample/boot/CreateBooks.java @@ -12,6 +12,7 @@ import org.springframework.core.annotation.Order; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.stereotype.Component; import java.io.File; @@ -51,9 +52,13 @@ public void run(String... args) throws Exception { TypeReference> typeReference = new TypeReference<>() { }; - Resource resource = resourceLoader.getResource("classpath:/data/books/"); - File directory = resource.getFile(); - File[] files = directory.listFiles((dir, name) -> name.endsWith(".json")); + // MODIFIED + // In the packaged jar getFile() throws FileNotFoundException: class path resource + // [data/books/] cannot be resolved to absolute file path -> startup dies. + File[] files = Arrays.stream(new PathMatchingResourcePatternResolver() + .getResources("classpath*:/data/books/*.json")) + .map(r -> new File(r.getFilename())).toArray(File[]::new); + // MODIFIED if (files == null || files.length == 0) { log.warn("No JSON files found in /data/books/ directory."); diff --git a/jdk_21_maven/em/embedded/rest/pom.xml b/jdk_21_maven/em/embedded/rest/pom.xml index 143794554..ee9b2fbe5 100644 --- a/jdk_21_maven/em/embedded/rest/pom.xml +++ b/jdk_21_maven/em/embedded/rest/pom.xml @@ -13,6 +13,7 @@ person-controller + redis-sample diff --git a/jdk_21_maven/em/embedded/rest/redis-sample/pom.xml b/jdk_21_maven/em/embedded/rest/redis-sample/pom.xml new file mode 100644 index 000000000..06d3f0432 --- /dev/null +++ b/jdk_21_maven/em/embedded/rest/redis-sample/pom.xml @@ -0,0 +1,51 @@ + + + + 4.0.0 + + evomaster-benchmark-jdk21-em-embedded-rest-redis-sample + jar + + + org.evomaster + evomaster-benchmark-jdk21-em-embedded-rest + 4.3.1-SNAPSHOT + + + + + + + org.springframework.boot + spring-boot-dependencies + 4.1.0 + pom + import + + + + + + + + id.my.hendisantika + spring-boot-redis-sample + 0.0.1-SNAPSHOT + + + + org.testcontainers + testcontainers + compile + + + + io.lettuce + lettuce-core + + + + diff --git a/jdk_21_maven/em/embedded/rest/redis-sample/src/main/java/em/embedded/redis/sample/EmbeddedEvoMasterController.java b/jdk_21_maven/em/embedded/rest/redis-sample/src/main/java/em/embedded/redis/sample/EmbeddedEvoMasterController.java new file mode 100644 index 000000000..fe63293d3 --- /dev/null +++ b/jdk_21_maven/em/embedded/rest/redis-sample/src/main/java/em/embedded/redis/sample/EmbeddedEvoMasterController.java @@ -0,0 +1,171 @@ +package em.embedded.redis.sample; + +import id.my.hendisantika.springbootredissample.SpringBootRedisSampleApplication; +import org.evomaster.client.java.controller.EmbeddedSutController; +import org.evomaster.client.java.controller.InstrumentedSutStarter; +import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto; +import org.evomaster.client.java.controller.api.dto.SutInfoDto; +import org.evomaster.client.java.sql.DbSpecification; +import org.evomaster.client.java.controller.problem.ProblemInfo; +import org.evomaster.client.java.controller.problem.RestProblem; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.testcontainers.containers.GenericContainer; +import io.lettuce.core.RedisClient; +import io.lettuce.core.api.StatefulRedisConnection; + +import java.util.List; +import java.util.Map; + +/** + * Class used to start/stop the SUT. This will be controller by the EvoMaster process + */ +public class EmbeddedEvoMasterController extends EmbeddedSutController { + + private static final String REDIS_VERSION = "7.4-alpine"; + + private static final int REDIS_PORT = 6379; + + private static final String REDIS_PASSWORD = "53cret"; + + private static final String SECURITY_EXCLUDE = + "org.springframework.boot.security.autoconfigure.web.servlet.ServletWebSecurityAutoConfiguration"; + + private static final int NUMBER_OF_RATINGS = 5000; + + private static final int RATING_STARS = 5; + + private static final String CACHE_KEY_PATTERN = "id.my.hendisantika.springbootredissample.*Cache::*"; + + private static final GenericContainer redis = new GenericContainer("redis:" + REDIS_VERSION) + .withCommand("redis-server", "--requirepass", REDIS_PASSWORD) + .withExposedPorts(REDIS_PORT); + + + public static void main(String[] args) { + + int port = 40100; + if (args.length > 0) { + port = Integer.parseInt(args[0]); + } + + EmbeddedEvoMasterController controller = new EmbeddedEvoMasterController(port); + InstrumentedSutStarter starter = new InstrumentedSutStarter(controller); + + starter.start(); + } + + + private ConfigurableApplicationContext ctx; + + private RedisClient redisClient; + + private StatefulRedisConnection redisConnection; + + public EmbeddedEvoMasterController() { + this(0); + } + + public EmbeddedEvoMasterController(int port) { + setControllerPort(port); + } + + + @Override + public String startSut() { + + redis.start(); + redisClient = RedisClient.create("redis://:" + REDIS_PASSWORD + "@" + + redis.getHost() + ":" + redis.getMappedPort(REDIS_PORT)); + redisConnection = redisClient.connect(); + + ctx = SpringApplication.run(SpringBootRedisSampleApplication.class, new String[]{ + "--server.port=0", + "--spring.data.redis.host=" + redis.getHost(), + "--spring.data.redis.port=" + redis.getMappedPort(REDIS_PORT), + "--spring.data.redis.password=" + REDIS_PASSWORD, + "--spring.autoconfigure.exclude=" + SECURITY_EXCLUDE, + "--app.numberOfRatings=" + NUMBER_OF_RATINGS, + "--app.ratingStars=" + RATING_STARS + }); + + return "http://localhost:" + getSutPort(); + } + + protected int getSutPort() { + return (Integer) ((Map) ctx.getEnvironment() + .getPropertySources().get("server.ports").getSource()) + .get("local.server.port"); + } + + + @Override + public boolean isSutRunning() { + return ctx != null && ctx.isRunning(); + } + + @Override + public void stopSut() { + + if (ctx != null) { + ctx.stop(); + ctx.close(); + ctx = null; + } + + if (redisConnection != null) { + redisConnection.close(); + redisClient.shutdown(); + redisConnection = null; + redisClient = null; + } + + redis.stop(); + } + + @Override + public String getPackagePrefixesToCover() { + return "id.my.hendisantika.springbootredissample."; + } + + /* + Only the Spring Cache entries accumulate: the API is read-only, and the seeded data is + written once at startup by runners guarded on an empty repository, so it must survive. + */ + @Override + public void resetStateOfSUT() { + if (redisConnection == null) { + return; + } + List keys = redisConnection.sync().keys(CACHE_KEY_PATTERN); + if (!keys.isEmpty()) { + redisConnection.sync().del(keys.toArray(new String[0])); + } + } + + + @Override + public List getDbSpecifications() { + return null; + } + + + @Override + public List getInfoForAuthentication() { + return null; + } + + + @Override + public ProblemInfo getProblemInfo() { + return new RestProblem( + "http://localhost:" + getSutPort() + "/v3/api-docs", + null + ); + } + + @Override + public SutInfoDto.OutputFormat getPreferredOutputFormat() { + return SutInfoDto.OutputFormat.JAVA_JUNIT_5; + } +} diff --git a/jdk_21_maven/em/external/rest/pom.xml b/jdk_21_maven/em/external/rest/pom.xml index 4a511f300..3e059511d 100644 --- a/jdk_21_maven/em/external/rest/pom.xml +++ b/jdk_21_maven/em/external/rest/pom.xml @@ -14,6 +14,7 @@ person-controller + redis-sample \ No newline at end of file diff --git a/jdk_21_maven/em/external/rest/redis-sample/pom.xml b/jdk_21_maven/em/external/rest/redis-sample/pom.xml new file mode 100644 index 000000000..91fb2b0cb --- /dev/null +++ b/jdk_21_maven/em/external/rest/redis-sample/pom.xml @@ -0,0 +1,84 @@ + + + + 4.0.0 + + evomaster-benchmark-jdk21-em-external-rest-redis-sample + jar + + + org.evomaster + evomaster-benchmark-jdk21-em-external-rest + 4.3.1-SNAPSHOT + + + + + + + org.testcontainers + testcontainers + compile + + + + io.lettuce + lettuce-core + 7.5.2.RELEASE + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + 3.6.2 + + + package + + shade + + + redis-sample-evomaster-runner + + + + em.external.redis.sample.ExternalEvoMasterController + + org.evomaster.client.java.instrumentation.InstrumentingAgent + + org.evomaster.client.java.instrumentation.InstrumentingAgent + + true + true + + + + + + + org.slf4j + shaded.emb.org.slf4j + + + com.fasterxml.jackson.annotation + shaded.emb.com.fasterxml.jackson.annotation + + + + + + + + + diff --git a/jdk_21_maven/em/external/rest/redis-sample/src/main/java/em/external/redis/sample/ExternalEvoMasterController.java b/jdk_21_maven/em/external/rest/redis-sample/src/main/java/em/external/redis/sample/ExternalEvoMasterController.java new file mode 100644 index 000000000..69afea8ec --- /dev/null +++ b/jdk_21_maven/em/external/rest/redis-sample/src/main/java/em/external/redis/sample/ExternalEvoMasterController.java @@ -0,0 +1,225 @@ +package em.external.redis.sample; + + +import org.evomaster.client.java.controller.ExternalSutController; +import org.evomaster.client.java.controller.InstrumentedSutStarter; +import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto; +import org.evomaster.client.java.controller.api.dto.SutInfoDto; +import org.evomaster.client.java.sql.DbSpecification; +import org.evomaster.client.java.controller.problem.ProblemInfo; +import org.evomaster.client.java.controller.problem.RestProblem; +import org.testcontainers.containers.GenericContainer; +import io.lettuce.core.RedisClient; +import io.lettuce.core.api.StatefulRedisConnection; + +import java.util.List; + +public class ExternalEvoMasterController extends ExternalSutController { + + private static final int DEFAULT_CONTROLLER_PORT = 40100; + + private static final int DEFAULT_SUT_PORT = 12345; + + private static final String REDIS_VERSION = "7.4-alpine"; + + private static final int REDIS_PORT = 6379; + + private static final String REDIS_PASSWORD = "53cret"; + + private static final String SECURITY_EXCLUDE = + "org.springframework.boot.security.autoconfigure.web.servlet.ServletWebSecurityAutoConfiguration"; + + private static final int NUMBER_OF_RATINGS = 5000; + + private static final int RATING_STARS = 5; + + private static final String CACHE_KEY_PATTERN = "id.my.hendisantika.springbootredissample.*Cache::*"; + + private static final GenericContainer redis = new GenericContainer("redis:" + REDIS_VERSION) + .withCommand("redis-server", "--requirepass", REDIS_PASSWORD) + .withExposedPorts(REDIS_PORT); + + + public static void main(String[] args) { + + int controllerPort = DEFAULT_CONTROLLER_PORT; + if (args.length > 0) { + controllerPort = Integer.parseInt(args[0]); + } + int sutPort = DEFAULT_SUT_PORT; + if (args.length > 1) { + sutPort = Integer.parseInt(args[1]); + } + String jarLocation = "cs/rest/redis-sample/target"; + if (args.length > 2) { + jarLocation = args[2]; + } + if (!jarLocation.endsWith(".jar")) { + jarLocation += "/redis-sample-sut.jar"; + } + + int timeoutSeconds = 120; + if (args.length > 3) { + timeoutSeconds = Integer.parseInt(args[3]); + } + + String command = "java"; + if (args.length > 4) { + command = args[4]; + } + + ExternalEvoMasterController controller = + new ExternalEvoMasterController(controllerPort, jarLocation, sutPort, timeoutSeconds, command); + + controller.setNeedsJdk17Options(true); + + InstrumentedSutStarter starter = new InstrumentedSutStarter(controller); + + starter.start(); + } + + + private final int timeoutSeconds; + + private final int sutPort; + + private String jarLocation; + + private RedisClient redisClient; + + private StatefulRedisConnection redisConnection; + + public ExternalEvoMasterController() { + this(DEFAULT_CONTROLLER_PORT, "../target/redis-sample-sut.jar", DEFAULT_SUT_PORT, 120, "java"); + } + + public ExternalEvoMasterController(String jarLocation) { + this(); + this.jarLocation = jarLocation; + } + + public ExternalEvoMasterController(int controllerPort, String jarLocation, int sutPort, int timeoutSeconds, String command) { + this.sutPort = sutPort; + this.jarLocation = jarLocation; + this.timeoutSeconds = timeoutSeconds; + + setControllerPort(controllerPort); + setJavaCommand(command); + } + + @Override + public String[] getInputParameters() { + return new String[]{ + "--server.port=" + sutPort, + "--spring.data.redis.host=" + redis.getHost(), + "--spring.data.redis.port=" + redis.getMappedPort(REDIS_PORT), + "--spring.data.redis.password=" + REDIS_PASSWORD, + "--spring.autoconfigure.exclude=" + SECURITY_EXCLUDE, + "--app.numberOfRatings=" + NUMBER_OF_RATINGS, + "--app.ratingStars=" + RATING_STARS + }; + } + + @Override + public String[] getJVMParameters() { + return new String[]{}; + } + + + @Override + public String getBaseURL() { + return "http://localhost:" + sutPort; + } + + @Override + public String getPathToExecutableJar() { + return jarLocation; + } + + /* + Spring logs "Started ... in" before the CommandLineRunners, and seeding the ratings takes + another ~12s. Fuzzing that early makes EvoMaster's kill switch abort the still-running + runner, which brings the whole SUT down. This is the last line the last runner writes. + */ + @Override + public String getLogMessageOfInitializedServer() { + return ">>>> BookRating created..."; + } + + @Override + public long getMaxAwaitForInitializationInSeconds() { + return timeoutSeconds; + } + + @Override + public void preStart() { + redis.start(); + redisClient = RedisClient.create("redis://:" + REDIS_PASSWORD + "@" + + redis.getHost() + ":" + redis.getMappedPort(REDIS_PORT)); + redisConnection = redisClient.connect(); + } + + @Override + public void postStart() { + } + + @Override + public void preStop() { + } + + @Override + public void postStop() { + if (redisConnection != null) { + redisConnection.close(); + redisClient.shutdown(); + redisConnection = null; + redisClient = null; + } + + redis.stop(); + } + + @Override + public String getPackagePrefixesToCover() { + return "id.my.hendisantika.springbootredissample."; + } + + @Override + public ProblemInfo getProblemInfo() { + return new RestProblem( + getBaseURL() + "/v3/api-docs", + null + ); + } + + @Override + public SutInfoDto.OutputFormat getPreferredOutputFormat() { + return SutInfoDto.OutputFormat.JAVA_JUNIT_5; + } + + @Override + public List getInfoForAuthentication() { + return null; + } + + /* + Only the Spring Cache entries accumulate: the API is read-only, and the seeded data is + written once at startup by runners guarded on an empty repository, so it must survive. + */ + @Override + public void resetStateOfSUT() { + if (redisConnection == null) { + return; + } + List keys = redisConnection.sync().keys(CACHE_KEY_PATTERN); + if (!keys.isEmpty()) { + redisConnection.sync().del(keys.toArray(new String[0])); + } + } + + @Override + public List getDbSpecifications() { + return null; + } + +} diff --git a/openapi-swagger/redis-sample.json b/openapi-swagger/redis-sample.json new file mode 100644 index 000000000..0a1ac93eb --- /dev/null +++ b/openapi-swagger/redis-sample.json @@ -0,0 +1,205 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost:13456", + "description": "Generated server url" + } + ], + "paths": { + "/api/users": { + "get": { + "tags": [ + "user-controller" + ], + "operationId": "getUsers", + "parameters": [ + { + "name": "email", + "in": "query", + "required": false, + "schema": { + "type": "string", + "default": "yuji@yopmail.com" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "object" + } + } + } + } + } + } + }, + "/api/books": { + "get": { + "tags": [ + "book-controller" + ], + "operationId": "getBooks", + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 0 + } + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "object", + "additionalProperties": {} + } + } + } + } + } + } + }, + "/api/books/{isbn}": { + "get": { + "tags": [ + "book-controller" + ], + "operationId": "getIsbn", + "parameters": [ + { + "name": "isbn", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/Book" + } + } + } + } + } + } + }, + "/api/books/categories": { + "get": { + "tags": [ + "book-controller" + ], + "operationId": "getCategories", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "object" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Book": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "title": { + "type": "string" + }, + "subtitle": { + "type": "string" + }, + "description": { + "type": "string" + }, + "language": { + "type": "string" + }, + "pageCount": { + "type": "integer", + "format": "int64" + }, + "thumbnail": { + "type": "string" + }, + "price": { + "type": "number", + "format": "double" + }, + "currency": { + "type": "string" + }, + "infoLink": { + "type": "string" + }, + "authors": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "categories": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Category" + }, + "uniqueItems": true + } + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/scripts/build/docker-compose.build.yml b/scripts/build/docker-compose.build.yml index 45b2871d7..645dfd930 100644 --- a/scripts/build/docker-compose.build.yml +++ b/scripts/build/docker-compose.build.yml @@ -255,10 +255,12 @@ services: (cd cs && mvn clean install -DskipTests) fi cp cs/rest/person-controller/target/person-controller-sut.jar /dist/ + cp cs/rest/redis-sample/target/redis-sample-sut.jar /dist/ cp cs/rest-gui/webgoat/target/webgoat-sut.jar /dist/ cp cs/rest-gui/microcks/webapp/target/microcks-sut.jar /dist/ if [ "$${BUILD_EVOMASTER:-false}" = "true" ]; then cp em/external/rest/person-controller/target/person-controller-evomaster-runner.jar /dist/ + cp em/external/rest/redis-sample/target/redis-sample-evomaster-runner.jar /dist/ cp em/external/rest-gui/webgoat/target/webgoat-evomaster-runner.jar /dist/ cp em/external/rest-gui/microcks/target/microcks-evomaster-runner.jar /dist/ fi diff --git a/scripts/dist.py b/scripts/dist.py index f28332b73..55a7aaa8b 100755 --- a/scripts/dist.py +++ b/scripts/dist.py @@ -294,6 +294,9 @@ def build_jdk_21_maven(): copy(folder + "/cs/rest/person-controller/target/person-controller-sut.jar", DIST) copy(folder + "/em/external/rest/person-controller/target/person-controller-evomaster-runner.jar", DIST) + copy(folder + "/cs/rest/redis-sample/target/redis-sample-sut.jar", DIST) + copy(folder + "/em/external/rest/redis-sample/target/redis-sample-evomaster-runner.jar", DIST) + copy(folder + "/cs/rest-gui/webgoat/target/webgoat-sut.jar", DIST) copy(folder + "/em/external/rest-gui/webgoat/target/webgoat-evomaster-runner.jar", DIST) diff --git a/scripts/dockerize/data/sut.csv b/scripts/dockerize/data/sut.csv index 7ae52af33..43c907bce 100644 --- a/scripts/dockerize/data/sut.csv +++ b/scripts/dockerize/data/sut.csv @@ -37,3 +37,4 @@ quartz-manager,TRUE,,--server.port=8080 --quartz-manager.security.accounts.in-me microcks,TRUE,-DPOSTMAN_RUNNER_URL=http://postman:3000 -DSERVICES_UPDATE_INTERVAL='0 0 0/2 * * *' -DKEYCLOAK_URL=http://keycloak:8080 -DKEYCLOAK_PUBLIC_URL=http://localhost:${AUTH_PORT:-8081} -DENABLE_CORS_POLICY=false -DCORS_REST_ALLOW_CREDENTIALS=true -DTEST_CALLBACK_URL=http://localhost:${HOST_PORT:-8080},--server.port=8080 --spring.profiles.active=prod --grpc.server.port=0 --spring.data.mongodb.uri=mongodb://mongodb:27017/test --spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:${AUTH_PORT:-8081}/realms/microcks --spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://keycloak:8080/realms/microcks/protocol/openid-connect/certs,http://localhost:8080/v3/api-docs,http://localhost:8080,FALSE,"","[{""name"": ""mongodb"", ""image_name"": ""mongo:7.0"", ""tmp_fs"": ""/data/db"", ""environment"": ""MONGODB_REPLICA_SET_MODE: primary;ALLOW_EMPTY_PASSWORD: yes"", ""volume"": """", ""health_check_command"": """"},{""name"": ""keycloak"",""image_name"": ""quay.io/keycloak/keycloak:26.0.0"", ""command"":[""start-dev"", ""--hostname=http://localhost:${AUTH_PORT:-8081}"", ""--import-realm"", ""--health-enabled=true""], ""port"": ""${AUTH_PORT:-8081}:8080"", ""tmp_fs"": """", ""environment"": ""KEYCLOAK_ADMIN: 'admin';KEYCLOAK_ADMIN_PASSWORD: 'admin';KC_HEALTH_ENABLED: 'true';KC_METRICS_ENABLED: 'true'"", ""volume"": ""../scripts/dockerize/data/additional_files/microcks/microcks-realm-sample.json:/opt/keycloak/data/import/microcks-realm.json"", ""health_check_command"": [""CMD"", ""sh"", ""-c"", ""echo -e 'GET /health/live HTTP/1.1\r\nHost: localhost\r\n\r\n' > /dev/tcp/localhost/9000""]},{""name"": ""postman"", ""image_name"": ""quay.io/microcks/microcks-postman-runtime:0.6.0"", ""tmp_fs"": """", ""environment"": """", ""volume"": """", ""health_check_command"": [""CMD"", ""curl"", ""-f"", ""http://localhost:3000/health""]}]" commafeed,TRUE,"-Dquarkus.http.port=8080 -Dquarkus.datasource.db-kind=h2 -Dquarkus.datasource.jdbc.url=""jdbc:h2:mem:commafeed;DB_CLOSE_DELAY=-1"" -Dquarkus.datasource.username=sa -Dquarkus.datasource.password=sa","",http://localhost:8080/openapi?format=json,http://localhost:8080,FALSE,"","" jasper,TRUE,,--server.port=8080 --spring.profiles.active=api-docs --spring.datasource.url=jdbc:postgresql://db:5432/jasper --spring.datasource.username=postgres --spring.datasource.password=password --spring.datasource.hikari.auto-commit=false --spring.jpa.database-platform=jasper.config.PostgreSQLDialect --springdoc.api-docs.path=/api/v3/api-docs --jasper.allow-user-tag-header=true --jasper.allow-user-role-header=true --jasper.allow-auth-headers=true,http://localhost:8080/api/v3/api-docs/jasper,http://localhost:8080,FALSE,,"[{""image_name"": ""postgres:18"", ""tmp_fs"": ""/var/lib/postgresql"", ""environment"": ""POSTGRES_PASSWORD: password;POSTGRES_HOST_AUTH_METHOD: trust;POSTGRES_DB: jasper"", ""volume"": """", ""health_check_command"": """"}]" +redis-sample,TRUE,"",--server.port=8080 --spring.data.redis.host=db --spring.data.redis.port=6379 --spring.data.redis.password=53cret --spring.autoconfigure.exclude=org.springframework.boot.security.autoconfigure.web.servlet.ServletWebSecurityAutoConfiguration --app.numberOfRatings=5000 --app.ratingStars=5,http://localhost:8080/v3/api-docs,http://localhost:8080,FALSE,"","[{""image_name"": ""redis:7.4-alpine"", ""tmp_fs"": """", ""environment"": """", ""volume"": """", ""health_check_command"": """", ""command"": ""redis-server --requirepass 53cret""}]" diff --git a/statistics/data.csv b/statistics/data.csv index 71ea4f7c2..80b1fbd4a 100644 --- a/statistics/data.csv +++ b/statistics/data.csv @@ -47,6 +47,7 @@ TRUE,signal-registration,gRPC,Java,JDK 17,Maven,177,13652,,UNDEFINED,5,FALSE,htt TRUE,webgoat,REST,Java,JDK 21,Maven,355,27638,H2,GPL,204,TRUE,https://github.com/WebGoat/WebGoat TRUE,commafeed,REST,Java,JDK 25,Maven,201,21287,H2,Apache,44,TRUE,https://github.com/Athou/commafeed TRUE,jasper,REST,Java,JDK 25,Maven,337,46791,PostgreSQL,MIT,61,TRUE,https://github.com/cjmalloy/jasper +TRUE,redis-sample,REST,Java,JDK 21,Maven,18,1006,Redis,UNDEFINED,4,FALSE,https://github.com/hendisantika/spring-boot-redis-sample FALSE,ind0,REST,Java,JDK 8,Gradle,103,17039,PostgreSQL,Proprietary,20,FALSE,UNDEFINED FALSE,ind1,REST,Java;Kotlin,JDK 11,Gradle,163,15240,PostgreSQL,Proprietary,53,FALSE,UNDEFINED diff --git a/statistics/table_emb.md b/statistics/table_emb.md index 4eb795fd6..de751d2e8 100644 --- a/statistics/table_emb.md +++ b/statistics/table_emb.md @@ -29,6 +29,7 @@ |REST|__person-controller__|1112|16|12|Java|JDK 21|Maven|MongoDB|| |REST|__proxyprint__|8338|73|74|Java|JDK 8|Maven|H2|✓| |REST|__quartz-manager__|5068|129|11|Java|JDK 11|Maven||✓| +|REST|__redis-sample__|1006|18|4|Java|JDK 21|Maven|Redis|| |REST|__reservations-api__|1853|39|7|Java|JDK 11|Gradle|MongoDB|✓| |REST|__rest-ncs__|605|9|6|Java|JDK 8|Maven||| |REST|__rest-news__|857|11|7|Kotlin|JDK 8|Maven|H2||