/** Test (Not really a test) that dumps the list of all Processes. */ @Test public static void test4() { printf(" Parent Child Info%n"); Stream<ProcessHandle> s = ProcessHandle.allProcesses(); ProcessHandle[] processes = s.toArray(ProcessHandle[]::new); int len = processes.length; ProcessHandle[] parent = new ProcessHandle[len]; Set<ProcessHandle> processesSet = Arrays.stream(processes).collect(Collectors.toSet()); Integer[] sortindex = new Integer[len]; for (int i = 0; i < len; i++) { sortindex[i] = i; } for (int i = 0; i < len; i++) { parent[sortindex[i]] = processes[sortindex[i]].parent().orElse(null); } Arrays.sort( sortindex, (i1, i2) -> { int cmp = Long.compare( (parent[i1] == null ? 0L : parent[i1].getPid()), (parent[i2] == null ? 0L : parent[i2].getPid())); if (cmp == 0) { cmp = Long.compare( (processes[i1] == null ? 0L : processes[i1].getPid()), (processes[i2] == null ? 0L : processes[i2].getPid())); } return cmp; }); boolean fail = false; for (int i = 0; i < len; i++) { ProcessHandle p = processes[sortindex[i]]; ProcessHandle p_parent = parent[sortindex[i]]; ProcessHandle.Info info = p.info(); String indent = " "; if (p_parent != null) { if (!processesSet.contains(p_parent)) { fail = true; indent = "*** "; } } printf("%s %7s, %7s, %s%n", indent, p_parent, p, info); } Assert.assertFalse(fail, "Parents missing from all Processes"); }
/** Test counting and spawning and counting of Processes. */ @Test public static void test2() { try { ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>(); ProcessHandle self = ProcessHandle.current(); List<ProcessHandle> initialChildren = getChildren(self); long count = initialChildren.size(); if (count > 0) { initialChildren.forEach(p -> printDeep(p, "test2 initial unexpected: ")); } JavaChild p1 = JavaChild.spawnJavaChild("stdin"); ProcessHandle p1Handle = p1.toHandle(); printf(" p1 pid: %d%n", p1.getPid()); // Gather the PIDs from the output of the spawing 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]); processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); } }); int spawnNew = 3; p1.sendAction("spawn", spawnNew, "stdin"); // Wait for direct children to be created and save the list 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); // Verify each child was started after the parent ph.info() .startInstant() .ifPresent( childStart -> p1Start.ifPresent( parentStart -> { Assert.assertFalse( childStart.isBefore(parentStart), String.format( "Child process started before parent: child: %s, parent: %s", childStart, parentStart)); })); } // Each child spawns two processes and waits for commands int spawnNewSub = 2; p1.sendAction("child", "spawn", spawnNewSub, "stdin"); // Poll until all 9 child processes exist or the timeout is reached int expected = 9; long timeout = Utils.adjustTimeout(60L); Instant endTimeout = Instant.now().plusSeconds(timeout); do { Thread.sleep(200L); printf(" subprocess count: %d, waiting for %d%n", processes.size(), expected); } while (processes.size() < expected && Instant.now().isBefore(endTimeout)); if (processes.size() < expected) { printf("WARNING: not all children have been started. Can't complete test.%n"); printf(" You can try to increase the timeout or%n"); printf(" you can try to use a faster VM (i.e. not a debug version).%n"); } // show the complete list of children (for debug) List<ProcessHandle> descendants = getDescendants(p1Handle); printf( " descendants: %s%n", descendants.stream().map(p -> p.getPid()).collect(Collectors.toList())); // 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); }); // Closing JavaChild's InputStream will cause all children to exit p1.getOutputStream().close(); for (ProcessHandle p : descendants) { try { p.onExit().get(); // wait for the child to exit } catch (ExecutionException e) { Assert.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(), "process should not be alive: " + ph)); } catch (IOException | InterruptedException t) { t.printStackTrace(); throw new RuntimeException(t); } }