From 38f29d0d6a3e74f89c63da403bfb4e9ddbe2d3e8 Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Sat, 7 Jun 2025 16:40:10 +0200 Subject: [PATCH 1/5] solves issue8567 by reversing order of stack evaluation This version works for ant projects. --- .../junit/ant/ui/AntJUnitNodeOpener.java | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index 7742482d8225..ba6e16ccbf38 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -29,6 +29,7 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.util.ElementFilter; import javax.swing.Action; +import jdk.internal.net.http.common.Log; import org.netbeans.api.extexecution.print.LineConvertors.FileLocator; import org.netbeans.api.java.source.CompilationController; import org.netbeans.api.java.source.JavaSource; @@ -38,6 +39,8 @@ import org.netbeans.modules.gsf.testrunner.api.CommonUtils; import org.netbeans.modules.gsf.testrunner.ui.api.TestMethodNode; import org.netbeans.modules.gsf.testrunner.ui.api.TestsuiteNode; +import org.netbeans.modules.java.testrunner.JavaRegexpPatterns; +import org.netbeans.modules.java.testrunner.JavaRegexpUtils; import org.openide.ErrorManager; import org.openide.filesystems.FileObject; import org.netbeans.modules.junit.api.JUnitTestSuite; @@ -157,6 +160,7 @@ public void openCallstackFrame(Node node, String frameInfo) { } // Method node might belong to an inner class FileObject testfo = methodNode.getTestcase().getClassFileObject(true); + String fqMethodName = methodNode.getTestcase().getClassName() + '.' + methodNode.getTestcase().getName(); if(testfo == null) { return; } @@ -164,22 +168,34 @@ public void openCallstackFrame(Node node, String frameInfo) { FileObject file = UIJavaUtils.getFile(frameInfo, lineNumStorage, locator); //lineNumStorage -1 means no regexp for stacktrace was matched. if ((file == null) && (methodNode.getTestcase().getTrouble() != null) && lineNumStorage[0] == -1) { - //213935 we could not recognize the stack trace line and map it to known file - //if it's a failure text, grab the testcase's own line from the stack. - boolean methodNodeParentOfStackTraceNode = false; String[] st = methodNode.getTestcase().getTrouble().getStackTrace(); if ((st != null) && (st.length > 0)) { - int index = st.length - 1; - //213935 we need to find the testcase linenumber to jump to. + int index = 0;//st.length - 1; + //Jump to the first line matching the fully qualified test method name. // and ignore the infrastructure stack lines in the process - while (!testfo.equals(file) && index != -1 && !methodNodeParentOfStackTraceNode) { - file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); - index = index - 1; - // if frameInfo.isEmpty() == true, user clicked on a failed method node. - // Try to find if the stack trace node is relevant to the method node - if(file != null && frameInfo.isEmpty()) { - methodNodeParentOfStackTraceNode = FileUtil.isParentOf(testfo.getParent(), file); + while (index < st.length) { + if (st[index].contains(fqMethodName)) { + file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); + break; } + index++; + } + // if not found, return top line of stack trace. + if (index == st.length) { + index=0; + while(true) { + String trimmed=JavaRegexpUtils.specialTrim(st[index]); + if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) || + trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX )){ + file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); + break; + } + } + } + // if that fails, return the test file object. + if (file == null) { + + file = testfo; } } } From 28ee396b1e2568de1c230ef503a8b0780a4e7ccc Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Sat, 7 Jun 2025 16:59:44 +0200 Subject: [PATCH 2/5] maven version --- .../modules/maven/junit/ui/MavenJUnitNodeOpener.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java b/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java index daf44d4eb19c..718ce66fca9e 100644 --- a/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java +++ b/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java @@ -188,14 +188,18 @@ public void openCallstackFrame(Node node, @NonNull String frameInfo) { if (testfo != null && file == null && methodNode.getTestcase().getTrouble() != null && lineNumStorage[0] == -1) { //213935 we could not recognize the stack trace line and map it to known file //if it's a failure text, grab the testcase's own line from the stack. + String fqMethodName= methodNode.getTestcase().getClassName()+ '.'+ methodNode.getTestcase().getName(); String[] st = methodNode.getTestcase().getTrouble().getStackTrace(); if ((st != null) && (st.length > 0)) { - int index = st.length - 1; + int index = 0;//st.length - 1; //213935 we need to find the testcase linenumber to jump to. // and ignore the infrastructure stack lines in the process - while (!testfo.equals(file) && index != -1) { - file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); - index = index - 1; + while (!testfo.equals(file) && index < st.length) { + if (st[index].contains(fqMethodName)) { + file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); + break; + } + index++; } } } From 49b64dc3e2d09661ddd0632c9948339065f7f118 Mon Sep 17 00:00:00 2001 From: Pieter van den Hombergh Date: Sun, 9 Nov 2025 11:12:40 +0100 Subject: [PATCH 3/5] Update java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Bläsing --- .../org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index ba6e16ccbf38..cc3cc311a5a6 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -183,7 +183,7 @@ public void openCallstackFrame(Node node, String frameInfo) { // if not found, return top line of stack trace. if (index == st.length) { index=0; - while(true) { + for(index=0; index < st.length; index++) { String trimmed=JavaRegexpUtils.specialTrim(st[index]); if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) || trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX )){ From 933a57b8af055579b9f7cd350711b0f3ee994d51 Mon Sep 17 00:00:00 2001 From: Pieter van den Hombergh Date: Sun, 9 Nov 2025 11:30:54 +0100 Subject: [PATCH 4/5] Update java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Bläsing --- .../modules/maven/junit/ui/MavenJUnitNodeOpener.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java b/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java index 80e58d772e14..a51461e78c25 100644 --- a/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java +++ b/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java @@ -188,18 +188,14 @@ public void openCallstackFrame(Node node, @NonNull String frameInfo) { if (testfo != null && file == null && methodNode.getTestcase().getTrouble() != null && lineNumStorage[0] == -1) { //213935 we could not recognize the stack trace line and map it to known file //if it's a failure text, grab the testcase's own line from the stack. - String fqMethodName= methodNode.getTestcase().getClassName()+ '.'+ methodNode.getTestcase().getName(); - String[] st = methodNode.getTestcase().getTrouble().getStackTrace(); - if ((st != null) && (st.length > 0)) { - int index = 0;//st.length - 1; - //213935 we need to find the testcase linenumber to jump to. + // 213935 we need to find the testcase linenumber to jump to. // and ignore the infrastructure stack lines in the process - while (!testfo.equals(file) && index < st.length) { + for(int index = 0; !testfo.equals(file) && index < st.length; index++) { if (st[index].contains(fqMethodName)) { file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); break; } - index++; + } } } } From 392ffe99f6be7bc7ded839e727874b236775d5b3 Mon Sep 17 00:00:00 2001 From: "Pieter van den Hombergh (homberghp)" Date: Fri, 20 Feb 2026 15:05:44 +0100 Subject: [PATCH 5/5] use same solution for ant and maven --- java/java.testrunner/nbproject/project.xml | 1 + .../junit/ant/ui/AntJUnitNodeOpener.java | 3 --- java/maven.junit.ui/nbproject/project.xml | 9 ++++++++ .../maven/junit/ui/MavenJUnitNodeOpener.java | 22 ++++++++++--------- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/java/java.testrunner/nbproject/project.xml b/java/java.testrunner/nbproject/project.xml index bd9d1d45e138..421c61f202cf 100644 --- a/java/java.testrunner/nbproject/project.xml +++ b/java/java.testrunner/nbproject/project.xml @@ -188,6 +188,7 @@ org.netbeans.modules.junit.ant org.netbeans.modules.junit.ant.ui org.netbeans.modules.junit.ui + org.netbeans.modules.maven.junit.ui org.netbeans.modules.selenium2.java org.netbeans.modules.testng org.netbeans.modules.testng.ant diff --git a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java index cc3cc311a5a6..04f013aa7c62 100644 --- a/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java +++ b/java/junit.ant.ui/src/org/netbeans/modules/junit/ant/ui/AntJUnitNodeOpener.java @@ -29,7 +29,6 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.util.ElementFilter; import javax.swing.Action; -import jdk.internal.net.http.common.Log; import org.netbeans.api.extexecution.print.LineConvertors.FileLocator; import org.netbeans.api.java.source.CompilationController; import org.netbeans.api.java.source.JavaSource; @@ -39,7 +38,6 @@ import org.netbeans.modules.gsf.testrunner.api.CommonUtils; import org.netbeans.modules.gsf.testrunner.ui.api.TestMethodNode; import org.netbeans.modules.gsf.testrunner.ui.api.TestsuiteNode; -import org.netbeans.modules.java.testrunner.JavaRegexpPatterns; import org.netbeans.modules.java.testrunner.JavaRegexpUtils; import org.openide.ErrorManager; import org.openide.filesystems.FileObject; @@ -48,7 +46,6 @@ import org.netbeans.modules.java.testrunner.ui.api.NodeOpener; import org.netbeans.modules.java.testrunner.ui.api.UIJavaUtils; import org.netbeans.modules.junit.ui.api.JUnitCallstackFrameNode; -import org.openide.filesystems.FileUtil; import org.openide.nodes.Node; /** diff --git a/java/maven.junit.ui/nbproject/project.xml b/java/maven.junit.ui/nbproject/project.xml index adba7995497c..8780a95581ba 100644 --- a/java/maven.junit.ui/nbproject/project.xml +++ b/java/maven.junit.ui/nbproject/project.xml @@ -60,6 +60,15 @@ 2.0 + + org.netbeans.modules.java.testrunner + + + + 1.17 + + + org.netbeans.modules.gsf.testrunner.ui diff --git a/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java b/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java index a51461e78c25..8f82f9dfcd0d 100644 --- a/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java +++ b/java/maven.junit.ui/src/org/netbeans/modules/maven/junit/ui/MavenJUnitNodeOpener.java @@ -39,8 +39,10 @@ import org.netbeans.modules.junit.ui.api.JUnitTestMethodNode; import org.netbeans.modules.java.testrunner.ui.api.NodeOpener; import org.netbeans.modules.java.testrunner.ui.api.UIJavaUtils; +import org.netbeans.modules.java.testrunner.JavaRegexpUtils; import org.netbeans.modules.junit.api.JUnitTestcase; import org.netbeans.modules.junit.ui.api.JUnitCallstackFrameNode; + import org.openide.ErrorManager; import org.openide.filesystems.FileObject; import org.openide.nodes.Children; @@ -146,7 +148,7 @@ public void openTestMethod(final TestMethodNode node) { @Override public void openCallstackFrame(Node node, @NonNull String frameInfo) { - if(frameInfo.isEmpty()) { // user probably clicked on a failed test method node, find failing line within the testMethod using the stacktrace + if (frameInfo.isEmpty()) { // user probably clicked on a failed test method node, find failing line within the testMethod using the stacktrace if (!(node instanceof JUnitTestMethodNode)) { return; } @@ -186,18 +188,18 @@ public void openCallstackFrame(Node node, @NonNull String frameInfo) { FileObject file = UIJavaUtils.getFile(frameInfo, lineNumStorage, locator); //lineNumStorage -1 means no regexp for stacktrace was matched. if (testfo != null && file == null && methodNode.getTestcase().getTrouble() != null && lineNumStorage[0] == -1) { - //213935 we could not recognize the stack trace line and map it to known file + //213935 we could not recognize the stack trace line and map it to known file //if it's a failure text, grab the testcase's own line from the stack. - // 213935 we need to find the testcase linenumber to jump to. - // and ignore the infrastructure stack lines in the process - for(int index = 0; !testfo.equals(file) && index < st.length; index++) { - if (st[index].contains(fqMethodName)) { - file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); - break; - } - } + String[] st = methodNode.getTestcase().getTrouble().getStackTrace(); + for (int index = 0; !testfo.equals(file) && index < st.length; index++) { + String trimmed = JavaRegexpUtils.specialTrim(st[index]); + if (trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX_CATCH) + || trimmed.startsWith(JavaRegexpUtils.CALLSTACK_LINE_PREFIX)) { + file = UIJavaUtils.getFile(st[index], lineNumStorage, locator); + break; } } + } // Is this a @Test(expected = *Exception.class) test method that failed? if (file == null && lineNumStorage[0] == -1 && node instanceof MavenJUnitTestMethodNode) {