ModuleAccessTest.java
/*
* 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.utils;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class ModuleAccessTest {
@TempDir
Path directory;
@Test
void mavenConsumersCanCompileAndRunOnTheModulePath() throws Exception {
for (String module : List.of(
"org.apache.maven.impl",
"org.apache.maven.cling",
"org.apache.maven.core",
"maven.compat",
"maven.embedder",
"maven.model.builder")) {
Path source = createConsumer(module);
Path output = directory.resolve(module).resolve("classes");
ToolResult compilation = compile(source, output);
assertEquals(0, compilation.exitCode(), compilation.output());
ToolResult execution = runTool(
"java", "--module-path", utilities() + File.pathSeparator + output, "-m", module + "/probe.Probe");
assertEquals(0, execution.exitCode(), execution.output());
assertEquals(Os.OS_FAMILY, execution.output().strip());
}
}
@Test
void unrelatedModulesCannotAccessUtilities() throws Exception {
Path source = createConsumer("org.apache.maven.unrelated");
ToolResult compilation = compile(source, directory.resolve("unrelated-classes"));
assertNotEquals(0, compilation.exitCode(), "An unrelated module must not be able to access Maven utilities");
assertTrue(compilation.output().contains("org.apache.maven.utils"), compilation.output());
}
private Path createConsumer(String module) throws Exception {
Path source = Files.createDirectories(directory.resolve(module).resolve("src"));
Files.writeString(
source.resolve("module-info.java"), "module " + module + " { requires org.apache.maven.utils; }");
Path probe = Files.createDirectories(source.resolve("probe"));
Files.writeString(probe.resolve("Probe.java"), """
package probe;
public class Probe {
public static void main(String[] args) {
System.out.print(org.apache.maven.utils.Os.OS_FAMILY);
}
}
""");
return source;
}
private ToolResult compile(Path source, Path output) throws Exception {
return runTool(
"javac",
"--release",
"17",
"--module-path",
utilities().toString(),
"-d",
output.toString(),
source.resolve("module-info.java").toString(),
source.resolve("probe/Probe.java").toString());
}
private Path utilities() throws Exception {
return Path.of(
Os.class.getProtectionDomain().getCodeSource().getLocation().toURI());
}
private ToolResult runTool(String tool, String... arguments) throws Exception {
List<String> command = new ArrayList<>();
command.add(Path.of(System.getProperty("java.home"), "bin", tool).toString());
command.addAll(List.of(arguments));
Process process = new ProcessBuilder(command).redirectErrorStream(true).start();
try {
assertTrue(process.waitFor(30, TimeUnit.SECONDS), tool + " timed out");
String output = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
return new ToolResult(process.exitValue(), output);
} finally {
process.destroyForcibly();
}
}
private record ToolResult(int exitCode, String output) {}
}