diff --git a/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/PlSqlPlugin.kt b/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/PlSqlPlugin.kt index a28d114c..7e2bb13e 100644 --- a/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/PlSqlPlugin.kt +++ b/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/PlSqlPlugin.kt @@ -83,13 +83,13 @@ class PlSqlPlugin : Plugin { private fun addUtPlSqlExtensions(context: Plugin.Context) { context.addExtensions( - PropertyDefinition.builder(UtPlSqlSensor.REPORT_PATH_KEY) + PropertyDefinition.builder(UtPlSqlSensor.TEST_REPORT_PATH_KEY) .name("Path to the utPLSQL test report(s)") .description("Paths (absolute or relative) to report files with utPLSQL test execution data.") .category(DEFAULT_CATEGORY) .subCategory(TEST_AND_COVERAGE) .onQualifiers(Qualifiers.PROJECT) - .defaultValue(UtPlSqlSensor.DEFAULT_REPORT_PATH) + .defaultValue(UtPlSqlSensor.DEFAULT_TEST_REPORT_PATH) .multiValues(true) .build(), diff --git a/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/utplsql/TestResultImporter.kt b/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/utplsql/TestResultImporter.kt new file mode 100644 index 00000000..6a630f7b --- /dev/null +++ b/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/utplsql/TestResultImporter.kt @@ -0,0 +1,97 @@ +package org.sonar.plsqlopen.utplsql + +import org.simpleframework.xml.core.Persister +import org.sonar.api.batch.fs.InputFile +import org.sonar.api.batch.measure.Metric +import org.sonar.api.batch.sensor.SensorContext +import org.sonar.api.config.Configuration +import org.sonar.api.measures.CoreMetrics +import org.sonar.api.notifications.AnalysisWarnings +import org.sonar.api.utils.WildcardPattern +import org.sonar.plsqlopen.symbols.ObjectLocator +import org.sonar.plsqlopen.utils.log.Logger +import org.sonar.plsqlopen.utils.log.Loggers +import org.sonar.plugins.plsqlopen.api.PlSqlGrammar +import java.io.File +import java.io.Serializable + +class TestResultImporter(private val conf: Configuration, + private val objectLocator: ObjectLocator, + private val analysisWarnings: AnalysisWarnings) { + + private val logger: Logger = Loggers.getLogger(TestResultImporter::class.java) + + fun execute(context: SensorContext) { + val reports = conf.getStringArray(UtPlSqlSensor.TEST_REPORT_PATH_KEY).flatMap { + getReports(context.fileSystem().baseDir(), it) + } + + for (report in reports) { + val testExecutions = readTestExecutionsReport(report) + logger.info("Processing test report {}", report) + processTestExecutions(context, testExecutions) + } + } + + private fun getReports(baseDir: File, reportPath: String): List { + val pattern = WildcardPattern.create(reportPath) + val matchingFiles = baseDir + .walkTopDown() + .filter { it.isFile && pattern.match(it.relativeTo(baseDir).invariantSeparatorsPath) } + .toMutableList() + + if (matchingFiles.isEmpty()) { + if (conf.hasKey(UtPlSqlSensor.TEST_REPORT_PATH_KEY)) { + val file = File(reportPath) + if (!file.exists()) { + val formattedMessage = + String.format("No utPLSQL test report was found for %s using pattern %s", UtPlSqlSensor.TEST_REPORT_PATH_KEY, reportPath) + logger.warn(formattedMessage) + analysisWarnings.addUnique(formattedMessage) + } else { + matchingFiles.add(file) + } + } else { + logger.info("No utPLSQL test report was found for {} using default pattern {}", UtPlSqlSensor.TEST_REPORT_PATH_KEY, reportPath) + } + } + return matchingFiles + } + + private fun readTestExecutionsReport(file: File): TestExecutions { + val serializer = Persister() + return serializer.read(TestExecutions::class.java, file) + } + + private fun processTestExecutions(context: SensorContext, testExecutions: TestExecutions) { + testExecutions.files?.forEach { file -> + val mappedTest = objectLocator.findTestObject(file.path, PlSqlGrammar.CREATE_PACKAGE_BODY) + val inputFile = mappedTest?.inputFile ?: + context.fileSystem().inputFile(context.fileSystem().predicates().hasPath(file.path)) + + if (inputFile != null) { + file.testCases?.let { testCase -> + val testCount = testCase.count { it.status != TestCaseStatus.SKIPPED } + val failureCount = testCase.count { it.status == TestCaseStatus.FAILED } + val errorCount = testCase.count { it.status == TestCaseStatus.ERROR } + val skippedCount = testCase.count { it.status == TestCaseStatus.SKIPPED } + val duration = testCase.sumOf { it.duration } + + saveMetricOnFile(context, inputFile, CoreMetrics.TESTS, testCount) + saveMetricOnFile(context, inputFile, CoreMetrics.TEST_FAILURES, failureCount) + saveMetricOnFile(context, inputFile, CoreMetrics.TEST_ERRORS, errorCount) + saveMetricOnFile(context, inputFile, CoreMetrics.SKIPPED_TESTS, skippedCount) + saveMetricOnFile(context, inputFile, CoreMetrics.TEST_EXECUTION_TIME, duration) + } + } + } + } + private fun saveMetricOnFile(context: SensorContext, inputFile: InputFile, metric: Metric, value: T) { + context.newMeasure() + .on(inputFile) + .forMetric(metric) + .withValue(value) + .save() + } + +} diff --git a/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/utplsql/UtPlSqlSensor.kt b/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/utplsql/UtPlSqlSensor.kt index 653be87b..16dd5907 100644 --- a/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/utplsql/UtPlSqlSensor.kt +++ b/sonar-zpa-plugin/src/main/kotlin/org/sonar/plsqlopen/utplsql/UtPlSqlSensor.kt @@ -19,110 +19,32 @@ */ package org.sonar.plsqlopen.utplsql -import org.simpleframework.xml.core.Persister -import org.sonar.api.batch.fs.InputFile -import org.sonar.api.batch.measure.Metric import org.sonar.api.batch.sensor.Sensor import org.sonar.api.batch.sensor.SensorContext import org.sonar.api.batch.sensor.SensorDescriptor import org.sonar.api.config.Configuration -import org.sonar.api.measures.CoreMetrics import org.sonar.api.notifications.AnalysisWarnings -import org.sonar.api.utils.WildcardPattern import org.sonar.plsqlopen.PlSql import org.sonar.plsqlopen.symbols.ObjectLocator -import org.sonar.plsqlopen.utils.log.Logger -import org.sonar.plsqlopen.utils.log.Loggers -import org.sonar.plugins.plsqlopen.api.PlSqlGrammar -import java.io.File -import java.io.Serializable -class UtPlSqlSensor(private val conf: Configuration, - private val objectLocator: ObjectLocator, - private val analysisWarnings: AnalysisWarnings) : Sensor { +class UtPlSqlSensor( + conf: Configuration, + objectLocator: ObjectLocator, + analysisWarnings: AnalysisWarnings) : Sensor { - private val logger: Logger = Loggers.getLogger(UtPlSqlSensor::class.java) + private val testResultImporter = TestResultImporter(conf, objectLocator, analysisWarnings) override fun describe(descriptor: SensorDescriptor) { - descriptor.name("Z PL/SQL Analyzer - utPLSQL Test Report Importer").onlyOnLanguage(PlSql.KEY) + descriptor.name("Z PL/SQL Analyzer - utPLSQL Report Importer").onlyOnLanguage(PlSql.KEY) } override fun execute(context: SensorContext) { - val reports = conf.getStringArray(REPORT_PATH_KEY).flatMap { - getReports(context.fileSystem().baseDir(), it) - } - - for (report in reports) { - val testExecutions = readTestExecutionsReport(report) - logger.info("Processing test report {}", report) - processTestExecutions(context, testExecutions) - } - } - - private fun getReports(baseDir: File, reportPath: String): List { - val pattern = WildcardPattern.create(reportPath) - val matchingFiles = baseDir - .walkTopDown() - .filter { it.isFile && pattern.match(it.relativeTo(baseDir).invariantSeparatorsPath) } - .toMutableList() - - if (matchingFiles.isEmpty()) { - if (conf.hasKey(REPORT_PATH_KEY)) { - val file = File(reportPath) - if (!file.exists()) { - val formattedMessage = - String.format("No utPLSQL test report was found for %s using pattern %s", REPORT_PATH_KEY, reportPath) - logger.warn(formattedMessage) - analysisWarnings.addUnique(formattedMessage) - } else { - matchingFiles.add(file) - } - } else { - logger.info("No utPLSQL test report was found for {} using default pattern {}", REPORT_PATH_KEY, reportPath) - } - } - return matchingFiles - } - - private fun readTestExecutionsReport(file: File): TestExecutions { - val serializer = Persister() - return serializer.read(TestExecutions::class.java, file) - } - - private fun processTestExecutions(context: SensorContext, testExecutions: TestExecutions) { - testExecutions.files?.forEach { file -> - val mappedTest = objectLocator.findTestObject(file.path, PlSqlGrammar.CREATE_PACKAGE_BODY) - val inputFile = mappedTest?.inputFile ?: - context.fileSystem().inputFile(context.fileSystem().predicates().hasPath(file.path)) - - if (inputFile != null) { - file.testCases?.let { testCase -> - val testCount = testCase.count { it.status != TestCaseStatus.SKIPPED } - val failureCount = testCase.count { it.status == TestCaseStatus.FAILED } - val errorCount = testCase.count { it.status == TestCaseStatus.ERROR } - val skippedCount = testCase.count { it.status == TestCaseStatus.SKIPPED } - val duration = testCase.sumOf { it.duration } - - saveMetricOnFile(context, inputFile, CoreMetrics.TESTS, testCount) - saveMetricOnFile(context, inputFile, CoreMetrics.TEST_FAILURES, failureCount) - saveMetricOnFile(context, inputFile, CoreMetrics.TEST_ERRORS, errorCount) - saveMetricOnFile(context, inputFile, CoreMetrics.SKIPPED_TESTS, skippedCount) - saveMetricOnFile(context, inputFile, CoreMetrics.TEST_EXECUTION_TIME, duration) - } - } - } - } - private fun saveMetricOnFile(context: SensorContext, inputFile: InputFile, metric: Metric, value: T) { - context.newMeasure() - .on(inputFile) - .forMetric(metric) - .withValue(value) - .save() + testResultImporter.execute(context) } companion object { - const val REPORT_PATH_KEY = "sonar.zpa.tests.reportPaths" - const val DEFAULT_REPORT_PATH = "utplsql-test.xml" + const val TEST_REPORT_PATH_KEY = "sonar.zpa.tests.reportPaths" + const val DEFAULT_TEST_REPORT_PATH = "utplsql-test.xml" } } diff --git a/sonar-zpa-plugin/src/test/kotlin/org/sonar/plsqlopen/utplsql/UtPlSqlSensorTest.kt b/sonar-zpa-plugin/src/test/kotlin/org/sonar/plsqlopen/utplsql/UtPlSqlSensorTest.kt index 4f5c99b0..9d0504f5 100644 --- a/sonar-zpa-plugin/src/test/kotlin/org/sonar/plsqlopen/utplsql/UtPlSqlSensorTest.kt +++ b/sonar-zpa-plugin/src/test/kotlin/org/sonar/plsqlopen/utplsql/UtPlSqlSensorTest.kt @@ -38,7 +38,6 @@ import org.sonar.plugins.plsqlopen.api.PlSqlFile import org.sonar.plugins.plsqlopen.api.PlSqlGrammar import java.io.File - class UtPlSqlSensorTest { private lateinit var settings: MapSettings @@ -73,7 +72,7 @@ class UtPlSqlSensorTest { whenever(objectLocator.findTestObject(any(), any())).thenReturn(null) - settings.setProperty(UtPlSqlSensor.REPORT_PATH_KEY, "test-report-with-paths.xml") + settings.setProperty(UtPlSqlSensor.TEST_REPORT_PATH_KEY, "test-report-with-paths.xml") sensor.execute(context) val key = testFile.key() @@ -94,7 +93,7 @@ class UtPlSqlSensorTest { whenever(objectLocator.findTestObject(eq("test_package"), any())).thenReturn( MappedObject("", PlSqlGrammar.CREATE_PACKAGE_BODY, PlSqlFile.Type.TEST, testFile.path(), testFile)) - settings.setProperty(UtPlSqlSensor.REPORT_PATH_KEY, "test-report-with-paths.xml") + settings.setProperty(UtPlSqlSensor.TEST_REPORT_PATH_KEY, "test-report-with-paths.xml") sensor.execute(context) val key = testFile.key() @@ -107,7 +106,7 @@ class UtPlSqlSensorTest { @Test fun invalidReport() { - settings.setProperty(UtPlSqlSensor.REPORT_PATH_KEY, "doesnotexists.xml") + settings.setProperty(UtPlSqlSensor.TEST_REPORT_PATH_KEY, "doesnotexists.xml") sensor.execute(context) verify(analysisWarnings).addUnique("No utPLSQL test report was found for sonar.zpa.tests.reportPaths using pattern doesnotexists.xml") }