1919
2020package org .netbeans .modules .gradle .test ;
2121
22+ import java .nio .file .Path ;
2223import java .util .Arrays ;
23- import org .netbeans .modules .gradle .api .NbGradleProject ;
2424import java .util .Collection ;
25- import org .netbeans .modules .gradle .spi .GradleProgressListenerProvider ;
2625import java .util .EnumSet ;
2726import java .util .Map ;
2827import java .util .Set ;
2928import java .util .concurrent .ConcurrentHashMap ;
3029import java .util .regex .Matcher ;
3130import java .util .regex .Pattern ;
31+ import java .util .stream .Collectors ;
32+ import javax .lang .model .element .ElementKind ;
3233import org .gradle .tooling .Failure ;
3334import org .gradle .tooling .events .OperationDescriptor ;
3435import org .gradle .tooling .events .OperationType ;
4647import org .gradle .tooling .events .test .TestSkippedResult ;
4748import org .gradle .tooling .events .test .TestStartEvent ;
4849import org .gradle .tooling .events .test .TestSuccessResult ;
50+ import org .netbeans .api .java .source .ClasspathInfo ;
51+ import org .netbeans .api .java .source .ElementHandle ;
52+ import org .netbeans .api .java .source .SourceUtils ;
4953import org .netbeans .api .project .Project ;
5054import org .netbeans .api .project .ProjectUtils ;
55+ import org .netbeans .modules .gradle .api .NbGradleProject ;
56+ import org .netbeans .modules .gradle .java .api .GradleJavaProject ;
57+ import org .netbeans .modules .gradle .java .api .GradleJavaSourceSet .SourceType ;
58+ import org .netbeans .modules .gradle .spi .GradleProgressListenerProvider ;
5159import org .netbeans .modules .gsf .testrunner .api .CommonUtils ;
5260import org .netbeans .modules .gsf .testrunner .api .CoreManager ;
5361import org .netbeans .modules .gsf .testrunner .api .Report ;
5765import org .netbeans .modules .gsf .testrunner .api .Testcase ;
5866import org .netbeans .modules .gsf .testrunner .api .Trouble ;
5967import org .netbeans .spi .project .ProjectServiceProvider ;
68+ import org .openide .filesystems .FileObject ;
69+ import org .openide .filesystems .FileUtil ;
6070import org .openide .util .Lookup ;
6171
6272/**
@@ -68,8 +78,8 @@ public final class GradleTestProgressListener implements ProgressListener, Gradl
6878
6979 private final Project project ;
7080 private final Map <String , TestSession > sessions = new ConcurrentHashMap <>();
71-
72- private Map <TestSession , Map <String , Testcase >> runningTests = new ConcurrentHashMap <>();
81+ private final Map < TestSession , Map < String , TestSuite >> runningSuites = new ConcurrentHashMap <>();
82+ private final Map <TestSession , Map <String , Testcase >> runningTests = new ConcurrentHashMap <>();
7383
7484 public GradleTestProgressListener (Project project ) {
7585 this .project = project ;
@@ -190,13 +200,21 @@ private void suiteFinish(TestFinishEvent evt, JvmTestOperationDescriptor op) {
190200 TestSession session = sessions .get (getSessionKey (evt .getDescriptor ()));
191201 assert session != null ;
192202 TestOperationResult result = evt .getResult ();
193- TestSuite currentSuite = session .getCurrentSuite ();
194203 String suiteName = GradleTestSuite .suiteName (op );
195- if (suiteName .equals (currentSuite .getName ())) {
204+ // In the NetBeans wording a testsuite is the class grouping multiple
205+ // methods (testcase). In the gradle wording a suite can be nested, for
206+ // example the hieararchy can be:
207+ // - Gradle Test Executor <Number> started
208+ // - Test class <Class> started
209+ // => We flatten the list (suites are registered base on executed
210+ // cases (see caseStart)
211+ TestSuite testSuite = runningSuites .get (session ).remove (suiteName );
212+ if (testSuite != null ) {
196213 Report report = session .getReport (result .getEndTime () - result .getStartTime ());
197- session .finishSuite (currentSuite );
214+ session .finishSuite (testSuite );
198215 CoreManager manager = getManager ();
199216 if (manager != null ) {
217+ manager .displaySuiteRunning (session , testSuite );
200218 manager .displayReport (session , report , true );
201219 }
202220 }
@@ -206,19 +224,21 @@ private void caseStart(TestStartEvent evt, JvmTestOperationDescriptor op) {
206224 TestSession session = sessions .get (getSessionKey (evt .getDescriptor ()));
207225 assert session != null ;
208226 assert op .getParent () != null ;
209- TestSuite currentSuite = session .getCurrentSuite ();
210- TestSuite newSuite = new GradleTestSuite (getSuiteOpDesc ((JvmTestOperationDescriptor ) op .getParent (), op .getClassName ()));
211- if ((currentSuite == null ) || !currentSuite .equals (newSuite )) {
212- session .addSuite (newSuite );
213- CoreManager manager = getManager ();
214- if (manager != null ) {
215- manager .displaySuiteRunning (session , newSuite );
216- }
227+ String suiteName = GradleTestSuite .suiteName (op .getParent ());
228+ Map <String , TestSuite > sessionSuites = runningSuites .computeIfAbsent (session , s -> new ConcurrentHashMap <>());
229+ TestSuite ts = sessionSuites .computeIfAbsent (suiteName , s -> {
230+ TestSuite suite = new GradleTestSuite (getSuiteOpDesc ((JvmTestOperationDescriptor ) op .getParent (), op .getClassName ()));
231+ session .addSuite (suite );
232+ return suite ;
233+ });
234+ CoreManager manager = getManager ();
235+ if (manager != null && sessionSuites .size () == 1 ) {
236+ manager .displaySuiteRunning (session , ts );
217237 }
218238 Testcase tc = new GradleTestcase (op , session );
219- synchronized (this ) {
239+ synchronized (this ) {
220240 runningTests .get (session ).put (getTestOpKey (op ), tc );
221- session .addTestCase (tc );
241+ session .addTestCase (tc );
222242 }
223243 }
224244
@@ -233,7 +253,7 @@ private void caseFinish(TestFinishEvent evt, JvmTestOperationDescriptor op) {
233253 TestOperationResult result = evt .getResult ();
234254 long time = result .getEndTime () - result .getStartTime ();
235255 tc .setTimeMillis (time );
236- tc .setLocation (searchLocation (op .getClassName (), op .getMethodName (), null ));
256+ tc .setLocation (searchLocation (tc , op .getClassName (), op .getMethodName (), null ));
237257 if (result instanceof TestSuccessResult ) {
238258 tc .setStatus (Status .PASSED );
239259 }
@@ -261,7 +281,7 @@ private void caseFinish(TestFinishEvent evt, JvmTestOperationDescriptor op) {
261281 stackTrace = desc .split ("\\ n" );
262282 trouble .setStackTrace (stackTrace );
263283 }
264- tc .setLocation (searchLocation (op .getClassName (), op .getMethodName (), stackTrace ));
284+ tc .setLocation (searchLocation (tc , op .getClassName (), op .getMethodName (), stackTrace ));
265285 tc .setTrouble (trouble );
266286 }
267287
@@ -322,7 +342,39 @@ private static CoreManager getManager() {
322342
323343 }
324344
325- private String searchLocation (String className , String methodName , String [] stackTrace ) {
345+ private String searchLocation (Testcase tc , String className , String methodName , String [] stackTrace ) {
346+ Map <ClasspathInfo , Path > classpathInfo = Map .of ();
347+ NbGradleProject nbGradleProject = tc .getSession ()
348+ .getProject ()
349+ .getLookup ()
350+ .lookup (NbGradleProject .class );
351+ GradleJavaProject gradleJavaProject = nbGradleProject != null ? nbGradleProject .projectLookup (GradleJavaProject .class ) : null ;
352+ if (gradleJavaProject != null ) {
353+ classpathInfo = gradleJavaProject
354+ .getSourceSets ()
355+ .values ()
356+ .stream ()
357+ .flatMap (gradleJavaSourceSet -> gradleJavaSourceSet .getSourceDirs (SourceType .JAVA ).stream ())
358+ .collect (
359+ Collectors .toMap (
360+ f -> ClasspathInfo .create (f ),
361+ f -> f .toPath ()
362+ )
363+ );
364+ }
365+
366+ String relativePath = null ;
367+ for (Map .Entry <ClasspathInfo , Path > ci : classpathInfo .entrySet ()) {
368+ FileObject fo = SourceUtils .getFile (ElementHandle .createTypeElementHandle (ElementKind .CLASS , className ), ci .getKey ());
369+ if (fo != null ) {
370+ relativePath = ci .getValue ().relativize (FileUtil .toFile (fo ).toPath ()).toString ();
371+ break ;
372+ }
373+ }
374+ if (relativePath != null ) {
375+ return relativePath ;
376+ }
377+
326378 StringBuilder ret = new StringBuilder (className .length () + methodName .length () + 10 );
327379 String fileName = null ;
328380 String line = null ;
0 commit comments