blob: 2073aa3bf303791d81041d81f8aeb6993f389027 [file] [log] [blame]
/*
* 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());
}
}
}