Run integration tests with an isolated Mavel local repo and settings.xml

This commit is contained in:
Peter Palaga
2020-05-29 10:45:21 +02:00
parent 2706747138
commit ea6079b06b
10 changed files with 244 additions and 26 deletions

View File

@@ -25,9 +25,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.UUID;
import java.util.function.Supplier;
import org.apache.maven.cli.CLIReportingUtils;
import org.jboss.fuse.mvnd.daemon.ClientOutput.TerminalOutput;
@@ -46,6 +46,7 @@ public class Client {
private static final Logger LOGGER = LoggerFactory.getLogger(Client.class);
public static final String DAEMON_DEBUG = "daemon.debug";
private final Layout layout;
private final Optional<ClientLayout> clientLayout;
public static void main(String[] argv) throws Exception {
final List<String> args = new ArrayList<>(Arrays.asList(argv));
@@ -62,12 +63,13 @@ public class Client {
}
try (TerminalOutput output = new TerminalOutput(logFile)) {
new Client(Layout.getEnvInstance()).execute(output, args);
new Client(Layout.getEnvInstance(), Optional.empty()).execute(output, args);
}
}
public Client(Layout layout) {
public Client(Layout layout, Optional<ClientLayout> clientLayout) {
this.layout = layout;
this.clientLayout = clientLayout;
}
public <O extends ClientOutput> ClientResult<O> execute(O output, String... argv) throws IOException {
@@ -88,8 +90,8 @@ public class Client {
try (InputStream is = Client.class.getResourceAsStream("build.properties")) {
props.load(is);
}
String v = buffer().strong( "Maven Daemon " + props.getProperty("version") ).toString()
+ System.getProperty( "line.separator" )
String v = buffer().strong("Maven Daemon " + props.getProperty("version")).toString()
+ System.getProperty("line.separator")
+ CLIReportingUtils.showVersion();
output.log(v);
if (version) {
@@ -129,6 +131,7 @@ public class Client {
}
setDefaultArgs(args);
clientLayout.ifPresent(cl -> clientLayout(cl, args));
DaemonConnector connector = new DaemonConnector(layout, registry, this::startDaemon, new MessageSerializer());
List<String> opts = new ArrayList<>();
@@ -168,6 +171,16 @@ public class Client {
}
static void clientLayout(ClientLayout cl, List<String> args) {
if (!args.stream().anyMatch(arg -> arg.equals("-s") || arg.equals("--settings"))) {
args.add("-s");
args.add(cl.getSettings().toString());
}
if (!args.stream().anyMatch(arg -> arg.startsWith("-Dmaven.repo.local"))) {
args.add("-Dmaven.repo.local=" + cl.getLocalMavenRepository().toString());
}
}
static void setDefaultArgs(List<String> args) {
if (!args.stream().anyMatch(arg -> arg.startsWith("-T") || arg.equals("--threads"))) {
args.add("-T1C");

View File

@@ -0,0 +1,28 @@
package org.jboss.fuse.mvnd.daemon;
import java.nio.file.Path;
import java.util.Objects;
/**
* Local paths relevant for the {@link Client}.
*/
public class ClientLayout {
private final Path localMavenRepository;
private final Path settings;
public ClientLayout(Path localMavenRepository, Path settings) {
super();
this.localMavenRepository = Objects.requireNonNull(localMavenRepository, "localMavenRepository");
this.settings = Objects.requireNonNull(settings, "settings");
}
public Path getLocalMavenRepository() {
return localMavenRepository;
}
public Path getSettings() {
return settings;
}
}

View File

@@ -47,11 +47,34 @@
<build>
<plugins>
<!-- mrm-maven-plugin creates a proxy backed by the local Maven repo of the main build -->
<!-- Thanks to this, the builds invoked from the tests do not have to download all the dependencies from the Central. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>mrm-maven-plugin</artifactId>
<executions>
<execution>
<id>mrm-start</id>
<phase>process-test-classes</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>mrm-stop</id>
<phase>prepare-package</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<mrm.repository.url>${mrm.repository.url}</mrm.repository.url>
<project.version>${project.version}</project.version>
<mvnd.home>${project.basedir}/../daemon/target/maven-distro</mvnd.home>
</systemPropertyVariables>

View File

@@ -3,6 +3,7 @@ package org.jboss.fuse.mvnd.it;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
import javax.inject.Inject;
@@ -10,6 +11,7 @@ import org.assertj.core.api.Assertions;
import org.jboss.fuse.mvnd.assertj.EqualsInOrderAmongOthers;
import org.jboss.fuse.mvnd.assertj.MatchInOrderAmongOthers;
import org.jboss.fuse.mvnd.daemon.Client;
import org.jboss.fuse.mvnd.daemon.ClientLayout;
import org.jboss.fuse.mvnd.daemon.ClientOutput;
import org.jboss.fuse.mvnd.daemon.Layout;
import org.jboss.fuse.mvnd.junit.MvndTest;
@@ -26,20 +28,33 @@ public class MultiModuleTest {
@Inject
Layout layout;
@Inject
ClientLayout clientLayout;
@Test
void cleanTest() throws IOException {
void cleanInstall() throws IOException {
final Path[] helloFilePaths = {
layout.multiModuleProjectDirectory().resolve("hello/target/hello.txt"),
layout.multiModuleProjectDirectory().resolve("hi/target/hi.txt")
};
for (Path path : helloFilePaths) {
if (Files.exists(path)) {
Files.delete(path);
Stream.of(helloFilePaths).forEach(path -> {
try {
Files.deleteIfExists(path);
} catch (IOException e) {
throw new RuntimeException("Could not delete " + path);
}
}
});
final Path localMavenRepo = clientLayout.getLocalMavenRepository();
final Path[] installedJars = {
localMavenRepo.resolve("org/jboss/fuse/mvnd/test/multi-module/multi-module-api/0.0.1-SNAPSHOT/multi-module-api-0.0.1-SNAPSHOT.jar"),
localMavenRepo.resolve("org/jboss/fuse/mvnd/test/multi-module/multi-module-hello/0.0.1-SNAPSHOT/multi-module-hello-0.0.1-SNAPSHOT.jar"),
localMavenRepo.resolve("org/jboss/fuse/mvnd/test/multi-module/multi-module-hi/0.0.1-SNAPSHOT/multi-module-hi-0.0.1-SNAPSHOT.jar")
};
Stream.of(installedJars).forEach(jar -> Assertions.assertThat(jar).doesNotExist());
final ClientOutput output = Mockito.mock(ClientOutput.class);
client.execute(output, "clean", "test").assertSuccess();
client.execute(output, "clean", "install").assertSuccess();
final ArgumentCaptor<String> logMessage = ArgumentCaptor.forClass(String.class);
Mockito.verify(output, Mockito.atLeast(1)).log(logMessage.capture());
@@ -78,9 +93,9 @@ public class MultiModuleTest {
"multi-module-hello")));
/* Make sure HelloTest and HiTest have created the files they were supposed to create */
for (Path path : helloFilePaths) {
Assertions.assertThat(path).exists();
}
Stream.of(helloFilePaths).forEach(path -> Assertions.assertThat(path).exists());
Stream.of(installedJars).forEach(jar -> Assertions.assertThat(jar).exists());
}
}

View File

@@ -10,6 +10,7 @@ import javax.inject.Inject;
import org.assertj.core.api.Assertions;
import org.jboss.fuse.mvnd.assertj.MatchInOrderAmongOthers;
import org.jboss.fuse.mvnd.daemon.Client;
import org.jboss.fuse.mvnd.daemon.ClientLayout;
import org.jboss.fuse.mvnd.daemon.ClientOutput;
import org.jboss.fuse.mvnd.daemon.Layout;
import org.jboss.fuse.mvnd.junit.MvndTest;
@@ -27,15 +28,21 @@ public class SingleModuleTest {
@Inject
Layout layout;
@Inject
ClientLayout clientLayout;
@Test
void cleanTest() throws IOException {
void cleanInstall() throws IOException {
final Path helloFilePath = layout.multiModuleProjectDirectory().resolve("target/hello.txt");
if (Files.exists(helloFilePath)) {
Files.delete(helloFilePath);
}
final Path installedJar = clientLayout.getLocalMavenRepository().resolve("org/jboss/fuse/mvnd/test/single-module/single-module/0.0.1-SNAPSHOT/single-module-0.0.1-SNAPSHOT.jar");
Assertions.assertThat(installedJar).doesNotExist();
final ClientOutput output = Mockito.mock(ClientOutput.class);
client.execute(output, "clean", "test").assertSuccess();
client.execute(output, "clean", "install").assertSuccess();
final ArgumentCaptor<String> logMessage = ArgumentCaptor.forClass(String.class);
Mockito.verify(output, Mockito.atLeast(1)).log(logMessage.capture());
@@ -46,6 +53,7 @@ public class SingleModuleTest {
"maven-compiler-plugin:[^:]+:compile",
"maven-compiler-plugin:[^:]+:testCompile",
"maven-surefire-plugin:[^:]+:test",
"maven-install-plugin:[^:]+:install",
"SUCCESS build of project org.jboss.fuse.mvnd.test.single-module:single-module"));
final Properties props = MvndTestUtil.properties(layout.multiModuleProjectDirectory().resolve("pom.xml"));
@@ -93,6 +101,10 @@ public class SingleModuleTest {
"single-module",
":single-module:org.apache.maven.plugins:" + MvndTestUtil.plugin(props, "maven-surefire-plugin")
+ ":test {execution: default-test}");
inOrder.verify(output).projectStateChanged(
"single-module",
":single-module:org.apache.maven.plugins:" + MvndTestUtil.plugin(props, "maven-install-plugin")
+ ":install {execution: default-install}");
inOrder.verify(output).projectStateChanged(
"single-module",
":single-module");
@@ -102,5 +114,7 @@ public class SingleModuleTest {
/* The target/hello.txt is created by HelloTest */
Assertions.assertThat(helloFilePath).exists();
Assertions.assertThat(installedJar).exists();
}
}

View File

@@ -2,17 +2,21 @@ package org.jboss.fuse.mvnd.junit;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import org.jboss.fuse.mvnd.daemon.Client;
import org.jboss.fuse.mvnd.daemon.DaemonInfo;
import org.jboss.fuse.mvnd.daemon.DaemonRegistry;
import org.jboss.fuse.mvnd.daemon.Layout;
import org.jboss.fuse.mvnd.daemon.ClientLayout;
import org.jboss.fuse.mvnd.jpm.ProcessImpl;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
@@ -23,6 +27,7 @@ import org.junit.jupiter.api.extension.ExtensionContext.Store;
public class MvndTestExtension implements BeforeAllCallback, BeforeEachCallback, AfterAllCallback {
private volatile Exception bootException;
public MvndTestExtension() {
super();
}
@@ -33,7 +38,8 @@ public class MvndTestExtension implements BeforeAllCallback, BeforeEachCallback,
final Store store = context.getRoot().getStore(ExtensionContext.Namespace.GLOBAL);
final Class<?> testClass = context.getRequiredTestClass();
final MvndTest mnvdTest = testClass.getAnnotation(MvndTest.class);
store.put(MvndResource.class.getName(), MvndResource.create(context.getRequiredTestClass().getSimpleName(), mnvdTest.projectDir()));
store.put(MvndResource.class.getName(),
MvndResource.create(context.getRequiredTestClass().getSimpleName(), mnvdTest.projectDir()));
} catch (Exception e) {
this.bootException = e;
}
@@ -59,7 +65,9 @@ public class MvndTestExtension implements BeforeAllCallback, BeforeEachCallback,
} else if (f.getType() == Layout.class) {
f.set(testInstance, resource.layout);
} else if (f.getType() == Client.class) {
f.set(testInstance, new Client(resource.layout));
f.set(testInstance, new Client(resource.layout, Optional.of(resource.clientLayout)));
} else if (f.getType() == ClientLayout.class) {
f.set(testInstance, resource.clientLayout);
}
}
}
@@ -78,6 +86,7 @@ public class MvndTestExtension implements BeforeAllCallback, BeforeEachCallback,
static class MvndResource implements ExtensionContext.Store.CloseableResource {
private final ClientLayout clientLayout;
private final Layout layout;
private final DaemonRegistry registry;
@@ -87,13 +96,15 @@ public class MvndTestExtension implements BeforeAllCallback, BeforeEachCallback,
}
final Path mvndTestSrcDir = Paths.get(rawProjectDir).toAbsolutePath().normalize();
if (!Files.exists(mvndTestSrcDir)) {
throw new IllegalStateException("@MvndTest(projectDir = \""+ rawProjectDir +"\") points at a path that does not exist: " + mvndTestSrcDir);
throw new IllegalStateException("@MvndTest(projectDir = \"" + rawProjectDir
+ "\") points at a path that does not exist: " + mvndTestSrcDir);
}
final Path testDir = Paths.get("target/mvnd-tests/" + className).toAbsolutePath();
final Path testExecutionDir = testDir.resolve("project");
try (Stream<Path> files = Files.walk(mvndTestSrcDir)) {
files.forEach(source -> {
final Path dest = testDir.resolve(mvndTestSrcDir.relativize(source));
final Path dest = testExecutionDir.resolve(mvndTestSrcDir.relativize(source));
try {
if (Files.isDirectory(source)) {
Files.createDirectories(dest);
@@ -107,22 +118,67 @@ public class MvndTestExtension implements BeforeAllCallback, BeforeEachCallback,
});
}
final Path mvndHome = Paths.get(Objects.requireNonNull(System.getProperty("mvnd.home"), "System property mvnd.home must be set")).normalize().toAbsolutePath();
final Path mvndHome = Paths
.get(Objects.requireNonNull(System.getProperty("mvnd.home"), "System property mvnd.home must be set"))
.normalize().toAbsolutePath();
if (!Files.isDirectory(mvndHome)) {
throw new IllegalStateException("The value of mvnd.home system property points at a path that does not exist or is not a directory");
throw new IllegalStateException(
"The value of mvnd.home system property points at a path that does not exist or is not a directory");
}
final Layout layout = new Layout(Paths.get(System.getProperty("java.home")).toAbsolutePath().normalize(),
mvndHome,
testDir,
testDir);
testExecutionDir,
testExecutionDir);
final DaemonRegistry registry = new DaemonRegistry(layout.registry());
return new MvndResource(layout, registry);
final Path localMavenRepository = deleteDir(testDir.resolve("local-maven-repo"));
final Path settingsPath = createSettings(testDir.resolve("settings.xml"));
final ClientLayout clientLayout = new ClientLayout(localMavenRepository, settingsPath);
return new MvndResource(layout, registry, clientLayout);
}
public MvndResource(Layout layout, DaemonRegistry registry) {
static Path deleteDir(Path dir) {
if (Files.exists(dir)) {
try (Stream<Path> files = Files.walk(dir)) {
files.sorted(Comparator.reverseOrder())
.forEach(f -> {
try {
Files.delete(f);
} catch (IOException e) {
throw new RuntimeException("Could not delete " + f);
}
});
} catch (IOException e1) {
throw new RuntimeException("Could not walk " + dir);
}
}
return dir;
}
static Path createSettings(Path settingsPath) {
final Path settingsTemplatePath = Paths.get("src/test/resources/settings-template.xml");
try {
final String template = new String(Files.readAllBytes(settingsTemplatePath), StandardCharsets.UTF_8);
/* mrm.repository.url is set by mrm-maven-plugin */
final String mrmsRepoUrl = Objects.requireNonNull(System.getProperty("mrm.repository.url"),
"System property mrm.repository.url");
final String content = template.replace("${mrm.repository.url}", mrmsRepoUrl);
try {
Files.write(settingsPath, content.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
throw new RuntimeException("Could not write " + settingsPath);
}
} catch (IOException e) {
throw new RuntimeException("Could not read " + settingsTemplatePath);
}
return settingsPath;
}
public MvndResource(Layout layout, DaemonRegistry registry, ClientLayout clientLayout) {
super();
this.layout = layout;
this.registry = registry;
this.clientLayout = clientLayout;
}
@Override

View File

@@ -11,6 +11,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-clean-plugin.version>2.5</maven-clean-plugin.version>
<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
<maven-install-plugin.version>2.4</maven-install-plugin.version>
<maven-resources-plugin.version>2.6</maven-resources-plugin.version>
<maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version>
</properties>
@@ -34,6 +35,11 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>${maven-install-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>

View File

@@ -11,6 +11,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-clean-plugin.version>2.5</maven-clean-plugin.version>
<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
<maven-install-plugin.version>2.4</maven-install-plugin.version>
<maven-resources-plugin.version>2.6</maven-resources-plugin.version>
<maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version>
</properties>
@@ -37,6 +38,11 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>${maven-install-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<mirrors>
<mirror>
<id>mrm-maven-plugin</id>
<name>Mock Repository Manager</name>
<url>${mrm.repository.url}</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>it-repo</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>snapshots</id>
<url>${mrm.repository.url}</url>
<releases>
<enabled>true</enabled>
<checksumPolicy>ignore</checksumPolicy>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<checksumPolicy>ignore</checksumPolicy>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>snapshots</id>
<url>${mrm.repository.url}</url>
<releases>
<enabled>true</enabled>
<checksumPolicy>ignore</checksumPolicy>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<checksumPolicy>ignore</checksumPolicy>
<updatePolicy>always</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</settings>

View File

@@ -30,6 +30,7 @@
<takariProvisioVersion>0.1.56</takariProvisioVersion>
<takariLocalRepositoryVersion>0.11.2</takariLocalRepositoryVersion>
<mavenCompilerPluginVersion>3.8.1</mavenCompilerPluginVersion>
<mrm.version>1.2.0</mrm.version>
<surefire.version>3.0.0-M4</surefire.version>
</properties>
@@ -88,6 +89,11 @@
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>mrm-maven-plugin</artifactId>
<version>${mrm.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>