Issue #5127: Fixed NPE in JavadocPackageCheck when relative path is used to run checkstyle CLI
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocPackageCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocPackageCheck.java
index 18c22cd..e8190b7 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocPackageCheck.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocPackageCheck.java
@@ -20,10 +20,12 @@
package com.puppycrawl.tools.checkstyle.checks.javadoc;
import java.io.File;
+import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
+import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.FileText;
/**
@@ -67,9 +69,16 @@
}
@Override
- protected void processFiltered(File file, FileText fileText) {
+ protected void processFiltered(File file, FileText fileText) throws CheckstyleException {
// Check if already processed directory
- final File dir = file.getParentFile();
+ final File dir;
+ try {
+ dir = file.getCanonicalFile().getParentFile();
+ }
+ catch (IOException ex) {
+ throw new CheckstyleException(
+ "Exception while getting canonical path to file " + file.getPath(), ex);
+ }
final boolean isDirChecked = !directoriesChecked.add(dir);
if (!isDirChecked) {
// Check for the preferred file.
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocPackageCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocPackageCheckTest.java
index 9a76336..ac88193 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocPackageCheckTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocPackageCheckTest.java
@@ -21,14 +21,21 @@
import static com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck.MSG_LEGACY_PACKAGE_HTML;
import static com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck.MSG_PACKAGE_INFO;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
import java.io.File;
+import java.util.Collections;
import org.junit.Test;
import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
+import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
+import com.puppycrawl.tools.checkstyle.api.FileText;
import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
public class JavadocPackageCheckTest
@@ -123,4 +130,48 @@
getPath("annotation"
+ File.separator + "package-info.java"), expected);
}
+
+ /**
+ * Test require readable file with no parent to be used.
+ * Usage of Mockito.spy() is the only way to satisfy these requirements
+ * without the need to create new file in current working directory.
+ *
+ * @throws Exception if error occurs
+ */
+ @Test
+ public void testWithFileWithoutParent() throws Exception {
+ final DefaultConfiguration moduleConfig = createModuleConfig(JavadocPackageCheck.class);
+ final File fileWithoutParent = spy(new File(getPath("noparentfile"
+ + File.separator + "package-info.java")));
+ when(fileWithoutParent.getParent()).thenReturn(null);
+ when(fileWithoutParent.getParentFile()).thenReturn(null);
+ final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
+ verify(createChecker(moduleConfig),
+ new File[] {fileWithoutParent},
+ getPath("annotation"
+ + File.separator + "package-info.java"), expected);
+ }
+
+ /**
+ * Using direct call to check here because there is no other way
+ * to reproduce exception with invalid canonical path.
+ *
+ * @throws Exception if error occurs
+ */
+ @Test
+ public void testCheckstyleExceptionIfFailedToGetCanonicalPathToFile() throws Exception {
+ final JavadocPackageCheck check = new JavadocPackageCheck();
+ final File fileWithInvalidPath = new File("\u0000\u0000\u0000");
+ final FileText mockFileText = new FileText(fileWithInvalidPath, Collections.emptyList());
+ final String expectedExceptionMessage =
+ "Exception while getting canonical path to file " + fileWithInvalidPath.getPath();
+ try {
+ check.processFiltered(fileWithInvalidPath, mockFileText);
+ fail("CheckstyleException expected to be thrown");
+ }
+ catch (CheckstyleException ex) {
+ assertEquals("Invalid exception message. Expected: " + expectedExceptionMessage,
+ expectedExceptionMessage, ex.getMessage());
+ }
+ }
}
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocpackage/noparentfile/package-info.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocpackage/noparentfile/package-info.java
new file mode 100644
index 0000000..f7832c2
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocpackage/noparentfile/package-info.java
@@ -0,0 +1 @@
+package com.puppycrawl.tools.checkstyle.checks.javadoc.javadocpackage.noparentfile;