From 41a617d63ed14943a78c8c73c4ad06008b7bd563 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Tue, 30 May 2023 13:34:29 +0200 Subject: [PATCH 01/19] Adjust InputHelper, MergeFilter and tests for new requirements #3307 --- .../filter/mergefilter/MergeFilter.kt | 6 +- .../filter/mergefilter/MergeFilterTest.kt | 7 +- .../codecharta/util/InputHelper.kt | 51 ++++++++++---- .../codecharta/util/InputHelperTest.kt | 67 +++++++++++++++---- 4 files changed, 102 insertions(+), 29 deletions(-) diff --git a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt index c28407811a..c813fec165 100644 --- a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt +++ b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt @@ -58,8 +58,10 @@ class MergeFilter( ) } - val sourceFiles = InputHelper.getAndCheckAllSpecifiedInputFiles(sources) - if (sourceFiles.isEmpty()) { + val sourceFiles: MutableList + try { + sourceFiles = InputHelper.getInputFileListIfValid(sources, true) + } catch (invalidFilesException: IllegalArgumentException) { logger.error("Aborting execution because one or more input files have not been found or no input was specified at all!") return null } diff --git a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt index dcda8783f3..aba11251cf 100644 --- a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt +++ b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt @@ -16,6 +16,7 @@ import java.io.ByteArrayOutputStream import java.io.File import java.io.FileInputStream import java.io.PrintStream +import java.lang.IllegalArgumentException class MergeFilterTest { val outContent = ByteArrayOutputStream() @@ -98,11 +99,11 @@ class MergeFilterTest { } @Test - fun `should abort if at least one input file does not exist`() { + fun `should abort if input is invalid`() { mockkObject(InputHelper) every { - InputHelper.getAndCheckAllSpecifiedInputFiles(any()) - } returns mutableListOf() + InputHelper.getInputFileListIfValid(any(), any()) + } throws IllegalArgumentException() mockkObject(ProjectDeserializer) every { diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt index b3d107df28..8f2b473175 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt @@ -2,34 +2,61 @@ package de.maibornwolff.codecharta.util import mu.KotlinLogging import java.io.File +import java.lang.IllegalArgumentException class InputHelper { companion object { private val logger = KotlinLogging.logger {} - fun getAndCheckAllSpecifiedInputFiles(inputFiles: Array): MutableList { - if (inputFiles.isEmpty()) { + fun getInputFileListIfValid(inputResources: Array, canInputBePiped: Boolean): MutableList { + val isInputValid = isInputValid(inputResources, canInputBePiped) + + return if (isInputValid) { + getFileListFromValidatedFileArray(inputResources) + } else { + throw IllegalArgumentException() + } + } + + private fun isInputValid(inputResources: Array, canInputBePiped: Boolean): Boolean { + return if (canInputBePiped) { + isAllInputExistentAndFoldersNotEmpty(inputResources) + } else { + !isInputEmpty(inputResources) && isAllInputExistentAndFoldersNotEmpty(inputResources) + } + } + + private fun isInputEmpty(inputResources: Array): Boolean{ + if (inputResources.isEmpty()) { logger.error("Did not find any input files!") - return mutableListOf() + return true } + return false + } - val resultList = mutableListOf() - var doesInputContainNonexistentFile = false + private fun isAllInputExistentAndFoldersNotEmpty(inputResources: Array): Boolean{ + var isInputValid = true - for (source in inputFiles) { + for (source in inputResources) { if (!source.exists()) { logger.error("Could not find file `${ source.path }` and did not merge!") - doesInputContainNonexistentFile = true + isInputValid = false } else { - resultList.addAll(getFilesInFolder(source)) + if (source.isDirectory && getFilesInFolder(source).isEmpty()) { + logger.error("The specified path `${ source.path }` exists but is empty!") + isInputValid = false + } } } + return isInputValid + } - return if (doesInputContainNonexistentFile) { - mutableListOf() - } else { - resultList + private fun getFileListFromValidatedFileArray(inputFiles: Array): MutableList { + val resultList = mutableListOf() + for (source in inputFiles) { + resultList.addAll(getFilesInFolder(source)) } + return resultList } private fun getFilesInFolder(folder: File): List { diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt index 48a4bb68d0..c7c5c9cd10 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt @@ -2,6 +2,9 @@ package de.maibornwolff.codecharta.util import org.assertj.core.api.Assertions import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource import java.io.ByteArrayOutputStream import java.io.File import java.io.PrintStream @@ -12,8 +15,18 @@ class InputHelperTest { val errContent = ByteArrayOutputStream() val originalErr = System.err - @Test - fun `should output warning for all files from parameters which were not found`() { + companion object { + @JvmStatic + fun providerParserArguments(): List { + return listOf( + Arguments.of(false), + Arguments.of(true)) + } + } + + @ParameterizedTest + @MethodSource("providerParserArguments") + fun `should output warning for all files which were not found`(canInputBePiped: Boolean) { System.setOut(PrintStream(outContent)) System.setErr(PrintStream(errContent)) @@ -21,7 +34,11 @@ class InputHelperTest { File("src/test/resources/example_api_version_1.3.cc.json"), File("src/test/resources/thisDoesNotExist1.json"), File("src/test/resources/thisDoesNotExist2.json")) - InputHelper.getAndCheckAllSpecifiedInputFiles(inputFiles) + try { + InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped) + } catch (exception: IllegalArgumentException) { + // do nothing + } System.setOut(originalOut) System.setErr(originalErr) @@ -32,38 +49,64 @@ class InputHelperTest { .contains("thisDoesNotExist2.json` and did not merge!") } - @Test - fun `should return empty list if input contains one nonexistent file`() { + @ParameterizedTest + @MethodSource("providerParserArguments") + fun `should throw exception if input contains one nonexistent file`(canInputBePiped: Boolean) { val inputFiles = arrayOf(File("src/test/resources/example.cc.json"), File("src/test/resources/example_api_version_1.3.cc.json"), File("src/test/resources/thisDoesNotExist1.json")) - val result = InputHelper.getAndCheckAllSpecifiedInputFiles(inputFiles) - Assertions.assertThat(result).isEmpty() + Assertions.assertThatIllegalArgumentException().isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped) } } @Test - fun `should return empty list if no files are specified`() { + fun `should throw exception if no files are specified and input can not be piped`() { val inputFiles = arrayOf() System.setErr(PrintStream(errContent)) - val result = InputHelper.getAndCheckAllSpecifiedInputFiles(inputFiles) + Assertions.assertThatIllegalArgumentException() + .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, false) } System.setErr(originalErr) - Assertions.assertThat(result).isEmpty() Assertions.assertThat(errContent.toString()) .contains("Did not find any input files!") } @Test - fun `should return list of all input files if all exist`() { + fun `should throw no exception if no files are specified and input can be piped`() { + val inputFiles = arrayOf() + + Assertions.assertThatNoException() + .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, true) } + } + + @ParameterizedTest + @MethodSource("providerParserArguments") + fun `should throw exception if input contains existent but empty directory as input`(canInputBePiped: Boolean) { + val emptyDirectoryPath = "src/test/resources/emptyDirectory" + val emptyTestDirectory = File(emptyDirectoryPath) + emptyTestDirectory.mkdir() + emptyTestDirectory.deleteOnExit() + + System.setErr(PrintStream(errContent)) + Assertions.assertThatIllegalArgumentException() + .isThrownBy { InputHelper.getInputFileListIfValid(arrayOf(emptyTestDirectory), false) } + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()) + .contains("The specified path `${ emptyTestDirectory.path }` exists but is empty!") + } + + @ParameterizedTest + @MethodSource("providerParserArguments") + fun `should return list of all input files if input is valid`(canInputBePiped: Boolean) { val validFile1 = File("src/test/resources/example.cc.json") val validFile2 = File("src/test/resources/example_api_version_1.3.cc.json") val validFile3 = File("src/test/resources/exampleUncompressed.txt") val inputFiles = arrayOf(validFile1, validFile2, validFile3) - val result = InputHelper.getAndCheckAllSpecifiedInputFiles(inputFiles) + val result = InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped) Assertions.assertThat(result).contains(validFile1) Assertions.assertThat(result).contains(validFile2) From ddb45cf8ffe594224140bbde3ef7cf67a63f1ac6 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Tue, 30 May 2023 15:02:50 +0200 Subject: [PATCH 02/19] Add input checking to CSVExporter #3307 --- .../codecharta/exporter/csv/CSVExporter.kt | 11 ++++- .../exporter/csvexporter/CSVExporterTest.kt | 44 +++++++++++++++++++ .../src/test/resources/dummyFile.cc.json | 0 .../filter/mergefilter/MergeFilter.kt | 6 +-- .../filter/mergefilter/MergeFilterTest.kt | 2 +- .../codecharta/util/InputHelper.kt | 11 ++++- .../codecharta/util/InputHelperTest.kt | 9 +++- .../test/resources/inputFiles/dummyFile1.txt | 0 .../test/resources/inputFiles/dummyFile2.txt | 0 9 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt create mode 100644 analysis/export/CSVExporter/src/test/resources/dummyFile.cc.json create mode 100644 analysis/model/src/test/resources/inputFiles/dummyFile1.txt create mode 100644 analysis/model/src/test/resources/inputFiles/dummyFile2.txt diff --git a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt index d8d68e2db4..774f4a3e6f 100644 --- a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt +++ b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt @@ -9,6 +9,7 @@ import de.maibornwolff.codecharta.serialization.ProjectDeserializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper import picocli.CommandLine import java.io.BufferedWriter import java.io.File @@ -51,7 +52,15 @@ class CSVExporter : Callable, InteractiveParser { throw IllegalArgumentException("depth-of-hierarchy must not be negative") } - val projects = sources.map { ProjectDeserializer.deserializeProject(it.inputStream()) } + val sourceFiles: MutableList + try { + sourceFiles = InputHelper.getInputFileListIfValid(sources, canInputBePiped = false) + } catch (invalidInputException: IllegalArgumentException) { + println("Aborting execution because of invalid input resources!") + return null + } + + val projects = sourceFiles.map { ProjectDeserializer.deserializeProject(it.inputStream()) } projects.forEach { writeUsingWriter(it, writer()) } diff --git a/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt b/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt new file mode 100644 index 0000000000..e0805a3976 --- /dev/null +++ b/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt @@ -0,0 +1,44 @@ +package de.maibornwolff.codecharta.exporter.csvexporter + +import de.maibornwolff.codecharta.exporter.csv.CSVExporter +import de.maibornwolff.codecharta.model.Project +import de.maibornwolff.codecharta.serialization.ProjectDeserializer +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.verify +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import picocli.CommandLine +import java.io.ByteArrayOutputStream +import java.io.FileInputStream +import java.io.PrintStream +import java.lang.IllegalArgumentException + +class CSVExporterTest { + val outContent = ByteArrayOutputStream() + val originalOut = System.out + + @Test + fun `should abort if input is invalid`() { + mockkObject(InputHelper) + every { + InputHelper.getInputFileListIfValid(any(), any()) + } throws IllegalArgumentException() + + mockkObject(ProjectDeserializer) + every { + ProjectDeserializer.deserializeProject(any()) + } returns Project("") + + System.setOut(PrintStream(outContent)) + CommandLine(CSVExporter()).execute( + "src/test/resources/dummyFile.cc.json", + "src/test/resources/thisDoesNotExist.cc.json").toString() + System.setOut(originalOut) + + Assertions.assertThat(outContent.toString()).contains("Aborting execution because of invalid input resources!") + + verify(exactly = 0) { ProjectDeserializer.deserializeProject(any()) } + } +} diff --git a/analysis/export/CSVExporter/src/test/resources/dummyFile.cc.json b/analysis/export/CSVExporter/src/test/resources/dummyFile.cc.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt index c813fec165..0719d75683 100644 --- a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt +++ b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt @@ -60,9 +60,9 @@ class MergeFilter( val sourceFiles: MutableList try { - sourceFiles = InputHelper.getInputFileListIfValid(sources, true) - } catch (invalidFilesException: IllegalArgumentException) { - logger.error("Aborting execution because one or more input files have not been found or no input was specified at all!") + sourceFiles = InputHelper.getInputFileListIfValid(sources, canInputBePiped = true) + } catch (invalidInputException: IllegalArgumentException) { + logger.error("Aborting execution because of invalid input resources!") return null } diff --git a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt index aba11251cf..b5d488445f 100644 --- a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt +++ b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt @@ -117,7 +117,7 @@ class MergeFilterTest { "src/test/resources/thisDoesNotExist.cc.json").toString() System.setErr(originalErr) - assertThat(errContent.toString()).contains("Aborting execution because one or more input files have not been found or no input was specified at all!") + assertThat(errContent.toString()).contains("Aborting execution because of invalid input resources!") verify(exactly = 0) { ProjectDeserializer.deserializeProject(any()) } } diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt index 8f2b473175..3e6d914ccd 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt @@ -8,6 +8,11 @@ class InputHelper { companion object { private val logger = KotlinLogging.logger {} + /** + * Returns list of the specified files if all conditions are met to consider input valid, otherwise throws IllegalArgumentException. + * If input can be piped, we check if all input resources exist and folders are not empty. + * If input can not be piped, we check for that as well and additionally check if input is not empty. + */ fun getInputFileListIfValid(inputResources: Array, canInputBePiped: Boolean): MutableList { val isInputValid = isInputValid(inputResources, canInputBePiped) @@ -54,7 +59,11 @@ class InputHelper { private fun getFileListFromValidatedFileArray(inputFiles: Array): MutableList { val resultList = mutableListOf() for (source in inputFiles) { - resultList.addAll(getFilesInFolder(source)) + if (source.isDirectory) { + resultList.addAll(getFilesInFolder(source)) + } else { + resultList.add(source) + } } return resultList } diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt index c7c5c9cd10..c1879eaeaa 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt @@ -103,15 +103,20 @@ class InputHelperTest { val validFile1 = File("src/test/resources/example.cc.json") val validFile2 = File("src/test/resources/example_api_version_1.3.cc.json") val validFile3 = File("src/test/resources/exampleUncompressed.txt") + val validDirectory = File("src/test/resources/inputFiles") + val amountOfFilesInDirectory = 2 - val inputFiles = arrayOf(validFile1, validFile2, validFile3) + val inputFiles = arrayOf(validFile1, validFile2, validFile3, validDirectory) val result = InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped) Assertions.assertThat(result).contains(validFile1) Assertions.assertThat(result).contains(validFile2) Assertions.assertThat(result).contains(validFile3) + Assertions.assertThat(result).contains(File("src/test/resources/inputFiles/dummyFile1.txt")) + Assertions.assertThat(result).contains(File("src/test/resources/inputFiles/dummyFile2.txt")) - Assertions.assertThat(result.size).isEqualTo(inputFiles.size) + // Subtract directory as file in list, add number of files in directory + Assertions.assertThat(result.size).isEqualTo(inputFiles.size - 1 + amountOfFilesInDirectory) } } diff --git a/analysis/model/src/test/resources/inputFiles/dummyFile1.txt b/analysis/model/src/test/resources/inputFiles/dummyFile1.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/analysis/model/src/test/resources/inputFiles/dummyFile2.txt b/analysis/model/src/test/resources/inputFiles/dummyFile2.txt new file mode 100644 index 0000000000..e69de29bb2 From 760d5e19cd65704e6317720c0e78ea7279a5cb73 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Tue, 30 May 2023 18:28:53 +0200 Subject: [PATCH 03/19] Refactor InputHelper to also look for illegal folder input #3307 --- .../codecharta/exporter/csv/CSVExporter.kt | 8 +- .../exporter/csvexporter/CSVExporterTest.kt | 27 ++++-- .../src/test/resources/dummyFile.cc.json | 0 .../filter/mergefilter/MergeFilter.kt | 8 +- .../filter/mergefilter/MergeFilterTest.kt | 7 +- .../codecharta/util/InputHelper.kt | 57 +++++++++--- .../codecharta/util/InputHelperTest.kt | 87 ++++++++++++++----- 7 files changed, 129 insertions(+), 65 deletions(-) delete mode 100644 analysis/export/CSVExporter/src/test/resources/dummyFile.cc.json diff --git a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt index 774f4a3e6f..0cec3e8236 100644 --- a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt +++ b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt @@ -52,13 +52,7 @@ class CSVExporter : Callable, InteractiveParser { throw IllegalArgumentException("depth-of-hierarchy must not be negative") } - val sourceFiles: MutableList - try { - sourceFiles = InputHelper.getInputFileListIfValid(sources, canInputBePiped = false) - } catch (invalidInputException: IllegalArgumentException) { - println("Aborting execution because of invalid input resources!") - return null - } + val sourceFiles = InputHelper.getInputFileListIfValid(sources, canInputBePiped = false, canInputContainFolders = false) val projects = sourceFiles.map { ProjectDeserializer.deserializeProject(it.inputStream()) } diff --git a/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt b/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt index e0805a3976..93cee52329 100644 --- a/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt +++ b/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt @@ -6,24 +6,32 @@ import de.maibornwolff.codecharta.serialization.ProjectDeserializer import de.maibornwolff.codecharta.util.InputHelper import io.mockk.every import io.mockk.mockkObject +import io.mockk.unmockkAll import io.mockk.verify -import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance import picocli.CommandLine import java.io.ByteArrayOutputStream import java.io.FileInputStream import java.io.PrintStream -import java.lang.IllegalArgumentException +import kotlin.IllegalArgumentException +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class CSVExporterTest { val outContent = ByteArrayOutputStream() val originalOut = System.out + @AfterAll + fun afterTest() { + unmockkAll() + } + @Test - fun `should abort if input is invalid`() { + fun `should not execute exporter if input is invalid`() { mockkObject(InputHelper) every { - InputHelper.getInputFileListIfValid(any(), any()) + InputHelper.getInputFileListIfValid(any(), any(), any()) } throws IllegalArgumentException() mockkObject(ProjectDeserializer) @@ -32,13 +40,14 @@ class CSVExporterTest { } returns Project("") System.setOut(PrintStream(outContent)) - CommandLine(CSVExporter()).execute( - "src/test/resources/dummyFile.cc.json", - "src/test/resources/thisDoesNotExist.cc.json").toString() + try { + CommandLine(CSVExporter()).execute( + "thisDoesNotExist.cc.json").toString() + } catch (invalidArgumentException: IllegalArgumentException) { + // do nothing + } System.setOut(originalOut) - Assertions.assertThat(outContent.toString()).contains("Aborting execution because of invalid input resources!") - verify(exactly = 0) { ProjectDeserializer.deserializeProject(any()) } } } diff --git a/analysis/export/CSVExporter/src/test/resources/dummyFile.cc.json b/analysis/export/CSVExporter/src/test/resources/dummyFile.cc.json deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt index 0719d75683..2fed42ff8d 100644 --- a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt +++ b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt @@ -58,13 +58,7 @@ class MergeFilter( ) } - val sourceFiles: MutableList - try { - sourceFiles = InputHelper.getInputFileListIfValid(sources, canInputBePiped = true) - } catch (invalidInputException: IllegalArgumentException) { - logger.error("Aborting execution because of invalid input resources!") - return null - } + val sourceFiles = InputHelper.getInputFileListIfValid(sources, canInputBePiped = true, canInputContainFolders = true) val srcProjects = sourceFiles .mapNotNull { diff --git a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt index b5d488445f..54d3ecee48 100644 --- a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt +++ b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt @@ -99,10 +99,10 @@ class MergeFilterTest { } @Test - fun `should abort if input is invalid`() { + fun `should not execute merge if input is invalid`() { mockkObject(InputHelper) every { - InputHelper.getInputFileListIfValid(any(), any()) + InputHelper.getInputFileListIfValid(any(), any(), any()) } throws IllegalArgumentException() mockkObject(ProjectDeserializer) @@ -113,12 +113,9 @@ class MergeFilterTest { System.setErr(PrintStream(errContent)) CommandLine(MergeFilter()).execute( "src/test/resources/mergeFolderTest/file1.cc.json", - "src/test/resources/mergeFolderTest/file2.cc.json", "src/test/resources/thisDoesNotExist.cc.json").toString() System.setErr(originalErr) - assertThat(errContent.toString()).contains("Aborting execution because of invalid input resources!") - verify(exactly = 0) { ProjectDeserializer.deserializeProject(any()) } } } diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt index 3e6d914ccd..8f29451b6b 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt @@ -9,46 +9,75 @@ class InputHelper { private val logger = KotlinLogging.logger {} /** - * Returns list of the specified files if all conditions are met to consider input valid, otherwise throws IllegalArgumentException. + * Returns list of the specified files (and all contained files if resource is directory and flag is given) if all conditions are met to consider input valid, otherwise throws IllegalArgumentException. * If input can be piped, we check if all input resources exist and folders are not empty. * If input can not be piped, we check for that as well and additionally check if input is not empty. + * An error is also thrown, if a folder is input, but `canInputContainFolders` is set to `false`. */ - fun getInputFileListIfValid(inputResources: Array, canInputBePiped: Boolean): MutableList { - val isInputValid = isInputValid(inputResources, canInputBePiped) + fun getInputFileListIfValid(inputResources: Array, + canInputBePiped: Boolean, + canInputContainFolders: Boolean): MutableList { + val isInputValid = isInputValid(inputResources, canInputBePiped, canInputContainFolders) return if (isInputValid) { getFileListFromValidatedFileArray(inputResources) } else { - throw IllegalArgumentException() + throw IllegalArgumentException("Invalid input resources (file/folder) specified!") } } - private fun isInputValid(inputResources: Array, canInputBePiped: Boolean): Boolean { + private fun isInputValid(inputResources: Array, + canInputBePiped: Boolean, + canInputContainFolders: Boolean): Boolean { return if (canInputBePiped) { - isAllInputExistentAndFoldersNotEmpty(inputResources) + areInputResourcesValid(inputResources, canInputContainFolders) } else { - !isInputEmpty(inputResources) && isAllInputExistentAndFoldersNotEmpty(inputResources) + !isInputEmpty(inputResources) && areInputResourcesValid(inputResources, canInputContainFolders) } } - private fun isInputEmpty(inputResources: Array): Boolean{ + private fun isInputEmpty(inputResources: Array): Boolean { if (inputResources.isEmpty()) { - logger.error("Did not find any input files!") + logger.error("Did not find any input resources!") return true } return false } - private fun isAllInputExistentAndFoldersNotEmpty(inputResources: Array): Boolean{ + private fun doesInputExist(inputResource: File): Boolean { + if (!inputResource.exists()) { + logger.error("Could not find file `${ inputResource.path }`!") + return false + } + return true + } + + private fun isResourceValid(inputResource: File, + canInputContainFolders: Boolean): Boolean { + if (canInputContainFolders) { + if (inputResource.isDirectory && getFilesInFolder(inputResource).isEmpty()) { + logger.error("The specified path `${ inputResource.path }` exists but is empty!") + return false + } + return true + } else { + if (inputResource.isDirectory) { + logger.error("Input folder where only files are allowed!") + return false + } + return true + } + } + + private fun areInputResourcesValid(inputResources: Array, + canInputContainFolders: Boolean): Boolean { var isInputValid = true for (source in inputResources) { - if (!source.exists()) { - logger.error("Could not find file `${ source.path }` and did not merge!") + if (!doesInputExist(source)) { isInputValid = false } else { - if (source.isDirectory && getFilesInFolder(source).isEmpty()) { - logger.error("The specified path `${ source.path }` exists but is empty!") + if (!isResourceValid(source, canInputContainFolders)) { isInputValid = false } } diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt index c1879eaeaa..8c6d8a59c2 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt @@ -1,7 +1,6 @@ package de.maibornwolff.codecharta.util import org.assertj.core.api.Assertions -import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource @@ -18,6 +17,15 @@ class InputHelperTest { companion object { @JvmStatic fun providerParserArguments(): List { + return listOf( + Arguments.of(false, false), + Arguments.of(true, false), + Arguments.of(false, true), + Arguments.of(true, true)) + } + + @JvmStatic + fun provideOneFlagArgument(): List { return listOf( Arguments.of(false), Arguments.of(true)) @@ -26,16 +34,19 @@ class InputHelperTest { @ParameterizedTest @MethodSource("providerParserArguments") - fun `should output warning for all files which were not found`(canInputBePiped: Boolean) { + fun `should output warning for all files which were not found`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { System.setOut(PrintStream(outContent)) System.setErr(PrintStream(errContent)) + val invalidFilePath1 = "src/test/resources/thisDoesNotExist1.json" + val invalidFilePath2 = "src/test/resources/thisDoesNotExist2.json" + val inputFiles = arrayOf(File("src/test/resources/example.cc.json"), File("src/test/resources/example_api_version_1.3.cc.json"), - File("src/test/resources/thisDoesNotExist1.json"), - File("src/test/resources/thisDoesNotExist2.json")) + File(invalidFilePath1), + File(invalidFilePath2)) try { - InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped) + InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, canInputContainFolders) } catch (exception: IllegalArgumentException) { // do nothing } @@ -44,44 +55,46 @@ class InputHelperTest { System.setErr(originalErr) Assertions.assertThat(errContent.toString()) - .contains("thisDoesNotExist1.json` and did not merge!") + .contains("Could not find file `$invalidFilePath1`") Assertions.assertThat(errContent.toString()) - .contains("thisDoesNotExist2.json` and did not merge!") + .contains("Could not find file `$invalidFilePath2`") } @ParameterizedTest @MethodSource("providerParserArguments") - fun `should throw exception if input contains one nonexistent file`(canInputBePiped: Boolean) { + fun `should throw exception if input contains one nonexistent file`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { val inputFiles = arrayOf(File("src/test/resources/example.cc.json"), File("src/test/resources/example_api_version_1.3.cc.json"), File("src/test/resources/thisDoesNotExist1.json")) - Assertions.assertThatIllegalArgumentException().isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped) } + Assertions.assertThatIllegalArgumentException().isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, canInputContainFolders) } } - @Test - fun `should throw exception if no files are specified and input can not be piped`() { + @ParameterizedTest + @MethodSource("provideOneFlagArgument") + fun `should throw exception if no files are specified and input can not be piped`(canInputContainFolders: Boolean) { val inputFiles = arrayOf() System.setErr(PrintStream(errContent)) Assertions.assertThatIllegalArgumentException() - .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, false) } + .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, false, canInputContainFolders) } System.setErr(originalErr) Assertions.assertThat(errContent.toString()) - .contains("Did not find any input files!") + .contains("Did not find any input resources!") } - @Test - fun `should throw no exception if no files are specified and input can be piped`() { + @ParameterizedTest + @MethodSource("provideOneFlagArgument") + fun `should throw no exception if no files are specified and input can be piped`(canInputContainFolders: Boolean) { val inputFiles = arrayOf() Assertions.assertThatNoException() - .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, true) } + .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, true, canInputContainFolders) } } @ParameterizedTest - @MethodSource("providerParserArguments") + @MethodSource("provideOneFlagArgument") fun `should throw exception if input contains existent but empty directory as input`(canInputBePiped: Boolean) { val emptyDirectoryPath = "src/test/resources/emptyDirectory" val emptyTestDirectory = File(emptyDirectoryPath) @@ -90,7 +103,7 @@ class InputHelperTest { System.setErr(PrintStream(errContent)) Assertions.assertThatIllegalArgumentException() - .isThrownBy { InputHelper.getInputFileListIfValid(arrayOf(emptyTestDirectory), false) } + .isThrownBy { InputHelper.getInputFileListIfValid(arrayOf(emptyTestDirectory), canInputBePiped, true) } System.setErr(originalErr) Assertions.assertThat(errContent.toString()) @@ -99,24 +112,52 @@ class InputHelperTest { @ParameterizedTest @MethodSource("providerParserArguments") - fun `should return list of all input files if input is valid`(canInputBePiped: Boolean) { + fun `should return list of all input files if input is valid`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { val validFile1 = File("src/test/resources/example.cc.json") val validFile2 = File("src/test/resources/example_api_version_1.3.cc.json") val validFile3 = File("src/test/resources/exampleUncompressed.txt") - val validDirectory = File("src/test/resources/inputFiles") - val amountOfFilesInDirectory = 2 - val inputFiles = arrayOf(validFile1, validFile2, validFile3, validDirectory) + val inputFiles = arrayOf(validFile1, validFile2, validFile3) - val result = InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped) + val result = InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, canInputContainFolders) Assertions.assertThat(result).contains(validFile1) Assertions.assertThat(result).contains(validFile2) Assertions.assertThat(result).contains(validFile3) + + Assertions.assertThat(result.size).isEqualTo(inputFiles.size) + } + + @ParameterizedTest + @MethodSource("provideOneFlagArgument") + fun `should return list of all contained input files in valid directory`(canInputBePiped: Boolean) { + val validDirectory = File("src/test/resources/inputFiles") + val amountOfFilesInDirectory = 2 + + val inputFiles = arrayOf(validDirectory) + + val result = InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, true) + Assertions.assertThat(result).contains(File("src/test/resources/inputFiles/dummyFile1.txt")) Assertions.assertThat(result).contains(File("src/test/resources/inputFiles/dummyFile2.txt")) // Subtract directory as file in list, add number of files in directory Assertions.assertThat(result.size).isEqualTo(inputFiles.size - 1 + amountOfFilesInDirectory) } + + @ParameterizedTest + @MethodSource("provideOneFlagArgument") + fun `should throw exception if folder is given with no-folder-flag`(canInputBePiped: Boolean) { + val validDirectory = File("src/test/resources/inputFiles") + + val inputFiles = arrayOf(validDirectory) + + System.setErr(PrintStream(errContent)) + Assertions.assertThatIllegalArgumentException() + .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, false) } + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()) + .contains("Input folder where only files are allowed!") + } } From a76194fe4fe493cd8e514bc6a5135d477a1fe3b9 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Wed, 31 May 2023 11:54:05 +0200 Subject: [PATCH 04/19] Refactor InputHelper, add input check to Exporter and Filters #3307 --- .../codecharta/exporter/csv/CSVExporter.kt | 7 +- .../exporter/csvexporter/CSVExporterTest.kt | 34 +++------ .../filter/edgefilter/EdgeFilter.kt | 15 +++- .../filter/edgefilter/EdgeFilterTest.kt | 37 ++++++++++ .../filter/edgefilter/ParserDialogTest.kt | 3 +- .../filter/mergefilter/MergeFilter.kt | 6 +- .../filter/mergefilter/MergeFilterTest.kt | 16 +---- .../structuremodifier/StructureModifier.kt | 8 ++- .../StructureModifierTest.kt | 31 +++++++++ .../codecharta/util/InputHelper.kt | 55 ++++++--------- .../codecharta/util/InputHelperTest.kt | 69 +++++++++++-------- 11 files changed, 174 insertions(+), 107 deletions(-) diff --git a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt index 0cec3e8236..ebef0c220d 100644 --- a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt +++ b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt @@ -52,9 +52,12 @@ class CSVExporter : Callable, InteractiveParser { throw IllegalArgumentException("depth-of-hierarchy must not be negative") } - val sourceFiles = InputHelper.getInputFileListIfValid(sources, canInputBePiped = false, canInputContainFolders = false) + if (!InputHelper.isInputValid(sources, canInputBePiped = false, canInputContainFolders = false)) { + System.err.println("Input invalid file for CSVExporter, stopping execution...") + return null + } - val projects = sourceFiles.map { ProjectDeserializer.deserializeProject(it.inputStream()) } + val projects = sources.map { ProjectDeserializer.deserializeProject(it.inputStream()) } projects.forEach { writeUsingWriter(it, writer()) } diff --git a/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt b/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt index 93cee52329..cdb9ca76bc 100644 --- a/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt +++ b/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt @@ -1,26 +1,22 @@ package de.maibornwolff.codecharta.exporter.csvexporter import de.maibornwolff.codecharta.exporter.csv.CSVExporter -import de.maibornwolff.codecharta.model.Project -import de.maibornwolff.codecharta.serialization.ProjectDeserializer import de.maibornwolff.codecharta.util.InputHelper import io.mockk.every import io.mockk.mockkObject import io.mockk.unmockkAll -import io.mockk.verify +import org.assertj.core.api.Assertions import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import picocli.CommandLine import java.io.ByteArrayOutputStream -import java.io.FileInputStream import java.io.PrintStream -import kotlin.IllegalArgumentException @TestInstance(TestInstance.Lifecycle.PER_CLASS) class CSVExporterTest { - val outContent = ByteArrayOutputStream() - val originalOut = System.out + val errContent = ByteArrayOutputStream() + val originalErr = System.err @AfterAll fun afterTest() { @@ -28,26 +24,16 @@ class CSVExporterTest { } @Test - fun `should not execute exporter if input is invalid`() { + fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.getInputFileListIfValid(any(), any(), any()) - } throws IllegalArgumentException() + InputHelper.isInputValid(any(), any(), any()) + } returns false - mockkObject(ProjectDeserializer) - every { - ProjectDeserializer.deserializeProject(any()) - } returns Project("") - - System.setOut(PrintStream(outContent)) - try { - CommandLine(CSVExporter()).execute( - "thisDoesNotExist.cc.json").toString() - } catch (invalidArgumentException: IllegalArgumentException) { - // do nothing - } - System.setOut(originalOut) + System.setErr(PrintStream(errContent)) + CommandLine(CSVExporter()).execute("thisDoesNotExist.cc.json").toString() + System.setErr(originalErr) - verify(exactly = 0) { ProjectDeserializer.deserializeProject(any()) } + Assertions.assertThat(errContent.toString()).contains("Input invalid file for CSVExporter, stopping execution") } } diff --git a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt index 24221444c2..74a15d968a 100644 --- a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt +++ b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt @@ -5,6 +5,8 @@ import de.maibornwolff.codecharta.serialization.ProjectSerializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper +import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.PrintStream @@ -22,8 +24,8 @@ class EdgeFilter( @CommandLine.Option(names = ["-h", "--help"], usageHelp = true, description = ["displays this help and exits"]) var help: Boolean = false - @CommandLine.Parameters(arity = "1..*", paramLabel = "FILE", description = ["files to filter"]) - private var source: String = "" + @CommandLine.Parameters(arity = "1", paramLabel = "FILE", description = ["files to filter"]) + private var source: File = File("") @CommandLine.Option(names = ["--path-separator"], description = ["path separator (default = '/')"]) private var pathSeparator = '/' @@ -32,7 +34,12 @@ class EdgeFilter( private var outputFile: String? = null override fun call(): Void? { - val srcProject = ProjectDeserializer.deserializeProject(File(source).inputStream()) + if (!InputHelper.isInputValid(arrayOf(source), canInputBePiped = true, canInputContainFolders = false)) { + logger.error("Input invalid file for EdgeFilter, stopping execution...") + return null + } + + val srcProject = ProjectDeserializer.deserializeProject(source.inputStream()) val newProject = EdgeProjectBuilder(srcProject, pathSeparator).merge() @@ -42,6 +49,8 @@ class EdgeFilter( } companion object { + private val logger = KotlinLogging.logger {} + @JvmStatic fun main(args: Array) { CommandLine(EdgeFilter()).execute(*args) diff --git a/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt b/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt index 861c1557ef..0b96c3133e 100644 --- a/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt +++ b/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt @@ -1,13 +1,36 @@ package de.maibornwolff.codecharta.filter.edgefilter import de.maibornwolff.codecharta.filter.edgefilter.EdgeFilter.Companion.main +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import picocli.CommandLine +import java.io.ByteArrayOutputStream import java.io.File +import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class EdgeFilterTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + @AfterEach + fun afterTest() { + unmockkAll() + } + @Test fun `should create json uncompressed file`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns true + main( arrayOf( "src/test/resources/coupling.json", "-o=src/test/resources/output" @@ -18,4 +41,18 @@ class EdgeFilterTest { assertTrue(file.exists()) } + + @Test + fun `should stop execution if input file is invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(EdgeFilter()).execute("thisDoesNotExist.cc.json").toString() + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()).contains("Input invalid file for EdgeFilter, stopping execution") + } } diff --git a/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/ParserDialogTest.kt b/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/ParserDialogTest.kt index 88f08fde4a..0784b427b3 100644 --- a/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/ParserDialogTest.kt +++ b/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/ParserDialogTest.kt @@ -10,6 +10,7 @@ import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import picocli.CommandLine +import java.io.File @TestInstance(TestInstance.Lifecycle.PER_CLASS) class ParserDialogTest { @@ -44,6 +45,6 @@ class ParserDialogTest { val parseResult = cmdLine.parseArgs(*parserArguments.toTypedArray()) assertThat(parseResult.matchedOption("output-file").getValue()).isEqualTo("sampleOutputFile") assertThat(parseResult.matchedOption("path-separator").getValue()).isEqualTo('/') - assertThat(parseResult.matchedPositional(0).getValue()).isEqualTo("sampleFile.cc.json") + assertThat(parseResult.matchedPositional(0).getValue()).isEqualTo(File("sampleFile.cc.json")) } } diff --git a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt index 2fed42ff8d..23b79d316f 100644 --- a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt +++ b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt @@ -58,7 +58,11 @@ class MergeFilter( ) } - val sourceFiles = InputHelper.getInputFileListIfValid(sources, canInputBePiped = true, canInputContainFolders = true) + if (!InputHelper.isInputValid(sources, canInputBePiped = true, canInputContainFolders = true)) { + logger.error("Input invalid files/folders for MergeFilter, stopping execution...") + return null + } + val sourceFiles = InputHelper.getFileListFromValidatedResourceArray(sources) val srcProjects = sourceFiles .mapNotNull { diff --git a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt index 54d3ecee48..841ad3d698 100644 --- a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt +++ b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt @@ -1,22 +1,17 @@ package de.maibornwolff.codecharta.filter.mergefilter import de.maibornwolff.codecharta.filter.mergefilter.MergeFilter.Companion.main -import de.maibornwolff.codecharta.model.Project -import de.maibornwolff.codecharta.serialization.ProjectDeserializer import de.maibornwolff.codecharta.util.InputHelper import io.mockk.every import io.mockk.mockkObject import io.mockk.unmockkAll -import io.mockk.verify import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test import picocli.CommandLine import java.io.ByteArrayOutputStream import java.io.File -import java.io.FileInputStream import java.io.PrintStream -import java.lang.IllegalArgumentException class MergeFilterTest { val outContent = ByteArrayOutputStream() @@ -102,13 +97,8 @@ class MergeFilterTest { fun `should not execute merge if input is invalid`() { mockkObject(InputHelper) every { - InputHelper.getInputFileListIfValid(any(), any(), any()) - } throws IllegalArgumentException() - - mockkObject(ProjectDeserializer) - every { - ProjectDeserializer.deserializeProject(any()) - } returns Project("") + InputHelper.isInputValid(any(), any(), any()) + } returns false System.setErr(PrintStream(errContent)) CommandLine(MergeFilter()).execute( @@ -116,6 +106,6 @@ class MergeFilterTest { "src/test/resources/thisDoesNotExist.cc.json").toString() System.setErr(originalErr) - verify(exactly = 0) { ProjectDeserializer.deserializeProject(any()) } + assertThat(errContent.toString()).contains("Input invalid files/folders for MergeFilter, stopping execution") } } diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index 3038a82f4f..79a3039f65 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -6,6 +6,7 @@ import de.maibornwolff.codecharta.serialization.ProjectSerializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper import mu.KotlinLogging import picocli.CommandLine import java.io.File @@ -78,8 +79,11 @@ class StructureModifier( private fun readProject(): Project? { if (source == null) { return ProjectDeserializer.deserializeProject(input) - } else if (!source!!.isFile) { - logger.error("${source!!.name} has not been found.") + } + + // Can not be piped here, because that case is already covered by the previous check (source == null) + if (!InputHelper.isInputValid(arrayOf(source!!), canInputBePiped = false, canInputContainFolders = false)) { + logger.error("Input invalid file for StructureModifier, stopping execution...") return null } diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt index 4287058569..78f0551b66 100644 --- a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt +++ b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt @@ -1,14 +1,30 @@ package de.maibornwolff.codecharta.filter.structuremodifier import de.maibornwolff.codecharta.serialization.ProjectDeserializer +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import picocli.CommandLine import java.io.ByteArrayOutputStream import java.io.File import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class StructureModifierTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterEach + fun afterTest() { + unmockkAll() + } + @Test fun `reads project from file`() { val cliResult = executeForOutput("", arrayOf("src/test/resources/sample_project.cc.json", "-r=/does/not/exist")) @@ -38,6 +54,7 @@ class StructureModifierTest { assertThat(errorStream.toString()).contains("invalid_project.cc.json is not a valid project") } + // TODO: Why is this disabled? Should it not be removed? @Disabled @Test fun `reads project piped input multiline`() { @@ -112,4 +129,18 @@ class StructureModifierTest { assertThat(resultProject.attributeDescriptors.size).isEqualTo(3) assertThat(resultProject.attributeDescriptors["yrloc"]).isNull() } + + @Test + fun `should stop execution if input file is invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(StructureModifier()).execute("thisDoesNotExist.cc.json").toString() + System.setErr(originalErr) + + assertThat(errContent.toString()).contains("Input invalid file for StructureModifier, stopping execution") + } } diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt index 8f29451b6b..3c0a1d3568 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt @@ -2,33 +2,20 @@ package de.maibornwolff.codecharta.util import mu.KotlinLogging import java.io.File -import java.lang.IllegalArgumentException class InputHelper { companion object { private val logger = KotlinLogging.logger {} /** - * Returns list of the specified files (and all contained files if resource is directory and flag is given) if all conditions are met to consider input valid, otherwise throws IllegalArgumentException. - * If input can be piped, we check if all input resources exist and folders are not empty. - * If input can not be piped, we check for that as well and additionally check if input is not empty. - * An error is also thrown, if a folder is input, but `canInputContainFolders` is set to `false`. + * Checks if input resources meet a number of requirements: + * If input can not be piped in, the array can not be empty. + * If input can not contain folders, no element in the list can be a path to a folder. + * All elements in the array have to either be existing files or if allowed, folders. */ - fun getInputFileListIfValid(inputResources: Array, - canInputBePiped: Boolean, - canInputContainFolders: Boolean): MutableList { - val isInputValid = isInputValid(inputResources, canInputBePiped, canInputContainFolders) - - return if (isInputValid) { - getFileListFromValidatedFileArray(inputResources) - } else { - throw IllegalArgumentException("Invalid input resources (file/folder) specified!") - } - } - - private fun isInputValid(inputResources: Array, - canInputBePiped: Boolean, - canInputContainFolders: Boolean): Boolean { + fun isInputValid(inputResources: Array, + canInputBePiped: Boolean, + canInputContainFolders: Boolean): Boolean { return if (canInputBePiped) { areInputResourcesValid(inputResources, canInputContainFolders) } else { @@ -44,16 +31,16 @@ class InputHelper { return false } - private fun doesInputExist(inputResource: File): Boolean { - if (!inputResource.exists()) { - logger.error("Could not find file `${ inputResource.path }`!") + private fun isInputExistentAndFolderOrFile(inputResource: File): Boolean { + if (!(inputResource.isFile || inputResource.isDirectory)) { + logger.error("Could not find resource `${ inputResource.path }`!") return false } return true } - private fun isResourceValid(inputResource: File, - canInputContainFolders: Boolean): Boolean { + private fun isInputValidFolderOrAnyFile(inputResource: File, + canInputContainFolders: Boolean): Boolean { if (canInputContainFolders) { if (inputResource.isDirectory && getFilesInFolder(inputResource).isEmpty()) { logger.error("The specified path `${ inputResource.path }` exists but is empty!") @@ -74,10 +61,10 @@ class InputHelper { var isInputValid = true for (source in inputResources) { - if (!doesInputExist(source)) { + if (!isInputExistentAndFolderOrFile(source)) { isInputValid = false } else { - if (!isResourceValid(source, canInputContainFolders)) { + if (!isInputValidFolderOrAnyFile(source, canInputContainFolders)) { isInputValid = false } } @@ -85,14 +72,14 @@ class InputHelper { return isInputValid } - private fun getFileListFromValidatedFileArray(inputFiles: Array): MutableList { + /** + * Returns list of all elements in input array. + * If element in array is a path to a folder, all child elements are added to the list. + */ + fun getFileListFromValidatedResourceArray(inputResources: Array): MutableList { val resultList = mutableListOf() - for (source in inputFiles) { - if (source.isDirectory) { - resultList.addAll(getFilesInFolder(source)) - } else { - resultList.add(source) - } + for (source in inputResources) { + resultList.addAll(getFilesInFolder(source)) } return resultList } diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt index 8c6d8a59c2..c15230c3b9 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt @@ -1,6 +1,7 @@ package de.maibornwolff.codecharta.util import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource @@ -46,7 +47,7 @@ class InputHelperTest { File(invalidFilePath1), File(invalidFilePath2)) try { - InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, canInputContainFolders) + InputHelper.isInputValid(inputFiles, canInputBePiped, canInputContainFolders) } catch (exception: IllegalArgumentException) { // do nothing } @@ -55,108 +56,122 @@ class InputHelperTest { System.setErr(originalErr) Assertions.assertThat(errContent.toString()) - .contains("Could not find file `$invalidFilePath1`") + .contains("Could not find resource `$invalidFilePath1`") Assertions.assertThat(errContent.toString()) - .contains("Could not find file `$invalidFilePath2`") + .contains("Could not find resource `$invalidFilePath2`") } @ParameterizedTest @MethodSource("providerParserArguments") - fun `should throw exception if input contains one nonexistent file`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { + fun `should return invalid if input contains one nonexistent file`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { val inputFiles = arrayOf(File("src/test/resources/example.cc.json"), File("src/test/resources/example_api_version_1.3.cc.json"), File("src/test/resources/thisDoesNotExist1.json")) - Assertions.assertThatIllegalArgumentException().isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, canInputContainFolders) } + val result = InputHelper.isInputValid(inputFiles, canInputBePiped, canInputContainFolders) + + Assertions.assertThat(result).isFalse() } @ParameterizedTest @MethodSource("provideOneFlagArgument") - fun `should throw exception if no files are specified and input can not be piped`(canInputContainFolders: Boolean) { + fun `should return invalid if no files are specified and input can not be piped`(canInputContainFolders: Boolean) { val inputFiles = arrayOf() System.setErr(PrintStream(errContent)) - Assertions.assertThatIllegalArgumentException() - .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, false, canInputContainFolders) } + val result = InputHelper.isInputValid(inputFiles, canInputBePiped = false, canInputContainFolders) System.setErr(originalErr) + Assertions.assertThat(result).isFalse() Assertions.assertThat(errContent.toString()) .contains("Did not find any input resources!") } @ParameterizedTest @MethodSource("provideOneFlagArgument") - fun `should throw no exception if no files are specified and input can be piped`(canInputContainFolders: Boolean) { + fun `should return valid if no files are specified and input can be piped`(canInputContainFolders: Boolean) { val inputFiles = arrayOf() - Assertions.assertThatNoException() - .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, true, canInputContainFolders) } + val result = InputHelper.isInputValid(inputFiles, true, canInputContainFolders) + Assertions.assertThat(result).isTrue() } @ParameterizedTest @MethodSource("provideOneFlagArgument") - fun `should throw exception if input contains existent but empty directory as input`(canInputBePiped: Boolean) { + fun `should return invalid if input contains existent but empty directory as input`(canInputBePiped: Boolean) { val emptyDirectoryPath = "src/test/resources/emptyDirectory" val emptyTestDirectory = File(emptyDirectoryPath) emptyTestDirectory.mkdir() emptyTestDirectory.deleteOnExit() System.setErr(PrintStream(errContent)) - Assertions.assertThatIllegalArgumentException() - .isThrownBy { InputHelper.getInputFileListIfValid(arrayOf(emptyTestDirectory), canInputBePiped, true) } + val result = InputHelper.isInputValid(arrayOf(emptyTestDirectory), canInputBePiped, true) System.setErr(originalErr) + Assertions.assertThat(result).isFalse() Assertions.assertThat(errContent.toString()) .contains("The specified path `${ emptyTestDirectory.path }` exists but is empty!") } @ParameterizedTest @MethodSource("providerParserArguments") - fun `should return list of all input files if input is valid`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { + fun `should return valid if input only contains existing files`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { + val validFile1 = File("src/test/resources/example.cc.json") + val validFile2 = File("src/test/resources/example_api_version_1.3.cc.json") + val validFile3 = File("src/test/resources/exampleUncompressed.txt") + + val inputFiles = arrayOf(validFile1, validFile2, validFile3) + + val result = InputHelper.isInputValid(inputFiles, canInputBePiped, canInputContainFolders) + + Assertions.assertThat(result).isTrue() + } + + @Test + fun `should return list of all contained input files in valid directory`() { val validFile1 = File("src/test/resources/example.cc.json") val validFile2 = File("src/test/resources/example_api_version_1.3.cc.json") val validFile3 = File("src/test/resources/exampleUncompressed.txt") val inputFiles = arrayOf(validFile1, validFile2, validFile3) - val result = InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, canInputContainFolders) + val result = InputHelper.getFileListFromValidatedResourceArray(inputFiles) - Assertions.assertThat(result).contains(validFile1) - Assertions.assertThat(result).contains(validFile2) - Assertions.assertThat(result).contains(validFile3) + Assertions.assertThat(validFile1) + Assertions.assertThat(validFile2) + Assertions.assertThat(validFile3) Assertions.assertThat(result.size).isEqualTo(inputFiles.size) } - @ParameterizedTest - @MethodSource("provideOneFlagArgument") - fun `should return list of all contained input files in valid directory`(canInputBePiped: Boolean) { + @Test + fun `should return list of all input files in valid directory`() { val validDirectory = File("src/test/resources/inputFiles") val amountOfFilesInDirectory = 2 val inputFiles = arrayOf(validDirectory) - val result = InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, true) + val result = InputHelper.getFileListFromValidatedResourceArray(inputFiles) Assertions.assertThat(result).contains(File("src/test/resources/inputFiles/dummyFile1.txt")) Assertions.assertThat(result).contains(File("src/test/resources/inputFiles/dummyFile2.txt")) // Subtract directory as file in list, add number of files in directory - Assertions.assertThat(result.size).isEqualTo(inputFiles.size - 1 + amountOfFilesInDirectory) + Assertions.assertThat(result.size).isEqualTo(amountOfFilesInDirectory) } @ParameterizedTest @MethodSource("provideOneFlagArgument") - fun `should throw exception if folder is given with no-folder-flag`(canInputBePiped: Boolean) { + fun `should return invalid if folder is given with no-folder-flag`(canInputBePiped: Boolean) { val validDirectory = File("src/test/resources/inputFiles") val inputFiles = arrayOf(validDirectory) System.setErr(PrintStream(errContent)) - Assertions.assertThatIllegalArgumentException() - .isThrownBy { InputHelper.getInputFileListIfValid(inputFiles, canInputBePiped, false) } + val result = InputHelper.isInputValid(inputFiles, canInputBePiped, false) System.setErr(originalErr) + Assertions.assertThat(result).isFalse() Assertions.assertThat(errContent.toString()) .contains("Input folder where only files are allowed!") } From 06a8af41791dd7b5bcd830f2c3821f0805af7d10 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Wed, 31 May 2023 17:21:50 +0200 Subject: [PATCH 05/19] Add input check and tests to all other parsers #3307 --- .../codecharta/importer/csv/CSVImporter.kt | 8 ++++ .../sourcemonitor/SourceMonitorImporter.kt | 9 ++++ .../importer/csv/CSVImporterTest.kt | 31 ++++++++++++++ .../SourceMonitorImporterTest.kt | 32 +++++++++++++++ .../importer/codemaat/CodeMaatImporter.kt | 9 ++++ .../importer/codemaat/CodeMaatImporterTest.kt | 30 ++++++++++++++ .../subcommands/LogScanCommand.kt | 10 +++++ .../subcommands/RepoScanCommand.kt | 10 +++++ .../subcommands/LogScanCommandTest.kt | 40 ++++++++++++++++++ .../subcommands/RepoScanCommandTest.kt | 39 ++++++++++++++++++ .../MetricGardenerImporter/build.gradle | 1 - .../MetricGardenerImporter.kt | 13 ++---- .../MetricGardenerImporterTest.kt | 33 +++++++++++++++ .../importer/svnlogparser/SVNLogParser.kt | 41 ++++--------------- .../importer/svnlogparser/SVNLogParserTest.kt | 31 ++++++++++++++ .../importer/sonar/SonarImporterMain.kt | 3 +- .../sourcecodeparser/SourceCodeParserMain.kt | 9 ++-- .../SourceCodeParserMainTest.kt | 31 ++++++++++++++ .../sourcecodeparser/e2e/FileDoesNotExist.kt | 20 --------- .../importer/tokeiimporter/TokeiImporter.kt | 10 +++++ .../tokeiimporter/TokeiImporterTest.kt | 28 +++++++++++++ .../parser/rawtextparser/RawTextParser.kt | 15 +++---- .../RawTextParserTest.kt | 28 +++++++++++++ .../tools/validation/ValidationTool.kt | 9 ++++ .../tools/validation/EveritValidatorTest.kt | 32 +++++++++++++++ 25 files changed, 443 insertions(+), 79 deletions(-) create mode 100644 analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommandTest.kt create mode 100644 analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommandTest.kt delete mode 100644 analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/e2e/FileDoesNotExist.kt diff --git a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt index 8c25b91b80..37979a5ca7 100644 --- a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt +++ b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt @@ -4,6 +4,8 @@ import de.maibornwolff.codecharta.serialization.ProjectSerializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper +import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.IOException @@ -43,6 +45,10 @@ class CSVImporter( @Throws(IOException::class) override fun call(): Void? { + if (!InputHelper.isInputValid(files.toTypedArray(), canInputBePiped = false, canInputContainFolders = false)) { + logger.error("Input invalid file for CSVImporter, stopping execution...") + return null + } val csvProjectBuilder = CSVProjectBuilder(pathSeparator, csvDelimiter, pathColumnName) files.map { it.inputStream() }.forEach { csvProjectBuilder.parseCSVStream(it) } @@ -54,6 +60,8 @@ class CSVImporter( } companion object { + private val logger = KotlinLogging.logger {} + @JvmStatic fun main(args: Array) { CommandLine(CSVImporter()).execute(*args) diff --git a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt index 3674ed0057..40bc57c1bb 100644 --- a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt +++ b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt @@ -6,6 +6,8 @@ import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.translator.MetricNameTranslator +import de.maibornwolff.codecharta.util.InputHelper +import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.IOException @@ -40,6 +42,11 @@ class SourceMonitorImporter( @Throws(IOException::class) override fun call(): Void? { + if (!InputHelper.isInputValid(files.toTypedArray(), canInputBePiped = false, canInputContainFolders = false)) { + logger.error("Input invalid file for SourceMonitorImporter, stopping execution...") + return null + } + val csvProjectBuilder = CSVProjectBuilder(pathSeparator, csvDelimiter, "File Name", sourceMonitorReplacement, getAttributeDescriptors()) files.map { it.inputStream() }.forEach { csvProjectBuilder.parseCSVStream(it) } @@ -78,6 +85,8 @@ class SourceMonitorImporter( } companion object { + private val logger = KotlinLogging.logger {} + @JvmStatic fun main(args: Array) { CommandLine(SourceMonitorImporter()).execute(*args) diff --git a/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporterTest.kt b/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporterTest.kt index ddf34c9185..160b4aefb5 100644 --- a/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporterTest.kt +++ b/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporterTest.kt @@ -1,14 +1,30 @@ package de.maibornwolff.codecharta.importer.csv import de.maibornwolff.codecharta.importer.csv.CSVImporter.Companion.main +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance import org.skyscreamer.jsonassert.JSONAssert import org.skyscreamer.jsonassert.JSONCompareMode +import java.io.ByteArrayOutputStream import java.io.File +import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class CSVImporterTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterEach + fun afterTest() { + unmockkAll() + } @Test fun `should create json uncompressed file`() { @@ -65,4 +81,19 @@ class CSVImporterTest { assertThat(file.readText()).contains(listOf("\"Lines\":44.0")) } + + @Test + fun `should stop execution if input file is invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + main(arrayOf("thisDoesNotExist.cc.json")) + System.setErr(originalErr) + + assertThat(errContent.toString()) + .contains("Input invalid file for CSVImporter, stopping execution") + } } diff --git a/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporterTest.kt b/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporterTest.kt index f255f46591..7334322e3a 100644 --- a/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporterTest.kt +++ b/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporterTest.kt @@ -2,12 +2,29 @@ package de.maibornwolff.codecharta.importer.sourcemonitor import de.maibornwolff.codecharta.importer.sourcemonitor.SourceMonitorImporter.Companion.main import de.maibornwolff.codecharta.serialization.ProjectDeserializer +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import java.io.ByteArrayOutputStream import java.io.File +import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class SourceMonitorImporterTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterEach + fun afterTest() { + unmockkAll() + } @Test fun `should create json uncompressed file`() { @@ -49,4 +66,19 @@ class SourceMonitorImporterTest { file.deleteOnExit() assertEquals(project.attributeDescriptors, getAttributeDescriptors()) } + + @Test + fun `should stop execution if input file is invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + main(arrayOf("thisDoesNotExist.cc.json")) + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()) + .contains("Input invalid file for SourceMonitorImporter, stopping execution") + } } diff --git a/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt b/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt index 1ddd936775..de819529d3 100644 --- a/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt +++ b/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt @@ -7,6 +7,8 @@ import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.translator.MetricNameTranslator +import de.maibornwolff.codecharta.util.InputHelper +import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.IOException @@ -40,6 +42,11 @@ class CodeMaatImporter( @Throws(IOException::class) override fun call(): Void? { + if (!InputHelper.isInputValid(files.toTypedArray(), canInputBePiped = false, canInputContainFolders = false)) { + logger.error("Input invalid file for CodeMaatImporter, stopping execution...") + return null + } + val csvProjectBuilder = CSVProjectBuilder(pathSeparator, csvDelimiter, codemaatReplacement, attributeTypes, getAttributeDescriptors()) files.map { it.inputStream() }.forEach { csvProjectBuilder.parseCSVStream(it) } @@ -73,6 +80,8 @@ class CodeMaatImporter( } companion object { + private val logger = KotlinLogging.logger {} + @JvmStatic fun main(args: Array) { CommandLine(CodeMaatImporter()).execute(*args) diff --git a/analysis/import/CodeMaatImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporterTest.kt b/analysis/import/CodeMaatImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporterTest.kt index 5322878dd1..59e9ae8116 100644 --- a/analysis/import/CodeMaatImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporterTest.kt +++ b/analysis/import/CodeMaatImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporterTest.kt @@ -2,13 +2,29 @@ package de.maibornwolff.codecharta.importer.codemaat import de.maibornwolff.codecharta.importer.codemaat.CodeMaatImporter.Companion.main import de.maibornwolff.codecharta.serialization.ProjectDeserializer +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import java.io.ByteArrayOutputStream import java.io.File +import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class CodeMaatImporterTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterEach + fun afterTest() { + unmockkAll() + } @Test fun `should create json uncompressed file`() { @@ -55,4 +71,18 @@ class CodeMaatImporterTest { assertThat(file.readText()).contains(listOf("attributeDescriptors", "\"description\":\"Average")) assertEquals(ProjectDeserializer.deserializeProject(file.reader()).attributeDescriptors, getAttributeDescriptors()) } + + @Test + fun `should stop execution if input file is invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + main(arrayOf("thisDoesNotExist.cc.json")) + System.setErr(originalErr) + + assertThat(errContent.toString()).contains("Input invalid file for CodeMaatImporter, stopping execution") + } } diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt index b7c6fef01d..7a4075948f 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt @@ -3,6 +3,8 @@ package de.maibornwolff.codecharta.importer.gitlogparser.subcommands import de.maibornwolff.codecharta.importer.gitlogparser.GitLogParser import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface +import de.maibornwolff.codecharta.util.InputHelper +import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.util.concurrent.Callable @@ -52,7 +54,15 @@ class LogScanCommand : Callable, InteractiveParser { @CommandLine.Option(names = ["--add-author"], description = ["add an array of authors to every file"]) private var addAuthor = false + companion object { + private val logger = KotlinLogging.logger {} + } + override fun call(): Void? { + if (gitLogFile == null || !InputHelper.isInputValid(arrayOf(gitLogFile!!), canInputBePiped = false, canInputContainFolders = false)) { + logger.error("Input invalid file for GitLogScan, stopping execution...") + return null + } GitLogParser().buildProject(gitLogFile!!, gitLsFile!!, outputFilePath, addAuthor, silent, compress) return null } diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt index eda0f4e946..c523529ed9 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt @@ -4,6 +4,8 @@ import de.maibornwolff.codecharta.importer.gitlogparser.GitLogParser import de.maibornwolff.codecharta.importer.gitlogparser.util.GitAdapter import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface +import de.maibornwolff.codecharta.util.InputHelper +import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.FileWriter @@ -45,12 +47,20 @@ class RepoScanCommand : Callable, InteractiveParser { @CommandLine.Option(names = ["--add-author"], description = ["add an array of authors to every file"]) private var addAuthor = false + companion object { + private val logger = KotlinLogging.logger {} + } + override fun call(): Void? { val repoPath: Path if (repoPathName.isNullOrBlank()) { println("--repo-path not set, aborting...") return null } else { + if (!InputHelper.isInputValid(arrayOf(File(repoPathName!!)), canInputBePiped = false, canInputContainFolders = true)) { + logger.error("Input invalid file for GitRepoScan, stopping execution...") + return null + } repoPath = Paths.get(repoPathName!!).normalize().toAbsolutePath() } println("Creating git.log file...") diff --git a/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommandTest.kt b/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommandTest.kt new file mode 100644 index 0000000000..c4a4a7195d --- /dev/null +++ b/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommandTest.kt @@ -0,0 +1,40 @@ +package de.maibornwolff.codecharta.importer.gitlogparser.subcommands + +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import picocli.CommandLine +import java.io.ByteArrayOutputStream +import java.io.PrintStream + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class LogScanCommandTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterAll + fun afterTest() { + unmockkAll() + } + + @Test + fun `should stop execution if input files are invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(LogScanCommand()).execute( + "--git-log=thisDoesNotExist.cc.json", + "--repo-files=thisDoesNotExist").toString() + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()).contains("Input invalid file for GitLogScan, stopping execution") + } +} diff --git a/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommandTest.kt b/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommandTest.kt new file mode 100644 index 0000000000..3cab2e0dbc --- /dev/null +++ b/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommandTest.kt @@ -0,0 +1,39 @@ +package de.maibornwolff.codecharta.importer.gitlogparser.subcommands + +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import picocli.CommandLine +import java.io.ByteArrayOutputStream +import java.io.PrintStream + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class RepoScanCommandTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterAll + fun afterTest() { + unmockkAll() + } + + @Test + fun `should stop execution if input files are invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(RepoScanCommand()).execute( + "--repo-path=thisDoesNotExist").toString() + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()).contains("Input invalid file for GitRepoScan, stopping execution") + } +} diff --git a/analysis/import/MetricGardenerImporter/build.gradle b/analysis/import/MetricGardenerImporter/build.gradle index 5d4ade5b42..77478958bc 100644 --- a/analysis/import/MetricGardenerImporter/build.gradle +++ b/analysis/import/MetricGardenerImporter/build.gradle @@ -1,6 +1,5 @@ dependencies { implementation project(':tools:InteractiveParser') - implementation project(':import:SourceCodeParser') implementation project(':model') implementation group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.2.21' diff --git a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt index 079593b777..442afe28b2 100644 --- a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt +++ b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt @@ -9,6 +9,7 @@ import de.maibornwolff.codecharta.serialization.ProjectSerializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper import de.maibornwolff.codecharta.util.ResourceSearchHelper import mu.KotlinLogging import picocli.CommandLine @@ -16,7 +17,6 @@ import java.io.File import java.io.IOException import java.io.PrintStream import java.nio.charset.Charset -import java.nio.file.Paths import java.util.concurrent.Callable @CommandLine.Command( @@ -55,10 +55,11 @@ class MetricGardenerImporter( @Throws(IOException::class) override fun call(): Void? { - if (!inputFile.exists()) { - printErrorLog() + if (!InputHelper.isInputValid(arrayOf(inputFile), canInputBePiped = true, canInputContainFolders = true)) { + logger.error("Input invalid file for MetricGardenerImporter, stopping execution...") return null } + if (!isJsonFile) { val tempMgOutput = File.createTempFile("MGOutput", ".json") tempMgOutput.deleteOnExit() @@ -85,12 +86,6 @@ class MetricGardenerImporter( return null } - private fun printErrorLog() { - val path = Paths.get("").toAbsolutePath().toString() - logger.error { "Current working directory = $path" } - logger.error { "Could not find $inputFile" } - } - companion object { @JvmStatic fun main(args: Array) { diff --git a/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt b/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt index 6256c1062e..7fd83d77e8 100644 --- a/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt +++ b/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt @@ -2,18 +2,35 @@ package de.maibornwolff.codecharta.importer.metricgardenerimporter import de.maibornwolff.codecharta.importer.metricgardenerimporter.MetricGardenerImporter.Companion.main import de.maibornwolff.codecharta.serialization.ProjectDeserializer +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource import picocli.CommandLine +import java.io.ByteArrayOutputStream import java.io.File +import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class MetricGardenerImporterTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterEach + fun afterTest() { + unmockkAll() + } companion object { @JvmStatic @@ -108,4 +125,20 @@ class MetricGardenerImporterTest { val isUsable = MetricGardenerImporter().isApplicable(resourceToBeParsed) Assertions.assertThat(isUsable).isFalse() } + + // TODO: Fix this test + @Disabled + @Test + fun `should stop execution if input files are invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(MetricGardenerImporter()).execute("thisDoesNotExist").toString() + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()).contains("Input invalid file for MetricGardenerImporter, stopping execution") + } } diff --git a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt index 05669f0139..f8cd01120a 100644 --- a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt +++ b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt @@ -12,10 +12,9 @@ import de.maibornwolff.codecharta.serialization.ProjectSerializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper import de.maibornwolff.codecharta.util.ResourceSearchHelper -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking +import mu.KotlinLogging import org.mozilla.universalchardet.UniversalDetector import picocli.CommandLine import java.io.File @@ -82,8 +81,13 @@ class SVNLogParser( @Throws(IOException::class) override fun call(): Void? { - print(" ") + + if (file == null || !InputHelper.isInputValid(arrayOf(file!!), canInputBePiped = true, canInputContainFolders = false)) { + logger.error("Input invalid file for SVNLogParser, stopping execution...") + return null + } + var project = createProjectFromLog( file!!, logParserStrategy, @@ -123,35 +127,8 @@ class SVNLogParser( ).parse(lines) } - // not implemented yet. - private fun printUsage() { - println("----") - printLogCreation() - - println("----") - printMetricInfo() - } - - private fun printLogCreation() { - println(" Log creation via:") - - println(String.format(" \t%s :\t\"%s\".", inputFormatNames, logParserStrategy.creationCommand())) - } - - private fun printMetricInfo() { - val infoFormat = " \t%s:\t %s" - println(" Available metrics:") - runBlocking(Dispatchers.Default) { - metricsFactory.createMetrics() - .forEach { - launch { - println(String.format(infoFormat, it.metricName(), it.description())) - } - } - } - } - companion object { + private val logger = KotlinLogging.logger {} @JvmStatic fun main(args: Array) { CommandLine(SVNLogParser()).execute(*args) diff --git a/analysis/import/SVNLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParserTest.kt b/analysis/import/SVNLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParserTest.kt index e1c0288a10..deffa4c928 100644 --- a/analysis/import/SVNLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParserTest.kt +++ b/analysis/import/SVNLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParserTest.kt @@ -1,15 +1,32 @@ package de.maibornwolff.codecharta.importer.svnlogparser import de.maibornwolff.codecharta.importer.svnlogparser.SVNLogParser.Companion.main +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource +import picocli.CommandLine +import java.io.ByteArrayOutputStream import java.io.File +import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class SVNLogParserTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterEach + fun afterTest() { + unmockkAll() + } companion object { @JvmStatic @@ -75,4 +92,18 @@ class SVNLogParserTest { val isUsable = SVNLogParser().isApplicable(resourceToBeParsed) Assertions.assertThat(isUsable).isFalse() } + + @Test + fun `should stop execution if input files are invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(SVNLogParser()).execute("thisDoesNotExist.cc.json").toString() + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()).contains("Input invalid file for SVNLogParser, stopping execution") + } } diff --git a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt index a89e1c6c5d..6c37e7f15e 100644 --- a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt +++ b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt @@ -38,7 +38,7 @@ class SonarImporterMain( ) private var help = false - @CommandLine.Parameters(index = "0", paramLabel = "URL", description = ["url of sonarqube server"]) + @CommandLine.Parameters(index = "0", arity = "1", paramLabel = "URL", description = ["url of sonarqube server"]) private var url: String = "http://localhost" @CommandLine.Parameters( @@ -81,7 +81,6 @@ class SonarImporterMain( } override fun call(): Void? { - val importer = createMeasuresAPIImporter() var project = importer.getProjectFromMeasureAPI(projectId, metrics) diff --git a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt index 218ac64f49..9a416e415d 100644 --- a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt +++ b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt @@ -8,6 +8,7 @@ import de.maibornwolff.codecharta.serialization.ProjectDeserializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper import de.maibornwolff.codecharta.util.ResourceSearchHelper import picocli.CommandLine import java.io.BufferedWriter @@ -19,7 +20,6 @@ import java.io.OutputStreamWriter import java.io.PrintStream import java.io.PrintWriter import java.io.Writer -import java.nio.file.Paths import java.util.concurrent.Callable @CommandLine.Command( @@ -73,12 +73,9 @@ class SourceCodeParserMain( @Throws(IOException::class) override fun call(): Void? { - print(" ") - if (!file.exists()) { - val path = Paths.get("").toAbsolutePath().toString() - error.println("Current working directory = $path") - error.println("Could not find $file") + if (!InputHelper.isInputValid(arrayOf(file), canInputBePiped = true, canInputContainFolders = true)) { + System.err.println("Input invalid file for SourceCodeParser, stopping execution...") return null } diff --git a/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt b/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt index eba6ae6893..72600994ab 100644 --- a/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt +++ b/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt @@ -1,12 +1,29 @@ package de.maibornwolff.codecharta.importer.sourcecodeparser +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource +import picocli.CommandLine +import java.io.ByteArrayOutputStream +import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class SourceCodeParserMainTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + @AfterEach + fun afterTest() { + unmockkAll() + } companion object { @JvmStatic fun provideValidInputFiles(): List { @@ -39,4 +56,18 @@ class SourceCodeParserMainTest { val isUsable = SourceCodeParserMain().isApplicable(resourceToBeParsed) Assertions.assertThat(isUsable).isFalse() } + + @Test + fun `should stop execution if input files are invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(SourceCodeParserMain()).execute("thisDoesNotExist").toString() + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()).contains("Input invalid file for SourceCodeParser, stopping execution") + } } diff --git a/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/e2e/FileDoesNotExist.kt b/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/e2e/FileDoesNotExist.kt deleted file mode 100644 index d7d8ba8dea..0000000000 --- a/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/e2e/FileDoesNotExist.kt +++ /dev/null @@ -1,20 +0,0 @@ -package de.maibornwolff.codecharta.importer.sourcecodeparser.e2e - -import de.maibornwolff.codecharta.importer.sourcecodeparser.SourceCodeParserMain -import de.maibornwolff.codecharta.importer.sourcecodeparser.e2e.StreamHelper.Companion.retrieveStreamAsString -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -class FileDoesNotExist { - private val resource = "src/test/resources/sampleproject/folder/does/not/exist/Foo.java" - - private val outputStream = retrieveStreamAsString { - SourceCodeParserMain.mainWithInOut(it, System.`in`, it, arrayOf(resource, "-out=table")) - } - - @Test - fun `prints working directory if file not found`() { - assertThat(outputStream.lines()[0]).contains("working directory") - assertThat(outputStream.lines()[1]).contains("Could not find") - } -} diff --git a/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt b/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt index d0ae61a5ae..deba3e077d 100644 --- a/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt +++ b/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt @@ -13,6 +13,7 @@ import de.maibornwolff.codecharta.serialization.mapLines import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -61,6 +62,7 @@ class TokeiImporter( @CommandLine.Option(names = ["-nc", "--not-compressed"], description = ["save uncompressed output File"]) private var compress = true + // TODO: Why is 0 allowed? @CommandLine.Parameters(arity = "0..1", paramLabel = "FILE", description = ["tokei generated json"]) private var file: File? = null @@ -69,6 +71,14 @@ class TokeiImporter( @Throws(IOException::class) override fun call(): Void? { print(" ") + + if (file == null) { + // do not do anything, if null there could come piped input + } else if (!InputHelper.isInputValid(arrayOf(file!!), canInputBePiped = true, canInputContainFolders = false)) { + logger.error("Input invalid file for TokeiImporter, stopping execution...") + return null + } + projectBuilder = ProjectBuilder() val root = getInput() ?: return null runBlocking(Dispatchers.Default) { diff --git a/analysis/import/TokeiImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporterTest.kt b/analysis/import/TokeiImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporterTest.kt index a436218673..7a870ca8a8 100644 --- a/analysis/import/TokeiImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporterTest.kt +++ b/analysis/import/TokeiImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporterTest.kt @@ -3,16 +3,30 @@ package de.maibornwolff.codecharta.importer.tokeiimporter import de.maibornwolff.codecharta.importer.tokeiimporter.TokeiImporter.Companion.mainWithInOut import de.maibornwolff.codecharta.model.AttributeType import de.maibornwolff.codecharta.serialization.ProjectDeserializer +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import picocli.CommandLine import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File import java.io.InputStream import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class TokeiImporterTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + @AfterEach + fun afterTest() { + unmockkAll() + } @Test fun `reads tokei from file`() { val cliResult = executeForOutput("", arrayOf("src/test/resources/tokei_results.json", "--path-separator=\\")) @@ -122,6 +136,20 @@ class TokeiImporterTest { val project = ProjectDeserializer.deserializeProject(cliResult) Assertions.assertThat(project.attributeDescriptors).isEqualTo(getAttributeDescriptors()) } + + @Test + fun `should stop execution if input files are invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(TokeiImporter()).execute("thisDoesNotExist.cc.json").toString() + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()).contains("Input invalid file for TokeiImporter, stopping execution") + } } fun executeForOutput(input: String, args: Array = emptyArray()) = diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index 986a49d552..67b1d87b8b 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -7,13 +7,15 @@ import de.maibornwolff.codecharta.serialization.ProjectSerializer import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper +import de.maibornwolff.codecharta.util.ResourceSearchHelper +import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.IOException import java.io.InputStream import java.io.PrintStream import java.io.PrintWriter -import java.nio.file.Paths import java.util.concurrent.Callable @CommandLine.Command( @@ -75,8 +77,8 @@ class RawTextParser( @Throws(IOException::class) override fun call(): Void? { print(" ") - if (!inputFile.exists()) { - fileNotExistentMessage() + if (!InputHelper.isInputValid(arrayOf(inputFile), canInputBePiped = true, canInputContainFolders = true)) { + logger.error("Input invalid file for RawTextParser, stopping execution...") return null } @@ -94,12 +96,6 @@ class RawTextParser( return null } - private fun fileNotExistentMessage() { - val path = Paths.get("").toAbsolutePath().toString() - error.println("Current working directory = $path") - error.println("Could not find $inputFile") - } - private fun assembleParameterMap(): Map { return mapOf( "verbose" to verbose.toInt(), @@ -109,6 +105,7 @@ class RawTextParser( } companion object { + private val logger = KotlinLogging.logger {} @JvmStatic fun mainWithInOut(outputStream: PrintStream, input: InputStream, error: PrintStream, args: Array) { CommandLine(RawTextParser(input, outputStream, error)).setOut(PrintWriter(outputStream)).execute(*args) diff --git a/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt b/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt index a2d99cba9c..86bf633f54 100644 --- a/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt +++ b/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt @@ -6,11 +6,18 @@ import de.maibornwolff.codecharta.parser.rawtextparser.RawTextParser import de.maibornwolff.codecharta.parser.rawtextparser.RawTextParser.Companion.mainWithInOut import de.maibornwolff.codecharta.serialization.ProjectDeserializer import de.maibornwolff.codecharta.serialization.ProjectSerializer +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll import org.assertj.core.api.Assertions +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource +import picocli.CommandLine import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File @@ -18,8 +25,15 @@ import java.io.InputStream import java.io.OutputStreamWriter import java.io.PrintStream +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class RawTextParserTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + @AfterEach + fun afterTest() { + unmockkAll() + } companion object { @JvmStatic fun provideValidInputFiles(): List { @@ -125,4 +139,18 @@ class RawTextParserTest { Assertions.assertThat(isNonExistentPathApplicable).isFalse() Assertions.assertThat(isEmptyStringApplicable).isFalse() } + + @Test + fun `should stop execution if input files are invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(RawTextParser()).execute("thisDoesNotExist.cc.json").toString() + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()).contains("Input invalid file for RawTextParser, stopping execution") + } } diff --git a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt index 77e948f0e6..33f91bf46d 100644 --- a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt +++ b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt @@ -3,6 +3,8 @@ package de.maibornwolff.codecharta.tools.validation import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper +import de.maibornwolff.codecharta.util.InputHelper +import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.FileInputStream @@ -22,12 +24,19 @@ class ValidationTool : Callable, InteractiveParser { var file: String = "" override fun call(): Void? { + if (!InputHelper.isInputValid(arrayOf(File(file)), canInputBePiped = false, canInputContainFolders = false)) { + logger.error("Input invalid file for ValidationTool, stopping execution...") + return null + } + EveritValidator(SCHEMA_PATH).validate(FileInputStream(File(file).absoluteFile)) return null } companion object { + private val logger = KotlinLogging.logger {} + const val SCHEMA_PATH = "cc.json" } diff --git a/analysis/tools/ValidationTool/src/test/kotlin/de/maibornwolff/codecharta/tools/validation/EveritValidatorTest.kt b/analysis/tools/ValidationTool/src/test/kotlin/de/maibornwolff/codecharta/tools/validation/EveritValidatorTest.kt index 9e203f524a..0b96970db9 100644 --- a/analysis/tools/ValidationTool/src/test/kotlin/de/maibornwolff/codecharta/tools/validation/EveritValidatorTest.kt +++ b/analysis/tools/ValidationTool/src/test/kotlin/de/maibornwolff/codecharta/tools/validation/EveritValidatorTest.kt @@ -1,11 +1,29 @@ package de.maibornwolff.codecharta.tools.validation +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll +import org.assertj.core.api.Assertions import org.everit.json.schema.ValidationException import org.json.JSONException +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import picocli.CommandLine +import java.io.ByteArrayOutputStream +import java.io.PrintStream import kotlin.test.assertFailsWith +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class EveritValidatorTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterEach + fun afterTest() { + unmockkAll() + } private val validator = EveritValidator(ValidationTool.SCHEMA_PATH) @@ -53,4 +71,18 @@ class EveritValidatorTest { validator.validate(this.javaClass.classLoader.getResourceAsStream("invalidJson.json")) } } + + @Test + fun `should stop execution if input files are invalid`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(ValidationTool()).execute("thisDoesNotExist.cc.json").toString() + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()).contains("Input invalid file for ValidationTool, stopping execution") + } } From caf0a9f31b608f150e1fc0bae9ba44c5dfc302c0 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Fri, 2 Jun 2023 12:21:49 +0200 Subject: [PATCH 06/19] Remove empty input allowed if pipeable #3307 --- .../codecharta/exporter/csv/CSVExporter.kt | 2 +- .../exporter/csvexporter/CSVExporterTest.kt | 2 +- .../filter/edgefilter/EdgeFilter.kt | 2 +- .../filter/edgefilter/EdgeFilterTest.kt | 4 +- .../filter/mergefilter/MergeFilter.kt | 2 +- .../filter/mergefilter/MergeFilterTest.kt | 2 +- .../structuremodifier/StructureModifier.kt | 2 +- .../StructureModifierTest.kt | 2 +- .../codecharta/importer/csv/CSVImporter.kt | 2 +- .../sourcemonitor/SourceMonitorImporter.kt | 2 +- .../importer/csv/CSVImporterTest.kt | 2 +- .../SourceMonitorImporterTest.kt | 2 +- .../importer/codemaat/CodeMaatImporter.kt | 2 +- .../importer/codemaat/CodeMaatImporterTest.kt | 2 +- .../subcommands/LogScanCommand.kt | 2 +- .../subcommands/RepoScanCommand.kt | 2 +- .../subcommands/LogScanCommandTest.kt | 2 +- .../subcommands/RepoScanCommandTest.kt | 2 +- .../MetricGardenerImporter.kt | 2 +- .../MetricGardenerImporterTest.kt | 2 +- .../importer/svnlogparser/SVNLogParser.kt | 2 +- .../importer/svnlogparser/SVNLogParserTest.kt | 2 +- .../sourcecodeparser/SourceCodeParserMain.kt | 2 +- .../SourceCodeParserMainTest.kt | 2 +- .../importer/tokeiimporter/TokeiImporter.kt | 2 +- .../tokeiimporter/TokeiImporterTest.kt | 2 +- .../codecharta/util/InputHelper.kt | 9 +-- .../codecharta/util/InputHelperTest.kt | 69 ++++++++----------- .../parser/rawtextparser/RawTextParser.kt | 2 +- .../RawTextParserTest.kt | 2 +- .../tools/validation/ValidationTool.kt | 2 +- .../tools/validation/EveritValidatorTest.kt | 2 +- 32 files changed, 63 insertions(+), 77 deletions(-) diff --git a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt index ebef0c220d..975c277dc2 100644 --- a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt +++ b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt @@ -52,7 +52,7 @@ class CSVExporter : Callable, InteractiveParser { throw IllegalArgumentException("depth-of-hierarchy must not be negative") } - if (!InputHelper.isInputValid(sources, canInputBePiped = false, canInputContainFolders = false)) { + if (!InputHelper.isInputValid(sources, canInputContainFolders = false)) { System.err.println("Input invalid file for CSVExporter, stopping execution...") return null } diff --git a/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt b/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt index cdb9ca76bc..329de469ed 100644 --- a/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt +++ b/analysis/export/CSVExporter/src/test/kotlin/de/maibornwolff/codecharta/exporter/csvexporter/CSVExporterTest.kt @@ -27,7 +27,7 @@ class CSVExporterTest { fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt index 74a15d968a..e0247f415b 100644 --- a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt +++ b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt @@ -34,7 +34,7 @@ class EdgeFilter( private var outputFile: String? = null override fun call(): Void? { - if (!InputHelper.isInputValid(arrayOf(source), canInputBePiped = true, canInputContainFolders = false)) { + if (!InputHelper.isInputValid(arrayOf(source), canInputContainFolders = false)) { logger.error("Input invalid file for EdgeFilter, stopping execution...") return null } diff --git a/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt b/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt index 0b96c3133e..2bf8b529da 100644 --- a/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt +++ b/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt @@ -28,7 +28,7 @@ class EdgeFilterTest { fun `should create json uncompressed file`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns true main( @@ -46,7 +46,7 @@ class EdgeFilterTest { fun `should stop execution if input file is invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt index 23b79d316f..f229bd1b67 100644 --- a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt +++ b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt @@ -58,7 +58,7 @@ class MergeFilter( ) } - if (!InputHelper.isInputValid(sources, canInputBePiped = true, canInputContainFolders = true)) { + if (!InputHelper.isInputValid(sources, canInputContainFolders = true)) { logger.error("Input invalid files/folders for MergeFilter, stopping execution...") return null } diff --git a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt index 841ad3d698..e33c2600ea 100644 --- a/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt +++ b/analysis/filter/MergeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilterTest.kt @@ -97,7 +97,7 @@ class MergeFilterTest { fun `should not execute merge if input is invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index 79a3039f65..56c3fe0514 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -82,7 +82,7 @@ class StructureModifier( } // Can not be piped here, because that case is already covered by the previous check (source == null) - if (!InputHelper.isInputValid(arrayOf(source!!), canInputBePiped = false, canInputContainFolders = false)) { + if (!InputHelper.isInputValid(arrayOf(source!!), canInputContainFolders = false)) { logger.error("Input invalid file for StructureModifier, stopping execution...") return null } diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt index 78f0551b66..6f5d7bdc53 100644 --- a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt +++ b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt @@ -134,7 +134,7 @@ class StructureModifierTest { fun `should stop execution if input file is invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt index 37979a5ca7..e319479f79 100644 --- a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt +++ b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt @@ -45,7 +45,7 @@ class CSVImporter( @Throws(IOException::class) override fun call(): Void? { - if (!InputHelper.isInputValid(files.toTypedArray(), canInputBePiped = false, canInputContainFolders = false)) { + if (!InputHelper.isInputValid(files.toTypedArray(), canInputContainFolders = false)) { logger.error("Input invalid file for CSVImporter, stopping execution...") return null } diff --git a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt index 40bc57c1bb..91fe72cd97 100644 --- a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt +++ b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt @@ -42,7 +42,7 @@ class SourceMonitorImporter( @Throws(IOException::class) override fun call(): Void? { - if (!InputHelper.isInputValid(files.toTypedArray(), canInputBePiped = false, canInputContainFolders = false)) { + if (!InputHelper.isInputValid(files.toTypedArray(), canInputContainFolders = false)) { logger.error("Input invalid file for SourceMonitorImporter, stopping execution...") return null } diff --git a/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporterTest.kt b/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporterTest.kt index 160b4aefb5..45f91cddea 100644 --- a/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporterTest.kt +++ b/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporterTest.kt @@ -86,7 +86,7 @@ class CSVImporterTest { fun `should stop execution if input file is invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporterTest.kt b/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporterTest.kt index 7334322e3a..ecf2756d16 100644 --- a/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporterTest.kt +++ b/analysis/import/CSVImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporterTest.kt @@ -71,7 +71,7 @@ class SourceMonitorImporterTest { fun `should stop execution if input file is invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt b/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt index de819529d3..d51771848c 100644 --- a/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt +++ b/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt @@ -42,7 +42,7 @@ class CodeMaatImporter( @Throws(IOException::class) override fun call(): Void? { - if (!InputHelper.isInputValid(files.toTypedArray(), canInputBePiped = false, canInputContainFolders = false)) { + if (!InputHelper.isInputValid(files.toTypedArray(), canInputContainFolders = false)) { logger.error("Input invalid file for CodeMaatImporter, stopping execution...") return null } diff --git a/analysis/import/CodeMaatImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporterTest.kt b/analysis/import/CodeMaatImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporterTest.kt index 59e9ae8116..167e3b9eae 100644 --- a/analysis/import/CodeMaatImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporterTest.kt +++ b/analysis/import/CodeMaatImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporterTest.kt @@ -76,7 +76,7 @@ class CodeMaatImporterTest { fun `should stop execution if input file is invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt index 7a4075948f..947beddc0e 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt @@ -59,7 +59,7 @@ class LogScanCommand : Callable, InteractiveParser { } override fun call(): Void? { - if (gitLogFile == null || !InputHelper.isInputValid(arrayOf(gitLogFile!!), canInputBePiped = false, canInputContainFolders = false)) { + if (gitLogFile == null || !InputHelper.isInputValid(arrayOf(gitLogFile!!), canInputContainFolders = false)) { logger.error("Input invalid file for GitLogScan, stopping execution...") return null } diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt index c523529ed9..bda7cc4f0a 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt @@ -57,7 +57,7 @@ class RepoScanCommand : Callable, InteractiveParser { println("--repo-path not set, aborting...") return null } else { - if (!InputHelper.isInputValid(arrayOf(File(repoPathName!!)), canInputBePiped = false, canInputContainFolders = true)) { + if (!InputHelper.isInputValid(arrayOf(File(repoPathName!!)), canInputContainFolders = true)) { logger.error("Input invalid file for GitRepoScan, stopping execution...") return null } diff --git a/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommandTest.kt b/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommandTest.kt index c4a4a7195d..b57f4ddc8e 100644 --- a/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommandTest.kt +++ b/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommandTest.kt @@ -26,7 +26,7 @@ class LogScanCommandTest { fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommandTest.kt b/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommandTest.kt index 3cab2e0dbc..5bf33701a8 100644 --- a/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommandTest.kt +++ b/analysis/import/GitLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommandTest.kt @@ -26,7 +26,7 @@ class RepoScanCommandTest { fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt index 442afe28b2..65808d65d2 100644 --- a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt +++ b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt @@ -55,7 +55,7 @@ class MetricGardenerImporter( @Throws(IOException::class) override fun call(): Void? { - if (!InputHelper.isInputValid(arrayOf(inputFile), canInputBePiped = true, canInputContainFolders = true)) { + if (!InputHelper.isInputValid(arrayOf(inputFile), canInputContainFolders = true)) { logger.error("Input invalid file for MetricGardenerImporter, stopping execution...") return null } diff --git a/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt b/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt index 7fd83d77e8..f7f82e93e9 100644 --- a/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt +++ b/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt @@ -132,7 +132,7 @@ class MetricGardenerImporterTest { fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt index f8cd01120a..f89cc0fc00 100644 --- a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt +++ b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt @@ -83,7 +83,7 @@ class SVNLogParser( override fun call(): Void? { print(" ") - if (file == null || !InputHelper.isInputValid(arrayOf(file!!), canInputBePiped = true, canInputContainFolders = false)) { + if (file == null || !InputHelper.isInputValid(arrayOf(file!!), canInputContainFolders = false)) { logger.error("Input invalid file for SVNLogParser, stopping execution...") return null } diff --git a/analysis/import/SVNLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParserTest.kt b/analysis/import/SVNLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParserTest.kt index deffa4c928..a7c6d96b43 100644 --- a/analysis/import/SVNLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParserTest.kt +++ b/analysis/import/SVNLogParser/src/test/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParserTest.kt @@ -97,7 +97,7 @@ class SVNLogParserTest { fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt index 9a416e415d..401bfa426a 100644 --- a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt +++ b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt @@ -74,7 +74,7 @@ class SourceCodeParserMain( @Throws(IOException::class) override fun call(): Void? { print(" ") - if (!InputHelper.isInputValid(arrayOf(file), canInputBePiped = true, canInputContainFolders = true)) { + if (!InputHelper.isInputValid(arrayOf(file), canInputContainFolders = true)) { System.err.println("Input invalid file for SourceCodeParser, stopping execution...") return null } diff --git a/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt b/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt index 72600994ab..b70b01dc7d 100644 --- a/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt +++ b/analysis/import/SourceCodeParser/src/test/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMainTest.kt @@ -61,7 +61,7 @@ class SourceCodeParserMainTest { fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt b/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt index deba3e077d..520f855182 100644 --- a/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt +++ b/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt @@ -74,7 +74,7 @@ class TokeiImporter( if (file == null) { // do not do anything, if null there could come piped input - } else if (!InputHelper.isInputValid(arrayOf(file!!), canInputBePiped = true, canInputContainFolders = false)) { + } else if (!InputHelper.isInputValid(arrayOf(file!!), canInputContainFolders = false)) { logger.error("Input invalid file for TokeiImporter, stopping execution...") return null } diff --git a/analysis/import/TokeiImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporterTest.kt b/analysis/import/TokeiImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporterTest.kt index 7a870ca8a8..fc0743eef7 100644 --- a/analysis/import/TokeiImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporterTest.kt +++ b/analysis/import/TokeiImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporterTest.kt @@ -141,7 +141,7 @@ class TokeiImporterTest { fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt index 3c0a1d3568..07987e9675 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt @@ -9,18 +9,13 @@ class InputHelper { /** * Checks if input resources meet a number of requirements: - * If input can not be piped in, the array can not be empty. + * The input array can not be empty. * If input can not contain folders, no element in the list can be a path to a folder. * All elements in the array have to either be existing files or if allowed, folders. */ fun isInputValid(inputResources: Array, - canInputBePiped: Boolean, canInputContainFolders: Boolean): Boolean { - return if (canInputBePiped) { - areInputResourcesValid(inputResources, canInputContainFolders) - } else { - !isInputEmpty(inputResources) && areInputResourcesValid(inputResources, canInputContainFolders) - } + return !isInputEmpty(inputResources) && areInputResourcesValid(inputResources, canInputContainFolders) } private fun isInputEmpty(inputResources: Array): Boolean { diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt index c15230c3b9..a644dd1356 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt @@ -17,16 +17,7 @@ class InputHelperTest { companion object { @JvmStatic - fun providerParserArguments(): List { - return listOf( - Arguments.of(false, false), - Arguments.of(true, false), - Arguments.of(false, true), - Arguments.of(true, true)) - } - - @JvmStatic - fun provideOneFlagArgument(): List { + fun provideBooleanValues(): List { return listOf( Arguments.of(false), Arguments.of(true)) @@ -34,8 +25,8 @@ class InputHelperTest { } @ParameterizedTest - @MethodSource("providerParserArguments") - fun `should output warning for all files which were not found`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { + @MethodSource("provideBooleanValues") + fun `should output warning for all files which were not found`(canInputContainFolders: Boolean) { System.setOut(PrintStream(outContent)) System.setErr(PrintStream(errContent)) @@ -47,7 +38,7 @@ class InputHelperTest { File(invalidFilePath1), File(invalidFilePath2)) try { - InputHelper.isInputValid(inputFiles, canInputBePiped, canInputContainFolders) + InputHelper.isInputValid(inputFiles, canInputContainFolders) } catch (exception: IllegalArgumentException) { // do nothing } @@ -62,24 +53,24 @@ class InputHelperTest { } @ParameterizedTest - @MethodSource("providerParserArguments") - fun `should return invalid if input contains one nonexistent file`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { + @MethodSource("provideBooleanValues") + fun `should return invalid if input contains one nonexistent file`(canInputContainFolders: Boolean) { val inputFiles = arrayOf(File("src/test/resources/example.cc.json"), File("src/test/resources/example_api_version_1.3.cc.json"), File("src/test/resources/thisDoesNotExist1.json")) - val result = InputHelper.isInputValid(inputFiles, canInputBePiped, canInputContainFolders) + val result = InputHelper.isInputValid(inputFiles, canInputContainFolders) Assertions.assertThat(result).isFalse() } @ParameterizedTest - @MethodSource("provideOneFlagArgument") - fun `should return invalid if no files are specified and input can not be piped`(canInputContainFolders: Boolean) { + @MethodSource("provideBooleanValues") + fun `should return invalid if no files are specified`(canInputContainFolders: Boolean) { val inputFiles = arrayOf() System.setErr(PrintStream(errContent)) - val result = InputHelper.isInputValid(inputFiles, canInputBePiped = false, canInputContainFolders) + val result = InputHelper.isInputValid(inputFiles, canInputContainFolders) System.setErr(originalErr) Assertions.assertThat(result).isFalse() @@ -87,25 +78,15 @@ class InputHelperTest { .contains("Did not find any input resources!") } - @ParameterizedTest - @MethodSource("provideOneFlagArgument") - fun `should return valid if no files are specified and input can be piped`(canInputContainFolders: Boolean) { - val inputFiles = arrayOf() - - val result = InputHelper.isInputValid(inputFiles, true, canInputContainFolders) - Assertions.assertThat(result).isTrue() - } - - @ParameterizedTest - @MethodSource("provideOneFlagArgument") - fun `should return invalid if input contains existent but empty directory as input`(canInputBePiped: Boolean) { + @Test + fun `should return invalid if input contains existent but empty directory as input`() { val emptyDirectoryPath = "src/test/resources/emptyDirectory" val emptyTestDirectory = File(emptyDirectoryPath) emptyTestDirectory.mkdir() emptyTestDirectory.deleteOnExit() System.setErr(PrintStream(errContent)) - val result = InputHelper.isInputValid(arrayOf(emptyTestDirectory), canInputBePiped, true) + val result = InputHelper.isInputValid(arrayOf(emptyTestDirectory), true) System.setErr(originalErr) Assertions.assertThat(result).isFalse() @@ -114,15 +95,26 @@ class InputHelperTest { } @ParameterizedTest - @MethodSource("providerParserArguments") - fun `should return valid if input only contains existing files`(canInputBePiped: Boolean, canInputContainFolders: Boolean) { + @MethodSource("provideBooleanValues") + fun `should return valid if input only contains existing files`(canInputContainFolders: Boolean) { val validFile1 = File("src/test/resources/example.cc.json") val validFile2 = File("src/test/resources/example_api_version_1.3.cc.json") val validFile3 = File("src/test/resources/exampleUncompressed.txt") val inputFiles = arrayOf(validFile1, validFile2, validFile3) - val result = InputHelper.isInputValid(inputFiles, canInputBePiped, canInputContainFolders) + val result = InputHelper.isInputValid(inputFiles, canInputContainFolders) + + Assertions.assertThat(result).isTrue() + } + + @Test + fun `should return valid if input contains folder with files`() { + val validDirectory = File("src/test/resources/inputFiles") + + val inputFiles = arrayOf(validDirectory) + + val result = InputHelper.isInputValid(inputFiles, true) Assertions.assertThat(result).isTrue() } @@ -160,15 +152,14 @@ class InputHelperTest { Assertions.assertThat(result.size).isEqualTo(amountOfFilesInDirectory) } - @ParameterizedTest - @MethodSource("provideOneFlagArgument") - fun `should return invalid if folder is given with no-folder-flag`(canInputBePiped: Boolean) { + @Test + fun `should return invalid if folder is given with no-folder-flag`() { val validDirectory = File("src/test/resources/inputFiles") val inputFiles = arrayOf(validDirectory) System.setErr(PrintStream(errContent)) - val result = InputHelper.isInputValid(inputFiles, canInputBePiped, false) + val result = InputHelper.isInputValid(inputFiles, false) System.setErr(originalErr) Assertions.assertThat(result).isFalse() diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index 67b1d87b8b..f7a578c15e 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -77,7 +77,7 @@ class RawTextParser( @Throws(IOException::class) override fun call(): Void? { print(" ") - if (!InputHelper.isInputValid(arrayOf(inputFile), canInputBePiped = true, canInputContainFolders = true)) { + if (!InputHelper.isInputValid(arrayOf(inputFile), canInputContainFolders = true)) { logger.error("Input invalid file for RawTextParser, stopping execution...") return null } diff --git a/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt b/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt index 86bf633f54..7b3c2baadd 100644 --- a/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt +++ b/analysis/parser/RawTextParser/src/test/kotlin/de/maibornwolff/codecharta/indentationlevelparser/RawTextParserTest.kt @@ -144,7 +144,7 @@ class RawTextParserTest { fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) diff --git a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt index 33f91bf46d..f4cece4e99 100644 --- a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt +++ b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt @@ -24,7 +24,7 @@ class ValidationTool : Callable, InteractiveParser { var file: String = "" override fun call(): Void? { - if (!InputHelper.isInputValid(arrayOf(File(file)), canInputBePiped = false, canInputContainFolders = false)) { + if (!InputHelper.isInputValid(arrayOf(File(file)), canInputContainFolders = false)) { logger.error("Input invalid file for ValidationTool, stopping execution...") return null } diff --git a/analysis/tools/ValidationTool/src/test/kotlin/de/maibornwolff/codecharta/tools/validation/EveritValidatorTest.kt b/analysis/tools/ValidationTool/src/test/kotlin/de/maibornwolff/codecharta/tools/validation/EveritValidatorTest.kt index 0b96970db9..e4c90d427f 100644 --- a/analysis/tools/ValidationTool/src/test/kotlin/de/maibornwolff/codecharta/tools/validation/EveritValidatorTest.kt +++ b/analysis/tools/ValidationTool/src/test/kotlin/de/maibornwolff/codecharta/tools/validation/EveritValidatorTest.kt @@ -76,7 +76,7 @@ class EveritValidatorTest { fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) every { - InputHelper.isInputValid(any(), any(), any()) + InputHelper.isInputValid(any(), any()) } returns false System.setErr(PrintStream(errContent)) From a27f167588ca2dcd098f58efca82fbffbee3f3f6 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Fri, 2 Jun 2023 16:08:40 +0200 Subject: [PATCH 07/19] Removed stale and disabled structure modifier test #3307 --- .../structuremodifier/StructureModifierTest.kt | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt index 6f5d7bdc53..5c79b05672 100644 --- a/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt +++ b/analysis/filter/StructureModifier/src/test/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifierTest.kt @@ -7,7 +7,6 @@ import io.mockk.mockkObject import io.mockk.unmockkAll import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import picocli.CommandLine @@ -54,17 +53,6 @@ class StructureModifierTest { assertThat(errorStream.toString()).contains("invalid_project.cc.json is not a valid project") } - // TODO: Why is this disabled? Should it not be removed? - @Disabled - @Test - fun `reads project piped input multiline`() { - val input = File("src/test/resources/sample_project.cc.json").bufferedReader().readLines() - .joinToString(separator = "\n") { it } - val cliResult = executeForOutput(input, arrayOf("-r=/does/not/exist")) - - assertThat(cliResult).contains(listOf("otherFile.java")) - } - @Test fun `returns error for malformed piped input`() { val originalError = System.err From a1b894de7a0e52c4e61e13c8280721c5adeee157 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Fri, 2 Jun 2023 16:26:40 +0200 Subject: [PATCH 08/19] Fix failing MetricGardener input test #3307 --- .../importer/metricgardenerimporter/MetricGardenerImporter.kt | 4 +--- .../metricgardenerimporter/MetricGardenerImporterTest.kt | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt index 65808d65d2..c5a385de6b 100644 --- a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt +++ b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt @@ -11,7 +11,6 @@ import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.util.InputHelper import de.maibornwolff.codecharta.util.ResourceSearchHelper -import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.IOException @@ -29,7 +28,6 @@ class MetricGardenerImporter( private val output: PrintStream = System.out ) : Callable, InteractiveParser { - private val logger = KotlinLogging.logger {} private val mapper = jacksonObjectMapper() @CommandLine.Option( @@ -56,7 +54,7 @@ class MetricGardenerImporter( @Throws(IOException::class) override fun call(): Void? { if (!InputHelper.isInputValid(arrayOf(inputFile), canInputContainFolders = true)) { - logger.error("Input invalid file for MetricGardenerImporter, stopping execution...") + System.err.println("Input invalid file for MetricGardenerImporter, stopping execution...") return null } diff --git a/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt b/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt index f7f82e93e9..021a7109ee 100644 --- a/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt +++ b/analysis/import/MetricGardenerImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporterTest.kt @@ -11,7 +11,6 @@ import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import org.junit.jupiter.params.ParameterizedTest @@ -126,8 +125,6 @@ class MetricGardenerImporterTest { Assertions.assertThat(isUsable).isFalse() } - // TODO: Fix this test - @Disabled @Test fun `should stop execution if input files are invalid`() { mockkObject(InputHelper) From 74645e4d5124ea79fca6d5cb0b221e9e2b921c6d Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Fri, 2 Jun 2023 17:20:32 +0200 Subject: [PATCH 09/19] Refactor various input file types to be File? #3307 --- .../codecharta/filter/edgefilter/EdgeFilter.kt | 6 +++--- .../metricgardenerimporter/MetricGardenerImporter.kt | 8 ++++---- .../importer/sourcecodeparser/SourceCodeParserMain.kt | 6 +++--- .../codecharta/parser/rawtextparser/RawTextParser.kt | 6 +++--- .../codecharta/tools/validation/ValidationTool.kt | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt index e0247f415b..11d91e3647 100644 --- a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt +++ b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt @@ -25,7 +25,7 @@ class EdgeFilter( var help: Boolean = false @CommandLine.Parameters(arity = "1", paramLabel = "FILE", description = ["files to filter"]) - private var source: File = File("") + private var source: File? = null @CommandLine.Option(names = ["--path-separator"], description = ["path separator (default = '/')"]) private var pathSeparator = '/' @@ -34,12 +34,12 @@ class EdgeFilter( private var outputFile: String? = null override fun call(): Void? { - if (!InputHelper.isInputValid(arrayOf(source), canInputContainFolders = false)) { + if (source == null || !InputHelper.isInputValid(arrayOf(source!!), canInputContainFolders = false)) { logger.error("Input invalid file for EdgeFilter, stopping execution...") return null } - val srcProject = ProjectDeserializer.deserializeProject(source.inputStream()) + val srcProject = ProjectDeserializer.deserializeProject(source!!.inputStream()) val newProject = EdgeProjectBuilder(srcProject, pathSeparator).merge() diff --git a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt index c5a385de6b..146fd8b3d2 100644 --- a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt +++ b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt @@ -40,7 +40,7 @@ class MetricGardenerImporter( arity = "1", paramLabel = "FOLDER or FILE", description = ["path for project folder or code file"] ) - private var inputFile = File("") + private var inputFile: File? = null @CommandLine.Option(names = ["-j", "--is-json-file"], description = ["Input file is a MetricGardener JSON file"]) private var isJsonFile: Boolean = false @@ -53,7 +53,7 @@ class MetricGardenerImporter( @Throws(IOException::class) override fun call(): Void? { - if (!InputHelper.isInputValid(arrayOf(inputFile), canInputContainFolders = true)) { + if (inputFile == null || !InputHelper.isInputValid(arrayOf(inputFile!!), canInputContainFolders = true)) { System.err.println("Input invalid file for MetricGardenerImporter, stopping execution...") return null } @@ -67,7 +67,7 @@ class MetricGardenerImporter( command = npm, arguments = listOf( "exec", "-y", "metric-gardener", "--", "parse", - inputFile.absolutePath, "--output-path", tempMgOutput.absolutePath + inputFile!!.absolutePath, "--output-path", tempMgOutput.absolutePath ), workingDirectory = ShellLocation.CURRENT_WORKING ) @@ -75,7 +75,7 @@ class MetricGardenerImporter( } val metricGardenerNodes: MetricGardenerNodes = - mapper.readValue(inputFile.reader(Charset.defaultCharset()), MetricGardenerNodes::class.java) + mapper.readValue(inputFile!!.reader(Charset.defaultCharset()), MetricGardenerNodes::class.java) val metricGardenerProjectBuilder = MetricGardenerProjectBuilder(metricGardenerNodes) val project = metricGardenerProjectBuilder.build() diff --git a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt index 401bfa426a..28a2c92ec1 100644 --- a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt +++ b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt @@ -69,12 +69,12 @@ class SourceCodeParserMain( private var verbose = false @CommandLine.Parameters(arity = "1", paramLabel = "FOLDER or FILE", description = ["project folder or code file"]) - private var file: File = File("") + private var file: File? = null @Throws(IOException::class) override fun call(): Void? { print(" ") - if (!InputHelper.isInputValid(arrayOf(file), canInputContainFolders = true)) { + if (file == null || !InputHelper.isInputValid(arrayOf(file!!), canInputContainFolders = true)) { System.err.println("Input invalid file for SourceCodeParser, stopping execution...") return null } @@ -84,7 +84,7 @@ class SourceCodeParserMain( val projectParser = ProjectParser(exclude, verbose, !findNoIssues) projectParser.setUpAnalyzers() - projectParser.scanProject(file) + projectParser.scanProject(file!!) val writer = getMetricWriter() val pipedProject = ProjectDeserializer.deserializeProject(input) diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index f7a578c15e..495a7dbd0f 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -38,7 +38,7 @@ class RawTextParser( private var verbose = false @CommandLine.Parameters(arity = "1", paramLabel = "FILE or FOLDER", description = ["file/project to parse"]) - private var inputFile: File = File("") + private var inputFile: File? = null @CommandLine.Option( arity = "0..", @@ -77,7 +77,7 @@ class RawTextParser( @Throws(IOException::class) override fun call(): Void? { print(" ") - if (!InputHelper.isInputValid(arrayOf(inputFile), canInputContainFolders = true)) { + if (inputFile == null || !InputHelper.isInputValid(arrayOf(inputFile!!), canInputContainFolders = true)) { logger.error("Input invalid file for RawTextParser, stopping execution...") return null } @@ -86,7 +86,7 @@ class RawTextParser( val parameterMap = assembleParameterMap() val results: Map = - MetricCollector(inputFile, exclude, fileExtensions, parameterMap, metrics).parse() + MetricCollector(inputFile!!, exclude, fileExtensions, parameterMap, metrics).parse() val pipedProject = ProjectDeserializer.deserializeProject(input) val project = ProjectGenerator().generate(results, pipedProject) diff --git a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt index f4cece4e99..362921fbf3 100644 --- a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt +++ b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt @@ -20,16 +20,16 @@ class ValidationTool : Callable, InteractiveParser { @CommandLine.Option(names = ["-h", "--help"], usageHelp = true, description = ["displays this help and exits"]) var help: Boolean = false - @CommandLine.Parameters(index = "0", description = ["file to validate"]) - var file: String = "" + @CommandLine.Parameters(index = "0", arity = "1", paramLabel = "FILE", description = ["file to validate"]) + var file: File? = null override fun call(): Void? { - if (!InputHelper.isInputValid(arrayOf(File(file)), canInputContainFolders = false)) { + if (file == null || !InputHelper.isInputValid(arrayOf(file!!), canInputContainFolders = false)) { logger.error("Input invalid file for ValidationTool, stopping execution...") return null } - EveritValidator(SCHEMA_PATH).validate(FileInputStream(File(file).absoluteFile)) + EveritValidator(SCHEMA_PATH).validate(FileInputStream(file!!.absoluteFile)) return null } From f92181be1c7aef239a76cd266c5efe0a9ce483b4 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Mon, 5 Jun 2023 11:08:34 +0200 Subject: [PATCH 10/19] Adjust null input check and TokeiImporter check #3307 --- .../filter/edgefilter/EdgeFilter.kt | 2 +- .../subcommands/LogScanCommand.kt | 2 +- .../MetricGardenerImporter.kt | 2 +- .../importer/svnlogparser/SVNLogParser.kt | 2 +- .../sourcecodeparser/SourceCodeParserMain.kt | 2 +- .../importer/tokeiimporter/TokeiImporter.kt | 13 ++---------- .../codecharta/util/InputHelper.kt | 20 ++++++++++++++++++- .../codecharta/util/InputHelperTest.kt | 14 +++++++++++++ .../parser/rawtextparser/RawTextParser.kt | 2 +- .../tools/validation/ValidationTool.kt | 2 +- 10 files changed, 42 insertions(+), 19 deletions(-) diff --git a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt index 11d91e3647..21474206c6 100644 --- a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt +++ b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt @@ -34,7 +34,7 @@ class EdgeFilter( private var outputFile: String? = null override fun call(): Void? { - if (source == null || !InputHelper.isInputValid(arrayOf(source!!), canInputContainFolders = false)) { + if (!InputHelper.isInputValidAndNotNull(arrayOf(source), canInputContainFolders = false)) { logger.error("Input invalid file for EdgeFilter, stopping execution...") return null } diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt index 947beddc0e..25d1f8c332 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt @@ -59,7 +59,7 @@ class LogScanCommand : Callable, InteractiveParser { } override fun call(): Void? { - if (gitLogFile == null || !InputHelper.isInputValid(arrayOf(gitLogFile!!), canInputContainFolders = false)) { + if (!InputHelper.isInputValidAndNotNull(arrayOf(gitLogFile), canInputContainFolders = false)) { logger.error("Input invalid file for GitLogScan, stopping execution...") return null } diff --git a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt index 146fd8b3d2..1393acc913 100644 --- a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt +++ b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt @@ -53,7 +53,7 @@ class MetricGardenerImporter( @Throws(IOException::class) override fun call(): Void? { - if (inputFile == null || !InputHelper.isInputValid(arrayOf(inputFile!!), canInputContainFolders = true)) { + if (!InputHelper.isInputValidAndNotNull(arrayOf(inputFile), canInputContainFolders = true)) { System.err.println("Input invalid file for MetricGardenerImporter, stopping execution...") return null } diff --git a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt index f89cc0fc00..c31cb75dad 100644 --- a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt +++ b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt @@ -83,7 +83,7 @@ class SVNLogParser( override fun call(): Void? { print(" ") - if (file == null || !InputHelper.isInputValid(arrayOf(file!!), canInputContainFolders = false)) { + if (!InputHelper.isInputValidAndNotNull(arrayOf(file), canInputContainFolders = false)) { logger.error("Input invalid file for SVNLogParser, stopping execution...") return null } diff --git a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt index 28a2c92ec1..26582abd17 100644 --- a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt +++ b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt @@ -74,7 +74,7 @@ class SourceCodeParserMain( @Throws(IOException::class) override fun call(): Void? { print(" ") - if (file == null || !InputHelper.isInputValid(arrayOf(file!!), canInputContainFolders = true)) { + if (!InputHelper.isInputValidAndNotNull(arrayOf(file), canInputContainFolders = true)) { System.err.println("Input invalid file for SourceCodeParser, stopping execution...") return null } diff --git a/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt b/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt index 520f855182..8f92fdb21f 100644 --- a/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt +++ b/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt @@ -62,7 +62,6 @@ class TokeiImporter( @CommandLine.Option(names = ["-nc", "--not-compressed"], description = ["save uncompressed output File"]) private var compress = true - // TODO: Why is 0 allowed? @CommandLine.Parameters(arity = "0..1", paramLabel = "FILE", description = ["tokei generated json"]) private var file: File? = null @@ -71,14 +70,6 @@ class TokeiImporter( @Throws(IOException::class) override fun call(): Void? { print(" ") - - if (file == null) { - // do not do anything, if null there could come piped input - } else if (!InputHelper.isInputValid(arrayOf(file!!), canInputContainFolders = false)) { - logger.error("Input invalid file for TokeiImporter, stopping execution...") - return null - } - projectBuilder = ProjectBuilder() val root = getInput() ?: return null runBlocking(Dispatchers.Default) { @@ -109,11 +100,11 @@ class TokeiImporter( runBlocking(Dispatchers.Default) { if (file != null) { launch { - if (file!!.isFile) { + if (InputHelper.isInputValid(arrayOf(file!!), canInputContainFolders = false)) { val bufferedReader = file!!.bufferedReader() root = JsonParser.parseReader(bufferedReader) } else { - logger.error("${file!!.name} has not been found.") + logger.error("Input invalid file for TokeiImporter, stopping execution...") } } } else { diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt index 07987e9675..f68285dd4e 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt @@ -7,6 +7,23 @@ class InputHelper { companion object { private val logger = KotlinLogging.logger {} + /** + * Checks the same as ´isInputValid(Array, Boolean)`, but additionally checks for nullness in elements in array. + */ + fun isInputValidAndNotNull(inputResources: Array, + canInputContainFolders: Boolean): Boolean { + + val nonNullInputResources: Array + try { + nonNullInputResources = inputResources.requireNoNulls() + } catch (e: IllegalArgumentException) { + logger.error("Input contained illegal null resource!") + return false + } + + return isInputValid(nonNullInputResources, canInputContainFolders) + } + /** * Checks if input resources meet a number of requirements: * The input array can not be empty. @@ -15,7 +32,8 @@ class InputHelper { */ fun isInputValid(inputResources: Array, canInputContainFolders: Boolean): Boolean { - return !isInputEmpty(inputResources) && areInputResourcesValid(inputResources, canInputContainFolders) + return !isInputEmpty(inputResources) && + areInputResourcesValid(inputResources, canInputContainFolders) } private fun isInputEmpty(inputResources: Array): Boolean { diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt index a644dd1356..49e9f81980 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt @@ -166,4 +166,18 @@ class InputHelperTest { Assertions.assertThat(errContent.toString()) .contains("Input folder where only files are allowed!") } + + @Test + fun `should return invalid if input contains null elements`() { + val nullInputFile: File? = null + val inputFiles = arrayOf(nullInputFile) + + System.setErr(PrintStream(errContent)) + val result = InputHelper.isInputValidAndNotNull(inputFiles, false) + System.setErr(originalErr) + + Assertions.assertThat(result).isFalse() + Assertions.assertThat(errContent.toString()) + .contains("Input contained illegal null resource!") + } } diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index 495a7dbd0f..9b7ffb3d46 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -77,7 +77,7 @@ class RawTextParser( @Throws(IOException::class) override fun call(): Void? { print(" ") - if (inputFile == null || !InputHelper.isInputValid(arrayOf(inputFile!!), canInputContainFolders = true)) { + if (!InputHelper.isInputValidAndNotNull(arrayOf(inputFile), canInputContainFolders = true)) { logger.error("Input invalid file for RawTextParser, stopping execution...") return null } diff --git a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt index 362921fbf3..d3adab4ebe 100644 --- a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt +++ b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt @@ -24,7 +24,7 @@ class ValidationTool : Callable, InteractiveParser { var file: File? = null override fun call(): Void? { - if (file == null || !InputHelper.isInputValid(arrayOf(file!!), canInputContainFolders = false)) { + if (!InputHelper.isInputValidAndNotNull(arrayOf(file), canInputContainFolders = false)) { logger.error("Input invalid file for ValidationTool, stopping execution...") return null } From 7fd724a751bce4f2c759c20a08e978d57b9f19a4 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Mon, 5 Jun 2023 12:47:45 +0200 Subject: [PATCH 11/19] Add check for empty strings #3307 --- .../codecharta/util/InputHelper.kt | 15 +++++++++++-- .../codecharta/util/InputHelperTest.kt | 22 ++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt index f68285dd4e..a5e44390a2 100644 --- a/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt @@ -44,7 +44,15 @@ class InputHelper { return false } - private fun isInputExistentAndFolderOrFile(inputResource: File): Boolean { + private fun isInputEmptyString(inputResource: File): Boolean { + if (inputResource.name == "") { + logger.error("Input empty string for input files/folders, which is not allowed!") + return true + } + return false + } + + private fun isInputExistentFolderOrFile(inputResource: File): Boolean { if (!(inputResource.isFile || inputResource.isDirectory)) { logger.error("Could not find resource `${ inputResource.path }`!") return false @@ -73,8 +81,11 @@ class InputHelper { canInputContainFolders: Boolean): Boolean { var isInputValid = true + // We do not end/break early here, so user is informed about all input faults in one run for (source in inputResources) { - if (!isInputExistentAndFolderOrFile(source)) { + if (isInputEmptyString(source)) { + isInputValid = false + } else if (!isInputExistentFolderOrFile(source)) { isInputValid = false } else { if (!isInputValidFolderOrAnyFile(source, canInputContainFolders)) { diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt index 49e9f81980..3edeb4de71 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt @@ -167,17 +167,33 @@ class InputHelperTest { .contains("Input folder where only files are allowed!") } - @Test - fun `should return invalid if input contains null elements`() { + @ParameterizedTest + @MethodSource("provideBooleanValues") + fun `should return invalid if input contains null elements`(canInputContainFolders: Boolean) { val nullInputFile: File? = null val inputFiles = arrayOf(nullInputFile) System.setErr(PrintStream(errContent)) - val result = InputHelper.isInputValidAndNotNull(inputFiles, false) + val result = InputHelper.isInputValidAndNotNull(inputFiles, canInputContainFolders) System.setErr(originalErr) Assertions.assertThat(result).isFalse() Assertions.assertThat(errContent.toString()) .contains("Input contained illegal null resource!") } + + @ParameterizedTest + @MethodSource("provideBooleanValues") + fun `should return invalid if input contains empty string`(canInputContainFolders: Boolean) { + val emptyStringFile = File("") + val inputFiles = arrayOf(emptyStringFile) + + System.setErr(PrintStream(errContent)) + val result = InputHelper.isInputValid(inputFiles, canInputContainFolders) + System.setErr(originalErr) + + Assertions.assertThat(result).isFalse() + Assertions.assertThat(errContent.toString()) + .contains("Input empty string for input files/folders, which is not allowed!") + } } From 7a64f36928850c2d5c4f8eaccf25dbae214ddfb9 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Mon, 5 Jun 2023 15:02:54 +0200 Subject: [PATCH 12/19] Add empty string check for SonarImporter, remove unneeded mock #3307 --- .../filter/edgefilter/EdgeFilterTest.kt | 6 +-- .../importer/sonar/SonarImporterMain.kt | 5 +++ .../importer/sonar/SonarImporterMainTest.kt | 42 +++++++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt b/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt index 2bf8b529da..8f890be73f 100644 --- a/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt +++ b/analysis/filter/EdgeFilter/src/test/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilterTest.kt @@ -19,6 +19,7 @@ import java.io.PrintStream class EdgeFilterTest { val errContent = ByteArrayOutputStream() val originalErr = System.err + @AfterEach fun afterTest() { unmockkAll() @@ -26,11 +27,6 @@ class EdgeFilterTest { @Test fun `should create json uncompressed file`() { - mockkObject(InputHelper) - every { - InputHelper.isInputValid(any(), any()) - } returns true - main( arrayOf( "src/test/resources/coupling.json", "-o=src/test/resources/output" diff --git a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt index 6c37e7f15e..064e6d4c7e 100644 --- a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt +++ b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt @@ -81,6 +81,11 @@ class SonarImporterMain( } override fun call(): Void? { + if (url == "" || projectId == "") { + System.err.println("Input invalid file for SonarImporter, stopping execution...") + return null + } + val importer = createMeasuresAPIImporter() var project = importer.getProjectFromMeasureAPI(projectId, metrics) diff --git a/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt b/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt index 9a0d916a2a..288b4fa8f8 100644 --- a/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt +++ b/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt @@ -6,6 +6,11 @@ import com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo import com.github.tomakehurst.wiremock.client.WireMock.verify import com.github.tomakehurst.wiremock.junit5.WireMockTest import de.maibornwolff.codecharta.importer.sonar.dataaccess.SonarMetricsAPIDatasource +import de.maibornwolff.codecharta.util.InputHelper +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkAll +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -13,12 +18,21 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource import picocli.CommandLine +import java.io.ByteArrayOutputStream +import java.io.PrintStream import javax.ws.rs.core.MediaType private const val PORT = 8089 @WireMockTest(httpPort = PORT) class SonarImporterMainTest { + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @AfterEach + fun afterTest() { + unmockkAll() + } companion object { private const val METRIC_LIST_URL_PATH = "/api/metrics/search?f=hidden,decimalScale&p=1&ps=${SonarMetricsAPIDatasource.PAGE_SIZE}" @@ -135,6 +149,34 @@ class SonarImporterMainTest { Assertions.assertFalse(isApplicable) } + @Test + fun `should stop execution if url is empty string`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(SonarImporterMain()).execute(*arrayOf("", "dummyVal")) + System.setErr(originalErr) + + Assertions.assertTrue(errContent.toString().contains("Input invalid file for SonarImporter, stopping execution")) + } + + @Test + fun `should stop execution if project key is empty string`() { + mockkObject(InputHelper) + every { + InputHelper.isInputValid(any(), any()) + } returns false + + System.setErr(PrintStream(errContent)) + CommandLine(SonarImporterMain()).execute(*arrayOf("dummyVal", "")) + System.setErr(originalErr) + + Assertions.assertTrue(errContent.toString().contains("Input invalid file for SonarImporter, stopping execution")) + } + @Test fun `should NOT be identified as applicable if input is a file but not the sonar properties file`() { val isApplicable = SonarImporterMain().isApplicable("src/test/resources/example.xml") From b9e8eb2f1bb256433e26757998e94b286f642842 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Mon, 5 Jun 2023 15:28:35 +0200 Subject: [PATCH 13/19] Add changelog entry #3307 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 390cbb5bfc..469e9a5769 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/) - Expand and restructure documentation regarding Docker usage [#3312](https://github.com/MaibornWolff/codecharta/pull/3312) - Add current working directories as hint or default value to interactive parser and parser suggestions when asking for input [#3319](https://github.com/MaibornWolff/codecharta/pull/3319) - Add helpful status messages when calculating parser suggestions [#3329](https://github.com/MaibornWolff/codecharta/pull/3329) +- Add basic validity checking for all input resources (files/folders, url for SonarImporter) [#3325](https://github.com/MaibornWolff/codecharta/pull/3325) ### Fixed 🐞 From 2720f6ba76a23d7c34f99e183029447417fea140 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Mon, 5 Jun 2023 15:46:16 +0200 Subject: [PATCH 14/19] Adjust Sonar error message #3307 --- .../codecharta/importer/sonar/SonarImporterMain.kt | 2 +- .../codecharta/importer/sonar/SonarImporterMainTest.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt index 064e6d4c7e..48fb233d13 100644 --- a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt +++ b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt @@ -82,7 +82,7 @@ class SonarImporterMain( override fun call(): Void? { if (url == "" || projectId == "") { - System.err.println("Input invalid file for SonarImporter, stopping execution...") + System.err.println("Input invalid Url or ProjectID for SonarImporter, stopping execution...") return null } diff --git a/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt b/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt index 288b4fa8f8..b72016fd3b 100644 --- a/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt +++ b/analysis/import/SonarImporter/src/test/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMainTest.kt @@ -160,7 +160,7 @@ class SonarImporterMainTest { CommandLine(SonarImporterMain()).execute(*arrayOf("", "dummyVal")) System.setErr(originalErr) - Assertions.assertTrue(errContent.toString().contains("Input invalid file for SonarImporter, stopping execution")) + Assertions.assertTrue(errContent.toString().contains("Input invalid Url or ProjectID for SonarImporter, stopping execution")) } @Test @@ -174,7 +174,7 @@ class SonarImporterMainTest { CommandLine(SonarImporterMain()).execute(*arrayOf("dummyVal", "")) System.setErr(originalErr) - Assertions.assertTrue(errContent.toString().contains("Input invalid file for SonarImporter, stopping execution")) + Assertions.assertTrue(errContent.toString().contains("Input invalid Url or ProjectID for SonarImporter, stopping execution")) } @Test From c918279c37d658f946928e6f902c5b8dce1ac548 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Wed, 7 Jun 2023 10:39:30 +0200 Subject: [PATCH 15/19] Fix merging mistake #3307 --- .../codecharta/parser/rawtextparser/RawTextParser.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index 9b7ffb3d46..d29f7f120c 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -8,7 +8,6 @@ import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.util.InputHelper -import de.maibornwolff.codecharta.util.ResourceSearchHelper import mu.KotlinLogging import picocli.CommandLine import java.io.File From 72802e13c6fd18c2fb2e5421a4c03471dd6282c8 Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Wed, 7 Jun 2023 13:11:57 +0200 Subject: [PATCH 16/19] Remove invalid comment and minor refactor of RepoScan check #3307 --- .../filter/structuremodifier/StructureModifier.kt | 1 - .../importer/gitlogparser/subcommands/RepoScanCommand.kt | 8 ++------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index 56c3fe0514..cb005801b2 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -81,7 +81,6 @@ class StructureModifier( return ProjectDeserializer.deserializeProject(input) } - // Can not be piped here, because that case is already covered by the previous check (source == null) if (!InputHelper.isInputValid(arrayOf(source!!), canInputContainFolders = false)) { logger.error("Input invalid file for StructureModifier, stopping execution...") return null diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt index bda7cc4f0a..66abc67a81 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt @@ -53,14 +53,10 @@ class RepoScanCommand : Callable, InteractiveParser { override fun call(): Void? { val repoPath: Path - if (repoPathName.isNullOrBlank()) { - println("--repo-path not set, aborting...") + if (repoPathName == null || !InputHelper.isInputValid(arrayOf(File(repoPathName!!)), canInputContainFolders = true)) { + logger.error("Input invalid file for GitRepoScan, stopping execution...") return null } else { - if (!InputHelper.isInputValid(arrayOf(File(repoPathName!!)), canInputContainFolders = true)) { - logger.error("Input invalid file for GitRepoScan, stopping execution...") - return null - } repoPath = Paths.get(repoPathName!!).normalize().toAbsolutePath() } println("Creating git.log file...") From 85d34d5d50dde354743625af0d297567c7bdf01f Mon Sep 17 00:00:00 2001 From: moritz-suckow Date: Wed, 7 Jun 2023 15:08:10 +0200 Subject: [PATCH 17/19] Add basic input check to parser suggestions #3307 --- .../InteractiveParserSuggestionDialog.kt | 15 +++++- .../InteractiveParserSuggestionDialogTest.kt | 50 ++++++++++++------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/analysis/tools/ccsh/src/main/kotlin/de/maibornwolff/codecharta/tools/ccsh/parser/InteractiveParserSuggestionDialog.kt b/analysis/tools/ccsh/src/main/kotlin/de/maibornwolff/codecharta/tools/ccsh/parser/InteractiveParserSuggestionDialog.kt index 4b3e38c420..a5a29b8283 100644 --- a/analysis/tools/ccsh/src/main/kotlin/de/maibornwolff/codecharta/tools/ccsh/parser/InteractiveParserSuggestionDialog.kt +++ b/analysis/tools/ccsh/src/main/kotlin/de/maibornwolff/codecharta/tools/ccsh/parser/InteractiveParserSuggestionDialog.kt @@ -7,6 +7,7 @@ import de.maibornwolff.codecharta.tools.ccsh.Ccsh import de.maibornwolff.codecharta.tools.ccsh.parser.repository.PicocliParserRepository import mu.KotlinLogging import picocli.CommandLine +import java.io.File import java.nio.file.Paths class InteractiveParserSuggestionDialog { @@ -30,13 +31,19 @@ class InteractiveParserSuggestionDialog { } private fun getApplicableInteractiveParsers(commandLine: CommandLine): List { - val inputFile: String = KInquirer.promptInput( + val inputFilePath: String = KInquirer.promptInput( message = "Which path should be scanned?", hint = "You can provide a directory path / file path / sonar url.", default = Paths.get("").toAbsolutePath().toString()) + val inputFile = File(inputFilePath) + if (inputFilePath == "" || !isInputFileOrDirectory(inputFile)) { + logger.error("Specified invalid or empty path to analyze! Aborting...") + return emptyList() + } + val applicableParsers = - ParserService.getParserSuggestions(commandLine, PicocliParserRepository(), inputFile) + ParserService.getParserSuggestions(commandLine, PicocliParserRepository(), inputFilePath) if (applicableParsers.isEmpty()) { logger.info(Ccsh.NO_USABLE_PARSER_FOUND_MESSAGE) @@ -57,5 +64,9 @@ class InteractiveParserSuggestionDialog { } return selectedParsers } + + private fun isInputFileOrDirectory(inputFile: File): Boolean { + return (inputFile.isDirectory || inputFile.isFile) + } } } diff --git a/analysis/tools/ccsh/src/test/kotlin/de/maibornwolff/codecharta/ccsh/parser/InteractiveParserSuggestionDialogTest.kt b/analysis/tools/ccsh/src/test/kotlin/de/maibornwolff/codecharta/ccsh/parser/InteractiveParserSuggestionDialogTest.kt index 70b1922046..3f50301edf 100644 --- a/analysis/tools/ccsh/src/test/kotlin/de/maibornwolff/codecharta/ccsh/parser/InteractiveParserSuggestionDialogTest.kt +++ b/analysis/tools/ccsh/src/test/kotlin/de/maibornwolff/codecharta/ccsh/parser/InteractiveParserSuggestionDialogTest.kt @@ -3,7 +3,6 @@ package de.maibornwolff.codecharta.ccsh.parser import com.github.kinquirer.KInquirer import com.github.kinquirer.components.promptCheckbox import com.github.kinquirer.components.promptInput -import com.github.kinquirer.components.promptList import de.maibornwolff.codecharta.tools.ccsh.Ccsh import de.maibornwolff.codecharta.tools.ccsh.parser.InteractiveParserSuggestionDialog import de.maibornwolff.codecharta.tools.ccsh.parser.ParserService @@ -50,12 +49,7 @@ class InteractiveParserSuggestionDialogTest { mockkStatic("com.github.kinquirer.components.InputKt") every { KInquirer.promptInput(any(), any(), any(), any(), any()) - } returns "" - - mockkStatic("com.github.kinquirer.components.ListKt") - every { - KInquirer.promptList(any(), any(), any(), any(), any()) - } returns "" + } returns "src" mockkObject(ParserService) every { @@ -74,12 +68,7 @@ class InteractiveParserSuggestionDialogTest { mockkStatic("com.github.kinquirer.components.InputKt") every { KInquirer.promptInput(any(), any(), any(), any(), any()) - } returns "" - - mockkStatic("com.github.kinquirer.components.ListKt") - every { - KInquirer.promptList(any(), any(), any(), any(), any()) - } returns "" + } returns "src" mockkStatic("com.github.kinquirer.components.CheckboxKt") every { @@ -104,12 +93,7 @@ class InteractiveParserSuggestionDialogTest { mockkStatic("com.github.kinquirer.components.InputKt") every { KInquirer.promptInput(any(), any(), any(), any(), any()) - } returns "" - - mockkStatic("com.github.kinquirer.components.ListKt") - every { - KInquirer.promptList(any(), any(), any(), any(), any()) - } returns "" + } returns "src" val parser = "dummyParser" val configuration = listOf("dummyArg") @@ -137,4 +121,32 @@ class InteractiveParserSuggestionDialogTest { Assertions.assertThat(configuredParsers).containsKey(parser) Assertions.assertThat(configuredParsers[parser] == configuration).isTrue() } + + @Test + fun `should return empty map when user enters empty input to scan`() { + mockkStatic("com.github.kinquirer.components.InputKt") + every { + KInquirer.promptInput(any(), any(), any(), any(), any()) + } returns "" + + val selectedParsers = InteractiveParserSuggestionDialog.offerAndGetInteractiveParserSuggestionsAndConfigurations(cmdLine) + + Assertions.assertThat(selectedParsers).isNotNull + Assertions.assertThat(selectedParsers).isEmpty() + Assertions.assertThat(errorOut.toString()).contains("Specified invalid or empty path to analyze! Aborting...") + } + + @Test + fun `should return empty map when user enters nonexistent input to scan`() { + mockkStatic("com.github.kinquirer.components.InputKt") + every { + KInquirer.promptInput(any(), any(), any(), any(), any()) + } returns "src/test/resources/does/not/exist" + + val selectedParsers = InteractiveParserSuggestionDialog.offerAndGetInteractiveParserSuggestionsAndConfigurations(cmdLine) + + Assertions.assertThat(selectedParsers).isNotNull + Assertions.assertThat(selectedParsers).isEmpty() + Assertions.assertThat(errorOut.toString()).contains("Specified invalid or empty path to analyze! Aborting...") + } } From 37edd48af1dae7cc7220105cbc3e7d97611d8ba4 Mon Sep 17 00:00:00 2001 From: Phanlezz <65733509+phanlezz@users.noreply.github.com> Date: Fri, 16 Jun 2023 13:10:12 +0200 Subject: [PATCH 18/19] Fix test for Windows os --- .../de/maibornwolff/codecharta/util/InputHelperTest.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt index 3edeb4de71..f0bd767ea3 100644 --- a/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt @@ -32,11 +32,13 @@ class InputHelperTest { val invalidFilePath1 = "src/test/resources/thisDoesNotExist1.json" val invalidFilePath2 = "src/test/resources/thisDoesNotExist2.json" + val invalidFile1 = File(invalidFilePath1) + val invalidFile2 = File(invalidFilePath2) val inputFiles = arrayOf(File("src/test/resources/example.cc.json"), File("src/test/resources/example_api_version_1.3.cc.json"), - File(invalidFilePath1), - File(invalidFilePath2)) + invalidFile1, + invalidFile2) try { InputHelper.isInputValid(inputFiles, canInputContainFolders) } catch (exception: IllegalArgumentException) { @@ -47,9 +49,9 @@ class InputHelperTest { System.setErr(originalErr) Assertions.assertThat(errContent.toString()) - .contains("Could not find resource `$invalidFilePath1`") + .contains("Could not find resource `${invalidFile1.path}`") Assertions.assertThat(errContent.toString()) - .contains("Could not find resource `$invalidFilePath2`") + .contains("Could not find resource `${invalidFile2.path}`") } @ParameterizedTest From b1a2410dbadb3438569ab4b7755552ae5affbffd Mon Sep 17 00:00:00 2001 From: Phanlezz <65733509+phanlezz@users.noreply.github.com> Date: Wed, 21 Jun 2023 10:43:53 +0200 Subject: [PATCH 19/19] Change error logging to exceptions to stop execution --- .../maibornwolff/codecharta/exporter/csv/CSVExporter.kt | 3 +-- .../codecharta/filter/edgefilter/EdgeFilter.kt | 6 +----- .../codecharta/filter/mergefilter/MergeFilter.kt | 3 +-- .../filter/structuremodifier/StructureModifier.kt | 3 +-- .../maibornwolff/codecharta/importer/csv/CSVImporter.kt | 5 +---- .../importer/sourcemonitor/SourceMonitorImporter.kt | 6 +----- .../codecharta/importer/codemaat/CodeMaatImporter.kt | 6 +----- .../importer/gitlogparser/subcommands/LogScanCommand.kt | 8 +------- .../importer/gitlogparser/subcommands/RepoScanCommand.kt | 8 +------- .../metricgardenerimporter/MetricGardenerImporter.kt | 3 +-- .../codecharta/importer/svnlogparser/SVNLogParser.kt | 5 +---- .../codecharta/importer/sonar/SonarImporterMain.kt | 3 +-- .../importer/sourcecodeparser/SourceCodeParserMain.kt | 3 +-- .../codecharta/importer/tokeiimporter/TokeiImporter.kt | 2 +- .../codecharta/parser/rawtextparser/RawTextParser.kt | 5 +---- .../codecharta/tools/validation/ValidationTool.kt | 6 +----- 16 files changed, 16 insertions(+), 59 deletions(-) diff --git a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt index 975c277dc2..74df63e0fe 100644 --- a/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt +++ b/analysis/export/CSVExporter/src/main/kotlin/de/maibornwolff/codecharta/exporter/csv/CSVExporter.kt @@ -53,8 +53,7 @@ class CSVExporter : Callable, InteractiveParser { } if (!InputHelper.isInputValid(sources, canInputContainFolders = false)) { - System.err.println("Input invalid file for CSVExporter, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for CSVExporter, stopping execution...") } val projects = sources.map { ProjectDeserializer.deserializeProject(it.inputStream()) } diff --git a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt index 21474206c6..d17f67e46f 100644 --- a/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt +++ b/analysis/filter/EdgeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/edgefilter/EdgeFilter.kt @@ -6,7 +6,6 @@ import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.util.InputHelper -import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.PrintStream @@ -35,8 +34,7 @@ class EdgeFilter( override fun call(): Void? { if (!InputHelper.isInputValidAndNotNull(arrayOf(source), canInputContainFolders = false)) { - logger.error("Input invalid file for EdgeFilter, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for EdgeFilter, stopping execution...") } val srcProject = ProjectDeserializer.deserializeProject(source!!.inputStream()) @@ -49,8 +47,6 @@ class EdgeFilter( } companion object { - private val logger = KotlinLogging.logger {} - @JvmStatic fun main(args: Array) { CommandLine(EdgeFilter()).execute(*args) diff --git a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt index f229bd1b67..2698df0b75 100644 --- a/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt +++ b/analysis/filter/MergeFilter/src/main/kotlin/de/maibornwolff/codecharta/filter/mergefilter/MergeFilter.kt @@ -59,8 +59,7 @@ class MergeFilter( } if (!InputHelper.isInputValid(sources, canInputContainFolders = true)) { - logger.error("Input invalid files/folders for MergeFilter, stopping execution...") - return null + throw IllegalArgumentException("Input invalid files/folders for MergeFilter, stopping execution...") } val sourceFiles = InputHelper.getFileListFromValidatedResourceArray(sources) diff --git a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt index cb005801b2..cc6ea80c4a 100644 --- a/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt +++ b/analysis/filter/StructureModifier/src/main/kotlin/de/maibornwolff/codecharta/filter/structuremodifier/StructureModifier.kt @@ -82,8 +82,7 @@ class StructureModifier( } if (!InputHelper.isInputValid(arrayOf(source!!), canInputContainFolders = false)) { - logger.error("Input invalid file for StructureModifier, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for StructureModifier, stopping execution...") } val input = source!!.inputStream() diff --git a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt index e319479f79..1770845063 100644 --- a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt +++ b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/csv/CSVImporter.kt @@ -5,7 +5,6 @@ import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.util.InputHelper -import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.IOException @@ -46,8 +45,7 @@ class CSVImporter( @Throws(IOException::class) override fun call(): Void? { if (!InputHelper.isInputValid(files.toTypedArray(), canInputContainFolders = false)) { - logger.error("Input invalid file for CSVImporter, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for CSVImporter, stopping execution...") } val csvProjectBuilder = CSVProjectBuilder(pathSeparator, csvDelimiter, pathColumnName) @@ -60,7 +58,6 @@ class CSVImporter( } companion object { - private val logger = KotlinLogging.logger {} @JvmStatic fun main(args: Array) { diff --git a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt index 91fe72cd97..cd3c21d454 100644 --- a/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt +++ b/analysis/import/CSVImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcemonitor/SourceMonitorImporter.kt @@ -7,7 +7,6 @@ import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.translator.MetricNameTranslator import de.maibornwolff.codecharta.util.InputHelper -import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.IOException @@ -43,8 +42,7 @@ class SourceMonitorImporter( @Throws(IOException::class) override fun call(): Void? { if (!InputHelper.isInputValid(files.toTypedArray(), canInputContainFolders = false)) { - logger.error("Input invalid file for SourceMonitorImporter, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for SourceMonitorImporter, stopping execution...") } val csvProjectBuilder = @@ -85,8 +83,6 @@ class SourceMonitorImporter( } companion object { - private val logger = KotlinLogging.logger {} - @JvmStatic fun main(args: Array) { CommandLine(SourceMonitorImporter()).execute(*args) diff --git a/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt b/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt index d51771848c..f7d39ce245 100644 --- a/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt +++ b/analysis/import/CodeMaatImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/codemaat/CodeMaatImporter.kt @@ -8,7 +8,6 @@ import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.translator.MetricNameTranslator import de.maibornwolff.codecharta.util.InputHelper -import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.IOException @@ -43,8 +42,7 @@ class CodeMaatImporter( @Throws(IOException::class) override fun call(): Void? { if (!InputHelper.isInputValid(files.toTypedArray(), canInputContainFolders = false)) { - logger.error("Input invalid file for CodeMaatImporter, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for CodeMaatImporter, stopping execution...") } val csvProjectBuilder = @@ -80,8 +78,6 @@ class CodeMaatImporter( } companion object { - private val logger = KotlinLogging.logger {} - @JvmStatic fun main(args: Array) { CommandLine(CodeMaatImporter()).execute(*args) diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt index 25d1f8c332..35a25c0d7d 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/LogScanCommand.kt @@ -4,7 +4,6 @@ import de.maibornwolff.codecharta.importer.gitlogparser.GitLogParser import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.util.InputHelper -import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.util.concurrent.Callable @@ -54,14 +53,9 @@ class LogScanCommand : Callable, InteractiveParser { @CommandLine.Option(names = ["--add-author"], description = ["add an array of authors to every file"]) private var addAuthor = false - companion object { - private val logger = KotlinLogging.logger {} - } - override fun call(): Void? { if (!InputHelper.isInputValidAndNotNull(arrayOf(gitLogFile), canInputContainFolders = false)) { - logger.error("Input invalid file for GitLogScan, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for GitLogScan, stopping execution...") } GitLogParser().buildProject(gitLogFile!!, gitLsFile!!, outputFilePath, addAuthor, silent, compress) return null diff --git a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt index 66abc67a81..4e3dcde0db 100644 --- a/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt +++ b/analysis/import/GitLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/gitlogparser/subcommands/RepoScanCommand.kt @@ -5,7 +5,6 @@ import de.maibornwolff.codecharta.importer.gitlogparser.util.GitAdapter import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.util.InputHelper -import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.FileWriter @@ -47,15 +46,10 @@ class RepoScanCommand : Callable, InteractiveParser { @CommandLine.Option(names = ["--add-author"], description = ["add an array of authors to every file"]) private var addAuthor = false - companion object { - private val logger = KotlinLogging.logger {} - } - override fun call(): Void? { val repoPath: Path if (repoPathName == null || !InputHelper.isInputValid(arrayOf(File(repoPathName!!)), canInputContainFolders = true)) { - logger.error("Input invalid file for GitRepoScan, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for GitRepoScan, stopping execution...") } else { repoPath = Paths.get(repoPathName!!).normalize().toAbsolutePath() } diff --git a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt index 1393acc913..69db3b1a31 100644 --- a/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt +++ b/analysis/import/MetricGardenerImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/metricgardenerimporter/MetricGardenerImporter.kt @@ -54,8 +54,7 @@ class MetricGardenerImporter( @Throws(IOException::class) override fun call(): Void? { if (!InputHelper.isInputValidAndNotNull(arrayOf(inputFile), canInputContainFolders = true)) { - System.err.println("Input invalid file for MetricGardenerImporter, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for MetricGardenerImporter, stopping execution...") } if (!isJsonFile) { diff --git a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt index c31cb75dad..b9d496957f 100644 --- a/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt +++ b/analysis/import/SVNLogParser/src/main/kotlin/de/maibornwolff/codecharta/importer/svnlogparser/SVNLogParser.kt @@ -14,7 +14,6 @@ import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.util.InputHelper import de.maibornwolff.codecharta.util.ResourceSearchHelper -import mu.KotlinLogging import org.mozilla.universalchardet.UniversalDetector import picocli.CommandLine import java.io.File @@ -84,8 +83,7 @@ class SVNLogParser( print(" ") if (!InputHelper.isInputValidAndNotNull(arrayOf(file), canInputContainFolders = false)) { - logger.error("Input invalid file for SVNLogParser, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for SVNLogParser, stopping execution...") } var project = createProjectFromLog( @@ -128,7 +126,6 @@ class SVNLogParser( } companion object { - private val logger = KotlinLogging.logger {} @JvmStatic fun main(args: Array) { CommandLine(SVNLogParser()).execute(*args) diff --git a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt index 48fb233d13..2ad8186ed3 100644 --- a/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt +++ b/analysis/import/SonarImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/sonar/SonarImporterMain.kt @@ -82,8 +82,7 @@ class SonarImporterMain( override fun call(): Void? { if (url == "" || projectId == "") { - System.err.println("Input invalid Url or ProjectID for SonarImporter, stopping execution...") - return null + throw IllegalArgumentException("Input invalid Url or ProjectID for SonarImporter, stopping execution...") } val importer = createMeasuresAPIImporter() diff --git a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt index 26582abd17..f919be9926 100644 --- a/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt +++ b/analysis/import/SourceCodeParser/src/main/kotlin/de/maibornwolff/codecharta/importer/sourcecodeparser/SourceCodeParserMain.kt @@ -75,8 +75,7 @@ class SourceCodeParserMain( override fun call(): Void? { print(" ") if (!InputHelper.isInputValidAndNotNull(arrayOf(file), canInputContainFolders = true)) { - System.err.println("Input invalid file for SourceCodeParser, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for SourceCodeParser, stopping execution...") } if (defaultExcludes) exclude += DEFAULT_EXCLUDES diff --git a/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt b/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt index 8f92fdb21f..b271325b6a 100644 --- a/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt +++ b/analysis/import/TokeiImporter/src/main/kotlin/de/maibornwolff/codecharta/importer/tokeiimporter/TokeiImporter.kt @@ -104,7 +104,7 @@ class TokeiImporter( val bufferedReader = file!!.bufferedReader() root = JsonParser.parseReader(bufferedReader) } else { - logger.error("Input invalid file for TokeiImporter, stopping execution...") + throw IllegalArgumentException("Input invalid file for TokeiImporter, stopping execution...") } } } else { diff --git a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt index d29f7f120c..e2f1cbb84c 100644 --- a/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt +++ b/analysis/parser/RawTextParser/src/main/kotlin/de/maibornwolff/codecharta/parser/rawtextparser/RawTextParser.kt @@ -8,7 +8,6 @@ import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.util.InputHelper -import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.IOException @@ -77,8 +76,7 @@ class RawTextParser( override fun call(): Void? { print(" ") if (!InputHelper.isInputValidAndNotNull(arrayOf(inputFile), canInputContainFolders = true)) { - logger.error("Input invalid file for RawTextParser, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for RawTextParser, stopping execution...") } if (!withoutDefaultExcludes) exclude += DEFAULT_EXCLUDES @@ -104,7 +102,6 @@ class RawTextParser( } companion object { - private val logger = KotlinLogging.logger {} @JvmStatic fun mainWithInOut(outputStream: PrintStream, input: InputStream, error: PrintStream, args: Array) { CommandLine(RawTextParser(input, outputStream, error)).setOut(PrintWriter(outputStream)).execute(*args) diff --git a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt index d3adab4ebe..7528788fe4 100644 --- a/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt +++ b/analysis/tools/ValidationTool/src/main/kotlin/de/maibornwolff/codecharta/tools/validation/ValidationTool.kt @@ -4,7 +4,6 @@ import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface import de.maibornwolff.codecharta.tools.interactiveparser.util.InteractiveParserHelper import de.maibornwolff.codecharta.util.InputHelper -import mu.KotlinLogging import picocli.CommandLine import java.io.File import java.io.FileInputStream @@ -25,8 +24,7 @@ class ValidationTool : Callable, InteractiveParser { override fun call(): Void? { if (!InputHelper.isInputValidAndNotNull(arrayOf(file), canInputContainFolders = false)) { - logger.error("Input invalid file for ValidationTool, stopping execution...") - return null + throw IllegalArgumentException("Input invalid file for ValidationTool, stopping execution...") } EveritValidator(SCHEMA_PATH).validate(FileInputStream(file!!.absoluteFile)) @@ -35,8 +33,6 @@ class ValidationTool : Callable, InteractiveParser { } companion object { - private val logger = KotlinLogging.logger {} - const val SCHEMA_PATH = "cc.json" }