8379437: Refactor ProcessBuilder and ProcessHandle tests to JUnit

Reviewed-by: jpai
This commit is contained in:
Roger Riggs 2026-03-10 13:05:11 +00:00
parent f95e8136b1
commit bad59c55d9
8 changed files with 215 additions and 287 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2026, 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
@ -23,21 +23,22 @@
/*
* @test
* @bug 8023130 8166026
* @summary Unit test for java.lang.ProcessBuilder inheritance of standard output and standard error streams
* @bug 8023130 8166026
* @requires vm.flagless
* @library /test/lib
* @build jdk.test.lib.process.*
* @run testng InheritIOTest
* @run junit InheritIOTest
*/
import java.util.List;
import static java.lang.ProcessBuilder.Redirect.INHERIT;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class InheritIOTest {
@ -45,25 +46,25 @@ public class InheritIOTest {
private static final String EXPECTED_RESULT_STDOUT = "message";
private static final String EXPECTED_RESULT_STDERR = EXIT_VALUE_TEMPLATE.formatted(0);
@DataProvider
public Object[][] testCases() {
return new Object[][]{
new Object[] { List.of("InheritIOTest$TestInheritIO", "printf", EXPECTED_RESULT_STDOUT) },
new Object[] { List.of("InheritIOTest$TestRedirectInherit", "printf", EXPECTED_RESULT_STDOUT) }
};
public static List<Arguments> testCases() {
return List.of(
Arguments.of(List.of("InheritIOTest$TestInheritIO", "printf", EXPECTED_RESULT_STDOUT)),
Arguments.of(List.of("InheritIOTest$TestRedirectInherit", "printf", EXPECTED_RESULT_STDOUT))
);
}
@Test(dataProvider = "testCases")
@ParameterizedTest
@MethodSource("testCases")
public void testInheritWithoutRedirect(List<String> arguments) throws Throwable {
ProcessBuilder processBuilder = ProcessTools.createLimitedTestJavaProcessBuilder(arguments);
OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(processBuilder);
outputAnalyzer.shouldHaveExitValue(0);
assertEquals(outputAnalyzer.getStdout(), EXPECTED_RESULT_STDOUT);
assertEquals(outputAnalyzer.getStderr(), EXPECTED_RESULT_STDERR);
assertEquals(EXPECTED_RESULT_STDOUT, outputAnalyzer.getStdout());
assertEquals(EXPECTED_RESULT_STDERR, outputAnalyzer.getStderr());
}
public static class TestInheritIO {
public static void main(String args[]) throws Throwable {
public static void main(String[] args) throws Throwable {
int err = new ProcessBuilder(args).inheritIO().start().waitFor();
System.err.printf(EXIT_VALUE_TEMPLATE, err);
System.exit(err);
@ -71,7 +72,7 @@ public class InheritIOTest {
}
public static class TestRedirectInherit {
public static void main(String args[]) throws Throwable {
public static void main(String[] args) throws Throwable {
int err = new ProcessBuilder(args)
.redirectInput(INHERIT)
.redirectOutput(INHERIT)
@ -81,5 +82,4 @@ public class InheritIOTest {
System.exit(err);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2026, 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
@ -23,9 +23,9 @@
/*
* @test
* @bug 8269488
* @summary verify that Process Reaper threads have a null CCL
* @run testng ProcessReaperCCL
* @bug 8269488
* @run junit ProcessReaperCCL
*/
import java.io.File;
@ -34,14 +34,13 @@ import java.net.URLClassLoader;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class ProcessReaperCCL {
@Test
static void test() throws Exception {
void test() throws Exception {
// create a class loader
File dir = new File(".");
URL[] urls = new URL[] {dir.toURI().toURL()};
@ -53,12 +52,12 @@ public class ProcessReaperCCL {
Process p = pb.start();
CompletableFuture<Process> cf = p.onExit();
int exitValue = cf.get().exitValue();
Assert.assertEquals(exitValue, 0, "error exit value");
Assertions.assertEquals(0, exitValue, "error exit value");
// Verify all "Process Reaper" threads have a null CCL
for (Thread th : Thread.getAllStackTraces().keySet()) {
if (th.getName().startsWith("process reaper")) {
Assert.assertEquals(th.getContextClassLoader(), null, "CCL not null");
Assertions.assertNull(th.getContextClassLoader(), "CCL not null");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2026, 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
@ -34,8 +34,7 @@ import java.util.stream.Stream;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.ParameterizedTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.*;
/*
* @test

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2026, 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
@ -21,17 +21,10 @@
* questions.
*/
import static org.testng.Assert.*;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.junit.jupiter.api.Assertions.*;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.hexdump.HexPrinter;
import jdk.test.lib.hexdump.HexPrinter.Formatters;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
@ -42,20 +35,23 @@ import java.nio.file.Files;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.util.List;
import java.util.Locale;
import java.util.stream.Stream;
import jtreg.SkippedException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
/*
* @test
* @requires vm.flagless
* @library /test/lib
* @build jdk.test.lib.process.ProcessTools jdk.test.lib.hexdump.HexPrinter
* @run testng ReaderWriterTest
* @build jdk.test.lib.process.ProcessTools
* @run junit ReaderWriterTest
*/
@Test
public class ReaderWriterTest {
static final String ASCII = "ASCII: \u0000_A-Z_a-Z_\u007C_\u007D_\u007E_\u007F_;";
@ -65,13 +61,12 @@ public class ReaderWriterTest {
public static final String TESTCHARS = "OneWay: " + ASCII + ISO_8859_1 + FRACTIONS;
public static final String ROUND_TRIP_TESTCHARS = "RoundTrip: " + ASCII + ISO_8859_1 + FRACTIONS;
@DataProvider(name="CharsetCases")
static Object[][] charsetCases() {
return new Object[][] {
{"UTF-8"},
{"ISO8859-1"},
{"US-ASCII"},
};
static Stream<Arguments> charsetCases() {
return Stream.of(
Arguments.of("UTF-8"),
Arguments.of("ISO8859-1"),
Arguments.of("US-ASCII")
);
}
/**
@ -93,7 +88,7 @@ public class ReaderWriterTest {
if (exitValue != 0)
System.out.println("exitValue: " + exitValue);
} catch (InterruptedException ie) {
Assert.fail("waitFor interrupted");
fail("waitFor interrupted");
}
}
@ -131,32 +126,28 @@ public class ReaderWriterTest {
if (errType == 2 || errType == 3) {
pb.redirectErrorStream(true);
}
Process p = pb.start();
// Output has been redirected to a null stream; success is IOException on the write
try {
try (Process p = pb.start()) {
// Output has been redirected to a null stream; success is IOException on the write
BufferedWriter wr = p.outputWriter();
wr.write("X");
wr.flush();
Assert.fail("writing to null stream should throw IOException");
} catch (IOException ioe) {
// Normal, A Null output stream is closed when created.
}
assertThrows(IOException.class, () -> {
wr.write("X");
wr.flush();
});
// InputReader should be empty; and at EOF
BufferedReader inputReader = p.inputReader();
int ch = inputReader.read();
Assert.assertEquals(ch, -1, "inputReader not at EOF: ch: " + (char)ch);
// InputReader should be empty; and at EOF
BufferedReader inputReader = p.inputReader();
int ch = inputReader.read();
assertEquals(-1, ch, "inputReader not at EOF: ch: " + (char) ch);
// InputReader should be empty; and at EOF
BufferedReader errorReader = p.errorReader();
ch = errorReader.read();
Assert.assertEquals(ch, -1, "errorReader not at EOF: ch: " + (char)ch);
// InputReader should be empty; and at EOF
BufferedReader errorReader = p.errorReader();
ch = errorReader.read();
assertEquals(-1, ch, "errorReader not at EOF: ch: " + (char) ch);
try {
int exitValue = p.waitFor();
if (exitValue != 0) System.out.println("exitValue: " + exitValue);
} catch (InterruptedException ie) {
Assert.fail("waitFor interrupted");
fail("waitFor interrupted");
}
}
}
@ -181,7 +172,8 @@ public class ReaderWriterTest {
*
* @param encoding a charset name
*/
@Test(dataProvider = "CharsetCases", enabled = true)
@ParameterizedTest
@MethodSource("charsetCases")
void testCase(String encoding) throws IOException {
Charset cs = null;
try {
@ -221,32 +213,10 @@ public class ReaderWriterTest {
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
"ReaderWriterTest$ChildWithCharset");
Process p = pb.start();
try {
writeTestChars(p.outputWriter(null));
Assert.fail("Process.outputWriter(null) did not throw NPE");
} catch (NullPointerException npe) {
// expected, ignore
}
try {
checkReader(p.inputReader(null), null, "Out");
Assert.fail("Process.inputReader(null) did not throw NPE");
} catch (NullPointerException npe) {
// expected, ignore
}
try {
checkReader(p.errorReader(null), null, "Err");
Assert.fail("Process.errorReader(null) did not throw NPE");
} catch (NullPointerException npe) {
// expected, ignore
}
p.destroyForcibly();
try {
// Collect the exit status to cleanup after the process; but ignore it
p.waitFor();
} catch (InterruptedException ie) {
// Ignored
try (Process p = pb.start()) {
assertThrows(NullPointerException.class, () -> writeTestChars(p.outputWriter(null)));
assertThrows(NullPointerException.class, () -> checkReader(p.inputReader(null), null, "Out"));
assertThrows(NullPointerException.class, () -> checkReader(p.errorReader(null), null, "Err"));
}
}
@ -272,7 +242,7 @@ public class ReaderWriterTest {
var writer = p.outputWriter(cs);
writer = p.outputWriter(cs); // try again with same
writer = p.outputWriter(otherCharset); // this should throw
Assert.fail("Process.outputWriter(otherCharset) did not throw IllegalStateException");
fail("Process.outputWriter(otherCharset) did not throw IllegalStateException");
} catch (IllegalStateException ile) {
// expected, ignore
System.out.println(ile);
@ -281,7 +251,7 @@ public class ReaderWriterTest {
var reader = p.inputReader(cs);
reader = p.inputReader(cs); // try again with same
reader = p.inputReader(otherCharset); // this should throw
Assert.fail("Process.inputReader(otherCharset) did not throw IllegalStateException");
fail("Process.inputReader(otherCharset) did not throw IllegalStateException");
} catch (IllegalStateException ile) {
// expected, ignore
System.out.println(ile);
@ -290,7 +260,7 @@ public class ReaderWriterTest {
var reader = p.errorReader(cs);
reader = p.errorReader(cs); // try again with same
reader = p.errorReader(otherCharset); // this should throw
Assert.fail("Process.errorReader(otherCharset) did not throw IllegalStateException");
fail("Process.errorReader(otherCharset) did not throw IllegalStateException");
} catch (IllegalStateException ile) {
// expected, ignore
System.out.println(ile);
@ -320,13 +290,13 @@ public class ReaderWriterTest {
String reencoded = cs.decode(bb).toString();
if (!firstline.equals(reencoded))
diffStrings(firstline, reencoded);
assertEquals(firstline, reencoded, label + " Test Chars");
assertEquals(reencoded, firstline, label + " Test Chars");
bb = cs.encode(ROUND_TRIP_TESTCHARS);
reencoded = cs.decode(bb).toString();
if (!secondline.equals(reencoded))
diffStrings(secondline, reencoded);
assertEquals(secondline, reencoded, label + " Round Trip Test Chars");
assertEquals(reencoded, secondline, label + " Round Trip Test Chars");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, 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
@ -21,21 +21,22 @@
* questions.
*/
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.testng.TestNG;
import org.testng.annotations.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/*
* @test
* @summary Basic tests for ProcessHandler
* @library /test/lib
* @modules java.base/jdk.internal.misc
* jdk.management
@ -45,20 +46,18 @@ import org.testng.annotations.Test;
* jdk.test.lib.JDKToolLauncher
* jdk.test.lib.Platform
* jdk.test.lib.process.*
* @run testng Basic
* @summary Basic tests for ProcessHandler
* @author Roger Riggs
* @run junit Basic
*/
public class Basic {
/**
* Tests of ProcessHandle.current.
*/
@Test
public static void test1() {
public void test1() {
try {
ProcessHandle self = ProcessHandle.current();
ProcessHandle self1 = ProcessHandle.current();
assertEquals(self, self1); //, "get pid twice should be same %d: %d");
assertEquals(self1, self); //, "get pid twice should be same %d: %d");
} finally {
// Cleanup any left over processes
ProcessHandle.current().children().forEach(ProcessHandle::destroy);
@ -69,16 +68,16 @@ public class Basic {
* Tests of ProcessHandle.get.
*/
@Test
public static void test2() {
public void test2() {
try {
ProcessHandle self = ProcessHandle.current();
long pid = self.pid(); // known native process id
Optional<ProcessHandle> self1 = ProcessHandle.of(pid);
assertEquals(self1.get(), self,
assertEquals(self, self1.get(),
"ProcessHandle.of(x.pid()) should be equal pid() %d: %d");
Optional<ProcessHandle> ph = ProcessHandle.of(pid);
assertEquals(pid, ph.get().pid());
assertEquals(ph.get().pid(), pid);
} finally {
// Cleanup any left over processes
ProcessHandle.current().children().forEach(ProcessHandle::destroy);
@ -86,7 +85,7 @@ public class Basic {
}
@Test
public static void test3() {
public void test3() {
// Test can get parent of current
ProcessHandle ph = ProcessHandle.current();
try {
@ -99,7 +98,7 @@ public class Basic {
}
@Test
public static void test4() {
public void test4() {
try {
Process p = new ProcessBuilder("sleep", "0").start();
p.waitFor();
@ -118,7 +117,7 @@ public class Basic {
}
@Test
public static void test5() {
public void test5() {
// Always contains itself.
ProcessHandle current = ProcessHandle.current();
List<ProcessHandle> list = ProcessHandle.allProcesses().collect(Collectors.toList());
@ -131,23 +130,17 @@ public class Basic {
}
}
@Test(expectedExceptions = IllegalStateException.class)
public static void test6() {
ProcessHandle.current().onExit();
@Test
public void test6() {
Assertions.assertThrows(IllegalStateException.class, () -> {
ProcessHandle.current().onExit();
});
}
@Test(expectedExceptions = IllegalStateException.class)
public static void test7() {
ProcessHandle.current().destroyForcibly();
@Test
public void test7() {
Assertions.assertThrows(IllegalStateException.class, () -> {
ProcessHandle.current().destroyForcibly();
});
}
// Main can be used to run the tests from the command line with only testng.jar.
@SuppressWarnings("raw_types")
public static void main(String[] args) {
Class<?>[] testclass = {TreeTest.class};
TestNG testng = new TestNG();
testng.setTestClasses(testclass);
testng.run();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, 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
@ -39,15 +39,15 @@ import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.testng.Assert;
import org.testng.TestNG;
import org.testng.annotations.Test;
import jdk.test.lib.Platform;
import jdk.test.lib.Utils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/*
* @test
* @summary Functions of ProcessHandle.Info
* @bug 8077350 8081566 8081567 8098852 8136597
* @requires os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")
* @library /test/lib
@ -59,8 +59,7 @@ import jdk.test.lib.Utils;
* jdk.test.lib.JDKToolLauncher
* jdk.test.lib.Platform
* jdk.test.lib.process.*
* @run testng InfoTest
* @summary Functions of ProcessHandle.Info
* @run junit InfoTest
* @author Roger Riggs
*/
@ -82,19 +81,11 @@ public class InfoTest {
}
}
// Main can be used to run the tests from the command line with only testng.jar.
public static void main(String[] args) {
Class<?>[] testclass = {InfoTest.class};
TestNG testng = new TestNG();
testng.setTestClasses(testclass);
testng.run();
}
/**
* Test that cputime used shows up in ProcessHandle.info
*/
@Test
public static void test1() {
public void test1() {
System.out.println("Note: when run in samevm mode the cputime of the " +
"test runner is included.");
ProcessHandle self = ProcessHandle.current();
@ -108,7 +99,7 @@ public class InfoTest {
System.out.printf(" info: %s%n", info);
Optional<Duration> totalCpu = info.totalCpuDuration();
if (totalCpu.isPresent() && (totalCpu.get().compareTo(someCPU) < 0)) {
Assert.fail("reported cputime less than expected: " + someCPU + ", " +
Assertions.fail("reported cputime less than expected: " + someCPU + ", " +
"actual: " + info.totalCpuDuration());
}
}
@ -117,7 +108,7 @@ public class InfoTest {
* Spawn a child with arguments and check they are visible via the ProcessHandle.
*/
@Test
public static void test2() {
public void test2() {
try {
long cpuLoopTime = 100; // 100 ms
String[] extraArgs = {"pid", "parent", "stdin"};
@ -170,7 +161,7 @@ public class InfoTest {
String expected = Platform.isWindows() ? javaExe + ".exe" : javaExe;
Path expectedPath = Paths.get(expected);
Path actualPath = Paths.get(command.get());
Assert.assertTrue(Files.isSameFile(expectedPath, actualPath),
Assertions.assertTrue(Files.isSameFile(expectedPath, actualPath),
"Command: expected: " + javaExe + ", actual: " + command.get());
}
@ -179,22 +170,20 @@ public class InfoTest {
int offset = args.length - extraArgs.length;
for (int i = 0; i < extraArgs.length; i++) {
Assert.assertEquals(args[offset + i], extraArgs[i],
Assertions.assertEquals(extraArgs[i], args[offset + i],
"Actual argument mismatch, index: " + i);
}
// Now check that the first argument is not the same as the executed command
if (args.length > 0) {
Assert.assertNotEquals(args[0], command,
"First argument should not be the executable: args[0]: "
+ args[0] + ", command: " + command);
}
Assertions.assertNotEquals(command, args[0],
"First argument should not be the executable: args[0]: "
+ args[0] + ", command: " + command);
}
if (command.isPresent() && info.arguments().isPresent()) {
// If both, 'command' and 'arguments' are present,
// 'commandLine' is just the concatenation of the two.
Assert.assertTrue(info.commandLine().isPresent(),
Assertions.assertTrue(info.commandLine().isPresent(),
"commandLine() must be available");
String javaExe = System.getProperty("test.jdk") +
@ -204,15 +193,15 @@ public class InfoTest {
String commandLine = info.commandLine().get();
String commandLineCmd = commandLine.split(" ")[0];
Path commandLineCmdPath = Paths.get(commandLineCmd);
Assert.assertTrue(Files.isSameFile(commandLineCmdPath, expectedPath),
Assertions.assertTrue(Files.isSameFile(commandLineCmdPath, expectedPath),
"commandLine() should start with: " + expectedPath +
" but starts with " + commandLineCmdPath);
Assert.assertTrue(commandLine.contains(command.get()),
Assertions.assertTrue(commandLine.contains(command.get()),
"commandLine() must contain the command: " + command.get());
List<String> allArgs = p1.getArgs();
for (int i = 1; i < allArgs.size(); i++) {
Assert.assertTrue(commandLine.contains(allArgs.get(i)),
Assertions.assertTrue(commandLine.contains(allArgs.get(i)),
"commandLine() must contain argument: " + allArgs.get(i));
}
} else if (info.commandLine().isPresent() &&
@ -222,14 +211,14 @@ public class InfoTest {
String commandLine = info.commandLine().get();
String javaExe = "java" + (Platform.isWindows() ? ".exe" : "");
int pos = commandLine.indexOf(javaExe);
Assert.assertTrue(pos > 0, "commandLine() should at least contain 'java'");
Assertions.assertTrue(pos > 0, "commandLine() should at least contain 'java'");
pos += javaExe.length() + 1; // +1 for the space after the command
List<String> allArgs = p1.getArgs();
// First argument is the command - skip it here as we've already checked that.
for (int i = 1; (i < allArgs.size()) &&
(pos + allArgs.get(i).length() < commandLine.length()); i++) {
Assert.assertTrue(commandLine.contains(allArgs.get(i)),
Assertions.assertTrue(commandLine.contains(allArgs.get(i)),
"commandLine() must contain argument: " + allArgs.get(i));
pos += allArgs.get(i).length() + 1;
}
@ -242,14 +231,14 @@ public class InfoTest {
System.out.printf(" info.totalCPU: %s, childCpuTime: %s, diff: %s%n",
totalCPU.toNanos(), childCpuTime.toNanos(),
childCpuTime.toNanos() - totalCPU.toNanos());
Assert.assertTrue(checkEpsilon(childCpuTime, totalCPU, epsilon),
Assertions.assertTrue(checkEpsilon(childCpuTime, totalCPU, epsilon),
childCpuTime + " should be within " +
epsilon + " of " + totalCPU);
}
Assert.assertTrue(totalCPU.toNanos() > 0L,
Assertions.assertTrue(totalCPU.toNanos() > 0L,
"total cpu time expected > 0ms, actual: " + totalCPU);
long t = Utils.adjustTimeout(10L); // Adjusted timeout seconds
Assert.assertTrue(totalCPU.toNanos() < lastCpu.toNanos() + t * 1_000_000_000L,
Assertions.assertTrue(totalCPU.toNanos() < lastCpu.toNanos() + t * 1_000_000_000L,
"total cpu time expected < " + t
+ " seconds more than previous iteration, actual: "
+ (totalCPU.toNanos() - lastCpu.toNanos()));
@ -258,18 +247,18 @@ public class InfoTest {
if (info.startInstant().isPresent()) {
Instant startTime = info.startInstant().get();
Assert.assertTrue(startTime.isBefore(afterStart),
Assertions.assertTrue(startTime.isBefore(afterStart),
"startTime after process spawn completed"
+ startTime + " + > " + afterStart);
}
}
}
p1.sendAction("exit");
Assert.assertTrue(p1.waitFor(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
Assertions.assertTrue(p1.waitFor(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
"timeout waiting for process to terminate");
} catch (IOException | InterruptedException ie) {
ie.printStackTrace(System.out);
Assert.fail("unexpected exception", ie);
Assertions.fail("unexpected exception", ie);
} finally {
// Destroy any children that still exist
ProcessUtil.destroyProcessTree(ProcessHandle.current());
@ -280,7 +269,7 @@ public class InfoTest {
* Spawn a child with arguments and check they are visible via the ProcessHandle.
*/
@Test
public static void test3() {
public void test3() {
try {
for (long sleepTime : Arrays.asList(Utils.adjustTimeout(30), Utils.adjustTimeout(32))) {
Process p = spawn("sleep", String.valueOf(sleepTime));
@ -302,22 +291,22 @@ public class InfoTest {
Path executable = Files.readSymbolicLink(Paths.get("/bin/sleep"));
expected = executable.getFileName().toString();
}
Assert.assertTrue(command.endsWith(expected), "Command: expected: \'" +
Assertions.assertTrue(command.endsWith(expected), "Command: expected: \'" +
expected + "\', actual: " + command);
// Verify the command exists and is executable
File exe = new File(command);
Assert.assertTrue(exe.exists(), "command must exist: " + exe);
Assert.assertTrue(exe.canExecute(), "command must be executable: " + exe);
Assertions.assertTrue(exe.exists(), "command must exist: " + exe);
Assertions.assertTrue(exe.canExecute(), "command must be executable: " + exe);
}
if (info.arguments().isPresent()) {
String[] args = info.arguments().get();
if (args.length > 0) {
Assert.assertEquals(args[0], String.valueOf(sleepTime));
Assertions.assertEquals(String.valueOf(sleepTime), args[0]);
}
}
p.destroy();
Assert.assertTrue(p.waitFor(Utils.adjustTimeout(30), TimeUnit.SECONDS),
Assertions.assertTrue(p.waitFor(Utils.adjustTimeout(30), TimeUnit.SECONDS),
"timeout waiting for process to terminate");
}
} catch (IOException | InterruptedException ex) {
@ -332,7 +321,7 @@ public class InfoTest {
* Cross check the cputime reported from java.management with that for the current process.
*/
@Test
public static void test4() {
public void test4() {
Duration myCputime1 = ProcessUtil.MXBeanCpuTime();
if (Platform.isAix()) {
@ -367,26 +356,26 @@ public class InfoTest {
Objects.toString(total2), myCputime2, myCputime2.minus(total2));
Duration epsilon = Duration.ofMillis(200L); // Epsilon is 200ms.
Assert.assertTrue(checkEpsilon(myCputime1, myCputime2, epsilon),
Assertions.assertTrue(checkEpsilon(myCputime1, myCputime2, epsilon),
myCputime1.toNanos() + " should be within " + epsilon
+ " of " + myCputime2.toNanos());
Assert.assertTrue(checkEpsilon(total1, total2, epsilon),
Assertions.assertTrue(checkEpsilon(total1, total2, epsilon),
total1.toNanos() + " should be within " + epsilon
+ " of " + total2.toNanos());
Assert.assertTrue(checkEpsilon(myCputime1, total1, epsilon),
Assertions.assertTrue(checkEpsilon(myCputime1, total1, epsilon),
myCputime1.toNanos() + " should be within " + epsilon
+ " of " + total1.toNanos());
Assert.assertTrue(checkEpsilon(total1, myCputime2, epsilon),
Assertions.assertTrue(checkEpsilon(total1, myCputime2, epsilon),
total1.toNanos() + " should be within " + epsilon
+ " of " + myCputime2.toNanos());
Assert.assertTrue(checkEpsilon(myCputime2, total2, epsilon),
Assertions.assertTrue(checkEpsilon(myCputime2, total2, epsilon),
myCputime2.toNanos() + " should be within " + epsilon
+ " of " + total2.toNanos());
}
}
@Test
public static void test5() {
public void test5() {
ProcessHandle self = ProcessHandle.current();
Random r = new Random();
for (int i = 0; i < 30; i++) {
@ -458,13 +447,12 @@ public class InfoTest {
return;
}
String user = info.user().get();
Assert.assertNotNull(user, "User name");
Assertions.assertNotNull(user, "User name");
if (Platform.isWindows() && "BUILTIN\\Administrators".equals(whoami)) {
int bsi = user.lastIndexOf("\\");
Assert.assertEquals(bsi == -1 ? user : user.substring(bsi + 1),
System.getProperty("user.name"), "User name");
Assertions.assertEquals(System.getProperty("user.name"), bsi == -1 ? user : user.substring(bsi + 1), "User name");
} else {
Assert.assertEquals(user, whoami, "User name");
Assertions.assertEquals(whoami, user, "User name");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, 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
@ -35,37 +35,27 @@ import java.util.concurrent.TimeUnit;
import jdk.test.lib.Platform;
import jdk.test.lib.Utils;
import org.testng.annotations.Test;
import org.testng.Assert;
import org.testng.TestNG;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/*
* @test
* @summary Functions of Process.onExit and ProcessHandle.onExit
* @bug 8333742
* @requires vm.flagless
* @library /test/lib
* @modules jdk.management
* @build jdk.test.lib.Utils
* @run testng OnExitTest
* @summary Functions of Process.onExit and ProcessHandle.onExit
* @author Roger Riggs
* @run junit OnExitTest
*/
public class OnExitTest extends ProcessUtil {
@SuppressWarnings("raw_types")
public static void main(String[] args) {
Class<?>[] testclass = { OnExitTest.class};
TestNG testng = new TestNG();
testng.setTestClasses(testclass);
testng.run();
}
/**
* Basic test of exitValue and onExit.
*/
@Test
public static void test1() {
public void test1() {
try {
int[] exitValues = {0, 1, 10, 259};
for (int value : exitValues) {
@ -73,24 +63,24 @@ public class OnExitTest extends ProcessUtil {
if (value == 259 && !Platform.isWindows()) continue;
Process p = JavaChild.spawn("exit", Integer.toString(value));
CompletableFuture<Process> future = p.onExit();
future.thenAccept( (ph) -> {
future.thenAccept((ph) -> {
int actualExitValue = ph.exitValue();
printf(" javaChild done: %s, exitStatus: %d%n",
ph, actualExitValue);
Assert.assertEquals(actualExitValue, value, "actualExitValue incorrect");
Assert.assertEquals(ph, p, "Different Process passed to thenAccept");
Assertions.assertEquals(value, actualExitValue, "actualExitValue incorrect");
Assertions.assertEquals(p, ph, "Different Process passed to thenAccept");
});
Process h = future.get();
Assert.assertEquals(h, p);
Assert.assertEquals(p.exitValue(), value);
Assert.assertFalse(p.isAlive(), "Process should not be alive");
Assert.assertEquals(p.waitFor(), value);
Assert.assertTrue(p.waitFor(1, TimeUnit.MILLISECONDS),
Assertions.assertEquals(p, h);
Assertions.assertEquals(value, p.exitValue());
Assertions.assertFalse(p.isAlive(), "Process should not be alive");
Assertions.assertEquals(value, p.waitFor());
Assertions.assertTrue(p.waitFor(1, TimeUnit.MILLISECONDS),
"waitFor should return true");
}
} catch (IOException | InterruptedException | ExecutionException ex) {
Assert.fail(ex.getMessage(), ex);
Assertions.fail(ex.getMessage(), ex);
} finally {
destroyProcessTree(ProcessHandle.current());
}
@ -101,7 +91,7 @@ public class OnExitTest extends ProcessUtil {
* Spawn 1 child to spawn 3 children each with 2 children.
*/
@Test
public static void test2() {
public void test2() {
// Please note (JDK-8284282):
//
@ -176,7 +166,7 @@ public class OnExitTest extends ProcessUtil {
// Check that each of the spawned processes is included in the children
List<ProcessHandle> remaining = new ArrayList<>(children);
processes.forEach((p, parent) -> {
Assert.assertTrue(remaining.remove(p), "spawned process should have been in children");
Assertions.assertTrue(remaining.remove(p), "spawned process should have been in children");
});
// Remove Win32 system spawned conhost.exe processes
@ -204,7 +194,7 @@ public class OnExitTest extends ProcessUtil {
// Verify that all 9 exit handlers were called with the correct ProcessHandle
processes.forEach((p, parent) -> {
ProcessHandle value = completions.get(p).getNow(null);
Assert.assertEquals(p, value, "onExit.get value expected: " + p
Assertions.assertEquals(value, p, "onExit.get value expected: " + p
+ ", actual: " + value
+ ": " + p.info());
});
@ -212,9 +202,9 @@ public class OnExitTest extends ProcessUtil {
// Show the status of the original children
children.forEach(p -> printProcess(p, "after onExit:"));
Assert.assertEquals(proc.isAlive(), false, "destroyed process is alive:: %s%n" + proc);
Assertions.assertFalse(proc.isAlive(), "destroyed process is alive:: %s%n" + proc);
} catch (IOException | InterruptedException ex) {
Assert.fail(ex.getMessage());
Assertions.fail(ex.getMessage(), ex);
} finally {
if (procHandle != null) {
destroyProcessTree(procHandle);
@ -231,7 +221,7 @@ public class OnExitTest extends ProcessUtil {
* Check that (B) does not complete until (A) has exited.
*/
@Test
public static void peerOnExitTest() {
public void peerOnExitTest() {
String line = null;
ArrayBlockingQueue<String> alines = new ArrayBlockingQueue<>(100);
ArrayBlockingQueue<String> blines = new ArrayBlockingQueue<>(100);
@ -265,9 +255,9 @@ public class OnExitTest extends ProcessUtil {
try {
line = blines.poll(5L, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
Assert.fail("interrupted", ie);
Assertions.fail("interrupted", ie);
}
Assert.assertNull(line, "waitpid didn't wait");
Assertions.assertNull(line, "waitpid didn't wait");
A.toHandle().onExit().thenAccept(p -> {
System.out.printf(" A.toHandle().onExit().A info: %s, now: %s%n",
@ -296,16 +286,16 @@ public class OnExitTest extends ProcessUtil {
split = getSplitLine(blines);
} while (!"waitpid".equals(split[1]));
Assert.assertEquals(split[2], "false", "Process A should not be alive");
Assertions.assertEquals("false", split[2], "Process A should not be alive");
B.sendAction("exit", 0L);
} catch (IOException ioe) {
Assert.fail("unable to start JavaChild B", ioe);
Assertions.fail("unable to start JavaChild B", ioe);
} finally {
B.destroyForcibly();
}
} catch (IOException ioe2) {
Assert.fail("unable to start JavaChild A", ioe2);
Assertions.fail("unable to start JavaChild A", ioe2);
} finally {
A.destroyForcibly();
}
@ -328,7 +318,7 @@ public class OnExitTest extends ProcessUtil {
}
return split;
} catch (InterruptedException ie) {
Assert.fail("interrupted", ie);
Assertions.fail("interrupted", ie);
return null;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, 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
@ -38,12 +38,12 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.test.lib.Utils;
import org.testng.Assert;
import org.testng.TestNG;
import org.testng.annotations.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/*
* @test
* @summary Test counting and JavaChild.spawning and counting of Processes.
* @requires vm.flagless
* @library /test/lib
* @modules java.base/jdk.internal.misc
@ -54,25 +54,15 @@ import org.testng.annotations.Test;
* jdk.test.lib.JDKToolLauncher
* jdk.test.lib.Platform
* jdk.test.lib.process.*
* @run testng/othervm TreeTest
* @summary Test counting and JavaChild.spawning and counting of Processes.
* @run junit/othervm TreeTest
* @author Roger Riggs
*/
public class TreeTest extends ProcessUtil {
// Main can be used to run the tests from the command line with only testng.jar.
@SuppressWarnings("raw_types")
public static void main(String[] args) {
Class<?>[] testclass = {TreeTest.class};
TestNG testng = new TestNG();
testng.setTestClasses(testclass);
testng.run();
}
/**
* Test counting and spawning and counting of Processes.
*/
@Test
public static void test1() {
public void test1() {
final int MAXCHILDREN = 2;
List<JavaChild> spawned = new ArrayList<>();
@ -92,14 +82,14 @@ public class TreeTest extends ProcessUtil {
spawned.stream()
.map(Process::toHandle)
.filter(p -> !initialChildren.contains(p))
.forEach(p -> Assert.fail("Spawned process missing from children: " + p));
.forEach(p -> Assertions.fail("Spawned process missing from children: " + p));
// Send exit command to each spawned Process
spawned.forEach(p -> {
try {
p.sendAction("exit", "");
} catch (IOException ex) {
Assert.fail("IOException in sendAction", ex);
Assertions.fail("IOException in sendAction", ex);
}
});
@ -107,7 +97,7 @@ public class TreeTest extends ProcessUtil {
spawned.forEach(p -> {
do {
try {
Assert.assertEquals(p.waitFor(), 0, "exit status incorrect");
Assertions.assertEquals(0, p.waitFor(), "exit status incorrect");
break;
} catch (InterruptedException ex) {
continue; // Retry
@ -118,7 +108,7 @@ public class TreeTest extends ProcessUtil {
// Verify that ProcessHandle.isAlive sees each of them as not alive
for (Process p : spawned) {
ProcessHandle ph = p.toHandle();
Assert.assertFalse(ph.isAlive(),
Assertions.assertFalse(ph.isAlive(),
"ProcessHandle.isAlive for exited process: " + ph);
}
@ -126,13 +116,13 @@ public class TreeTest extends ProcessUtil {
final List<ProcessHandle> afterChildren = getChildren(self);
spawned.stream()
.map(Process::toHandle)
.filter(p -> afterChildren.contains(p))
.forEach(p -> Assert.fail("Spawned process missing from children: " + p));
.filter(afterChildren::contains)
.forEach(p -> Assertions.fail("Spawned process missing from children: " + p));
} catch (IOException ioe) {
Assert.fail("unable to spawn process", ioe);
Assertions.fail("unable to spawn process", ioe);
} finally {
// Cleanup any left over processes
// Cleanup any leftover processes
spawned.stream()
.map(Process::toHandle)
.filter(ProcessHandle::isAlive)
@ -147,7 +137,7 @@ public class TreeTest extends ProcessUtil {
* Test counting and spawning and counting of Processes.
*/
@Test
public static void test2() {
public void test2() {
try {
ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>();
@ -162,12 +152,12 @@ public class TreeTest extends ProcessUtil {
ProcessHandle p1Handle = p1.toHandle();
printf(" p1 pid: %d%n", p1.pid());
// Gather the PIDs from the output of the spawing process
// Gather the PIDs from the output of the spawning process
p1.forEachOutputLine((s) -> {
String[] split = s.trim().split(" ");
if (split.length == 3 && split[1].equals("spawn")) {
Long child = Long.valueOf(split[2]);
Long parent = Long.valueOf(split[0].split(":")[0]);
long child = Long.parseLong(split[2]);
long parent = Long.parseLong(split[0].split(":")[0]);
processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get());
}
});
@ -179,11 +169,11 @@ public class TreeTest extends ProcessUtil {
List<ProcessHandle> subprocesses = waitForAllChildren(p1Handle, spawnNew);
Optional<Instant> p1Start = p1Handle.info().startInstant();
for (ProcessHandle ph : subprocesses) {
Assert.assertTrue(ph.isAlive(), "Child should be alive: " + ph);
Assertions.assertTrue(ph.isAlive(), "Child should be alive: " + ph);
// Verify each child was started after the parent
ph.info().startInstant()
.ifPresent(childStart -> p1Start.ifPresent(parentStart -> {
Assert.assertFalse(childStart.isBefore(parentStart),
Assertions.assertFalse(childStart.isBefore(parentStart),
String.format("Child process started before parent: child: %s, parent: %s",
childStart, parentStart));
}));
@ -217,8 +207,8 @@ public class TreeTest extends ProcessUtil {
// Verify that all spawned children show up in the descendants List
processes.forEach((p, parent) -> {
Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p);
Assert.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p);
Assertions.assertTrue(p.isAlive(), "Child should be alive: " + p);
Assertions.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p);
});
// Closing JavaChild's InputStream will cause all children to exit
@ -228,13 +218,13 @@ public class TreeTest extends ProcessUtil {
try {
p.onExit().get(); // wait for the child to exit
} catch (ExecutionException e) {
Assert.fail("waiting for process to exit", e);
Assertions.fail("waiting for process to exit", e);
}
}
p1.waitFor(); // wait for spawned process to exit
// Verify spawned processes are no longer alive
processes.forEach((ph, parent) -> Assert.assertFalse(ph.isAlive(),
processes.forEach((ph, parent) -> Assertions.assertFalse(ph.isAlive(),
"process should not be alive: " + ph));
} catch (IOException | InterruptedException t) {
t.printStackTrace();
@ -250,7 +240,7 @@ public class TreeTest extends ProcessUtil {
* After they exit they should no longer be listed by descendants.
*/
@Test
public static void test3() {
public void test3() {
ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>();
try {
@ -269,15 +259,15 @@ public class TreeTest extends ProcessUtil {
p1.forEachOutputLine((s) -> {
String[] split = s.trim().split(" ");
if (split.length == 3 && split[1].equals("spawn")) {
Long child = Long.valueOf(split[2]);
Long parent = Long.valueOf(split[0].split(":")[0]);
long child = Long.parseLong(split[2]);
long parent = Long.parseLong(split[0].split(":")[0]);
processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get());
spawnCount.countDown();
}
});
// Wait for all the subprocesses to be listed as started
Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
Assertions.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
"Timeout waiting for processes to start");
// Debugging; list descendants that are not expected in processes
@ -290,17 +280,17 @@ public class TreeTest extends ProcessUtil {
.filter(ph -> !processes.containsKey(ph))
.forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: "));
ProcessUtil.logTaskList();
Assert.assertEquals(0, count, "Extra processes in descendants");
Assertions.assertEquals(0, count, "Extra processes in descendants");
}
// Verify that all spawned children are alive, show up in the descendants list
// then destroy them
processes.forEach((p, parent) -> {
Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p);
Assert.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p);
Assertions.assertTrue(p.isAlive(), "Child should be alive: " + p);
Assertions.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p);
p.destroyForcibly();
});
Assert.assertEquals(processes.size(), newChildren, "Wrong number of children");
Assertions.assertEquals(newChildren, processes.size(), "Wrong number of children");
// Wait for each of the processes to exit
processes.forEach((p, parent) -> {
@ -317,21 +307,21 @@ public class TreeTest extends ProcessUtil {
}
printf("Timeout waiting for exit of pid %s, parent: %s, info: %s%n",
p, parent, p.info());
Assert.fail("Process still alive: " + p);
Assertions.fail("Process still alive: " + p);
});
p1.destroyForcibly();
p1.waitFor();
// Verify that none of the spawned children are still listed by descendants
List<ProcessHandle> remaining = getDescendants(self);
Assert.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited");
Assertions.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited");
remaining = remaining.stream().filter(processes::containsKey).collect(Collectors.toList());
Assert.assertEquals(remaining.size(), 0, "Subprocess(es) should have exited: " + remaining);
Assertions.assertEquals(0, remaining.size(), "Subprocess(es) should have exited: " + remaining);
} catch (IOException ioe) {
Assert.fail("Spawn of subprocess failed", ioe);
Assertions.fail("Spawn of subprocess failed", ioe);
} catch (InterruptedException inte) {
Assert.fail("InterruptedException", inte);
Assertions.fail("InterruptedException", inte);
} finally {
processes.forEach((p, parent) -> {
if (p.isAlive()) {
@ -346,7 +336,7 @@ public class TreeTest extends ProcessUtil {
* Test (Not really a test) that dumps the list of all Processes.
*/
@Test
public static void test4() {
public void test4() {
printf(" Parent Child Info%n");
Stream<ProcessHandle> s = ProcessHandle.allProcesses();
ProcessHandle[] processes = s.toArray(ProcessHandle[]::new);
@ -384,7 +374,7 @@ public class TreeTest extends ProcessUtil {
}
printf("%s %7s, %7s, %s%n", indent, p_parent, p, info);
}
Assert.assertFalse(fail, "Parents missing from all Processes");
Assertions.assertFalse(fail, "Parents missing from all Processes");
}
@ -392,7 +382,7 @@ public class TreeTest extends ProcessUtil {
* A test for scale; launch a large number (14) of subprocesses.
*/
@Test
public static void test5() {
public void test5() {
ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>();
int factor = 2;
@ -421,15 +411,15 @@ public class TreeTest extends ProcessUtil {
p1.forEachOutputLine((s) -> {
String[] split = s.trim().split(" ");
if (split.length == 3 && split[1].equals("spawn")) {
Long child = Long.valueOf(split[2]);
Long parent = Long.valueOf(split[0].split(":")[0]);
long child = Long.parseLong(split[2]);
long parent = Long.parseLong(split[0].split(":")[0]);
processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get());
spawnCount.countDown();
}
});
// Wait for all the subprocesses to be listed as started
Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
Assertions.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
"Timeout waiting for processes to start");
// Debugging; list descendants that are not expected in processes
@ -442,30 +432,29 @@ public class TreeTest extends ProcessUtil {
.filter(ph -> !processes.containsKey(ph))
.forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: "));
ProcessUtil.logTaskList();
Assert.assertEquals(0, count, "Extra processes in descendants");
Assertions.assertEquals(0, count, "Extra processes in descendants");
}
List<ProcessHandle> subprocesses = getChildren(p1Handle);
printf(" children: %s%n",
subprocesses.stream().map(p -> p.pid())
subprocesses.stream().map(ProcessHandle::pid)
.collect(Collectors.toList()));
Assert.assertEquals(getChildren(p1Handle).size(),
factor, "expected direct children");
Assertions.assertEquals(factor, getChildren(p1Handle).size(), "expected direct children");
count = getDescendants(p1Handle).size();
long totalChildren = factor * factor * factor + factor * factor + factor;
Assert.assertTrue(count >= totalChildren,
Assertions.assertTrue(count >= totalChildren,
"expected at least " + totalChildren + ", actual: " + count);
List<ProcessHandle> descSubprocesses = getDescendants(p1Handle);
printf(" descendants: %s%n",
descSubprocesses.stream().map(p -> p.pid())
descSubprocesses.stream().map(ProcessHandle::pid)
.collect(Collectors.toList()));
p1.getOutputStream().close(); // Close stdin for the controlling p1
p1.waitFor();
} catch (InterruptedException | IOException ex) {
Assert.fail("Unexpected Exception", ex);
Assertions.fail("Unexpected Exception", ex);
} finally {
printf("Duration: %s%n", Duration.between(start, Instant.now()));
if (p1 != null) {