From ac0e28dcba081a130bb4c99af66cad31d38c3221 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 12 Nov 2025 12:23:53 +0100 Subject: [PATCH 1/2] backport 8347300 from 21 --- .../helpers/jdk/jpackage/test/CfgFile.java | 113 ++++++++++++++---- .../helpers/jdk/jpackage/test/Executor.java | 19 +-- .../helpers/jdk/jpackage/test/HelloApp.java | 20 +++- .../jdk/jpackage/test/JPackageCommand.java | 34 ++++-- .../jdk/jpackage/test/WindowsHelper.java | 95 ++++++++++++++- .../jpackage/share/AppLauncherEnvTest.java | 6 +- test/jdk/tools/jpackage/share/BasicTest.java | 2 +- .../jpackage/windows/WinChildProcessTest.java | 20 ++-- 8 files changed, 246 insertions(+), 63 deletions(-) diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java index 31bf0520a31..9df28b3915e 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java @@ -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 @@ -25,53 +25,108 @@ 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 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> 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
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 (var section : data.reversed()) { + 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> result = new HashMap<>(); + List
sections = new ArrayList<>(); String currentSectionName = null; - Map currentSection = new HashMap<>(); + List> 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(); @@ -80,19 +135,31 @@ 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> data) { + String getValue(String key) { + Objects.requireNonNull(key); + for (var kvp : data.reversed()) { + if (key.equals(kvp.getKey())) { + return kvp.getValue(); + } + } + return null; + } } - private final Map> data; + private final List
data; private final String id; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java index e94cbc79aac..c1c51f1ef55 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java @@ -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 @@ -54,7 +54,6 @@ public static Executor of(String... cmdline) { public Executor() { saveOutputType = new HashSet<>(Set.of(SaveOutputType.NONE)); - removePath = false; winEnglishOutput = false; } @@ -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; } @@ -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() + "..."); @@ -512,7 +513,7 @@ private static void trace(String msg) { private Path executable; private Set saveOutputType; private Path directory; - private boolean removePath; + private Set removeEnvVars = new HashSet<>(); private boolean winEnglishOutput; private String winTmpDir = null; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java index bc722e7acd9..a004dd421c1 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java @@ -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 @@ -464,13 +464,14 @@ private Executor getExecutor(String...args) { } final List 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; @@ -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; @@ -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); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index d16f843988d..54532579a4f 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -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 criticalRuntimeFiles; if (TKit.isWindows()) { criticalRuntimeFiles = WindowsHelper.CRITICAL_RUNTIME_FILES; @@ -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) { @@ -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; @@ -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)); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index 60006fc1944..0b675aceda6 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -28,9 +28,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.test.Functional.ThrowingRunnable; @@ -165,6 +168,90 @@ public static String getMsiProperty(JPackageCommand cmd, String propertyName) { .executeAndGetOutput().stream().collect(Collectors.joining("\n")); } + public static void killProcess(long pid) { + Executor.of("taskkill", "/F", "/PID", Long.toString(pid)).dumpOutput(true).execute(); + } + + public static void killAppLauncherProcess(JPackageCommand cmd, + String launcherName, int expectedCount) { + var pids = findAppLauncherPIDs(cmd, launcherName); + try { + TKit.assertEquals(expectedCount, pids.length, String.format( + "Check [%d] %s app launcher processes found running", + expectedCount, Optional.ofNullable(launcherName).map( + str -> "[" + str + "]").orElse("
"))); + } finally { + if (pids.length != 0) { + killProcess(pids[0]); + } + } + } + + private static long[] findAppLauncherPIDs(JPackageCommand cmd, String launcherName) { + // Get the list of PIDs and PPIDs of app launcher processes. + // wmic process where (name = "foo.exe") get ProcessID,ParentProcessID + List output = Executor.of("wmic", "process", "where", "(name", + "=", + "\"" + cmd.appLauncherPath(launcherName).getFileName().toString() + "\"", + ")", "get", "ProcessID,ParentProcessID").dumpOutput(true). + saveOutput().executeAndGetOutput(); + + if ("No Instance(s) Available.".equals(output.getFirst().trim())) { + return new long[0]; + } + + String[] headers = Stream.of(output.getFirst().split("\\s+", 2)).map( + String::trim).map(String::toLowerCase).toArray(String[]::new); + Pattern pattern; + if (headers[0].equals("parentprocessid") && headers[1].equals( + "processid")) { + pattern = Pattern.compile("^(?\\d+)\\s+(?\\d+)\\s+$"); + } else if (headers[1].equals("parentprocessid") && headers[0].equals( + "processid")) { + pattern = Pattern.compile("^(?\\d+)\\s+(?\\d+)\\s+$"); + } else { + throw new RuntimeException( + "Unrecognizable output of \'wmic process\' command"); + } + + List processes = output.stream().skip(1).map(line -> { + Matcher m = pattern.matcher(line); + long[] pids = null; + if (m.matches()) { + pids = new long[]{Long.parseLong(m.group("pid")), Long. + parseLong(m.group("ppid"))}; + } + return pids; + }).filter(Objects::nonNull).toList(); + + switch (processes.size()) { + case 2 -> { + final long parentPID; + final long childPID; + if (processes.get(0)[0] == processes.get(1)[1]) { + parentPID = processes.get(0)[0]; + childPID = processes.get(1)[0]; + } else if (processes.get(1)[0] == processes.get(0)[1]) { + parentPID = processes.get(1)[0]; + childPID = processes.get(0)[0]; + } else { + TKit.assertUnexpected("App launcher processes unrelated"); + return null; // Unreachable + } + return new long[]{parentPID, childPID}; + } + case 1 -> { + return new long[]{processes.get(0)[0]}; + } + default -> { + TKit.assertUnexpected(String.format( + "Unexpected number of running processes [%d]", + processes.size())); + return null; // Unreachable + } + } + } + private static boolean isUserLocalInstall(JPackageCommand cmd) { return cmd.hasArgument("--win-per-user-install"); } @@ -378,15 +465,15 @@ private static String queryRegistryValueCache(String keyPath, "bin\\server\\jvm.dll")); // jtreg resets %ProgramFiles% environment variable by some reason. - private final static Path PROGRAM_FILES = Path.of(Optional.ofNullable( + private static final Path PROGRAM_FILES = Path.of(Optional.ofNullable( System.getenv("ProgramFiles")).orElse("C:\\Program Files")); - private final static Path USER_LOCAL = Path.of(System.getProperty( + private static final Path USER_LOCAL = Path.of(System.getProperty( "user.home"), "AppData", "Local"); - private final static String SYSTEM_SHELL_FOLDERS_REGKEY = "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; - private final static String USER_SHELL_FOLDERS_REGKEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; + private static final String SYSTEM_SHELL_FOLDERS_REGKEY = "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; + private static final String USER_SHELL_FOLDERS_REGKEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"; private static final Map REGISTRY_VALUES = new HashMap<>(); } diff --git a/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java b/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java index a16ff9c18f9..52016e6f4ab 100644 --- a/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java +++ b/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -30,6 +30,7 @@ import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.Executor; +import static jdk.jpackage.test.HelloApp.configureEnvironment; import jdk.jpackage.test.TKit; /** @@ -53,6 +54,7 @@ public static void test() throws Exception { JPackageCommand cmd = JPackageCommand .helloAppImage(TEST_APP_JAVA + "*Hello") + .ignoreFakeRuntime() .addArguments("--java-options", "-D" + testAddDirProp + "=$APPDIR"); @@ -62,7 +64,7 @@ public static void test() throws Exception { final int attempts = 3; final int waitBetweenAttemptsSeconds = 5; - List output = new Executor() + List output = configureEnvironment(new Executor()) .saveOutput() .setExecutable(cmd.appLauncherPath().toAbsolutePath()) .addArguments("--print-env-var=" + envVarName) diff --git a/test/jdk/tools/jpackage/share/BasicTest.java b/test/jdk/tools/jpackage/share/BasicTest.java index 15c8836e7ac..0b967373dc9 100644 --- a/test/jdk/tools/jpackage/share/BasicTest.java +++ b/test/jdk/tools/jpackage/share/BasicTest.java @@ -72,7 +72,7 @@ public void testJpackageProps() { .saveConsoleOutput(true) .addArguments("--app-version", appVersion, "--arguments", "jpackage.app-version jpackage.app-path") - .ignoreDefaultRuntime(true); + .ignoreFakeRuntime(); cmd.executeAndAssertImageCreated(); Path launcherPath = cmd.appLauncherPath(); diff --git a/test/jdk/tools/jpackage/windows/WinChildProcessTest.java b/test/jdk/tools/jpackage/windows/WinChildProcessTest.java index 8bab8eac5fb..5b0ff9b1f01 100644 --- a/test/jdk/tools/jpackage/windows/WinChildProcessTest.java +++ b/test/jdk/tools/jpackage/windows/WinChildProcessTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -27,7 +27,6 @@ * when System.exit(0) is invoked along with terminating java program. * @library /test/jdk/tools/jpackage/helpers * @requires os.family == "windows" - * @build WinChildProcessTest * @build jdk.jpackage.test.* * @build WinChildProcessTest * @run main/othervm -Xmx512m jdk.jpackage.test.Main @@ -41,27 +40,30 @@ import java.nio.file.Path; import jdk.jpackage.test.JPackageCommand; +import static jdk.jpackage.test.HelloApp.configureEnvironment; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.Executor; import jdk.jpackage.test.TKit; +import static jdk.jpackage.test.WindowsHelper.killProcess; public class WinChildProcessTest { private static final Path TEST_APP_JAVA = TKit.TEST_SRC_ROOT .resolve("apps/ChildProcessAppLauncher.java"); @Test - public static void test() throws Throwable { + public static void test() { long childPid = 0; try { JPackageCommand cmd = JPackageCommand - .helloAppImage(TEST_APP_JAVA + "*Hello"); + .helloAppImage(TEST_APP_JAVA + "*Hello") + .ignoreFakeRuntime(); // Create the image of the third party application launcher cmd.executeAndAssertImageCreated(); // Start the third party application launcher and dump and save the // output of the application - List output = new Executor().saveOutput().dumpOutput() + List output = configureEnvironment(new Executor()).saveOutput().dumpOutput() .setExecutable(cmd.appLauncherPath().toAbsolutePath()) .execute(0).getOutput(); String pidStr = output.get(0); @@ -76,10 +78,12 @@ public static void test() throws Throwable { Optional processHandle = ProcessHandle.of(childPid); boolean isAlive = processHandle.isPresent() && processHandle.get().isAlive(); - TKit.assertTrue(isAlive, "Check is child process is alive"); + TKit.assertTrue(isAlive, "Check child process is alive"); } finally { - // Kill only a specific child instance - Runtime.getRuntime().exec("taskkill /F /PID " + childPid); + if (childPid != 0) { + // Kill only a specific child instance + killProcess(childPid); + } } } } From a0b89dfcaa288657659052ac8492bf62f05bad52 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 12 Nov 2025 13:39:32 +0100 Subject: [PATCH 2/2] Test adaptions to make it compile --- .../helpers/jdk/jpackage/test/CfgFile.java | 6 ++- .../helpers/jdk/jpackage/test/Comm.java | 39 +++++++++++++++++++ .../helpers/jdk/jpackage/test/TKit.java | 27 ++++--------- .../jdk/jpackage/test/WindowsHelper.java | 4 +- 4 files changed, 53 insertions(+), 23 deletions(-) create mode 100644 test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Comm.java diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java index 9df28b3915e..2604e266d5a 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CfgFile.java @@ -102,7 +102,8 @@ public void save(Path path) { private Section getSection(String name) { Objects.requireNonNull(name); - for (var section : data.reversed()) { + for (int i = data.size()-1; i >=0; i--) { + var section = data.get(i); if (name.equals(section.name)) { return section; } @@ -151,7 +152,8 @@ public static CfgFile load(Path path) throws IOException { private static record Section(String name, List> data) { String getValue(String key) { Objects.requireNonNull(key); - for (var kvp : data.reversed()) { + for (int i = data.size()-1; i >= 0; i--) { + var kvp = data.get(i); if (key.equals(kvp.getKey())) { return kvp.getValue(); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Comm.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Comm.java new file mode 100644 index 00000000000..23798f326fe --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Comm.java @@ -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(Set common, Set unique1, Set unique2) { + + static Comm compare(Set a, Set b) { + Set common = new HashSet<>(a); + common.retainAll(b); + Set unique1 = new HashSet<>(a); + unique1.removeAll(common); + Set unique2 = new HashSet<>(b); + unique2.removeAll(common); + return new Comm(common, unique1, unique2); + } +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index 45081f9efa7..e9f06e3512a 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -761,18 +761,18 @@ public void match(Path ... expected) { public void match(Set expected) { currentTest.notifyAssert(); var comm = Comm.compare(content, expected); - if (!comm.unique1.isEmpty() && !comm.unique2.isEmpty()) { + if (!comm.unique1().isEmpty() && !comm.unique2().isEmpty()) { error(String.format( "assertDirectoryContentEquals(%s): Some expected %s. Unexpected %s. Missing %s", - baseDir, format(comm.common), format(comm.unique1), format(comm.unique2))); - } else if (!comm.unique1.isEmpty()) { + baseDir, format(comm.common()), format(comm.unique1()), format(comm.unique2()))); + } else if (!comm.unique1().isEmpty()) { error(String.format( "assertDirectoryContentEquals%s: Expected %s. Unexpected %s", - baseDir, format(comm.common), format(comm.unique1))); - } else if (!comm.unique2.isEmpty()) { + baseDir, format(comm.common()), format(comm.unique1()))); + } else if (!comm.unique2().isEmpty()) { error(String.format( "assertDirectoryContentEquals(%s): Some expected %s. Missing %s", - baseDir, format(comm.common), format(comm.unique2))); + baseDir, format(comm.common()), format(comm.unique2()))); } else { traceAssert(String.format( "assertDirectoryContentEquals(%s): Expected %s", @@ -785,10 +785,10 @@ public void contains(Path ... expected) { public void contains(Set expected) { currentTest.notifyAssert(); var comm = Comm.compare(content, expected); - if (!comm.unique2.isEmpty()) { + if (!comm.unique2().isEmpty()) { error(String.format( "assertDirectoryContentContains(%s): Some expected %s. Missing %s", - baseDir, format(comm.common), format(comm.unique2))); + baseDir, format(comm.common()), format(comm.unique2()))); } else { traceAssert(String.format( "assertDirectoryContentContains(%s): Expected %s", @@ -804,17 +804,6 @@ private DirectoryContentVerifier(Path baseDir, Set contents) { this.baseDir = baseDir; this.content = contents; } - private static record Comm(Set common, Set unique1, Set unique2) { - static Comm compare(Set a, Set b) { - Set common = new HashSet<>(a); - common.retainAll(b); - Set unique1 = new HashSet<>(a); - unique1.removeAll(common); - Set unique2 = new HashSet<>(b); - unique2.removeAll(common); - return new Comm(common, unique1, unique2); - } - } private static String format(Set paths) { return Arrays.toString( paths.stream().sorted().map(Path::toString).toArray( diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index 0b675aceda6..7a853ca83f1 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -196,11 +196,11 @@ private static long[] findAppLauncherPIDs(JPackageCommand cmd, String launcherNa ")", "get", "ProcessID,ParentProcessID").dumpOutput(true). saveOutput().executeAndGetOutput(); - if ("No Instance(s) Available.".equals(output.getFirst().trim())) { + if ("No Instance(s) Available.".equals(output.get(0).trim())) { return new long[0]; } - String[] headers = Stream.of(output.getFirst().split("\\s+", 2)).map( + String[] headers = Stream.of(output.get(0).split("\\s+", 2)).map( String::trim).map(String::toLowerCase).toArray(String[]::new); Pattern pattern; if (headers[0].equals("parentprocessid") && headers[1].equals(