This is an automated email from the ASF dual-hosted git repository. elharo pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven-filtering.git
The following commit(s) were added to refs/heads/master by this push: new cf4f901 [MSHARED-1285] - refactor IncrementalResourceFilteringTest (#82) cf4f901 is described below commit cf4f901fdf348a7bd4eb8d03fea9c79d2307f8f3 Author: Laurent <lalme...@gmail.com> AuthorDate: Fri Dec 1 12:36:07 2023 +0100 [MSHARED-1285] - refactor IncrementalResourceFilteringTest (#82) Existing test uses a TestIncrementalBuildContext from plexus-build-api:tests that is buggy. isUptodate and hasDelta methods return wrong result, due to path resolution issues (wrong basedir, leading/trailing slashes). It seems it was not an issue for previous implementation as only the scanners were invoked by tests, and they provide the expected result. Future code changes need a better mock (and customizable, project bound) to allow now behaviour that invokes isUpdtodate or hasDelta methods. plexus-build-api:tests dependency is removed. --- pom.xml | 7 - .../IncrementalResourceFilteringTest.java | 91 ++++----- .../filtering/TestIncrementalBuildContext.java | 225 +++++++++++++++++++++ 3 files changed, 268 insertions(+), 55 deletions(-) diff --git a/pom.xml b/pom.xml index fe07781..b10733b 100644 --- a/pom.xml +++ b/pom.xml @@ -147,13 +147,6 @@ <version>${slf4jVersion}</version> <scope>test</scope> </dependency> - <dependency> - <groupId>org.sonatype.plexus</groupId> - <artifactId>plexus-build-api</artifactId> - <version>${plexusBuildApiVersion}</version> - <classifier>tests</classifier> - <scope>test</scope> - </dependency> <dependency> <groupId>org.eclipse.sisu</groupId> <artifactId>org.eclipse.sisu.plexus</artifactId> diff --git a/src/test/java/org/apache/maven/shared/filtering/IncrementalResourceFilteringTest.java b/src/test/java/org/apache/maven/shared/filtering/IncrementalResourceFilteringTest.java index b8104cb..0e6a5e9 100644 --- a/src/test/java/org/apache/maven/shared/filtering/IncrementalResourceFilteringTest.java +++ b/src/test/java/org/apache/maven/shared/filtering/IncrementalResourceFilteringTest.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -32,21 +33,25 @@ import java.util.Set; import org.apache.commons.io.FileUtils; import org.apache.maven.model.Resource; import org.sonatype.plexus.build.incremental.ThreadBuildContext; -import org.sonatype.plexus.build.incremental.test.TestIncrementalBuildContext; public class IncrementalResourceFilteringTest extends TestSupport { - File outputDirectory = new File(getBasedir(), "target/IncrementalResourceFilteringTest"); - - File unitDirectory = new File(getBasedir(), "src/test/units-files/incremental"); + Path baseDirectory = new File(getBasedir()).toPath(); + Path outputDirectory = baseDirectory.resolve("target/IncrementalResourceFilteringTest"); + Path unitDirectory = baseDirectory.resolve("src/test/units-files/incremental"); + Path filters = unitDirectory.resolve("filters.txt"); + Path inputFile01 = unitDirectory.resolve("files/file01.txt"); + Path inputFile02 = unitDirectory.resolve("files/file02.txt"); + Path outputFile01 = outputDirectory.resolve("file01.txt"); + Path outputFile02 = outputDirectory.resolve("file02.txt"); @Override protected void setUp() throws Exception { super.setUp(); - if (outputDirectory.exists()) { - FileUtils.deleteDirectory(outputDirectory); + if (outputDirectory.toFile().exists()) { + FileUtils.deleteDirectory(outputDirectory.toFile()); } - outputDirectory.mkdirs(); + outputDirectory.toFile().mkdirs(); } public void testSimpleIncrementalFiltering() throws Exception { @@ -57,33 +62,30 @@ public class IncrementalResourceFilteringTest extends TestSupport { assertTime("time", "file02.txt"); // only one file is expected to change - Set<String> changedFiles = new HashSet<>(); - changedFiles.add("file01.txt"); + Set<Path> changedFiles = new HashSet<>(); + changedFiles.add(inputFile01); - TestIncrementalBuildContext ctx = - new TestIncrementalBuildContext(unitDirectory, changedFiles, Collections.emptyMap()); + TestIncrementalBuildContext ctx = new TestIncrementalBuildContext(baseDirectory, changedFiles); ThreadBuildContext.setThreadBuildContext(ctx); filter("notime"); assertTime("notime", "file01.txt"); assertTime("time", "file02.txt"); // this one is unchanged - assertTrue(ctx.getRefreshFiles().contains(new File(outputDirectory, "file01.txt"))); + assertTrue(ctx.getRefreshFiles().contains(outputFile01)); + + // only one file is expected to change + Set<Path> deletedFiles = new HashSet<>(); + deletedFiles.add(inputFile01); - ctx = new TestIncrementalBuildContext( - unitDirectory, - Collections.emptySet(), - changedFiles, - Collections.emptyMap(), - new ArrayList(), - new ArrayList()); + ctx = new TestIncrementalBuildContext(baseDirectory, null, deletedFiles); ThreadBuildContext.setThreadBuildContext(ctx); filter("moretime"); - assertFalse(new File(outputDirectory, "file01.txt").exists()); + assertFalse(outputFile01.toFile().exists()); assertTime("time", "file02.txt"); // this one is unchanged - assertTrue(ctx.getRefreshFiles().contains(new File(outputDirectory, "file01.txt"))); + assertTrue(ctx.getRefreshFiles().contains(outputFile01)); } public void testOutputChange() throws Exception { @@ -91,18 +93,17 @@ public class IncrementalResourceFilteringTest extends TestSupport { filter("time"); // all files are reprocessed after contents of output directory changed (e.g. was deleted) - Set<String> changedFiles = new HashSet<>(); - changedFiles.add("target/IncrementalResourceFilteringTest"); - TestIncrementalBuildContext ctx = - new TestIncrementalBuildContext(unitDirectory, changedFiles, Collections.emptyMap()); + Set<Path> changedFiles = new HashSet<>(); + changedFiles.add(outputDirectory); + TestIncrementalBuildContext ctx = new TestIncrementalBuildContext(baseDirectory, changedFiles); ThreadBuildContext.setThreadBuildContext(ctx); filter("notime"); assertTime("notime", "file01.txt"); assertTime("notime", "file02.txt"); - assertTrue(ctx.getRefreshFiles().contains(new File(outputDirectory, "file01.txt"))); - assertTrue(ctx.getRefreshFiles().contains(new File(outputDirectory, "file02.txt"))); + assertTrue(ctx.getRefreshFiles().contains(outputFile01)); + assertTrue(ctx.getRefreshFiles().contains(outputFile02)); } public void testFilterChange() throws Exception { @@ -110,18 +111,17 @@ public class IncrementalResourceFilteringTest extends TestSupport { filter("time"); // all files are reprocessed after content of filters changes - Set<String> changedFiles = new HashSet<>(); - changedFiles.add("filters.txt"); - TestIncrementalBuildContext ctx = - new TestIncrementalBuildContext(unitDirectory, changedFiles, Collections.emptyMap()); + Set<Path> changedFiles = new HashSet<>(); + changedFiles.add(filters); + TestIncrementalBuildContext ctx = new TestIncrementalBuildContext(baseDirectory, changedFiles); ThreadBuildContext.setThreadBuildContext(ctx); filter("notime"); assertTime("notime", "file01.txt"); assertTime("notime", "file02.txt"); - assertTrue(ctx.getRefreshFiles().contains(new File(outputDirectory, "file01.txt"))); - assertTrue(ctx.getRefreshFiles().contains(new File(outputDirectory, "file02.txt"))); + assertTrue(ctx.getRefreshFiles().contains(outputFile01)); + assertTrue(ctx.getRefreshFiles().contains(outputFile02)); } public void testFilterDeleted() throws Exception { @@ -129,29 +129,24 @@ public class IncrementalResourceFilteringTest extends TestSupport { filter("time"); // all files are reprocessed after content of filters changes - Set<String> deletedFiles = new HashSet<>(); - deletedFiles.add("filters.txt"); - TestIncrementalBuildContext ctx = new TestIncrementalBuildContext( - unitDirectory, - Collections.emptySet(), - deletedFiles, - Collections.emptyMap(), - new ArrayList(), - new ArrayList()); + Set<Path> deletedFiles = new HashSet<>(); + deletedFiles.add(filters); + TestIncrementalBuildContext ctx = new TestIncrementalBuildContext(unitDirectory, null, deletedFiles); ThreadBuildContext.setThreadBuildContext(ctx); filter("notime"); assertTime("notime", "file01.txt"); assertTime("notime", "file02.txt"); - assertTrue(ctx.getRefreshFiles().contains(new File(outputDirectory, "file01.txt"))); - assertTrue(ctx.getRefreshFiles().contains(new File(outputDirectory, "file02.txt"))); + assertTrue(ctx.getRefreshFiles().contains(outputFile01)); + assertTrue(ctx.getRefreshFiles().contains(outputFile02)); } private void assertTime(String time, String relpath) throws IOException { Properties properties = new Properties(); - try (InputStream is = new FileInputStream(new File(outputDirectory, relpath))) { + try (InputStream is = + new FileInputStream(outputDirectory.resolve(relpath).toFile())) { properties.load(is); } @@ -171,7 +166,7 @@ public class IncrementalResourceFilteringTest extends TestSupport { mavenProject.setProperties(projectProperties); MavenResourcesFiltering mavenResourcesFiltering = lookup(MavenResourcesFiltering.class); - String unitFilesDir = new File(unitDirectory, "files").getPath(); + String unitFilesDir = unitDirectory.resolve("files").toString(); Resource resource = new Resource(); List<Resource> resources = new ArrayList<>(); @@ -180,11 +175,11 @@ public class IncrementalResourceFilteringTest extends TestSupport { resource.setFiltering(true); List<String> filtersFile = new ArrayList<>(); - filtersFile.add(new File(unitDirectory, "filters.txt").getPath()); + filtersFile.add(unitDirectory.resolve("filters.txt").toString()); MavenResourcesExecution mre = new MavenResourcesExecution(); mre.setResources(resources); - mre.setOutputDirectory(outputDirectory); + mre.setOutputDirectory(outputDirectory.toFile()); mre.setEncoding("UTF-8"); mre.setMavenProject(mavenProject); mre.setFilters(filtersFile); diff --git a/src/test/java/org/apache/maven/shared/filtering/TestIncrementalBuildContext.java b/src/test/java/org/apache/maven/shared/filtering/TestIncrementalBuildContext.java new file mode 100644 index 0000000..f04b8e5 --- /dev/null +++ b/src/test/java/org/apache/maven/shared/filtering/TestIncrementalBuildContext.java @@ -0,0 +1,225 @@ +/* + * 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 java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.Scanner; +import org.sonatype.plexus.build.incremental.BuildContext; + +/** + * {@link TestIncrementalBuildContext} mock for testing purpose. It allows to + * check build behavior based on {@link #isUptodate(File, File)} return value. + * + * Constructor parameters allow to indicate folder/files to declare files as + * modified / deleted. + * + * hasDelta, isUptodate, newScanner, newDeleteScanner methods output consistent + * values based upon changedFiles / deletedFiles inputs. + * + * getRefreshFiles method allows to check files modified by build. + */ +public class TestIncrementalBuildContext implements BuildContext { + + private final Path basedir; + private final Set<Path> refresh = new HashSet<Path>(); + private final Set<Path> changedFiles = new HashSet<Path>(); + private final Set<Path> deletedFiles = new HashSet<Path>(); + private final Map<String, Object> context = new HashMap<>(); + + public TestIncrementalBuildContext(Path basedir, Set<Path> changedFiles) { + this(basedir, changedFiles, null); + } + + public TestIncrementalBuildContext(Path basedir, Set<Path> changedFiles, Set<Path> deletedFiles) { + checkPath(basedir); + this.basedir = basedir; + Optional.ofNullable(changedFiles).ifPresent(this.changedFiles::addAll); + Optional.ofNullable(deletedFiles).ifPresent(this.deletedFiles::addAll); + this.changedFiles.forEach(TestIncrementalBuildContext::checkPath); + this.deletedFiles.forEach(TestIncrementalBuildContext::checkPath); + } + + public static void checkPath(Path path) { + if (!path.isAbsolute()) { + throw new IllegalStateException(String.format("Absolute path are expected. Failing path %s" + path)); + } + } + + public Set<Path> getRefreshFiles() { + return Collections.unmodifiableSet(refresh); + } + + /** + * Check that relpath or parent folders of relpath is not listed in modified / + * deleted files. + */ + @Override + public boolean hasDelta(String relpath) { + Path resolved = basedir.resolve(relpath); + Path candidate = resolved; + boolean changed = false; + while (candidate != null) { + changed = changedFiles.contains(candidate) || deletedFiles.contains(candidate); + if (changed || candidate.equals(basedir)) { + break; + } + candidate = candidate.getParent(); + } + return changed; + } + + @SuppressWarnings("unchecked") + @Override + public boolean hasDelta(@SuppressWarnings("rawtypes") List relpaths) { + return ((List<String>) relpaths).stream().anyMatch(this::hasDelta); + } + + @Override + public boolean hasDelta(File file) { + return hasDelta(file.getAbsolutePath()); + } + + @Override + public boolean isIncremental() { + return true; + } + + @Override + public Scanner newDeleteScanner(File basedir) { + return new TestScanner(basedir, deletedFiles); + } + + @Override + public OutputStream newFileOutputStream(File file) throws IOException { + refresh(file); + return new FileOutputStream(file); + } + + @Override + public Scanner newScanner(final File basedir) { + return new TestScanner(basedir, changedFiles); + } + + @Override + public Scanner newScanner(File basedir, boolean ignoreDelta) { + if (ignoreDelta) { + DirectoryScanner directoryScanner = new DirectoryScanner(); + directoryScanner.setBasedir(basedir); + return directoryScanner; + } + + return newScanner(basedir); + } + + @Override + public void refresh(File file) { + refresh.add(file.toPath()); + } + + @Override + public Object getValue(String key) { + return context.get(key); + } + + @Override + public void setValue(String key, Object value) { + context.put(key, value); + } + + @Override + public void addError(File file, int line, int column, String message, Throwable cause) {} + + @Override + public void addWarning(File file, int line, int column, String message, Throwable cause) {} + + @Override + public void addMessage(File file, int line, int column, String message, int severity, Throwable cause) {} + + @Override + public void removeMessages(File file) {} + + @Override + public boolean isUptodate(File target, File source) { + return target != null + && target.exists() + && !hasDelta(target) + && source != null + && source.exists() + && !hasDelta(source) + && target.lastModified() > source.lastModified(); + } + + private static final class TestScanner implements Scanner { + private final Path basedir; + private final Set<Path> files = new HashSet<>(); + + private TestScanner(File basedir, Set<Path> files) { + this.basedir = basedir.toPath().toAbsolutePath(); + Optional.ofNullable(files).ifPresent(this.files::addAll); + } + + @Override + public void addDefaultExcludes() {} + + @Override + public String[] getIncludedDirectories() { + return new String[0]; + } + + @Override + public String[] getIncludedFiles() { + return files.stream() + .filter(p -> p.startsWith(basedir)) + .map(p -> basedir.relativize(p)) + .map(Path::toString) + .toArray(i -> new String[i]); + } + + @Override + public void scan() {} + + @Override + public void setExcludes(String[] excludes) {} + + @Override + public void setIncludes(String[] includes) {} + + @Override + public File getBasedir() { + return basedir.toFile(); + } + + @Override + public void setFilenameComparator(Comparator<String> filenameComparator) {} + } +}