2323import java .io .IOException ;
2424import java .io .Serializable ;
2525import java .util .Arrays ;
26+ import java .util .Collection ;
2627import java .util .Collections ;
2728import java .util .List ;
2829import javax .xml .stream .XMLStreamException ;
30+ import org .sonar .api .batch .fs .InputFile ;
31+ import org .sonar .api .batch .fs .InputFile .Type ;
2932import org .sonar .api .batch .sensor .SensorContext ;
3033import org .sonar .api .batch .sensor .SensorDescriptor ;
3134import org .sonar .api .config .PropertyDefinition ;
@@ -46,6 +49,7 @@ public class CxxXunitSensor extends CxxReportSensor {
4649
4750 public static final String REPORT_PATH_KEY = "sonar.cxx.xunit.reportPath" ;
4851 private static final Logger LOG = Loggers .get (CxxXunitSensor .class );
52+ private SensorContext context ;
4953
5054 public static List <PropertyDefinition > properties () {
5155 return Collections .unmodifiableList (Arrays .asList (
@@ -76,17 +80,17 @@ public void describe(SensorDescriptor descriptor) {
7680 @ Override
7781 public void executeImpl (SensorContext context ) {
7882 try {
83+ this .context = context ;
7984 List <File > reports = getReports (context .config (), context .fileSystem ().baseDir (), REPORT_PATH_KEY );
8085 if (!reports .isEmpty ()) {
8186 XunitReportParser parserHandler = parseReport (reports );
82- List <TestCase > testcases = parserHandler .getTestCases ();
83- save (context , testcases );
87+ save (parserHandler .getTestFiles ());
8488 } else {
8589 LOG .debug ("No xUnit reports found, nothing to process" );
8690 }
8791 } catch (IOException | XMLStreamException e ) {
8892 var msg = new StringBuilder (256 )
89- .append ("Cannot feed the data into SonarQube, details: '" )
93+ .append ("Cannot feed the xUnit report data into SonarQube, details: '" )
9094 .append (e )
9195 .append ("'" )
9296 .toString ();
@@ -102,7 +106,7 @@ public void executeImpl(SensorContext context) {
102106 * @throws IOException
103107 */
104108 private XunitReportParser parseReport (List <File > reports ) throws XMLStreamException , IOException {
105- var parserHandler = new XunitReportParser ();
109+ var parserHandler = new XunitReportParser (context . fileSystem (). baseDir (). getPath () );
106110 var parser = new StaxParser (parserHandler , false );
107111 for (var report : reports ) {
108112 LOG .info ("Processing xUnit report '{}'" , report );
@@ -116,73 +120,61 @@ private XunitReportParser parseReport(List<File> reports) throws XMLStreamExcept
116120 return parserHandler ;
117121 }
118122
119- private void save (final SensorContext context , List < TestCase > testcases ) {
123+ private void save (Collection < TestFile > testfiles ) {
120124
121125 int testsCount = 0 ;
122126 int testsSkipped = 0 ;
123127 int testsErrors = 0 ;
124128 int testsFailures = 0 ;
125129 long testsTime = 0 ;
126- for (var tc : testcases ) {
127- if (tc .isSkipped ()) {
128- testsSkipped ++;
129- } else if (tc .isFailure ()) {
130- testsFailures ++;
131- } else if (tc .isError ()) {
132- testsErrors ++;
130+ for (var tf : testfiles ) {
131+ if (!tf .getFilename ().isEmpty ()) {
132+ InputFile inputFile = getInputFileIfInProject (context , tf .getFilename ());
133+ if (inputFile != null ) {
134+ if (inputFile .language () != null && inputFile .type () == Type .TEST ) {
135+ LOG .debug ("Saving xUnit data for '{}': tests={} | errors:{} | failure:{} | skipped:{} | time:{}" ,
136+ tf .getFilename (), tf .getTests (), tf .getErrors (), tf .getFailures (), tf .getSkipped (),
137+ tf .getExecutionTime ());
138+ saveMetric (inputFile , CoreMetrics .TESTS , tf .getTests ());
139+ saveMetric (inputFile , CoreMetrics .TEST_ERRORS , tf .getErrors ());
140+ saveMetric (inputFile , CoreMetrics .TEST_FAILURES , tf .getFailures ());
141+ saveMetric (inputFile , CoreMetrics .SKIPPED_TESTS , tf .getSkipped ());
142+ saveMetric (inputFile , CoreMetrics .TEST_EXECUTION_TIME , tf .getExecutionTime ());
143+ }
144+ }
133145 }
134- testsCount ++;
135- testsTime += tc .getTime ();
146+ testsTime += tf .getExecutionTime ();
147+ testsCount += tf .getTests ();
148+ testsFailures += tf .getFailures ();
149+ testsErrors += tf .getErrors ();
150+ testsSkipped += tf .getSkipped ();
136151 }
137- testsCount -= testsSkipped ;
138152
139153 if (testsCount > 0 ) {
140-
141- try {
142- saveProjectMetric (context , CoreMetrics .TESTS , testsCount );
143- } catch (IllegalArgumentException ex ) {
144- LOG .error ("Cannot save measure TESTS : '{}', ignoring measure" , ex .getMessage ());
145- CxxUtils .validateRecovery (ex , context .config ());
146- }
147-
148- try {
149- saveProjectMetric (context , CoreMetrics .TEST_ERRORS , testsErrors );
150- } catch (IllegalArgumentException ex ) {
151- LOG .error ("Cannot save measure TEST_ERRORS : '{}', ignoring measure" , ex .getMessage ());
152- CxxUtils .validateRecovery (ex , context .config ());
153- }
154-
155- try {
156- saveProjectMetric (context , CoreMetrics .TEST_FAILURES , testsFailures );
157- } catch (IllegalArgumentException ex ) {
158- LOG .error ("Cannot save measure TEST_FAILURES : '{}', ignoring measure" , ex .getMessage ());
159- CxxUtils .validateRecovery (ex , context .config ());
160- }
161-
162- try {
163- saveProjectMetric (context , CoreMetrics .SKIPPED_TESTS , testsSkipped );
164- } catch (IllegalArgumentException ex ) {
165- LOG .error ("Cannot save measure SKIPPED_TESTS : '{}', ignoring measure" , ex .getMessage ());
166- CxxUtils .validateRecovery (ex , context .config ());
167- }
168-
169- try {
170- saveProjectMetric (context , CoreMetrics .TEST_EXECUTION_TIME , testsTime );
171- } catch (IllegalArgumentException ex ) {
172- LOG .error ("Cannot save measure TEST_EXECUTION_TIME : '{}', ignoring measure" , ex .getMessage ());
173- CxxUtils .validateRecovery (ex , context .config ());
174- }
175- } else {
176- LOG .debug ("The reports contain no testcases" );
154+ LOG .debug ("Saving xUnit report total data: tests={} | errors:{} | failure:{} | skipped:{} | time:{}" ,
155+ testsCount , testsErrors , testsFailures , testsSkipped , testsTime );
156+ saveMetric (CoreMetrics .TESTS , testsCount );
157+ saveMetric (CoreMetrics .TEST_ERRORS , testsErrors );
158+ saveMetric (CoreMetrics .TEST_FAILURES , testsFailures );
159+ saveMetric (CoreMetrics .SKIPPED_TESTS , testsSkipped );
160+ saveMetric (CoreMetrics .TEST_EXECUTION_TIME , testsTime );
177161 }
178162 }
179163
180- private <T extends Serializable > void saveProjectMetric ( SensorContext context , Metric <T > metric , T value ) {
164+ private <T extends Serializable > void saveMetric ( Metric <T > metric , T value ) {
181165 context .<T >newMeasure ()
182166 .withValue (value )
183167 .forMetric (metric )
184168 .on (context .project ())
185169 .save ();
186170 }
187171
172+ private <T extends Serializable > void saveMetric (InputFile file , Metric <T > metric , T value ) {
173+ context .<T >newMeasure ()
174+ .withValue (value )
175+ .forMetric (metric )
176+ .on (file )
177+ .save ();
178+ }
179+
188180}
0 commit comments