diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPlugin.java b/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPlugin.java index 51d56347154a6..3d3b31f50b1b1 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPlugin.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPlugin.java @@ -31,6 +31,8 @@ import org.gradle.util.GradleVersion; import io.quarkus.gradle.builder.QuarkusModelBuilder; +import io.quarkus.gradle.extension.QuarkusPluginExtension; +import io.quarkus.gradle.extension.SourceSetExtension; import io.quarkus.gradle.tasks.QuarkusAddExtension; import io.quarkus.gradle.tasks.QuarkusBuild; import io.quarkus.gradle.tasks.QuarkusDev; @@ -244,13 +246,37 @@ private void configureBuildNativeTask(Project project) { private void afterEvaluate(Project project) { final HashSet visited = new HashSet<>(); - project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME) + ConfigurationContainer configurations = project.getConfigurations(); + configurations.getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME) .getIncoming().getDependencies() .forEach(d -> { if (d instanceof ProjectDependency) { visitProjectDep(project, ((ProjectDependency) d).getDependencyProject(), visited); } }); + + SourceSetExtension sourceSetExtension = project.getExtensions().getByType(QuarkusPluginExtension.class) + .sourceSetExtension(); + + if (sourceSetExtension.extraNativeTest() != null) { + + SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class) + .getSourceSets(); + SourceSet nativeTestSourceSets = sourceSets.getByName(NATIVE_TEST_SOURCE_SET_NAME); + nativeTestSourceSets.setCompileClasspath( + nativeTestSourceSets.getCompileClasspath().plus(sourceSetExtension.extraNativeTest().getOutput())); + nativeTestSourceSets.setRuntimeClasspath( + nativeTestSourceSets.getRuntimeClasspath().plus(sourceSetExtension.extraNativeTest().getOutput())); + + configurations.findByName(NATIVE_TEST_IMPLEMENTATION_CONFIGURATION_NAME).extendsFrom( + configurations.findByName(sourceSetExtension.extraNativeTest().getImplementationConfigurationName())); + configurations.findByName(NATIVE_TEST_RUNTIME_ONLY_CONFIGURATION_NAME).extendsFrom( + configurations.findByName(sourceSetExtension.extraNativeTest().getRuntimeOnlyConfigurationName())); + + QuarkusTestNative nativeTest = (QuarkusTestNative) project.getTasks().getByName(TEST_NATIVE_TASK_NAME); + nativeTest.setTestClassesDirs(nativeTestSourceSets.getOutput().getClassesDirs()); + nativeTest.setClasspath(nativeTestSourceSets.getRuntimeClasspath()); + } } private void visitProjectDep(Project project, Project dep, Set visited) { diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPluginExtension.java b/devtools/gradle/src/main/java/io/quarkus/gradle/extension/QuarkusPluginExtension.java similarity index 94% rename from devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPluginExtension.java rename to devtools/gradle/src/main/java/io/quarkus/gradle/extension/QuarkusPluginExtension.java index 944aaba7f0f11..0090ae6b749cc 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPluginExtension.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/extension/QuarkusPluginExtension.java @@ -1,4 +1,4 @@ -package io.quarkus.gradle; +package io.quarkus.gradle.extension; import java.io.File; import java.nio.file.Path; @@ -9,6 +9,7 @@ import java.util.StringJoiner; import java.util.stream.Collectors; +import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.file.FileCollection; import org.gradle.api.file.RegularFile; @@ -28,6 +29,7 @@ import io.quarkus.bootstrap.resolver.model.ModelParameter; import io.quarkus.bootstrap.resolver.model.QuarkusModel; import io.quarkus.bootstrap.resolver.model.impl.ModelParameterImpl; +import io.quarkus.gradle.AppModelGradleResolver; import io.quarkus.gradle.builder.QuarkusModelBuilder; import io.quarkus.gradle.tasks.QuarkusGradleUtils; import io.quarkus.runtime.LaunchMode; @@ -46,11 +48,14 @@ public class QuarkusPluginExtension { private File outputConfigDirectory; + private final SourceSetExtension sourceSetExtension; + public QuarkusPluginExtension(Project project) { this.project = project; + this.sourceSetExtension = new SourceSetExtension(); } - void beforeTest(Test task) { + public void beforeTest(Test task) { try { final Map props = task.getSystemProperties(); @@ -176,6 +181,14 @@ public void setFinalName(String finalName) { this.finalName = finalName; } + public void sourceSets(Action action) { + action.execute(this.sourceSetExtension); + } + + public SourceSetExtension sourceSetExtension() { + return sourceSetExtension; + } + public Set resourcesDir() { return getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME).getResources().getSrcDirs(); } diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/extension/SourceSetExtension.java b/devtools/gradle/src/main/java/io/quarkus/gradle/extension/SourceSetExtension.java new file mode 100644 index 0000000000000..7685ddb1c4eaa --- /dev/null +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/extension/SourceSetExtension.java @@ -0,0 +1,16 @@ +package io.quarkus.gradle.extension; + +import org.gradle.api.tasks.SourceSet; + +public class SourceSetExtension { + + private SourceSet extraNativeTestSourceSet; + + public SourceSet extraNativeTest() { + return extraNativeTestSourceSet; + } + + public void setExtraNativeTest(SourceSet extraNativeTestSourceSet) { + this.extraNativeTestSourceSet = extraNativeTestSourceSet; + } +} diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusTask.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusTask.java index d040a63ec5216..257ce171183a4 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusTask.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusTask.java @@ -6,7 +6,7 @@ import org.gradle.api.DefaultTask; import io.quarkus.bootstrap.model.AppArtifact; -import io.quarkus.gradle.QuarkusPluginExtension; +import io.quarkus.gradle.extension.QuarkusPluginExtension; public abstract class QuarkusTask extends DefaultTask { diff --git a/devtools/gradle/src/test/java/io/quarkus/gradle/QuarkusPluginTest.java b/devtools/gradle/src/test/java/io/quarkus/gradle/QuarkusPluginTest.java index f948f3eb6e761..eb3ead6946675 100644 --- a/devtools/gradle/src/test/java/io/quarkus/gradle/QuarkusPluginTest.java +++ b/devtools/gradle/src/test/java/io/quarkus/gradle/QuarkusPluginTest.java @@ -14,6 +14,8 @@ import org.gradle.testfixtures.ProjectBuilder; import org.junit.jupiter.api.Test; +import io.quarkus.gradle.extension.QuarkusPluginExtension; + public class QuarkusPluginTest { @Test diff --git a/docs/src/main/asciidoc/gradle-tooling.adoc b/docs/src/main/asciidoc/gradle-tooling.adoc index a4301c5b9bede..49252ce363928 100644 --- a/docs/src/main/asciidoc/gradle-tooling.adoc +++ b/docs/src/main/asciidoc/gradle-tooling.adoc @@ -397,6 +397,21 @@ Run the native tests using: This task depends on `quarkusBuild`, so it will generate the native image before running the tests. +[NOTE] +==== +By default, the `native-test` source set is based on `main` and `test` source sets. It is possible to add an extra source set. For example, if your integration tests are located in an `integrationTest` source set, you can specify it as: + +[source,groovy] +---- +quarkus { + sourceSets { + extraNativeTest = sourceSets.integrationTest + } +} +---- + +==== + == Building Uber-Jars Quarkus Gradle plugin supports the generation of Uber-Jars by specifying a `quarkus.package.type` argument as follows: diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/CustomNativeTestSourceSetTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/CustomNativeTestSourceSetTest.java new file mode 100644 index 0000000000000..e93ca9c7d11cb --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/CustomNativeTestSourceSetTest.java @@ -0,0 +1,21 @@ +package io.quarkus.gradle.nativeimage; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; + +import org.junit.jupiter.api.Test; + +import io.quarkus.gradle.BuildResult; + +public class CustomNativeTestSourceSetTest extends QuarkusNativeGradleTestBase { + + @Test + public void runNativeTests() throws Exception { + final File projectDir = getProjectDir("custom-java-native-sourceset-module"); + + final BuildResult build = runGradleWrapper(projectDir, "clean", "testNative"); + assertThat(build.getTasks().get(":testNative")).isEqualTo(BuildResult.SUCCESS_OUTCOME); + } + +} diff --git a/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/build.gradle b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/build.gradle new file mode 100644 index 0000000000000..706e36869c219 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/build.gradle @@ -0,0 +1,55 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + if (System.properties.containsKey('maven.repo.local')) { + maven { + url System.properties.get('maven.repo.local') + } + } else { + mavenLocal() + } + mavenCentral() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-resteasy' + + testImplementation 'io.quarkus:quarkus-junit5' + testImplementation 'io.rest-assured:rest-assured' +} + +group 'org.acme' +version '1.0.0-SNAPSHOT' + +compileJava { + options.encoding = 'UTF-8' + options.compilerArgs << '-parameters' +} + +compileTestJava { + options.encoding = 'UTF-8' +} + +sourceSets { + integrationTest { + java.srcDir file('src/integration-test/java') + resources.srcDir file('src/integration-test/resources') + compileClasspath += sourceSets.main.output + project.configurations.testCompileClasspath + runtimeClasspath += sourceSets.main.output + project.configurations.testRuntimeClasspath + } +} + +quarkus { + sourceSets { + extraNativeTest = sourceSets.integrationTest + } +} +quarkusBuild { + nativeArgs { + additionalArgs= ["--verbose"] + } +} diff --git a/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/gradle.properties b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/gradle.properties new file mode 100644 index 0000000000000..ec2b6ef199c2c --- /dev/null +++ b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/gradle.properties @@ -0,0 +1,2 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus diff --git a/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/settings.gradle b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/settings.gradle new file mode 100644 index 0000000000000..72f00e40a2b5b --- /dev/null +++ b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/settings.gradle @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + if (System.properties.containsKey('maven.repo.local')) { + maven { + url System.properties.get('maven.repo.local') + } + } else { + mavenLocal() + } + mavenCentral() + gradlePluginPortal() + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + } +} +rootProject.name='foo' \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/src/integration-test/java/org/acme/ExampleResourceTest.java b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/src/integration-test/java/org/acme/ExampleResourceTest.java new file mode 100644 index 0000000000000..b695c6be461e1 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/src/integration-test/java/org/acme/ExampleResourceTest.java @@ -0,0 +1,21 @@ +package org.acme; + +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; + +@QuarkusTest +public class ExampleResourceTest { + + @Test + public void testHelloEndpoint() { + given() + .when().get("/hello") + .then() + .statusCode(200) + .body(is("hello")); + } + +} \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/src/main/java/org/acme/HelloResource.java b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/src/main/java/org/acme/HelloResource.java new file mode 100644 index 0000000000000..89804c62b5e24 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/src/main/java/org/acme/HelloResource.java @@ -0,0 +1,16 @@ +package org.acme; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/hello") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/src/native-test/java/org/acme/ExampleResourceNativeTest.java b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/src/native-test/java/org/acme/ExampleResourceNativeTest.java new file mode 100644 index 0000000000000..6213d57d91613 --- /dev/null +++ b/integration-tests/gradle/src/test/resources/custom-java-native-sourceset-module/src/native-test/java/org/acme/ExampleResourceNativeTest.java @@ -0,0 +1,6 @@ +package org.acme; + +import io.quarkus.test.junit.NativeImageTest; + +@NativeImageTest +public class ExampleResourceNativeTest extends ExampleResourceTest {} \ No newline at end of file