diff --git a/src/main/java/io/jenkins/plugins/util/AgentFileVisitor.java b/src/main/java/io/jenkins/plugins/util/AgentFileVisitor.java index d5fef04..bfc1b78 100644 --- a/src/main/java/io/jenkins/plugins/util/AgentFileVisitor.java +++ b/src/main/java/io/jenkins/plugins/util/AgentFileVisitor.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.apache.tools.ant.BuildException; @@ -110,8 +111,14 @@ else if (fileSystemFacade.isEmpty(file)) { } } else { - results.add(processFile(file, new CharsetValidation().getCharset(encoding), log)); - log.logInfo("Successfully processed file '%s'", fileName); + Optional result = processFile(file, new CharsetValidation().getCharset(encoding), log); + if (result.isPresent()) { + results.add(result.get()); + log.logInfo("Successfully processed file '%s'", fileName); + } + else { + log.logError("No result created for file '%s' due to some errors", fileName); + } } } return results; @@ -131,7 +138,7 @@ protected String plural(final int count, @SuppressWarnings("SameParameterValue") return String.format("%d %s%s", count, itemName, count == 1 ? "" : "s"); } - protected abstract T processFile(Path file, Charset charset, FilteredLog log); + protected abstract Optional processFile(Path file, Charset charset, FilteredLog log); /** * File system facade that can be replaced by a stub in unit tests. diff --git a/src/test/java/io/jenkins/plugins/util/AgentFileVisitorTest.java b/src/test/java/io/jenkins/plugins/util/AgentFileVisitorTest.java index 6307f76..9b14275 100644 --- a/src/test/java/io/jenkins/plugins/util/AgentFileVisitorTest.java +++ b/src/test/java/io/jenkins/plugins/util/AgentFileVisitorTest.java @@ -3,6 +3,7 @@ import java.io.File; import java.nio.charset.Charset; import java.nio.file.Path; +import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -30,6 +31,7 @@ class AgentFileVisitorTest extends SerializableTest { private static final String CONTENT = "Hello World!"; private static final String PATTERN = "**/*.txt"; + private static final String ENCODING = "UTF-8"; @TempDir private File workspace; @@ -38,7 +40,7 @@ class AgentFileVisitorTest extends SerializableTest { @CsvSource({"true, enabled", "false, disabled"}) @ParameterizedTest(name = "{index} => followSymbolicLinks={0}, message={1}") void shouldReportErrorOnEmptyResults(final boolean followLinks, final String message) { - StringScanner scanner = new StringScanner(PATTERN, "UTF-8", followLinks, true, + StringScanner scanner = new StringScanner(PATTERN, ENCODING, followLinks, true, createFileSystemFacade(followLinks)); FileVisitorResult actualResult = scanner.invoke(workspace, null); @@ -57,7 +59,7 @@ void shouldReportErrorOnEmptyResults(final boolean followLinks, final String mes @CsvSource({"true, enabled", "false, disabled"}) @ParameterizedTest(name = "{index} => followSymbolicLinks={0}, message={1}") void shouldReturnSingleResult(final boolean followLinks, final String message) { - StringScanner scanner = new StringScanner(PATTERN, "UTF-8", followLinks, true, + StringScanner scanner = new StringScanner(PATTERN, ENCODING, followLinks, true, createFileSystemFacade(followLinks, "/one.txt")); FileVisitorResult actualResult = scanner.invoke(workspace, null); @@ -75,7 +77,7 @@ void shouldReturnSingleResult(final boolean followLinks, final String message) { @CsvSource({"true, enabled", "false, disabled"}) @ParameterizedTest(name = "{index} => followSymbolicLinks={0}, message={1}") void shouldReturnMultipleResults(final boolean followLinks, final String message) { - StringScanner scanner = new StringScanner(PATTERN, "UTF-8", followLinks, true, + StringScanner scanner = new StringScanner(PATTERN, ENCODING, followLinks, true, createFileSystemFacade(followLinks, "/one.txt", "/two.txt")); FileVisitorResult actualResult = scanner.invoke(workspace, null); @@ -104,7 +106,7 @@ void shouldLogErrorForEmptyAndForbiddenFiles() { when(fileSystemFacade.resolve(workspace, "not-readable.txt")).thenReturn(notReadable); when(fileSystemFacade.isNotReadable(notReadable)).thenReturn(true); - StringScanner scanner = new StringScanner(PATTERN, "UTF-8", true, true, + StringScanner scanner = new StringScanner(PATTERN, ENCODING, true, true, fileSystemFacade); FileVisitorResult actualResult = scanner.invoke(workspace, null); @@ -130,7 +132,7 @@ void shouldSkipLoggingOfErrorsForEmptyFiles() { when(fileSystemFacade.resolve(workspace, "empty.txt")).thenReturn(empty); when(fileSystemFacade.isEmpty(empty)).thenReturn(true); - StringScanner scanner = new StringScanner(PATTERN, "UTF-8", true, false, + StringScanner scanner = new StringScanner(PATTERN, ENCODING, true, false, fileSystemFacade); FileVisitorResult actualResult = scanner.invoke(workspace, null); @@ -145,6 +147,24 @@ void shouldSkipLoggingOfErrorsForEmptyFiles() { assertThat(actualResult.getLog().getErrorMessages()).isEmpty(); } + @Test + @DisplayName("Should log error if no results are returned") + void shouldLogErrorIfNoResultIsAvailable() { + FileSystemFacade fileSystemFacade = createFileSystemFacade(false, "/one.txt"); + + EmptyScanner scanner = new EmptyScanner(fileSystemFacade); + + FileVisitorResult actualResult = scanner.invoke(workspace, null); + assertThat(actualResult.getResults()).isEmpty(); + assertThat(actualResult.getLog().getInfoMessages()).containsExactly( + "Searching for all files in '/absolute/path' that match the pattern '**/*.txt'", + "Traversing of symbolic links: disabled", + "-> found 1 file"); + assertThat(actualResult.hasErrors()).isTrue(); + assertThat(actualResult.getLog().getErrorMessages()).containsExactly("Errors during parsing", + "No result created for file '/one.txt' due to some errors"); + } + private FileSystemFacade createFileSystemFacade(final boolean followLinks, final String... files) { FileSystemFacade fileSystem = mock(FileSystemFacade.class); @@ -156,7 +176,7 @@ private FileSystemFacade createFileSystemFacade(final boolean followLinks, final @Override protected StringScanner createSerializable() { - return new StringScanner(PATTERN, "UTF-8", true, true, createFileSystemFacade(true)); + return new StringScanner(PATTERN, ENCODING, true, true, createFileSystemFacade(true)); } static class StringScanner extends AgentFileVisitor { @@ -169,8 +189,35 @@ protected StringScanner(final String filePattern, final String encoding, final b } @Override - protected String processFile(final Path file, final Charset charset, final FilteredLog log) { - return CONTENT + counter++; + protected Optional processFile(final Path file, final Charset charset, final FilteredLog log) { + return Optional.of(CONTENT + counter++); + } + + @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") + @SuppressFBWarnings(value = "EQ_ALWAYS_TRUE", justification = "Required for serializable test") + @Override + public boolean equals(final Object o) { + return true; + } + + @Override + public int hashCode() { + return 0; + } + } + + private static class EmptyScanner extends AgentFileVisitor { + + private static final long serialVersionUID = 3700448215163706213L; + + @VisibleForTesting + protected EmptyScanner(final FileSystemFacade fileSystemFacade) { + super(PATTERN, ENCODING, false, false, fileSystemFacade); + } + + @Override + protected Optional processFile(final Path file, final Charset charset, final FilteredLog log) { + return Optional.empty(); } @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")