You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2026/05/10 15:48:45 UTC

(maven-filtering) 01/02: Add regression test for filtering with overlapping entries

This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a commit to branch maven-filtering-3.x
in repository https://gitbox.apache.org/repos/asf/maven-filtering.git

commit 306db119ad9571e176de7558ba6e37877c78f8ac
Author: Richard Zowalla <rz...@apache.org>
AuthorDate: Tue May 5 11:17:42 2026 +0200

    Add regression test for filtering with overlapping <resource> entries
    
    When a directory is covered by two <resource> entries — one with
    filtering=true and a narrow <include>, the other with filtering=false and
    <include>**</include> — the placeholder in the file selected by the first
    entry is no longer replaced. This was introduced between maven-filtering
    3.3.1 and 3.3.2 and surfaced downstream as
    https://github.com/apache/maven-resources-plugin/issues/471.
    
    The new test calls MavenResourcesFiltering directly (no plugin invoker), so
    the failure can be reproduced and bisected within this repository. It also
    asserts that files matched only by the unfiltered <resource> entry still
    keep their literal placeholders, so a fix cannot trivially "filter
    everything".
---
 .../OverlappingResourcesFilteringTest.java         | 148 +++++++++++++++++++++
 src/test/units-files/MRP-471/config/filtered.xml   |   4 +
 src/test/units-files/MRP-471/static/keep-as-is.txt |   1 +
 3 files changed, 153 insertions(+)

diff --git a/src/test/java/org/apache/maven/shared/filtering/OverlappingResourcesFilteringTest.java b/src/test/java/org/apache/maven/shared/filtering/OverlappingResourcesFilteringTest.java
new file mode 100644
index 0000000..8e2a099
--- /dev/null
+++ b/src/test/java/org/apache/maven/shared/filtering/OverlappingResourcesFilteringTest.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.shared.filtering;
+
+import javax.inject.Inject;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.model.Resource;
+import org.codehaus.plexus.testing.PlexusTest;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.codehaus.plexus.testing.PlexusExtension.getBasedir;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Reproduces the regression first reported against
+ * <a href="https://github.com/apache/maven-resources-plugin/issues/471">
+ * maven-resources-plugin issue #471</a>.
+ *
+ * <p>When a single source directory is covered by two {@link Resource} entries — one with
+ * {@code filtering=true} and a narrow {@code <include>}, the other with {@code filtering=false}
+ * and a broad {@code <include>**</include>} — the file selected by the first entry must still be
+ * filtered. From {@code maven-filtering 3.3.2} onwards (pulled in by
+ * {@code maven-resources-plugin 3.4.0}), the placeholder is left as the literal {@code ${...}}
+ * text instead of being replaced.</p>
+ *
+ * <p>The {@code static/keep-as-is.txt} file, only matched by the second (unfiltered) entry, is
+ * expected to keep its placeholder verbatim — the test asserts both halves so a future fix
+ * cannot trivially "always filter everything".</p>
+ */
+@PlexusTest
+class OverlappingResourcesFilteringTest {
+
+    private final File outputDirectory = new File(getBasedir(), "target/OverlappingResourcesFilteringTest");
+    private final File baseDir = new File(getBasedir());
+    private final StubMavenProject mavenProject = new StubMavenProject(baseDir);
+
+    @Inject
+    private MavenResourcesFiltering mavenResourcesFiltering;
+
+    @BeforeEach
+    void setUp() throws Exception {
+        if (outputDirectory.exists()) {
+            FileUtils.deleteDirectory(outputDirectory);
+        }
+        outputDirectory.mkdirs();
+
+        mavenProject.setVersion("1.0");
+        mavenProject.setGroupId("org.apache");
+        mavenProject.setName("MRP-471 repro");
+    }
+
+    @Test
+    void overlappingResourceEntriesShouldStillFilter() throws Exception {
+        Properties projectProperties = new Properties();
+        projectProperties.put("repro.value", "REPLACED_BY_FILTERING");
+        mavenProject.setProperties(projectProperties);
+
+        String unitFilesDir = getBasedir() + "/src/test/units-files/MRP-471";
+
+        // Mirrors the failing POM configuration:
+        //   <resource>
+        //     <filtering>true</filtering>
+        //     <directory>src/main/resources</directory>
+        //     <includes><include>config/filtered.xml</include></includes>
+        //   </resource>
+        //   <resource>
+        //     <filtering>false</filtering>
+        //     <directory>src/main/resources</directory>
+        //     <includes><include>**</include></includes>
+        //   </resource>
+        Resource filtered = new Resource();
+        filtered.setDirectory(unitFilesDir);
+        filtered.setFiltering(true);
+        filtered.addInclude("config/filtered.xml");
+
+        Resource unfiltered = new Resource();
+        unfiltered.setDirectory(unitFilesDir);
+        unfiltered.setFiltering(false);
+        unfiltered.addInclude("**");
+
+        List<Resource> resources = Arrays.asList(filtered, unfiltered);
+
+        MavenResourcesExecution execution = new MavenResourcesExecution(
+                resources,
+                outputDirectory,
+                mavenProject,
+                "UTF-8",
+                Collections.emptyList(),
+                Collections.emptyList(),
+                new StubMavenSession());
+        execution.setUseDefaultFilterWrappers(true);
+
+        mavenResourcesFiltering.filterResources(execution);
+
+        File filteredOut = new File(outputDirectory, "config/filtered.xml");
+        File unfilteredOut = new File(outputDirectory, "static/keep-as-is.txt");
+        assertTrue(filteredOut.isFile(), "expected " + filteredOut + " to be copied");
+        assertTrue(unfilteredOut.isFile(), "expected " + unfilteredOut + " to be copied");
+
+        String filteredContent = new String(Files.readAllBytes(filteredOut.toPath()), StandardCharsets.UTF_8);
+        String unfilteredContent = new String(Files.readAllBytes(unfilteredOut.toPath()), StandardCharsets.UTF_8);
+
+        // The placeholder targeted by the filtered <resource> entry must be replaced.
+        // Regression on maven-filtering >= 3.3.2: the literal ${repro.value} is left in place.
+        assertTrue(
+                filteredContent.contains("REPLACED_BY_FILTERING"),
+                "config/filtered.xml should have ${repro.value} replaced; got:\n" + filteredContent);
+        assertFalse(
+                filteredContent.contains("${repro.value}"),
+                "config/filtered.xml still contains the literal placeholder — see "
+                        + "https://github.com/apache/maven-resources-plugin/issues/471\n"
+                        + filteredContent);
+
+        // The second (unfiltered) entry must leave files matched only by it untouched —
+        // this guards against a fix that just turns filtering on for everything.
+        assertTrue(
+                unfilteredContent.contains("${repro.value}"),
+                "static/keep-as-is.txt is matched by filtering=false and must keep the literal "
+                        + "placeholder; got:\n" + unfilteredContent);
+    }
+}
diff --git a/src/test/units-files/MRP-471/config/filtered.xml b/src/test/units-files/MRP-471/config/filtered.xml
new file mode 100644
index 0000000..c503f42
--- /dev/null
+++ b/src/test/units-files/MRP-471/config/filtered.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<config>
+  <property name="value">${repro.value}</property>
+</config>
diff --git a/src/test/units-files/MRP-471/static/keep-as-is.txt b/src/test/units-files/MRP-471/static/keep-as-is.txt
new file mode 100644
index 0000000..7ea53b2
--- /dev/null
+++ b/src/test/units-files/MRP-471/static/keep-as-is.txt
@@ -0,0 +1 @@
+Not filtered. Placeholder must stay verbatim: ${repro.value}