Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 92 additions & 23 deletions test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, 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
Expand All @@ -25,53 +25,109 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;


public final class CfgFile {
public String getValue(String section, String key) {
Objects.requireNonNull(section);
Objects.requireNonNull(key);
public String getValue(String sectionName, String key) {
var section = getSection(sectionName);
TKit.assertTrue(section != null, String.format(
"Check section [%s] is found in [%s] cfg file", sectionName, id));

Map<String, String> entries = data.get(section);
TKit.assertTrue(entries != null, String.format(
"Check section [%s] is found in [%s] cfg file", section, id));

String value = entries.get(key);
String value = section.getValue(key);
TKit.assertNotNull(value, String.format(
"Check key [%s] is found in [%s] section of [%s] cfg file", key,
section, id));
sectionName, id));

return value;
}

private CfgFile(Map<String, Map<String, String>> data, String id) {
public String getValueUnchecked(String sectionName, String key) {
var section = getSection(sectionName);
if (section != null) {
return section.getValue(key);
} else {
return null;
}
}

public void addValue(String sectionName, String key, String value) {
var section = getSection(sectionName);
if (section == null) {
section = new Section(sectionName, new ArrayList<>());
data.add(section);
}
section.data.add(Map.entry(key, value));
}

public CfgFile() {
this(new ArrayList<>(), "*");
}

public static CfgFile combine(CfgFile base, CfgFile mods) {
var cfgFile = new CfgFile(new ArrayList<>(), "*");
for (var src : List.of(base, mods)) {
for (var section : src.data) {
for (var kvp : section.data) {
cfgFile.addValue(section.name, kvp.getKey(), kvp.getValue());
}
}
}
return cfgFile;
}

private CfgFile(List<Section> data, String id) {
this.data = data;
this.id = id;
}

public static CfgFile readFromFile(Path path) throws IOException {
public void save(Path path) {
var lines = data.stream().flatMap(section -> {
return Stream.concat(
Stream.of(String.format("[%s]", section.name)),
section.data.stream().map(kvp -> {
return String.format("%s=%s", kvp.getKey(), kvp.getValue());
}));
});
TKit.createTextFile(path, lines);
}

private Section getSection(String name) {
Objects.requireNonNull(name);
for (int i = data.size()-1; i >=0; i--) {
var section = data.get(i);
if (name.equals(section.name)) {
return section;
}
}
return null;
}

public static CfgFile load(Path path) throws IOException {
TKit.trace(String.format("Read [%s] jpackage cfg file", path));

final Pattern sectionBeginRegex = Pattern.compile( "\\s*\\[([^]]*)\\]\\s*");
final Pattern keyRegex = Pattern.compile( "\\s*([^=]*)=(.*)" );

Map<String, Map<String, String>> result = new HashMap<>();
List<Section> sections = new ArrayList<>();

String currentSectionName = null;
Map<String, String> currentSection = new HashMap<>();
List<Map.Entry<String, String>> currentSection = new ArrayList<>();
for (String line : Files.readAllLines(path)) {
Matcher matcher = sectionBeginRegex.matcher(line);
if (matcher.find()) {
if (currentSectionName != null) {
result.put(currentSectionName, Collections.unmodifiableMap(
new HashMap<>(currentSection)));
sections.add(new Section(currentSectionName,
Collections.unmodifiableList(new ArrayList<>(
currentSection))));
}
currentSectionName = matcher.group(1);
currentSection.clear();
Expand All @@ -80,19 +136,32 @@ public static CfgFile readFromFile(Path path) throws IOException {

matcher = keyRegex.matcher(line);
if (matcher.find()) {
currentSection.put(matcher.group(1), matcher.group(2));
continue;
currentSection.add(Map.entry(matcher.group(1), matcher.group(2)));
}
}

if (!currentSection.isEmpty()) {
result.put(Optional.ofNullable(currentSectionName).orElse(""),
Collections.unmodifiableMap(currentSection));
sections.add(new Section(
Optional.ofNullable(currentSectionName).orElse(""),
Collections.unmodifiableList(currentSection)));
}

return new CfgFile(Collections.unmodifiableMap(result), path.toString());
return new CfgFile(sections, path.toString());
}

private static record Section(String name, List<Map.Entry<String, String>> data) {
String getValue(String key) {
Objects.requireNonNull(key);
for (int i = data.size()-1; i >= 0; i--) {
var kvp = data.get(i);
if (key.equals(kvp.getKey())) {
return kvp.getValue();
}
}
return null;
}
}

private final Map<String, Map<String, String>> data;
private final List<Section> data;
private final String id;
}
39 changes: 39 additions & 0 deletions test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Comm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2024, 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.
*/
package jdk.jpackage.test;

import java.util.HashSet;
import java.util.Set;

record Comm<T>(Set<T> common, Set<T> unique1, Set<T> unique2) {

static <T> Comm<T> compare(Set<T> a, Set<T> b) {
Set<T> common = new HashSet<>(a);
common.retainAll(b);
Set<T> unique1 = new HashSet<>(a);
unique1.removeAll(common);
Set<T> unique2 = new HashSet<>(b);
unique2.removeAll(common);
return new Comm(common, unique1, unique2);
}
}
19 changes: 10 additions & 9 deletions test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2025, 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
Expand Down Expand Up @@ -54,7 +54,6 @@ public static Executor of(String... cmdline) {

public Executor() {
saveOutputType = new HashSet<>(Set.of(SaveOutputType.NONE));
removePath = false;
winEnglishOutput = false;
}

Expand Down Expand Up @@ -91,8 +90,8 @@ public Executor setExecutable(JavaTool v) {
return setExecutable(v.getPath());
}

public Executor setRemovePath(boolean value) {
removePath = value;
public Executor removeEnvVar(String envVarName) {
removeEnvVars.add(Objects.requireNonNull(envVarName));
return this;
}

Expand Down Expand Up @@ -370,10 +369,12 @@ private Result runExecutable() throws IOException, InterruptedException {
builder.directory(directory.toFile());
sb.append(String.format("; in directory [%s]", directory));
}
if (removePath) {
// run this with cleared Path in Environment
TKit.trace("Clearing PATH in environment");
builder.environment().remove("PATH");
if (!removeEnvVars.isEmpty()) {
final var envComm = Comm.compare(builder.environment().keySet(), removeEnvVars);
builder.environment().keySet().removeAll(envComm.common());
envComm.common().forEach(envVar -> {
TKit.trace(String.format("Clearing %s in environment", envVar));
});
}

trace("Execute " + sb.toString() + "...");
Expand Down Expand Up @@ -512,7 +513,7 @@ private static void trace(String msg) {
private Path executable;
private Set<SaveOutputType> saveOutputType;
private Path directory;
private boolean removePath;
private Set<String> removeEnvVars = new HashSet<>();
private boolean winEnglishOutput;
private String winTmpDir = null;

Expand Down
20 changes: 16 additions & 4 deletions test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2025, 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
Expand Down Expand Up @@ -464,13 +464,14 @@ private Executor getExecutor(String...args) {
}

final List<String> launcherArgs = List.of(args);
return new Executor()
final var executor = new Executor()
.setDirectory(outputFile.getParent())
.saveOutput(saveOutput)
.dumpOutput()
.setRemovePath(removePath)
.setExecutable(executablePath)
.addArguments(launcherArgs);
.addArguments(List.of(args));

return configureEnvironment(executor);
}

private boolean launcherNoExit;
Expand All @@ -487,6 +488,14 @@ public static AppOutputVerifier assertApp(Path helloAppLauncher) {
return new AppOutputVerifier(helloAppLauncher);
}

public static Executor configureEnvironment(Executor executor) {
if (CLEAR_JAVA_ENV_VARS) {
executor.removeEnvVar("JAVA_TOOL_OPTIONS");
executor.removeEnvVar("_JAVA_OPTIONS");
}
return executor;
}

static final String OUTPUT_FILENAME = "appOutput.txt";

private final JavaAppDesc appDesc;
Expand All @@ -496,4 +505,7 @@ public static AppOutputVerifier assertApp(Path helloAppLauncher) {

private static final String CLASS_NAME = HELLO_JAVA.getFileName().toString().split(
"\\.", 2)[0];

private static final boolean CLEAR_JAVA_ENV_VARS = Optional.ofNullable(
TKit.getConfigProperty("clear-app-launcher-java-env-vars")).map(Boolean::parseBoolean).orElse(false);
}
Original file line number Diff line number Diff line change
Expand Up @@ -570,8 +570,18 @@ public Path appLauncherCfgPath(String launcherName) {
}

public boolean isFakeRuntime(String msg) {
Path runtimeDir = appRuntimeDirectory();
if (isFakeRuntime()) {
// Fake runtime
Path runtimeDir = appRuntimeDirectory();
TKit.trace(String.format(
"%s because application runtime directory [%s] is incomplete",
msg, runtimeDir));
return true;
}
return false;
}

private boolean isFakeRuntime() {
final Collection<Path> criticalRuntimeFiles;
if (TKit.isWindows()) {
criticalRuntimeFiles = WindowsHelper.CRITICAL_RUNTIME_FILES;
Expand All @@ -583,16 +593,9 @@ public boolean isFakeRuntime(String msg) {
throw TKit.throwUnknownPlatformError();
}

if (!criticalRuntimeFiles.stream().anyMatch(v -> {
return runtimeDir.resolve(v).toFile().exists();
})) {
// Fake runtime
TKit.trace(String.format(
"%s because application runtime directory [%s] is incomplete",
msg, runtimeDir));
return true;
}
return false;
Path runtimeDir = appRuntimeDirectory();
return !criticalRuntimeFiles.stream().map(runtimeDir::resolve).allMatch(
Files::exists);
}

public boolean canRunLauncher(String msg) {
Expand Down Expand Up @@ -657,6 +660,13 @@ public JPackageCommand ignoreDefaultRuntime(boolean v) {
return this;
}

public JPackageCommand ignoreFakeRuntime() {
if (isFakeRuntime()) {
ignoreDefaultRuntime(true);
}
return this;
}

public JPackageCommand ignoreDefaultVerbose(boolean v) {
verifyMutable();
ignoreDefaultVerbose = v;
Expand Down Expand Up @@ -876,7 +886,7 @@ public CfgFile readLauncherCfgFile(String launcherName) {
if (isRuntime()) {
return null;
}
return ThrowingFunction.toFunction(CfgFile::readFromFile).apply(
return ThrowingFunction.toFunction(CfgFile::load).apply(
appLauncherCfgPath(launcherName));
}

Expand Down
Loading