From c22cc5801ef1a80bddc6c13f2bfa19b03f27e820 Mon Sep 17 00:00:00 2001
From: liscju
Date: Sun, 3 Jan 2016 00:38:15 +0100
Subject: [PATCH] Issue #1002: Add optional attribute to suppression filter
---
pom.xml | 2 +-
.../checkstyle/filters/SuppressionFilter.java | 72 ++++++++-
.../filters/SuppressionFilterTest.java | 139 +++++++++++++++++-
src/xdocs/config_filters.xml | 16 +-
4 files changed, 217 insertions(+), 12 deletions(-)
diff --git a/pom.xml b/pom.xml
index ae26f0a83..a3ecd0f39 100644
--- a/pom.xml
+++ b/pom.xml
@@ -271,7 +271,7 @@
nl.jqno.equalsverifier
equalsverifier
- 1.7.6
+ 1.7.7
test
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilter.java
index 39465ab5b..9069f7ac9 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilter.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilter.java
@@ -19,6 +19,10 @@
package com.puppycrawl.tools.checkstyle.filters;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
import java.util.Objects;
import com.puppycrawl.tools.checkstyle.api.AuditEvent;
@@ -26,6 +30,7 @@ import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Filter;
import com.puppycrawl.tools.checkstyle.api.FilterSet;
+import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
/**
*
@@ -33,21 +38,32 @@ import com.puppycrawl.tools.checkstyle.api.FilterSet;
* column, as specified in a suppression file.
*
* @author Rick Giles
+ * @author liscju
*/
public class SuppressionFilter
extends AutomaticBean
implements Filter {
+ /** Filename of supression file. */
+ private String file;
+ /** Tells whether config file existence is optional. */
+ private boolean optional;
/** Set of individual suppresses. */
private FilterSet filters = new FilterSet();
/**
- * Loads the suppressions for a file.
+ * Sets name of the supression file.
* @param fileName name of the suppressions file.
- * @throws CheckstyleException if there is an error.
*/
- public void setFile(String fileName)
- throws CheckstyleException {
- filters = SuppressionsLoader.loadSuppressions(fileName);
+ public void setFile(String fileName) {
+ file = fileName;
+ }
+
+ /**
+ * Sets whether config file existence is optional.
+ * @param optional tells if config file existence is optional.
+ */
+ public void setOptional(boolean optional) {
+ this.optional = optional;
}
@Override
@@ -71,4 +87,50 @@ public class SuppressionFilter
public int hashCode() {
return Objects.hash(filters);
}
+
+ @Override
+ protected void finishLocalSetup() throws CheckstyleException {
+ if (file != null) {
+ if (optional) {
+ if (suppressionSourceExists(file)) {
+ filters = SuppressionsLoader.loadSuppressions(file);
+ }
+ else {
+ filters = new FilterSet();
+ }
+ }
+ else {
+ filters = SuppressionsLoader.loadSuppressions(file);
+ }
+ }
+ }
+
+ /**
+ * Checks if suppression source with given fileName exists.
+ * @param fileName name of the suppressions file.
+ * @return true if suppression file exists, otherwise false
+ */
+ private static boolean suppressionSourceExists(String fileName) {
+ boolean suppressionSourceExists = true;
+ InputStream sourceInput = null;
+ try {
+ final URI uriByFilename = CommonUtils.getUriByFilename(fileName);
+ final URL url = uriByFilename.toURL();
+ sourceInput = url.openStream();
+ }
+ catch (CheckstyleException | IOException ignored) {
+ suppressionSourceExists = false;
+ }
+ finally {
+ if (sourceInput != null) {
+ try {
+ sourceInput.close();
+ }
+ catch (IOException ignored) {
+ suppressionSourceExists = false;
+ }
+ }
+ }
+ return suppressionSourceExists;
+ }
}
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilterTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilterTest.java
index d065f4dc2..0fd06b8c4 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilterTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilterTest.java
@@ -19,14 +19,34 @@
package com.puppycrawl.tools.checkstyle.filters;
-import org.junit.Assert;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.mockito.BDDMockito;
+import org.mockito.Mockito;
+
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
import com.puppycrawl.tools.checkstyle.api.AuditEvent;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
+import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
+
import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({SuppressionFilter.class, CommonUtils.class})
public class SuppressionFilterTest {
@Test
public void testEqualsAndHashCode() {
@@ -39,13 +59,122 @@ public class SuppressionFilterTest {
@Test
public void testAccept() throws CheckstyleException {
- final SuppressionFilter filter = new SuppressionFilter();
- filter.setFile("src/test/resources/com/puppycrawl/tools/checkstyle/filters/"
- + "suppressions_none.xml");
+ final String fileName = "src/test/resources/com/puppycrawl/tools/checkstyle/filters/"
+ + "suppressions_none.xml";
+ final boolean optional = false;
+ final SuppressionFilter filter = createSupressionFilter(fileName, optional);
final AuditEvent ev = new AuditEvent(this, "ATest.java", null);
- Assert.assertTrue(filter.accept(ev));
+ assertTrue(filter.accept(ev));
}
+ @Test
+ public void testAcceptOnNullFile() throws CheckstyleException {
+ final String fileName = null;
+ final boolean optional = false;
+ final SuppressionFilter filter = createSupressionFilter(fileName, optional);
+
+ final AuditEvent ev = new AuditEvent(this, "AnyJava.java", null);
+
+ assertTrue(filter.accept(ev));
+ }
+
+ @Test
+ public void testNonExistanceSuppressionFileWithFalseOptional() throws Exception {
+ final String fileName = "src/test/resources/com/puppycrawl/tools/checkstyle/filters/"
+ + "non_existance_suppresion_file.xml";
+ try {
+ final boolean optional = false;
+ createSupressionFilter(fileName, optional);
+ fail("Exception is expected");
+ }
+ catch (CheckstyleException ex) {
+ assertEquals("Unable to find: " + fileName, ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testExistanceInvalidSuppressionFileWithTrueOptional() throws Exception {
+ final String fileName = "src/test/resources/com/puppycrawl/tools/checkstyle/filters/"
+ + "suppressions_invalid_file.xml";
+ try {
+ final boolean optional = true;
+ createSupressionFilter(fileName, optional);
+ fail("Exception is expected");
+ }
+ catch (CheckstyleException ex) {
+ assertEquals("Unable to parse " + fileName + " - invalid files or checks format",
+ ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testExistingSuppressionFileWithTrueOptional() throws Exception {
+ final String fileName = "src/test/resources/com/puppycrawl/tools/checkstyle/filters/"
+ + "suppressions_none.xml";
+ final boolean optional = true;
+ final SuppressionFilter filter = createSupressionFilter(fileName, optional);
+
+ final AuditEvent ev = new AuditEvent(this, "AnyFile.java", null);
+
+ assertTrue(filter.accept(ev));
+ }
+
+ @Test
+ public void testExistingConfigWithTrueOptionalThrowsIoErrorWhileClosing()
+ throws Exception {
+ final InputStream inputStream = PowerMockito.mock(InputStream.class);
+ Mockito.doThrow(IOException.class).when(inputStream).close();
+
+ final URL url = PowerMockito.mock(URL.class);
+ BDDMockito.given(url.openStream()).willReturn(inputStream);
+
+ final URI uri = PowerMockito.mock(URI.class);
+ BDDMockito.given(uri.toURL()).willReturn(url);
+
+ PowerMockito.mockStatic(CommonUtils.class);
+
+ final String fileName = "src/test/resources/com/puppycrawl/tools/checkstyle/filters/"
+ + "suppressions_none.xml";
+ BDDMockito.given(CommonUtils.getUriByFilename(fileName)).willReturn(uri);
+
+ final boolean optional = true;
+ final SuppressionFilter filter = createSupressionFilter(fileName, optional);
+ final AuditEvent ev = new AuditEvent(this, "AnyFile.java", null);
+ assertTrue(filter.accept(ev));
+ }
+
+ @Test
+ public void testNonExistanceSuppressionFileWithTrueOptional() throws Exception {
+ final String fileName = "src/test/resources/com/puppycrawl/tools/checkstyle/filters/"
+ + "non_existance_suppresion_file.xml";
+ final boolean optional = true;
+ final SuppressionFilter filter = createSupressionFilter(fileName, optional);
+
+ final AuditEvent ev = new AuditEvent(this, "AnyFile.java", null);
+
+ assertTrue(filter.accept(ev));
+ }
+
+ @Test
+ public void testNonExistanceSuppressionUrlWithTrueOptional() throws Exception {
+ final String fileName =
+ "http://checkstyle.sourceforge.net/non_existing_suppression.xml";
+ final boolean optional = true;
+ final SuppressionFilter filter = createSupressionFilter(fileName, optional);
+
+ final AuditEvent ev = new AuditEvent(this, "AnyFile.java", null);
+
+ assertTrue(filter.accept(ev));
+ }
+
+ private static SuppressionFilter createSupressionFilter(String fileName, boolean optional)
+ throws CheckstyleException {
+ final SuppressionFilter suppressionFilter = new SuppressionFilter();
+ suppressionFilter.setFile(fileName);
+ suppressionFilter.setOptional(optional);
+ suppressionFilter.finishLocalSetup();
+ return suppressionFilter;
+ }
}
diff --git a/src/xdocs/config_filters.xml b/src/xdocs/config_filters.xml
index 18563a246..aa8172203 100644
--- a/src/xdocs/config_filters.xml
+++ b/src/xdocs/config_filters.xml
@@ -389,7 +389,8 @@ public static void foo() {
audit events for Check errors according to
a suppressions XML
document in a file. If there is no configured
- suppressions file, the Filter accepts all audit events.
+ suppressions file or the optional is set to true and
+ suppressions file was not found the Filter accepts all audit events.
@@ -421,6 +422,18 @@ public static void foo() {
string
none
+
+ optional
+
+ Tells what to do when the file is not existing. If
+ optional is set to false the file must exist, or else
+ it ends with error. On the other hand if optional is
+ true and file is not found, the filter accept all
+ audit events.
+
+ boolean
+ false
+
@@ -433,6 +446,7 @@ public static void foo() {
<module name="SuppressionFilter">
<property name="file" value="config/suppressions.xml"/>
+ <property name="optional" value="false"/>
</module>