E2E-functional-tests: Maven functional tests exercise real Maven Native Image builds
August 26, 2026 · View on GitHub
Maven end-to-end coverage lives under native-maven-plugin/src/functionalTest/. These tests run
sample projects, generated projects, or issue reproducers through an isolated Maven executor,
seed a local Maven repository with plugin and support artifacts, and verify the behavior users see
from the Maven plugin. They provide executable evidence for the focused Maven functional specs
under docs/functional/, §AR-maven-plugin, and the shared product contract in
§root/FS-plugin-common.
1. Full local suite
Run the full Maven plugin functional suite locally with:
./gradlew :native-maven-plugin:functionalTest
This suite publishes the plugin and support artifacts to the local test repository, then runs Maven sample or reproducer projects as external builds. That shape is intentional: it catches descriptor, goal, lifecycle, repository, and command-line behavior that unit tests cannot see.
2. Single functional test class
Run one Maven functional test class with:
./gradlew :native-maven-plugin:functionalTest \
--tests org.graalvm.buildtools.maven.JavaApplicationFunctionalTest
For tests that require process isolation while debugging, use the documented -DnoTestIsolation
flag from the repository developer guide. Use Maven debug output from the functional test when the
goal configuration, lifecycle phase, or generated command line is the failure surface.
3. Scenario Coverage
3.1 Lifecycle native builds
JavaApplicationFunctionalTest, JavaLibraryFunctionalTest, and profile-based sample builds verify
compile-no-fork bound to lifecycle phases such as package. This protects
§FS-goal-surface.1, §FS-goal-surface.4, and §FS-native-builds.
3.2 Direct goal usage
JavaApplicationFunctionalTest and related functional tests verify direct goal usage such as
native:compile, native:write-args-file, and support goals. This protects
§FS-goal-surface.1, §FS-goal-surface.3, and §FS-native-builds.8.
3.3 Native tests
JavaApplicationWithTestsFunctionalTest, MavenTestExecutionFunctionalTests,
JUnitFunctionalTests, and issues/ModuleWithoutSourcesFunctionalTest verify native:test, skip
flags, no-test behavior, runtime arguments, launcher selection, and reactor modules without source
artifacts. This protects §FS-goal-surface.2, §FS-native-tests, and
§root/FS-native-tests.
3.4 Resources
JavaApplicationWithResourcesFunctionalTest verifies main and test resource configuration
generation and resource propagation into native builds. This protects §FS-native-builds.4 and
§FS-resources-and-metadata.1.
3.5 Reachability metadata
MetadataRepositoryFunctionalTest, OfficialMetadataRepositoryFunctionalTest, and
issues/ExcludeDependenciesFunctionalTest with reproducers/issue-612 verify official and local
metadata repositories, exclusions, forced versions, archives, URLs, and missing metadata reports.
This protects §FS-resources-and-metadata.2, §FS-resources-and-metadata.3, and §common/FS-common-libraries.5.
3.6 Tracing agent
JavaApplicationWithAgentFunctionalTest verifies -Dagent=true, standard/direct/conditional modes,
disabled stages, merge behavior, and native:metadata-copy. This protects §FS-tracing-agent and
§common/FS-common-libraries.3.
3.6.1 Shared reactor destination
issues/MetadataCopyReactorFunctionalTest with reproducers/issue-650 verifies deterministic
replacement and merge behavior when sequential reactor modules share one metadata destination. It
also verifies that replacement removes metadata types absent from the later module and that a failed
native-image-configure invocation leaves the destination unchanged without staging output. This
protects §FS-tracing-agent.4.1.
3.7 Maven integration
SBOMFunctionalTest, JavaApplicationWithTestsFunctionalTest, issues/JavaAppWithTestsAndParentPomFunctionalTest
with reproducers/issue-144, and issues/ModuleWithoutSourcesFunctionalTest with
reproducers/issue-727 verify shaded JARs, custom packaging, SBOM behavior, parent POM merging,
issue reproducers, and local repository seeding. This protects §FS-native-builds.6,
§FS-config-model.3, and §AR-maven-plugin.6.
3.8 Layer artifacts
LayeredApplicationFunctionalTest verifies that a reactor producer creates and attaches a nil
layer artifact, a consumer resolves it outside the Java classpath, and the application image
consumes the layer, executes, and produces the expected output. This protects §FS-goal-surface.6,
§FS-native-builds.3, and
§FS-config-model.7.
The class is the executable evidence for module, package, explicit-path, and all selection,
plus main, native-test, and shared-library layer consumption.
Layer-consumption scenarios that exercise all selection, explicit paths, native tests, shared
libraries are skipped on GraalVM 25.0.x because Native Image can fail after -H:LayerUse loads a
valid layer.
When adding behavior that a user can observe through a Maven goal, plugin parameter, generated file, lifecycle binding, or Native Image invocation, add or update a functional test in the closest scenario family.
4. Local repository setup
Functional tests seed a local Maven repository before executing sample or reproducer builds. This keeps tests independent from external publication and protects the Maven-specific architecture in §AR-maven-plugin.6.
The local repository is part of the test contract: tests should resolve the plugin exactly as a sample project would, rather than reaching into compiled classes directly.
Online prepareMavenLocalRepo builds a replacement seed in staging and publishes it only after
Maven succeeds. Its seed-state manifest keys the prepared seeding project, Maven settings,
embedder classpath, goals, flags, supplied version/system-property values, the explicit Java 17
launcher, and seed schema. The fresh staging repository follows Maven's normal remote snapshot
policy rather than requesting unconditional snapshot updates. The manifest inventories every
stable repository file by relative path and content hash; transient locks, temporary downloads,
and resolver-status files are excluded.
Repository-internal Maven executions use the Gradle toolchain-provided Java 17 launcher regardless
of the runtime that launched Gradle or the separately selected functional-test JVM. Ordinary
execution captures Maven's routine streams, omits Maven error stacks, and reports one actionable
Gradle failure. A dependency-resolution failure identifies the first unresolved artifact and
repository, sanitizing repository URLs by removing credentials, query values, and fragments; an
unclassified failure reports the final meaningful Maven error. Gradle --info replays the captured
Maven output and enables Maven error detail, while Gradle --debug additionally enables Maven debug
output. Descriptor generation uses an isolated task-local Maven repository and clears failed-transfer
markers before execution so stale negative cache entries cannot require snapshot refreshes. These
launcher and effective argument inputs participate in seed validity.
Offline descriptor and functional-test prerequisites validate that manifest without invoking
Maven or modifying the repository. Validation requires the current input key and the complete
inventoried file set with matching hashes. Missing, stale, truncated, or corrupted state fails
with: The seeded Maven repository is missing or stale; run prepareMavenLocalRepo online. A
failed online refresh or offline validation must leave the previous repository unchanged. Offline
functional tests copy the validated seed and current common publication repository into their
isolated local repository and invoke Maven offline, so they neither alter the seed nor contact
remote repositories.
5. CI coverage
test-native-maven-plugin.yml runs generated Maven functional-test matrices, Maven plugin
inspections, and GraalVM dev-build
functional tests on pull requests. The CI workflow is specified by §root/AR-repository-ci.1.4.
The CI matrix is the merge gate. Local runs should reproduce the failing class or reproducer first, then broaden to the full suite before pushing behavior changes that affect goals, Maven parameter binding, Native Image invocation, metadata, resources, SBOM behavior, or native tests.