Skip to content

Commit

Permalink
8287008: Improve tests for thread dumps in JSON format
Browse files Browse the repository at this point in the history
Reviewed-by: cjplummer
  • Loading branch information
Alan Bateman committed May 24, 2022
1 parent a5caffd commit 15f1583
Show file tree
Hide file tree
Showing 4 changed files with 421 additions and 32 deletions.
8 changes: 4 additions & 4 deletions src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ private static void dumpThreadsToJson(PrintStream out) {

String now = Instant.now().toString();
String runtimeVersion = Runtime.version().toString();
out.format(" \"processId\": %d,%n", processId());
out.format(" \"processId\": \"%d\",%n", processId());
out.format(" \"time\": \"%s\",%n", escape(now));
out.format(" \"runtimeVersion\": \"%s\",%n", escape(runtimeVersion));

Expand Down Expand Up @@ -226,7 +226,7 @@ private static void dumpThreadsToJson(ThreadContainer container,
if (owner == null) {
out.format(" \"owner\": null,%n");
} else {
out.format(" \"owner\": %d,%n", owner.threadId());
out.format(" \"owner\": \"%d\",%n", owner.threadId());
}

long threadCount = 0;
Expand All @@ -241,7 +241,7 @@ private static void dumpThreadsToJson(ThreadContainer container,

// thread count
threadCount = Long.max(threadCount, container.threadCount());
out.format(" \"threadCount\": %d%n", threadCount);
out.format(" \"threadCount\": \"%d\"%n", threadCount);

if (more) {
out.println(" },");
Expand All @@ -255,7 +255,7 @@ private static void dumpThreadsToJson(ThreadContainer container,
*/
private static void dumpThreadToJson(Thread thread, PrintStream out, boolean more) {
out.println(" {");
out.format(" \"tid\": %d,%n", thread.threadId());
out.format(" \"tid\": \"%d\",%n", thread.threadId());
out.format(" \"name\": \"%s\",%n", escape(thread.getName()));
out.format(" \"stack\": [%n");
int i = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

/*
* @test
* @bug 8284161 8287008
* @summary Basic test for jcmd Thread.dump_to_file
* @library /test/lib
* @run testng/othervm ThreadDumpToFileTest
Expand All @@ -34,6 +35,8 @@
import java.util.stream.Stream;
import jdk.test.lib.dcmd.PidJcmdExecutor;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.threaddump.ThreadDump;

import org.testng.annotations.Test;
import static org.testng.Assert.*;

Expand Down Expand Up @@ -65,13 +68,17 @@ public void testJsonThreadDump() throws IOException {
Path file = genThreadDumpPath(".json");
threadDump(file, "-format=json").shouldMatch("Created");

// test that the threadDump object is present
assertTrue(find(file, "threadDump"), "`threadDump` not found in " + file);
// parse the JSON text
String jsonText = Files.readString(file);
ThreadDump threadDump = ThreadDump.parse(jsonText);

// test that thread dump contains the id of the current thread
long tid = Thread.currentThread().threadId();
String expected = "\"tid\": " + tid;
assertTrue(find(file, expected), expected + " not found in " + file);
// test that the process id is this process
assertTrue(threadDump.processId() == ProcessHandle.current().pid());

// test that the current thread is in the root thread container
var rootContainer = threadDump.rootThreadContainer();
var tid = Thread.currentThread().threadId();
rootContainer.findThread(tid).orElseThrow();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,29 @@

/**
* @test
* @bug 8284161 8287008
* @summary Basic test for com.sun.management.HotSpotDiagnosticMXBean.dumpThreads
* @compile --enable-preview -source ${jdk.version} DumpThreads.java
* @run testng/othervm --enable-preview DumpThreads
* @run testng/othervm --enable-preview -Djdk.trackAllThreads DumpThreads
* @run testng/othervm --enable-preview -Djdk.trackAllThreads=true DumpThreads
* @run testng/othervm --enable-preview -Djdk.trackAllThreadds=false DumpThreads
* @enablePreview
* @library /test/lib
* @run testng/othervm DumpThreads
* @run testng/othervm -Djdk.trackAllThreads DumpThreads
* @run testng/othervm -Djdk.trackAllThreads=true DumpThreads
* @run testng/othervm -Djdk.trackAllThreadds=false DumpThreads
*/

import java.lang.management.ManagementFactory;
import java.nio.file.Files;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Path;
import java.time.ZonedDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
import java.util.stream.Stream;
import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.HotSpotDiagnosticMXBean.ThreadDumpFormat;
import jdk.test.lib.threaddump.ThreadDump;

import org.testng.annotations.Test;
import static org.testng.Assert.*;
Expand Down Expand Up @@ -103,21 +107,37 @@ public void testJson() throws Exception {
mbean.dumpThreads(file.toString(), ThreadDumpFormat.JSON);
cat(file);

assertTrue(count(file, "threadDump") >= 1L);
assertTrue(count(file, "time") >= 1L);
assertTrue(count(file, "runtimeVersion") >= 1L);
assertTrue(count(file, "threadContainers") >= 1L);
assertTrue(count(file, "threads") >= 1L);
// parse the JSON text
String jsonText = Files.readString(file);
ThreadDump threadDump = ThreadDump.parse(jsonText);

// virtual thread should be found
assertTrue(isJsonPresent(file, vthread));
// test threadDump/processId
assertTrue(threadDump.processId() == ProcessHandle.current().pid());

// if the current thread is a platform thread then it should be included
// test threadDump/time can be parsed
ZonedDateTime.parse(threadDump.time());

// test threadDump/runtimeVersion
assertEquals(threadDump.runtimeVersion(), Runtime.version().toString());

// test root container
var rootContainer = threadDump.rootThreadContainer();
assertFalse(rootContainer.owner().isPresent());
assertFalse(rootContainer.parent().isPresent());

// if the current thread is a platform thread then it will be in root container
Thread currentThread = Thread.currentThread();
if (!currentThread.isVirtual() || TRACK_ALL_THREADS) {
assertTrue(isJsonPresent(file, currentThread));
rootContainer.findThread(currentThread.threadId()).orElseThrow();
}

// find the thread container for the executor. The name of this executor
// is its String representaiton in this case.
String name = executor.toString();
var container = threadDump.findThreadContainer(name).orElseThrow();
assertFalse(container.owner().isPresent());
assertTrue(container.parent().get() == rootContainer);
container.findThread(vthread.threadId()).orElseThrow();
} finally {
LockSupport.unpark(vthread);
}
Expand Down Expand Up @@ -188,14 +208,6 @@ private static boolean isPresent(Path file, Thread thread) throws Exception {
return count(file, expect) > 0;
}

/**
* Returns true if the file contains "tid": <tid>
*/
private static boolean isJsonPresent(Path file, Thread thread) throws Exception {
String expect = "\"tid\": " + thread.threadId();
return count(file, expect) > 0;
}

/**
* Generate a file path with the given suffix to use as an output file.
*/
Expand Down
Loading

1 comment on commit 15f1583

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.