8271170: Add unit test for what jpackage app launcher puts in the environment

Reviewed-by: almatvee, herrick
This commit is contained in:
Alexey Semenyuk 2021-08-11 23:39:50 +00:00
parent cd2dbe5f00
commit 44f137ff9c
7 changed files with 214 additions and 130 deletions

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.List;
import java.util.ArrayList;
public class PrintEnv {
public static void main(String[] args) {
List<String> lines = printArgs(args);
lines.forEach(System.out::println);
}
private static List<String> printArgs(String[] args) {
List<String> lines = new ArrayList<>();
for (String arg : args) {
if (arg.startsWith(PRINT_ENV_VAR)) {
String name = arg.substring(PRINT_ENV_VAR.length());
lines.add(name + "=" + System.getenv(name));
} else if (arg.startsWith(PRINT_SYS_PROP)) {
String name = arg.substring(PRINT_SYS_PROP.length());
lines.add(name + "=" + System.getProperty(name));
} else {
throw new IllegalArgumentException();
}
}
return lines;
}
private final static String PRINT_ENV_VAR = "--print-env-var=";
private final static String PRINT_SYS_PROP = "--print-sys-prop=";
}

View File

@ -1,113 +0,0 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.awt.Desktop;
import java.awt.desktop.OpenFilesEvent;
import java.awt.desktop.OpenFilesHandler;
import java.util.List;
public class Hello implements OpenFilesHandler {
private static final String MSG = "jpackage test application";
private static final int EXPECTED_NUM_OF_PARAMS = 3; // Starts at 1
private static List<File> files;
public static void main(String[] args) {
if(Desktop.getDesktop().isSupported(Desktop.Action.APP_OPEN_FILE)) {
Desktop.getDesktop().setOpenFileHandler(new Hello());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
printToStdout(args);
if (args.length == 1 || (files != null && files.size() == 1)) { // Called via file association
printToFile(args);
}
}
private static void printToStdout(String[] args) {
System.out.println(MSG);
System.out.println("args.length: " + (files == null ? args.length : args.length + files.size()));
for (String arg : args) {
System.out.println(arg);
}
if (files != null) {
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
}
for (int index = 1; index <= EXPECTED_NUM_OF_PARAMS; index++) {
String value = System.getProperty("param" + index);
if (value != null) {
System.out.println("-Dparam" + index + "=" + value);
}
}
}
private static void printToFile(String[] args) {
File inputFile = files == null ? new File(args[0]) : files.get(0);
String outputFile = inputFile.getParent() + File.separator + "appOutput.txt";
File file = new File(outputFile);
try (PrintWriter out
= new PrintWriter(new BufferedWriter(new FileWriter(file)))) {
out.println(MSG);
out.println("args.length: " + (files == null ? args.length : args.length + files.size()));
for (String arg : args) {
out.println(arg);
}
if (files != null) {
for (File f : files) {
out.println(f.getAbsolutePath());
}
}
for (int index = 1; index <= EXPECTED_NUM_OF_PARAMS; index++) {
String value = System.getProperty("param" + index);
if (value != null) {
out.println("-Dparam" + index + "=" + value);
}
}
} catch (Exception ex) {
System.err.println(ex.getMessage());
}
}
@Override
public void openFiles(OpenFilesEvent e) {
files = e.getFiles();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -56,6 +56,8 @@ public final class HelloApp {
}
private JarBuilder prepareSources(Path srcDir) throws IOException {
final String srcClassName = appDesc.srcClassName();
final String qualifiedClassName = appDesc.className();
final String className = qualifiedClassName.substring(
@ -83,9 +85,9 @@ public final class HelloApp {
// Add package directive and replace class name in java source file.
// Works with simple test Hello.java.
// Don't expect too much from these regexps!
Pattern classNameRegex = Pattern.compile("\\bHello\\b");
Pattern classNameRegex = Pattern.compile("\\b" + srcClassName + "\\b");
Pattern classDeclaration = Pattern.compile(
"(^.*\\bclass\\s+)\\bHello\\b(.*$)");
"(^.*\\bclass\\s+)\\b" + srcClassName + "\\b(.*$)");
Pattern importDirective = Pattern.compile(
"(?<=import (?:static )?+)[^;]+");
AtomicBoolean classDeclared = new AtomicBoolean();
@ -97,7 +99,8 @@ public final class HelloApp {
System.lineSeparator(), line);
});
Files.write(srcFile, Files.readAllLines(HELLO_JAVA).stream().map(line -> {
Files.write(srcFile,
Files.readAllLines(appDesc.srcJavaPath()).stream().map(line -> {
Matcher m;
if (classDeclared.getPlain()) {
if ((m = classNameRegex.matcher(line)).find()) {
@ -144,13 +147,14 @@ public final class HelloApp {
return cmd.getArgumentValue("--module-path", cmd::inputDir, Path::of);
};
if (moduleName == null && CLASS_NAME.equals(qualifiedClassName)) {
if (moduleName == null && CLASS_NAME.equals(qualifiedClassName)
&& HELLO_JAVA.equals(appDesc.srcJavaPath())) {
// Use Hello.java as is.
cmd.addPrerequisiteAction((self) -> {
if (self.inputDir() != null) {
Path jarFile = self.inputDir().resolve(appDesc.jarFileName());
createJarBuilder().setOutputJar(jarFile).addSourceFile(
HELLO_JAVA).create();
appDesc.srcJavaPath()).create();
}
});
} else if (appDesc.jmodFileName() != null) {
@ -159,7 +163,7 @@ public final class HelloApp {
createBundle(appDesc, getModulePath.get());
});
} else {
// Modular app in .jar file
// Modular/non-modular app in .jar file
cmd.addPrerequisiteAction(unused -> {
final Path jarFile;
if (moduleName == null) {
@ -195,7 +199,7 @@ public final class HelloApp {
}
static JavaAppDesc createDefaltAppDesc() {
return new JavaAppDesc().setClassName(CLASS_NAME).setBundleFileName("hello.jar");
return new JavaAppDesc().setSrcJavaPath(HELLO_JAVA).setClassName(CLASS_NAME).setBundleFileName("hello.jar");
}
static void verifyOutputFile(Path outputFile, List<String> args,
@ -462,7 +466,7 @@ public final class HelloApp {
private final JavaAppDesc appDesc;
private static final Path HELLO_JAVA = TKit.TEST_SRC_ROOT.resolve(
"apps/image/Hello.java");
"apps/Hello.java");
private final static String CLASS_NAME = HELLO_JAVA.getFileName().toString().split(
"\\.", 2)[0];

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,11 @@ public final class JavaAppDesc {
public JavaAppDesc() {
}
public JavaAppDesc setSrcJavaPath(Path v) {
srcJavaPath = v;
return this;
}
public JavaAppDesc setClassName(String v) {
qualifiedClassName = v;
return this;
@ -55,6 +60,15 @@ public final class JavaAppDesc {
return this;
}
public Path srcJavaPath() {
return srcJavaPath;
}
public String srcClassName() {
String fname = srcJavaPath().getFileName().toString();
return fname.substring(0, fname.lastIndexOf('.'));
}
public String className() {
return qualifiedClassName;
}
@ -113,6 +127,9 @@ public final class JavaAppDesc {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (srcJavaPath != null) {
sb.append(srcJavaPath.toString()).append('*');
}
if (bundleFileName != null) {
sb.append(bundleFileName).append(':');
}
@ -135,7 +152,7 @@ public final class JavaAppDesc {
* Create Java application description form encoded string value.
*
* Syntax of encoded Java application description is
* [(jar_file|jmods_file|exploded_jmods_file):][module_name/]qualified_class_name[!][@module_version].
* [src_java_file*][(jar_file|jmods_file|exploded_jmods_file):][module_name/]qualified_class_name[!][@module_version].
*
* E.g.: `duke.jar:com.other/com.other.foo.bar.Buz!@3.7` encodes modular
* application. Module name is `com.other`. Main class is
@ -168,8 +185,16 @@ public final class JavaAppDesc {
return desc;
}
String srcJavaPathAndOther = Functional.identity(() -> {
String[] components = javaAppDesc.split("\\*", 2);
if (components.length == 2) {
desc.setSrcJavaPath(Path.of(components[0]));
}
return components[components.length - 1];
}).get();
String moduleNameAndOther = Functional.identity(() -> {
String[] components = javaAppDesc.split(":", 2);
String[] components = srcJavaPathAndOther.split(":", 2);
if (components.length == 2) {
desc.setBundleFileName(components[0]);
}
@ -206,6 +231,7 @@ public final class JavaAppDesc {
return desc;
}
private Path srcJavaPath;
private String qualifiedClassName;
private String moduleName;
private String bundleFileName;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -185,9 +185,13 @@ public class AddLauncherTest {
cmd.ignoreDefaultRuntime(true); // because of --add-modules
}
final String expectedMod = JavaAppDesc.parse(modularAppDesc.toString())
.setBundleFileName(null)
.setSrcJavaPath(null)
.toString();
new AdditionalLauncher("ModularAppLauncher")
.addRawProperties(Map.entry("module", JavaAppDesc.parse(
modularAppDesc.toString()).setBundleFileName(null).toString()))
.addRawProperties(Map.entry("module", expectedMod))
.addRawProperties(Map.entry("main-jar", ""))
.applyTo(cmd);
@ -208,8 +212,6 @@ public class AddLauncherTest {
String moduleValue = cfg.getValue("Application", "app.mainmodule");
String mainClass = null;
String classpath = null;
String expectedMod = JavaAppDesc.parse(
modularAppDesc.toString()).setBundleFileName(null).toString();
TKit.assertEquals(expectedMod, moduleValue,
String.format("Check value of app.mainmodule=[%s]" +
"in ModularAppLauncher cfg file is as expected", expectedMod));

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
import jdk.jpackage.test.JPackageCommand;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.Executor;
import jdk.jpackage.test.TKit;
/**
* Tests values of environment variables altered by jpackage launcher.
*/
/*
* @test
* @summary Tests values of environment variables altered by jpackage launcher
* @library ../helpers
* @library /test/lib
* @build AppLauncherEnvTest
* @build jdk.jpackage.test.*
* @build AppLauncherEnvTest
* @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm -Xmx512m jdk.jpackage.test.Main
* --jpt-run=AppLauncherEnvTest
*/
public class AppLauncherEnvTest {
@Test
public static void test() throws Exception {
final String testAddDirProp = "jpackage.test.AppDir";
JPackageCommand cmd = JPackageCommand
.helloAppImage(TEST_APP_JAVA + "*Hello")
.addArguments("--java-options", "-D" + testAddDirProp
+ "=$APPDIR");
cmd.executeAndAssertImageCreated();
final String envVarName = envVarName();
final int attempts = 3;
final int waitBetweenAttemptsSeconds = 5;
List<String> output = new Executor()
.saveOutput()
.setExecutable(cmd.appLauncherPath().toAbsolutePath())
.addArguments("--print-env-var=" + envVarName)
.addArguments("--print-sys-prop=" + testAddDirProp)
.addArguments("--print-sys-prop=" + "java.library.path")
.executeAndRepeatUntilExitCode(0, attempts,
waitBetweenAttemptsSeconds).getOutput();
BiFunction<Integer, String, String> getValue = (idx, name) -> {
return output.get(idx).substring((name + "=").length());
};
final String actualEnvVarValue = getValue.apply(0, envVarName);
final String appDir = getValue.apply(1, testAddDirProp);
final String expectedEnvVarValue = Optional.ofNullable(System.getenv(
envVarName)).orElse("") + File.pathSeparator + appDir;
TKit.assertEquals(expectedEnvVarValue, actualEnvVarValue, String.format(
"Check value of %s env variable", envVarName));
final String javaLibraryPath = getValue.apply(2, "java.library.path");
TKit.assertTrue(
List.of(javaLibraryPath.split(File.pathSeparator)).contains(
appDir), String.format(
"Check java.library.path system property [%s] contains app dir [%s]",
javaLibraryPath, appDir));
}
private static String envVarName() {
if (TKit.isLinux()) {
return "LD_LIBRARY_PATH";
} else if (TKit.isWindows()) {
return "PATH";
} else if (TKit.isOSX()) {
return "DYLD_LIBRARY_PATH";
} else {
throw new IllegalStateException();
}
}
private static final Path TEST_APP_JAVA = TKit.TEST_SRC_ROOT.resolve(
"apps/PrintEnv.java");
}