Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtual threads debug view update + JdiThread new API + unit tests #535

Merged
merged 1 commit into from
Oct 21, 2024
Merged
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
25 changes: 25 additions & 0 deletions org.eclipse.jdt.debug.tests/java23/Main21.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*******************************************************************************
* Copyright (c) 2024 IBM Corporation.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation -- initial API and implementation
*******************************************************************************/
public class Main21 {
public static void main(String[] args) throws InterruptedException {
try {
Thread.startVirtualThread(() -> {
int p = 21;
System.out.println("From Virtual Thread");
}).join();
} catch (Exception e) {

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ synchronized void assert23Project() {
jp.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_23);
cfgs.add(createLaunchConfiguration(jp, "Main1"));
cfgs.add(createLaunchConfiguration(jp, "Main2"));
cfgs.add(createLaunchConfiguration(jp, "Main21"));
loaded23 = true;
waitForBuild();
assertNoErrorMarkersExist(jp.getProject());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
import org.eclipse.jdt.debug.tests.ui.JavaSnippetEditorTest;
import org.eclipse.jdt.debug.tests.ui.OpenFromClipboardTests;
import org.eclipse.jdt.debug.tests.ui.ViewManagementTests;
import org.eclipse.jdt.debug.tests.ui.VirtualThreadsDebugViewTests;
import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests;
import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests18;
import org.eclipse.jdt.debug.tests.variables.DetailFormatterTests;
Expand Down Expand Up @@ -417,5 +418,8 @@ public AutomatedSuite() {
if (JavaProjectHelper.isJava16_Compatible()) {
addTest(new TestSuite(RecordBreakpointTests.class));
}
if (Runtime.version().feature() == 23 && JavaProjectHelper.isJava23_Compatible()) {
addTest(new TestSuite(VirtualThreadsDebugViewTests.class));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*******************************************************************************
* Copyright (c) 2024 IBM Corporation.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation -- initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.debug.tests.ui;

import org.eclipse.core.resources.IFile;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.internal.ui.views.console.ProcessConsole;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.IDebugView;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.tests.TestUtil;
import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
import org.eclipse.jdt.internal.debug.core.model.JDIThread;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.test.OrderedTestSuite;

import junit.framework.Test;

/**
* Tests for debug view.
*/
public class VirtualThreadsDebugViewTests extends AbstractDebugUiTests {


public static Test suite() {
return new OrderedTestSuite(VirtualThreadsDebugViewTests.class);
}

private boolean showMonitorsOriginal;

public VirtualThreadsDebugViewTests(String name) {
super(name);
}

@Override
protected void setUp() throws Exception {
super.setUp();
IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore();
showMonitorsOriginal = jdiUIPreferences.getBoolean(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO);
jdiUIPreferences.setValue(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO, true);
resetPerspective(DebugViewPerspectiveFactory.ID);
processUiEvents(100);
}

@Override
protected void tearDown() throws Exception {
IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore();
jdiUIPreferences.setValue(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO, showMonitorsOriginal);
sync(() -> getActivePage().closeAllEditors(false));
processUiEvents(100);
super.tearDown();
}

@Override
protected IJavaProject getProjectContext() {
return super.get23Project();
}

public void testVirtualThreadDebugView() throws Exception {
sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
final String typeName = "Main21";
final int bpLine = 19;

IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName);
bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
IFile file = (IFile) bp.getMarker().getResource();
assertEquals(typeName + ".java", file.getName());

IJavaThread mainThread = null;
try {
mainThread = launchToBreakpoint(typeName);
assertNotNull("Launch unsuccessful", mainThread);
openEditorInDebug(file);
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
IDebugView debugViewer = (IDebugView) getActivePage().findView(IDebugUIConstants.ID_DEBUG_VIEW);
ISelection currentSelection = debugViewer.getViewer().getSelection();
assertNotNull("Debug View is not available", debugViewer);
if (currentSelection instanceof IStructuredSelection) {
Object sel = ((IStructuredSelection) currentSelection).getFirstElement();
if (sel instanceof IStackFrame stackFrame) {
IThread thread = stackFrame.getThread();
JDIThread vThread = (JDIThread) stackFrame.getThread();
assertTrue("Not a Virtual thread", vThread.isVirtualThread());
StructuredSelection select = new StructuredSelection(thread);
debugViewer.getViewer().setSelection(select, true);
IDebugModelPresentation md = DebugUITools.newDebugModelPresentation();
String groupName = md.getText(thread);
assertTrue("Not a Virtual thread grouping", groupName.contains("Virtual"));
}
}
}
});
mainThread.resume();
} catch (Exception e) {
DebugPlugin.log(e);
} finally {
terminateAndRemove(mainThread);
removeAllBreakpoints();
}
}

private void openEditorInDebug(IFile file) throws Exception {
// Let now all pending jobs proceed, ignore console jobs
sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
@SuppressWarnings("unused")
CompilationUnitEditor part = (CompilationUnitEditor) sync(() -> openEditor(file));
processUiEvents(100);
}

@Override
protected boolean enableUIEventLoopProcessingInWaiter() {
return true;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -243,6 +243,23 @@ public class DebugUIMessages extends NLS {
public static String thread_daemon_system_suspended_fieldmodification;
public static String thread_daemon_system_suspended_runtoline;
public static String thread_daemon_system_suspended_classprepare;

public static String thread_virtual_terminated;
public static String thread_virtual_evaluating;
public static String thread_virtual_running;
public static String thread_virtual_stepping;
public static String thread_virtual_suspended;
public static String thread_virtual_suspended_problem;
public static String thread_virtual_suspended_fieldaccess;
public static String thread_virtual_suspended_linebreakpoint;
public static String thread_virtual_suspended_methodentry;
public static String thread_virtual_suspended_exception;
public static String thread_virtual_suspended_exception_uncaught;
public static String thread_virtual_suspended_methodexit;
public static String thread_virtual_suspended_fieldmodification;
public static String thread_virtual_suspended_runtoline;
public static String thread_virtual_suspended_classprepare;

public static String SuspendTimeoutHandler_suspend;
public static String SuspendTimeoutHandler_timeout_occurred;
public static String JDIDebugUIPlugin_Searching_1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2000, 2022 IBM Corporation and others.
# Copyright (c) 2000, 2024 IBM Corporation and others.
#
# This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -184,6 +184,21 @@ thread_daemon_system_suspended_fieldmodification=Daemon System Thread [{0}] (Sus
thread_daemon_system_suspended_runtoline=Daemon System Thread [{0}] (Suspended (run to line {1} in {2}))
thread_daemon_system_suspended_classprepare=Daemon System Thread [{0}] (Class load: {1})

thread_virtual_terminated=Virtual Thread [{0}] (Terminated)
thread_virtual_evaluating=Virtual Thread [{0}] (Evaluating)
thread_virtual_running=Virtual Thread [{0}] (Running)
thread_virtual_stepping=Virtual Thread [{0}] (Stepping)
thread_virtual_suspended=Virtual Thread [{0}] (Suspended)
thread_virtual_suspended_problem=Virtual Thread [{0}] (Suspended ({1}))
thread_virtual_suspended_fieldaccess=Virtual Thread [{0}] (Suspended (access of field {1} in {2}))
thread_virtual_suspended_linebreakpoint=Virtual Thread [{0}] (Suspended (breakpoint at line {1} in {2}))
thread_virtual_suspended_methodentry=Virtual Thread [{0}] (Suspended (entry into method {1} in {2}))
thread_virtual_suspended_exception=Virtual Thread [{0}] (Suspended (exception {1}))
thread_virtual_suspended_exception_uncaught=Virtual Thread [{0}] (Suspended (uncaught exception {1}))
thread_virtual_suspended_methodexit=Virtual Thread [{0}] (Suspended (exit of method {1} in {2}))
thread_virtual_suspended_fieldmodification=Virtual Thread [{0}] (Suspended (modification of field {1} in {2}))
thread_virtual_suspended_runtoline=Virtual Thread [{0}] (Suspended (run to line {1} in {2}))
thread_virtual_suspended_classprepare=Virtual Thread [{0}] (Class load: {1})
###############################################################################

JDIModelPresentation_target_suspended=\ (Suspended)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2022 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -318,14 +318,19 @@ protected String getThreadText(IJavaThread thread, boolean qualified) throws Cor
}
if (thread.isSystemThread()) {
key.append("system_"); //$NON-NLS-1$
} else if (thread instanceof JDIThread jdi) {
if (jdi.isVirtualThread()) {
key.append("virtual_"); //$NON-NLS-1$
}
}
if (thread.isTerminated()) {
key.append("terminated"); //$NON-NLS-1$
args = new String[] {thread.getName()};
} else if (thread.isStepping()) {
key.append("stepping"); //$NON-NLS-1$
args = new String[] {thread.getName()};
} else if ((thread instanceof JDIThread && ((JDIThread)thread).isSuspendVoteInProgress()) && !thread.getDebugTarget().isSuspended()) {
} else if ((thread instanceof JDIThread jdi && jdi.isSuspendVoteInProgress()) && !thread.getDebugTarget().isSuspended()
&& !jdi.isVirtualThread()) {
// show running when listener notification is in progress
key.append("running"); //$NON-NLS-1$
args = new String[] {thread.getName()};
Expand Down Expand Up @@ -415,8 +420,15 @@ protected String getThreadText(IJavaThread thread, boolean qualified) throws Cor
args = new String[] {thread.getName()};
}
}
if (args[0].isEmpty() && thread instanceof JDIThread jdi && jdi.isVirtualThread()) { // Virtual Thread
long virtualThreadID = thread.getThreadObject().getUniqueId();
String id = "ID#" + virtualThreadID; //$NON-NLS-1$
args[0] = id;
}
try {
return getFormattedString((String)DebugUIMessages.class.getDeclaredField(key.toString()).get(null), args);

return getFormattedString((String) DebugUIMessages.class.getDeclaredField(key.toString()).get(null), args);

} catch (IllegalArgumentException e) {
JDIDebugUIPlugin.log(e);
} catch (SecurityException e) {
Expand Down
Loading
Loading