diff --git a/CHANGELOG.md b/CHANGELOG.md index 389145743d..6619eb1de9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/) - Show again delta of a building which have nothing in common in red or green [#3271](https://github.com/MaibornWolff/codecharta/pull/3271) - Always show description of suspicious metrics [#3285](https://github.com/MaibornWolff/codecharta/pull/3285) - Show suspicious metrics and risk profile documentation pages in navigation bar [#3290](https://github.com/MaibornWolff/codecharta/pull/3290) +- Merge filter will now abort execution when an invalid file is specified as input [#3305](https://github.com/MaibornWolff/codecharta/pull/3305) - Fix formatting issues in docs turning `--` to `–` [#3301](https://github.com/MaibornWolff/codecharta/pull/3301) ### Changed 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 e141832d6d..c28407811a 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 @@ -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 @@ -57,9 +58,10 @@ class MergeFilter( ) } - val sourceFiles = mutableListOf() - for (source in sources) { - sourceFiles.addAll(getFilesInFolder(source)) + val sourceFiles = InputHelper.getAndCheckAllSpecifiedInputFiles(sources) + if (sourceFiles.isEmpty()) { + logger.error("Aborting execution because one or more input files have not been found or no input was specified at all!") + return null } val srcProjects = sourceFiles @@ -80,11 +82,6 @@ class MergeFilter( return null } - private fun getFilesInFolder(folder: File): List { - val files = folder.walk().filter { !it.name.startsWith(".") && !it.isDirectory } - return files.toList() - } - companion object { fun mergePipedWithCurrentProject(pipedProject: Project, currentProject: Project): Project { return ProjectMerger( 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 9637f914b6..dcda8783f3 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,11 +1,20 @@ 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 class MergeFilterTest { @@ -14,6 +23,11 @@ class MergeFilterTest { val errContent = ByteArrayOutputStream() val originalErr = System.err + @AfterEach + fun unmockEverything() { + unmockkAll() + } + @Test fun `should merge all files in a folder correctly`() { val projectLocation = "src/test/resources/mergeFolderTest" @@ -54,9 +68,12 @@ class MergeFilterTest { @Test fun `should create json uncompressed file`() { + val inputFile1 = "src/test/resources/test.json" + val inputFile2 = "src/test/resources/test2.json" + main( arrayOf( - "src/test/resources/test.json", "src/test/resources/test2.json", "-nc", + inputFile1, inputFile2, "-nc", "-o=src/test/resources/output" ) ) @@ -79,4 +96,28 @@ class MergeFilterTest { assertThat(file.exists()).isTrue } + + @Test + fun `should abort if at least one input file does not exist`() { + mockkObject(InputHelper) + every { + InputHelper.getAndCheckAllSpecifiedInputFiles(any()) + } returns mutableListOf() + + mockkObject(ProjectDeserializer) + every { + ProjectDeserializer.deserializeProject(any()) + } returns Project("") + + 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 one or more input files have not been found or no input was specified at all!") + + 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 new file mode 100644 index 0000000000..b3d107df28 --- /dev/null +++ b/analysis/model/src/main/kotlin/de/maibornwolff/codecharta/util/InputHelper.kt @@ -0,0 +1,40 @@ +package de.maibornwolff.codecharta.util + +import mu.KotlinLogging +import java.io.File + +class InputHelper { + companion object { + private val logger = KotlinLogging.logger {} + + fun getAndCheckAllSpecifiedInputFiles(inputFiles: Array): MutableList { + if (inputFiles.isEmpty()) { + logger.error("Did not find any input files!") + return mutableListOf() + } + + val resultList = mutableListOf() + var doesInputContainNonexistentFile = false + + for (source in inputFiles) { + if (!source.exists()) { + logger.error("Could not find file `${ source.path }` and did not merge!") + doesInputContainNonexistentFile = true + } else { + resultList.addAll(getFilesInFolder(source)) + } + } + + return if (doesInputContainNonexistentFile) { + mutableListOf() + } else { + resultList + } + } + + private fun getFilesInFolder(folder: File): List { + val files = folder.walk().filter { !it.name.startsWith(".") && !it.isDirectory } + return files.toList() + } + } +} 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 new file mode 100644 index 0000000000..48a4bb68d0 --- /dev/null +++ b/analysis/model/src/test/kotlin/de/maibornwolff/codecharta/util/InputHelperTest.kt @@ -0,0 +1,74 @@ +package de.maibornwolff.codecharta.util + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.PrintStream + +class InputHelperTest { + val outContent = ByteArrayOutputStream() + val originalOut = System.out + val errContent = ByteArrayOutputStream() + val originalErr = System.err + + @Test + fun `should output warning for all files from parameters which were not found`() { + System.setOut(PrintStream(outContent)) + System.setErr(PrintStream(errContent)) + + 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")) + InputHelper.getAndCheckAllSpecifiedInputFiles(inputFiles) + + System.setOut(originalOut) + System.setErr(originalErr) + + Assertions.assertThat(errContent.toString()) + .contains("thisDoesNotExist1.json` and did not merge!") + Assertions.assertThat(errContent.toString()) + .contains("thisDoesNotExist2.json` and did not merge!") + } + + @Test + fun `should return empty list if input contains one nonexistent file`() { + 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() + } + + @Test + fun `should return empty list if no files are specified`() { + val inputFiles = arrayOf() + + System.setErr(PrintStream(errContent)) + val result = InputHelper.getAndCheckAllSpecifiedInputFiles(inputFiles) + 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`() { + 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) + + Assertions.assertThat(result).contains(validFile1) + Assertions.assertThat(result).contains(validFile2) + Assertions.assertThat(result).contains(validFile3) + + Assertions.assertThat(result.size).isEqualTo(inputFiles.size) + } +}