| /* |
| * 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.it; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.nio.file.FileVisitResult; |
| import java.nio.file.FileVisitor; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.nio.file.attribute.BasicFileAttributes; |
| |
| import org.apache.maven.shared.utils.io.FileUtils; |
| import org.apache.maven.shared.verifier.VerificationException; |
| import org.apache.maven.shared.verifier.Verifier; |
| import org.apache.maven.shared.verifier.util.ResourceExtractor; |
| import org.junit.jupiter.api.Test; |
| |
| import static java.nio.file.FileVisitResult.CONTINUE; |
| |
| /** |
| * This is a test case for a new check introduced with <a href="https://issues.apache.org/jira/browse/MNG-4660">MNG-4660</a>. |
| * That check verifies if a packaged artifact within the Reactor is up-to-date with the outputDirectory of the same project. |
| * |
| * @author Maarten Mulders |
| * @author Martin Kanters |
| */ |
| public class MavenITmng4660OutdatedPackagedArtifact extends AbstractMavenIntegrationTestCase { |
| public MavenITmng4660OutdatedPackagedArtifact() { |
| super("[4.0.0-alpha-1,)"); |
| } |
| |
| /** |
| * Test that Maven logs a warning when a packaged artifact is found that is older than the outputDirectory of the |
| * same artifact. |
| * |
| * @throws Exception in case of failure |
| */ |
| @Test |
| public void testShouldWarnWhenPackagedArtifactIsOutdated() throws Exception { |
| final File testDir = |
| ResourceExtractor.simpleExtractResources(getClass(), "/mng-4660-outdated-packaged-artifact"); |
| Files.createDirectories(testDir.toPath().resolve(".mvn")); |
| |
| // 1. Package the whole project |
| final Verifier verifier1 = newVerifier(testDir.getAbsolutePath()); |
| verifier1.deleteDirectory("target"); |
| verifier1.deleteArtifacts("org.apache.maven.its.mng4660"); |
| |
| verifier1.addCliArgument("package"); |
| verifier1.execute(); |
| |
| Path module1Jar = |
| testDir.toPath().resolve("module-a/target/module-a-1.0.jar").toAbsolutePath(); |
| verifier1.verifyErrorFreeLog(); |
| verifier1.verifyFilePresent(module1Jar.toString()); |
| |
| if (System.getProperty("java.version", "").startsWith("1.")) { |
| // Simulating the delay between two invocations. It also makes sure we're not hit by tests that run so fast, |
| // that the difference in file modification time (see below) is too small to observe. Java 8 on Linux and |
| // macOS returns that value with "just" second precision, which is not detailed enough. |
| Thread.sleep(1_000); |
| } |
| |
| // 2. Create a properties file with some content and compile only that module (module A). |
| final Verifier verifier2 = newVerifier(testDir.getAbsolutePath()); |
| final Path resourcesDirectory = |
| Files.createDirectories(Paths.get(testDir.toString(), "module-a", "src", "main", "resources")); |
| final Path fileToWrite = resourcesDirectory.resolve("example.properties"); |
| FileUtils.fileWrite(fileToWrite.toString(), "x=42"); |
| |
| verifier2.setAutoclean(false); |
| verifier2.addCliArgument("--projects"); |
| verifier2.addCliArgument(":module-a"); |
| verifier2.addCliArgument("compile"); |
| verifier2.execute(); |
| |
| Path module1PropertiesFile = testDir.toPath() |
| .resolve("module-a/target/classes/example.properties") |
| .toAbsolutePath(); |
| |
| verifier2.verifyFilePresent(module1PropertiesFile.toString()); |
| assertTrue( |
| Files.getLastModifiedTime(module1PropertiesFile).compareTo(Files.getLastModifiedTime(module1Jar)) >= 0); |
| |
| Path module1Class = testDir.toPath() |
| .resolve("module-a/target/classes/org/apache/maven/it/Example.class") |
| .toAbsolutePath(); |
| verifier2.verifyErrorFreeLog(); |
| verifier2.verifyFilePresent(module1Class.toString()); |
| |
| // 3. Resume project build from module B, that depends on module A we just touched. Its packaged artifact |
| // is no longer in sync with its compiled artifacts. |
| final Verifier verifier3 = newVerifier(testDir.getAbsolutePath()); |
| verifier3.setAutoclean(false); |
| verifier3.addCliArgument("--resume-from"); |
| verifier3.addCliArgument(":module-b"); |
| verifier3.addCliArgument("compile"); |
| verifier3.execute(); |
| |
| verifier3.verifyErrorFreeLog(); |
| try { |
| verifier3.verifyTextInLog( |
| "File '" |
| + Paths.get("module-a", "target", "classes", "example.properties") |
| + "' is more recent than the packaged artifact for 'module-a', please run a full `mvn package` build"); |
| } catch (VerificationException e) { |
| final StringBuilder message = new StringBuilder(e.getMessage()); |
| message.append(System.lineSeparator()); |
| |
| message.append(" ") |
| .append(module1Jar.toAbsolutePath()) |
| .append(" -> ") |
| .append(Files.getLastModifiedTime(module1Jar)) |
| .append(System.lineSeparator()); |
| |
| message.append(System.lineSeparator()); |
| |
| Path outputDirectory = Paths.get(testDir.toString(), "module-a", "target", "classes"); |
| |
| Files.walkFileTree(outputDirectory, new FileVisitor<Path>() { |
| @Override |
| public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { |
| return CONTINUE; |
| } |
| |
| @Override |
| public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { |
| message.append(" ") |
| .append(file.toAbsolutePath()) |
| .append(" -> ") |
| .append(attrs.lastModifiedTime()) |
| .append(System.lineSeparator()); |
| return CONTINUE; |
| } |
| |
| @Override |
| public FileVisitResult visitFileFailed(Path file, IOException exc) { |
| return CONTINUE; |
| } |
| |
| @Override |
| public FileVisitResult postVisitDirectory(Path dir, IOException exc) { |
| return CONTINUE; |
| } |
| }); |
| |
| throw new VerificationException(message.toString(), e.getCause()); |
| } |
| } |
| } |