Environment: Linux, Eclipse Juno, Java 7, JUnit
When a simple application (a java class with main method) is run in debug mode, 'Drop to Frame' feature works fine in Eclipse. However if the same method is invoked from a junit test case, 'Drop to Frame' feature is disabled in Eclipse. From the documentation
Note this command is only available if the current VM supports drop to frame and the selected stackframe is not the top frame or a frame in a native method.
As we can see from the stack frames in Debug window when a junit test case is run, there is a frame 'NativeMethodAccessorImpl.invoke' which is native. I'm assuming this is the reason for 'Drop to Frame' being disabled.
Let me know if this reasoning is correct and if yes, any workarounds available to overcome this.
I use Eclipse Luna, Java 7 under Windows.
The situation is still as described: "Drop to frame" is disabled for the test method which immediately follows the 'NativeMethodAccessorImpl.invoke' frame.
The disabled state of the "Drop to frame" is bound to method canDropToFrame()
respective supportsDropToFrame()
in class org.eclipse.jdt.internal.debug.core.model.JDIStackFrame
,
(in my distribution) part of plugins/org.eclipse.jdt.debug_3.8.102.v20150115-1323/jdimodel.jar
.
Method supportsDropToFrame() checks if a specific frame can be dropped, and tests
So the assumption of Ramesh was right. This is the original code snippet for tests 3 + 4:
int index = 0;
JDIStackFrame frame = null;
while (index < frames.size()) {
frame = (JDIStackFrame) frames.get(index);
index++;
if (frame.isNative()) {
return false;
}
if (frame.equals(this)) {
if (jdkSupport) {
// JDK 1.4 VMs are currently unable to pop the
// frame directly above a native frame
if (index < frames.size()
&& ((JDIStackFrame) frames.get(index))
.isNative()) {
return false;
}
}
return true;
}
}
The comment suggests that it was written in JDK 1.4 times, so maybe in the meantime the JVM can now also drop frames above native frames.
I created a patched version of JDIStackFrame, which skips test 4. Now when pausing in a Junit test method, "Drop to frame" was enabled, as expected.
But when actually dropping the frame, I received an error message box which stated "com.sun.jdi.InternalException: Got error code in reply: 32 occurred popping stack frame".
I assume that this is a JDWP error code. Therefore it seems that such a "Drop to frame" does not work in JDK 1.7 (don't know about 1.8), and it's not a Eclipse thing.
This is an old one, but for the time being this is still an issue with Eclipse 2018-09, Java 1.8 and testng as test runner. The workaround (simple and obvious) is to extract the contents of the test into another method, debug it and then inline it back. E.g.:
@Test
public void test() {
// test goes here
assertTrue(true);
}
One may use refactoring shortcuts to speed up things: select the body of the test, press Alt+Shift+M, enter name 'inner', and the result is:
@Test
public void test() {
inner();
}
private void inner() {
// test goes here and 'drop-to-frame' works well
assertTrue(true);
}
When done debugging, inline it back by pressing Alt+Shift+I while inside inner().
I've always dealt with this problem by splitting between the @Test
function and a thunk that I can drop frames into.
Pre JDK-8, I'd do this:
@Test
public void testSomeFooInBar() {
drop_to_frame_testSomeFooInBar();
}
private void drop_to_frame_testSomeFooInBar() {
assertTrue(somethingOrWhatever);
}
Even though it's verbose, I insist/insisted in calling my thunks after the test functions, with the name indicating what they are for (to "jump/drop to frame"). This is always necessary because there's always someone who does "refactoring" without reading comments and start removing the thunks as "unnecessary."
With JDK 8 and above, I do this:
@Test
public void testSomeFooInBar() {
final Runnable drop_to_frame = () -> {
assertTrue(somethingOrWhatever);
};
jump_to_frame.run();
}
Simpler. Eclipse will allow you to set a breakpoint inside the runnable lambda and drop to frame as many times as you needed (assuming your logic is sufficiently re-entrant.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With