aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch/src/test/java
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-02-18 15:00:19 +0100
committerJulien HENRY <julien.henry@sonarsource.com>2014-02-18 15:02:05 +0100
commitc128fb65044ab2664b459e741d2e793112f540e4 (patch)
treeea10f482f7207c944706ab4463868d1450dbe311 /sonar-batch/src/test/java
parent9250493c833f593b55be4e09e59fafa8b198339c (diff)
downloadsonarqube-c128fb65044ab2664b459e741d2e793112f540e4.tar.gz
sonarqube-c128fb65044ab2664b459e741d2e793112f540e4.zip
Issue exclusions patterns are now initialized prior to sensor phase
Diffstat (limited to 'sonar-batch/src/test/java')
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/EnforceIssuesFilterTest.java151
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilterTest.java69
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IssueExclusionsConfigurationTest.java33
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java142
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java72
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssuePatternTest.java115
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/LineRangeTest.java74
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternDecoderTest.java191
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternMatcherTest.java124
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java175
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java163
11 files changed, 1309 insertions, 0 deletions
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/EnforceIssuesFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/EnforceIssuesFilterTest.java
new file mode 100644
index 00000000000..9c1731097e5
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/EnforceIssuesFilterTest.java
@@ -0,0 +1,151 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore;
+
+import org.sonar.batch.issue.ignore.EnforceIssuesFilter;
+import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
+import org.sonar.batch.issue.ignore.pattern.IssuePattern;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.batch.IssueFilterChain;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.WildcardPattern;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class EnforceIssuesFilterTest {
+
+ private IssueInclusionPatternInitializer exclusionPatternInitializer;
+ private EnforceIssuesFilter ignoreFilter;
+ private Issue issue;
+ private IssueFilterChain chain;
+
+ @Before
+ public void init() {
+ exclusionPatternInitializer = mock(IssueInclusionPatternInitializer.class);
+ issue = mock(Issue.class);
+ chain = mock(IssueFilterChain.class);
+ when(chain.accept(issue)).thenReturn(true);
+
+ ignoreFilter = new EnforceIssuesFilter(exclusionPatternInitializer);
+ }
+
+ @Test
+ public void shouldPassToChainIfNoConfiguredPatterns() {
+ assertThat(ignoreFilter.accept(issue, chain)).isTrue();
+ verify(chain).accept(issue);
+ }
+
+ @Test
+ public void shouldPassToChainIfRuleDoesNotMatch() {
+ String rule = "rule";
+ RuleKey ruleKey = mock(RuleKey.class);
+ when(ruleKey.toString()).thenReturn(rule);
+ when(issue.ruleKey()).thenReturn(ruleKey);
+
+ IssuePattern matching = mock(IssuePattern.class);
+ WildcardPattern rulePattern = mock(WildcardPattern.class);
+ when(matching.getRulePattern()).thenReturn(rulePattern);
+ when(rulePattern.match(rule)).thenReturn(false);
+ when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching));
+
+ assertThat(ignoreFilter.accept(issue, chain)).isTrue();
+ verify(chain).accept(issue);
+ }
+
+ @Test
+ public void shouldAcceptIssueIfFullyMatched() {
+ String rule = "rule";
+ String path = "org/sonar/api/Issue.java";
+ String componentKey = "org.sonar.api.Issue";
+ RuleKey ruleKey = mock(RuleKey.class);
+ when(ruleKey.toString()).thenReturn(rule);
+ when(issue.ruleKey()).thenReturn(ruleKey);
+ when(issue.componentKey()).thenReturn(componentKey);
+
+ IssuePattern matching = mock(IssuePattern.class);
+ WildcardPattern rulePattern = mock(WildcardPattern.class);
+ when(matching.getRulePattern()).thenReturn(rulePattern);
+ when(rulePattern.match(rule)).thenReturn(true);
+ WildcardPattern pathPattern = mock(WildcardPattern.class);
+ when(matching.getResourcePattern()).thenReturn(pathPattern);
+ when(pathPattern.match(path)).thenReturn(true);
+ when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching));
+ when(exclusionPatternInitializer.getPathForComponent(componentKey)).thenReturn(path);
+
+ assertThat(ignoreFilter.accept(issue, chain)).isTrue();
+ verifyZeroInteractions(chain);
+ }
+
+ @Test
+ public void shouldRefuseIssueIfRuleMatchesButNotPath() {
+ String rule = "rule";
+ String path = "org/sonar/api/Issue.java";
+ String componentKey = "org.sonar.api.Issue";
+ RuleKey ruleKey = mock(RuleKey.class);
+ when(ruleKey.toString()).thenReturn(rule);
+ when(issue.ruleKey()).thenReturn(ruleKey);
+ when(issue.componentKey()).thenReturn(componentKey);
+
+ IssuePattern matching = mock(IssuePattern.class);
+ WildcardPattern rulePattern = mock(WildcardPattern.class);
+ when(matching.getRulePattern()).thenReturn(rulePattern);
+ when(rulePattern.match(rule)).thenReturn(true);
+ WildcardPattern pathPattern = mock(WildcardPattern.class);
+ when(matching.getResourcePattern()).thenReturn(pathPattern);
+ when(pathPattern.match(path)).thenReturn(false);
+ when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching));
+ when(exclusionPatternInitializer.getPathForComponent(componentKey)).thenReturn(path);
+
+ assertThat(ignoreFilter.accept(issue, chain)).isFalse();
+ verifyZeroInteractions(chain);
+ }
+
+ @Test
+ public void shouldRefuseIssueIfRuleMatchesAndPathUnknown() {
+ String rule = "rule";
+ String path = "org/sonar/api/Issue.java";
+ String componentKey = "org.sonar.api.Issue";
+ RuleKey ruleKey = mock(RuleKey.class);
+ when(ruleKey.toString()).thenReturn(rule);
+ when(issue.ruleKey()).thenReturn(ruleKey);
+ when(issue.componentKey()).thenReturn(componentKey);
+
+ IssuePattern matching = mock(IssuePattern.class);
+ WildcardPattern rulePattern = mock(WildcardPattern.class);
+ when(matching.getRulePattern()).thenReturn(rulePattern);
+ when(rulePattern.match(rule)).thenReturn(true);
+ WildcardPattern pathPattern = mock(WildcardPattern.class);
+ when(matching.getResourcePattern()).thenReturn(pathPattern);
+ when(pathPattern.match(path)).thenReturn(false);
+ when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching));
+ when(exclusionPatternInitializer.getPathForComponent(componentKey)).thenReturn(null);
+
+ assertThat(ignoreFilter.accept(issue, chain)).isFalse();
+ verifyZeroInteractions(chain);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilterTest.java
new file mode 100644
index 00000000000..2dae552a56a
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilterTest.java
@@ -0,0 +1,69 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore;
+
+import org.sonar.batch.issue.ignore.IgnoreIssuesFilter;
+import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
+import org.sonar.batch.issue.ignore.pattern.IssuePattern;
+import org.sonar.batch.issue.ignore.pattern.PatternMatcher;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.batch.IssueFilterChain;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class IgnoreIssuesFilterTest {
+
+ private IssueExclusionPatternInitializer exclusionPatternInitializer;
+ private PatternMatcher exclusionPatternMatcher;
+ private IgnoreIssuesFilter ignoreFilter;
+ private Issue issue;
+ private IssueFilterChain chain;
+
+ @Before
+ public void init() {
+ exclusionPatternMatcher = mock(PatternMatcher.class);
+ exclusionPatternInitializer = mock(IssueExclusionPatternInitializer.class);
+ when(exclusionPatternInitializer.getPatternMatcher()).thenReturn(exclusionPatternMatcher);
+ issue = mock(Issue.class);
+ chain = mock(IssueFilterChain.class);
+ when(chain.accept(issue)).thenReturn(true);
+
+ ignoreFilter = new IgnoreIssuesFilter(exclusionPatternInitializer);
+ }
+
+ @Test
+ public void shouldPassToChainIfMatcherHasNoPatternForIssue() {
+ when(exclusionPatternMatcher.getMatchingPattern(issue)).thenReturn(null);
+
+ assertThat(ignoreFilter.accept(issue, chain)).isTrue();
+ }
+
+ @Test
+ public void shouldAcceptOrRefuseIfMatcherHasPatternForIssue() {
+ when(exclusionPatternMatcher.getMatchingPattern(issue)).thenReturn(mock(IssuePattern.class));
+
+ assertThat(ignoreFilter.accept(issue, chain)).isFalse();
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IssueExclusionsConfigurationTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IssueExclusionsConfigurationTest.java
new file mode 100644
index 00000000000..ef93bd8a4c9
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IssueExclusionsConfigurationTest.java
@@ -0,0 +1,33 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore;
+
+import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration;
+
+import org.junit.Test;
+import static org.fest.assertions.Assertions.assertThat;
+
+public class IssueExclusionsConfigurationTest {
+ @Test
+ public void justForCoverage() {
+ assertThat(IssueExclusionsConfiguration.getPropertyDefinitions()).hasSize(4);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java
new file mode 100644
index 00000000000..fb769ec2569
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java
@@ -0,0 +1,142 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore.pattern;
+
+import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration;
+import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.SonarException;
+import static org.fest.assertions.Assertions.assertThat;
+
+public class IssueExclusionPatternInitializerTest {
+
+ private IssueExclusionPatternInitializer patternsInitializer;
+
+ private Settings settings;
+
+ @Before
+ public void init() {
+ settings = new Settings(new PropertyDefinitions(IssueExclusionsConfiguration.getPropertyDefinitions()));
+ patternsInitializer = new IssueExclusionPatternInitializer(settings);
+ }
+
+ @Test
+ public void testNoConfiguration() {
+ patternsInitializer.initPatterns();
+ assertThat(patternsInitializer.hasConfiguredPatterns()).isFalse();
+ assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0);
+ }
+
+ @Test
+ public void shouldHavePatternsBasedOnMulticriteriaPattern() {
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY, "1,2");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RESOURCE_KEY, "org/foo/Bar.java");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RULE_KEY, "*");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".2." + IssueExclusionsConfiguration.RESOURCE_KEY, "org/foo/Hello.java");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".2." + IssueExclusionsConfiguration.RULE_KEY, "checkstyle:MagicNumber");
+ patternsInitializer.initPatterns();
+
+ assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue();
+ assertThat(patternsInitializer.hasFileContentPattern()).isFalse();
+ assertThat(patternsInitializer.hasMulticriteriaPatterns()).isTrue();
+ assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(2);
+ assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(0);
+ assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(0);
+
+ patternsInitializer.initializePatternsForPath("org/foo/Bar.java", "org.foo.Bar");
+ patternsInitializer.initializePatternsForPath("org/foo/Baz.java", "org.foo.Baz");
+ patternsInitializer.initializePatternsForPath("org/foo/Hello.java", "org.foo.Hello");
+
+ assertThat(patternsInitializer.getPatternMatcher().getPatternsForComponent("org.foo.Bar")).hasSize(1);
+ assertThat(patternsInitializer.getPatternMatcher().getPatternsForComponent("org.foo.Baz")).hasSize(0);
+ assertThat(patternsInitializer.getPatternMatcher().getPatternsForComponent("org.foo.Hello")).hasSize(1);
+
+ }
+
+ @Test(expected = SonarException.class)
+ public void shouldLogInvalidResourceKey() {
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY, "1");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RESOURCE_KEY, "");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RULE_KEY, "*");
+ patternsInitializer.initPatterns();
+ }
+
+ @Test(expected = SonarException.class)
+ public void shouldLogInvalidRuleKey() {
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY, "1");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RESOURCE_KEY, "*");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RULE_KEY, "");
+ patternsInitializer.initPatterns();
+ }
+
+ @Test
+ public void shouldReturnBlockPattern() {
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY, "1,2,3");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".1." + IssueExclusionsConfiguration.BEGIN_BLOCK_REGEXP, "// SONAR-OFF");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".1." + IssueExclusionsConfiguration.END_BLOCK_REGEXP, "// SONAR-ON");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".2." + IssueExclusionsConfiguration.BEGIN_BLOCK_REGEXP, "// FOO-OFF");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".2." + IssueExclusionsConfiguration.END_BLOCK_REGEXP, "// FOO-ON");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".3." + IssueExclusionsConfiguration.BEGIN_BLOCK_REGEXP, "// IGNORE-TO-EOF");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".3." + IssueExclusionsConfiguration.END_BLOCK_REGEXP, "");
+ patternsInitializer.loadFileContentPatterns();
+
+ assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue();
+ assertThat(patternsInitializer.hasFileContentPattern()).isTrue();
+ assertThat(patternsInitializer.hasMulticriteriaPatterns()).isFalse();
+ assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0);
+ assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(3);
+ assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(0);
+ }
+
+ @Test(expected = SonarException.class)
+ public void shouldLogInvalidStartBlockPattern() {
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY, "1");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".1." + IssueExclusionsConfiguration.BEGIN_BLOCK_REGEXP, "");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".1." + IssueExclusionsConfiguration.END_BLOCK_REGEXP, "// SONAR-ON");
+ patternsInitializer.loadFileContentPatterns();
+ }
+
+ @Test
+ public void shouldReturnAllFilePattern() {
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY, "1,2");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY + ".1." + IssueExclusionsConfiguration.FILE_REGEXP, "@SONAR-IGNORE-ALL");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY + ".2." + IssueExclusionsConfiguration.FILE_REGEXP, "//FOO-IGNORE-ALL");
+ patternsInitializer.loadFileContentPatterns();
+
+ assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue();
+ assertThat(patternsInitializer.hasFileContentPattern()).isTrue();
+ assertThat(patternsInitializer.hasMulticriteriaPatterns()).isFalse();
+ assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0);
+ assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(0);
+ assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(2);
+ }
+
+ @Test(expected = SonarException.class)
+ public void shouldLogInvalidAllFilePattern() {
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY, "1");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY + ".1." + IssueExclusionsConfiguration.FILE_REGEXP, "");
+ patternsInitializer.loadFileContentPatterns();
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java
new file mode 100644
index 00000000000..59542512bfc
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java
@@ -0,0 +1,72 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore.pattern;
+
+import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration;
+import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import static org.fest.assertions.Assertions.assertThat;
+
+public class IssueInclusionPatternInitializerTest {
+
+ private IssueInclusionPatternInitializer patternsInitializer;
+
+ private Settings settings;
+
+ @Before
+ public void init() {
+ settings = new Settings(new PropertyDefinitions(IssueExclusionsConfiguration.getPropertyDefinitions()));
+ patternsInitializer = new IssueInclusionPatternInitializer(settings);
+ }
+
+ @Test
+ public void testNoConfiguration() {
+ patternsInitializer.initPatterns();
+ assertThat(patternsInitializer.hasConfiguredPatterns()).isFalse();
+ }
+
+ @Test
+ public void shouldHavePatternsBasedOnMulticriteriaPattern() {
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY, "1,2");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RESOURCE_KEY, "org/foo/Bar.java");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RULE_KEY, "*");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".2." + IssueExclusionsConfiguration.RESOURCE_KEY, "org/foo/Hello.java");
+ settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".2." + IssueExclusionsConfiguration.RULE_KEY, "checkstyle:MagicNumber");
+ patternsInitializer.initPatterns();
+
+ assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue();
+ assertThat(patternsInitializer.hasMulticriteriaPatterns()).isTrue();
+ assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(2);
+
+ patternsInitializer.initializePatternsForPath("org/foo/Bar.java", "org.foo.Bar");
+ patternsInitializer.initializePatternsForPath("org/foo/Baz.java", "org.foo.Baz");
+ patternsInitializer.initializePatternsForPath("org/foo/Hello.java", "org.foo.Hello");
+
+ assertThat(patternsInitializer.getPathForComponent("org.foo.Bar")).isEqualTo("org/foo/Bar.java");
+ assertThat(patternsInitializer.getPathForComponent("org.foo.Baz")).isEqualTo("org/foo/Baz.java");
+ assertThat(patternsInitializer.getPathForComponent("org.foo.Hello")).isEqualTo("org/foo/Hello.java");
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssuePatternTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssuePatternTest.java
new file mode 100644
index 00000000000..3c9d43dfe13
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssuePatternTest.java
@@ -0,0 +1,115 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore.pattern;
+
+import org.sonar.batch.issue.ignore.pattern.IssuePattern;
+
+import org.junit.Test;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.Rule;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class IssuePatternTest {
+
+ @Test
+ public void shouldMatchLines() {
+ IssuePattern pattern = new IssuePattern("*", "*");
+ pattern.addLine(12).addLine(15).addLineRange(20, 25);
+
+ assertThat(pattern.matchLine(3)).isFalse();
+ assertThat(pattern.matchLine(12)).isTrue();
+ assertThat(pattern.matchLine(14)).isFalse();
+ assertThat(pattern.matchLine(21)).isTrue();
+ assertThat(pattern.matchLine(6599)).isFalse();
+ }
+
+ @Test
+ public void shouldMatchJavaFile() {
+ String javaFile = "org.foo.Bar";
+ assertThat(new IssuePattern("org.foo.Bar", "*").matchResource(javaFile)).isTrue();
+ assertThat(new IssuePattern("org.foo.*", "*").matchResource(javaFile)).isTrue();
+ assertThat(new IssuePattern("*Bar", "*").matchResource(javaFile)).isTrue();
+ assertThat(new IssuePattern("*", "*").matchResource(javaFile)).isTrue();
+ assertThat(new IssuePattern("org.*.?ar", "*").matchResource(javaFile)).isTrue();
+
+ assertThat(new IssuePattern("org.other.Hello", "*").matchResource(javaFile)).isFalse();
+ assertThat(new IssuePattern("org.foo.Hello", "*").matchResource(javaFile)).isFalse();
+ assertThat(new IssuePattern("org.*.??ar", "*").matchResource(javaFile)).isFalse();
+ assertThat(new IssuePattern("org.*.??ar", "*").matchResource(null)).isFalse();
+ assertThat(new IssuePattern("org.*.??ar", "*").matchResource("plop")).isFalse();
+ }
+
+ @Test
+ public void shouldMatchRule() {
+ RuleKey rule = Rule.create("checkstyle", "IllegalRegexp", "").ruleKey();
+ assertThat(new IssuePattern("*", "*").matchRule(rule)).isTrue();
+ assertThat(new IssuePattern("*", "checkstyle:*").matchRule(rule)).isTrue();
+ assertThat(new IssuePattern("*", "checkstyle:IllegalRegexp").matchRule(rule)).isTrue();
+ assertThat(new IssuePattern("*", "checkstyle:Illegal*").matchRule(rule)).isTrue();
+ assertThat(new IssuePattern("*", "*:*Illegal*").matchRule(rule)).isTrue();
+
+ assertThat(new IssuePattern("*", "pmd:IllegalRegexp").matchRule(rule)).isFalse();
+ assertThat(new IssuePattern("*", "pmd:*").matchRule(rule)).isFalse();
+ assertThat(new IssuePattern("*", "*:Foo*IllegalRegexp").matchRule(rule)).isFalse();
+ }
+
+ @Test
+ public void shouldMatchViolation() {
+ Rule rule = Rule.create("checkstyle", "IllegalRegexp", "");
+ String javaFile = "org.foo.Bar";
+
+ IssuePattern pattern = new IssuePattern("*", "*");
+ pattern.addLine(12);
+
+ assertThat(pattern.match(create(rule, javaFile, null))).isFalse();
+ assertThat(pattern.match(create(rule, javaFile, 12))).isTrue();
+ assertThat(pattern.match(create((Rule) null, javaFile, 5))).isFalse();
+ assertThat(pattern.match(create(rule, null, null))).isFalse();
+ assertThat(pattern.match(create((Rule) null, null, null))).isFalse();
+ }
+
+ private Issue create(Rule rule, String component, Integer line) {
+ Issue mockIssue = mock(Issue.class);
+ RuleKey ruleKey = null;
+ if (rule != null) {
+ ruleKey = rule.ruleKey();
+ }
+ when(mockIssue.ruleKey()).thenReturn(ruleKey);
+ when(mockIssue.componentKey()).thenReturn(component);
+ when(mockIssue.line()).thenReturn(line);
+ return mockIssue;
+ }
+
+ @Test
+ public void shouldNotMatchNullRule() {
+ assertThat(new IssuePattern("*", "*").matchRule(null)).isFalse();
+ }
+
+ @Test
+ public void shouldPrintPatternToString() {
+ IssuePattern pattern = new IssuePattern("*", "checkstyle:*");
+
+ assertThat(pattern.toString()).isEqualTo("IssuePattern[resourcePattern=*,rulePattern=checkstyle:*,lines=[],lineRanges=[],beginBlockRegexp=<null>,endBlockRegexp=<null>,allFileRegexp=<null>,checkLines=true]");
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/LineRangeTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/LineRangeTest.java
new file mode 100644
index 00000000000..21df72ba862
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/LineRangeTest.java
@@ -0,0 +1,74 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore.pattern;
+
+import org.sonar.batch.issue.ignore.pattern.LineRange;
+
+import org.junit.Test;
+import static org.fest.assertions.Assertions.assertThat;
+
+public class LineRangeTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void lineRangeShouldBeOrdered() {
+ new LineRange(25, 12);
+ }
+
+ @Test
+ public void shouldConvertLineRangeToLines() {
+ LineRange range = new LineRange(12, 15);
+
+ assertThat(range.toLines()).containsOnly(12, 13, 14, 15);
+ }
+
+ @Test
+ public void shouldTestInclusionInRangeOfLines() {
+ LineRange range = new LineRange(12, 15);
+
+ assertThat(range.in(3)).isFalse();
+ assertThat(range.in(12)).isTrue();
+ assertThat(range.in(13)).isTrue();
+ assertThat(range.in(14)).isTrue();
+ assertThat(range.in(15)).isTrue();
+ assertThat(range.in(16)).isFalse();
+ }
+
+ @Test
+ public void testToString() throws Exception {
+ assertThat(new LineRange(12, 15).toString()).isEqualTo("[12-15]");
+ }
+
+ @Test
+ public void testEquals() throws Exception {
+ LineRange range = new LineRange(12, 15);
+ assertThat(range).isEqualTo(range);
+ assertThat(range).isEqualTo(new LineRange(12, 15));
+ assertThat(range).isNotEqualTo(new LineRange(12, 2000));
+ assertThat(range).isNotEqualTo(new LineRange(1000, 2000));
+ assertThat(range).isNotEqualTo(null);
+ assertThat(range).isNotEqualTo(new StringBuffer());
+ }
+
+ @Test
+ public void testHashCode() throws Exception {
+ assertThat(new LineRange(12, 15).hashCode()).isEqualTo(new LineRange(12, 15).hashCode());
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternDecoderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternDecoderTest.java
new file mode 100644
index 00000000000..b993e82e8ff
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternDecoderTest.java
@@ -0,0 +1,191 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore.pattern;
+
+import org.sonar.batch.issue.ignore.pattern.IssuePattern;
+import org.sonar.batch.issue.ignore.pattern.PatternDecoder;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.SonarException;
+
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class PatternDecoderTest {
+
+ private PatternDecoder decoder = new PatternDecoder();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void shouldReadString() {
+ String patternsList = "# a comment followed by a blank line\n\n" +
+ "# suppress all violations\n" +
+ "*;*;*\n\n" +
+ "# exclude a Java file\n" +
+ "com.foo.Bar;*;*\n\n" +
+ "# exclude a Java package\n" +
+ "com.foo.*;*;*\n\n" +
+ "# exclude a specific rule\n" +
+ "*;checkstyle:IllegalRegexp;*\n\n" +
+ "# exclude a specific rule on a specific file\n" +
+ "com.foo.Bar;checkstyle:IllegalRegexp;*\n";
+ List<IssuePattern> patterns = decoder.decode(patternsList);
+
+ assertThat(patterns).hasSize(5);
+ }
+
+ @Test
+ public void shouldCheckFormatOfResource() {
+ assertThat(PatternDecoder.isResource("")).isFalse();
+ assertThat(PatternDecoder.isResource("*")).isTrue();
+ assertThat(PatternDecoder.isResource("com.foo.*")).isTrue();
+ }
+
+ @Test
+ public void shouldCheckFormatOfRule() {
+ assertThat(PatternDecoder.isRule("")).isFalse();
+ assertThat(PatternDecoder.isRule("*")).isTrue();
+ assertThat(PatternDecoder.isRule("com.foo.*")).isTrue();
+ }
+
+ @Test
+ public void shouldCheckFormatOfLinesRange() {
+ assertThat(PatternDecoder.isLinesRange("")).isFalse();
+ assertThat(PatternDecoder.isLinesRange(" ")).isFalse();
+ assertThat(PatternDecoder.isLinesRange("12")).isFalse();
+ assertThat(PatternDecoder.isLinesRange("12,212")).isFalse();
+
+ assertThat(PatternDecoder.isLinesRange("*")).isTrue();
+ assertThat(PatternDecoder.isLinesRange("[]")).isTrue();
+ assertThat(PatternDecoder.isLinesRange("[13]")).isTrue();
+ assertThat(PatternDecoder.isLinesRange("[13,24]")).isTrue();
+ assertThat(PatternDecoder.isLinesRange("[13,24,25-500]")).isTrue();
+ assertThat(PatternDecoder.isLinesRange("[24-65]")).isTrue();
+ assertThat(PatternDecoder.isLinesRange("[13,24-65,84-89,122]")).isTrue();
+ }
+
+ @Test
+ public void shouldReadStarPatterns() {
+ IssuePattern pattern = decoder.decodeLine("*;*;*");
+
+ assertThat(pattern.getResourcePattern().toString()).isEqualTo("*");
+ assertThat(pattern.getRulePattern().toString()).isEqualTo("*");
+ assertThat(pattern.isCheckLines()).isFalse();
+ }
+
+ @Test
+ public void shouldReadLineIds() {
+ IssuePattern pattern = decoder.decodeLine("*;*;[10,25,98]");
+
+ assertThat(pattern.isCheckLines()).isTrue();
+ assertThat(pattern.getAllLines()).containsOnly(10, 25, 98);
+ }
+
+ @Test
+ public void shouldReadRangeOfLineIds() {
+ IssuePattern pattern = decoder.decodeLine("*;*;[10-12,25,97-100]");
+
+ assertThat(pattern.isCheckLines()).isTrue();
+ assertThat(pattern.getAllLines()).containsOnly(10, 11, 12, 25, 97, 98, 99, 100);
+ }
+
+ @Test
+ public void shouldNotExcludeLines() {
+ // [] is different than *
+ // - all violations are excluded on *
+ // * no violations are excluded on []
+ IssuePattern pattern = decoder.decodeLine("*;*;[]");
+
+ assertThat(pattern.isCheckLines()).isTrue();
+ assertThat(pattern.getAllLines()).isEmpty();
+ }
+
+ @Test
+ public void shouldReadBlockPattern() {
+ IssuePattern pattern = decoder.decodeLine("SONAR-OFF;SONAR-ON");
+
+ assertThat(pattern.getResourcePattern()).isNull();
+ assertThat(pattern.getBeginBlockRegexp()).isEqualTo("SONAR-OFF");
+ assertThat(pattern.getEndBlockRegexp()).isEqualTo("SONAR-ON");
+ }
+
+ @Test
+ public void shouldReadAllFilePattern() {
+ IssuePattern pattern = decoder.decodeLine("SONAR-ALL-OFF");
+
+ assertThat(pattern.getResourcePattern()).isNull();
+ assertThat(pattern.getAllFileRegexp()).isEqualTo("SONAR-ALL-OFF");
+ }
+
+ @Test
+ public void shouldFailToReadUncorrectLine1() {
+ thrown.expect(SonarException.class);
+ thrown.expectMessage("Exclusions > Issues : Invalid format. The following line has more than 3 fields separated by comma");
+
+ decoder.decode(";;;;");
+ }
+
+ @Test
+ public void shouldFailToReadUncorrectLine3() {
+ thrown.expect(SonarException.class);
+ thrown.expectMessage("Exclusions > Issues : Invalid format. The first field does not define a resource pattern");
+
+ decoder.decode(";*;*");
+ }
+
+ @Test
+ public void shouldFailToReadUncorrectLine4() {
+ thrown.expect(SonarException.class);
+ thrown.expectMessage("Exclusions > Issues : Invalid format. The second field does not define a rule pattern");
+
+ decoder.decode("*;;*");
+ }
+
+ @Test
+ public void shouldFailToReadUncorrectLine5() {
+ thrown.expect(SonarException.class);
+ thrown.expectMessage("Exclusions > Issues : Invalid format. The third field does not define a range of lines");
+
+ decoder.decode("*;*;blabla");
+ }
+
+ @Test
+ public void shouldFailToReadUncorrectLine6() {
+ thrown.expect(SonarException.class);
+ thrown.expectMessage("Exclusions > Issues : Invalid format. The first field does not define a regular expression");
+
+ decoder.decode(";ON");
+ }
+
+ @Test
+ public void shouldAcceptEmptyEndBlockRegexp() {
+ IssuePattern pattern = decoder.decodeLine("OFF;");
+
+ assertThat(pattern.getResourcePattern()).isNull();
+ assertThat(pattern.getBeginBlockRegexp()).isEqualTo("OFF");
+ assertThat(pattern.getEndBlockRegexp()).isEmpty();
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternMatcherTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternMatcherTest.java
new file mode 100644
index 00000000000..a948aac47f7
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternMatcherTest.java
@@ -0,0 +1,124 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.issue.ignore.pattern;
+
+import org.sonar.batch.issue.ignore.pattern.IssuePattern;
+import org.sonar.batch.issue.ignore.pattern.LineRange;
+import org.sonar.batch.issue.ignore.pattern.PatternDecoder;
+import org.sonar.batch.issue.ignore.pattern.PatternMatcher;
+
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.Rule;
+
+import java.io.IOException;
+import java.util.Set;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class PatternMatcherTest {
+
+ public static final Rule CHECKSTYLE_RULE = Rule.create("checkstyle", "MagicNumber", "");
+ public static final String JAVA_FILE = "org.foo.Hello";
+
+ private PatternMatcher patternMatcher;
+
+ @Before
+ public void setUp() {
+ patternMatcher = new PatternMatcher();
+ }
+
+ @Test
+ public void shouldReturnExtraPatternForResource() {
+ String file = "foo";
+ patternMatcher.addPatternToExcludeResource(file);
+
+ IssuePattern extraPattern = patternMatcher.getPatternsForComponent(file).iterator().next();
+ assertThat(extraPattern.matchResource(file)).isTrue();
+ assertThat(extraPattern.isCheckLines()).isFalse();
+ }
+
+ @Test
+ public void shouldReturnExtraPatternForLinesOfResource() {
+ String file = "foo";
+ Set<LineRange> lineRanges = Sets.newHashSet();
+ lineRanges.add(new LineRange(25, 28));
+ patternMatcher.addPatternToExcludeLines(file, lineRanges);
+
+ IssuePattern extraPattern = patternMatcher.getPatternsForComponent(file).iterator().next();
+ assertThat(extraPattern.matchResource(file)).isTrue();
+ assertThat(extraPattern.getAllLines()).isEqualTo(Sets.newHashSet(25, 26, 27, 28));
+ }
+
+ @Test
+ public void shouldHaveNoMatcherIfNoneDefined() {
+ assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, null))).isNull();
+ }
+
+ @Test
+ public void shouldMatchWithStandardPatterns() throws IOException {
+ patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;checkstyle:MagicNumber;[15-200]"));
+
+ assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isNotNull();
+ }
+
+ @Test
+ public void shouldNotMatchWithStandardPatterns() throws IOException {
+ patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;checkstyle:MagicNumber;[15-200]"));
+
+ assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isNull();
+ }
+
+ @Test
+ public void shouldMatchWithExtraPattern() throws IOException {
+ patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;*;[15-200]"));
+
+ assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isNotNull();
+ }
+
+ @Test
+ public void shouldNotMatchWithExtraPattern() throws IOException {
+ patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;*;[15-200]"));
+
+ assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isNull();
+ }
+
+ private Issue create(Rule rule, String component, Integer line) {
+ Issue mockIssue = mock(Issue.class);
+ RuleKey ruleKey = null;
+ if (rule != null) {
+ ruleKey = rule.ruleKey();
+ }
+ when(mockIssue.ruleKey()).thenReturn(ruleKey);
+ when(mockIssue.componentKey()).thenReturn(component);
+ when(mockIssue.line()).thenReturn(line);
+ return mockIssue;
+ }
+
+ private IssuePattern createPattern(String line) {
+ return new PatternDecoder().decode(line).get(0);
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java
new file mode 100644
index 00000000000..8f8eba536f7
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java
@@ -0,0 +1,175 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore.scanner;
+
+import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
+import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
+import org.sonar.batch.issue.ignore.pattern.PatternMatcher;
+import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
+import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner;
+
+import com.google.common.base.Charsets;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.sonar.api.scan.filesystem.FileQuery;
+import org.sonar.api.scan.filesystem.internal.DefaultInputFile;
+import org.sonar.api.scan.filesystem.internal.InputFileBuilder;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+import static com.google.common.base.Charsets.UTF_8;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class IssueExclusionsLoaderTest {
+
+ private IssueExclusionsLoader scanner;
+
+ @Mock
+ private IssueExclusionsRegexpScanner regexpScanner;
+ @Mock
+ private IssueInclusionPatternInitializer inclusionPatternInitializer;
+ @Mock
+ private IssueExclusionPatternInitializer exclusionPatternInitializer;
+ @Mock
+ private PatternMatcher patternMatcher;
+ @Mock
+ private DefaultModuleFileSystem fs;
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private File baseDir;
+
+ @Before
+ public void init() throws IOException {
+ baseDir = temp.newFolder();
+ MockitoAnnotations.initMocks(this);
+
+ when(fs.sourceCharset()).thenReturn(UTF_8);
+
+ scanner = new IssueExclusionsLoader(regexpScanner, exclusionPatternInitializer, inclusionPatternInitializer, fs);
+ }
+
+ @Test
+ public void testToString() throws Exception {
+ assertThat(scanner.toString()).isEqualTo("Issues Exclusions - Source Scanner");
+ }
+
+ @Test
+ public void shouldExecute() throws IOException {
+ when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true);
+ when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true);
+ assertThat(scanner.shouldExecuteOnProject(null)).isTrue();
+
+ when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true);
+ when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false);
+ assertThat(scanner.shouldExecuteOnProject(null)).isTrue();
+
+ when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false);
+ when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true);
+ assertThat(scanner.shouldExecuteOnProject(null)).isTrue();
+
+ when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false);
+ when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false);
+ assertThat(scanner.shouldExecuteOnProject(null)).isFalse();
+
+ }
+
+ @Test
+ public void shouldAnalyseProject() throws IOException {
+ File javaFile1 = new File(baseDir, "src/main/java/Foo.java");
+ File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java");
+ when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList(
+ new InputFileBuilder(javaFile1, Charsets.UTF_8, "src/main/java/Foo.java")
+ .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/main/java/Foo.java")
+ .build(),
+ new InputFileBuilder(javaTestFile1, Charsets.UTF_8, "src/test/java/FooTest.java")
+ .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/test/java/FooTest.java")
+ .build()));
+
+ when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true);
+
+ scanner.execute();
+
+ verify(inclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java");
+ verify(inclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java");
+ verify(exclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java");
+ verify(exclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java");
+ verify(regexpScanner).scan("polop:src/main/java/Foo.java", javaFile1, UTF_8);
+ verify(regexpScanner).scan("polop:src/test/java/FooTest.java", javaTestFile1, UTF_8);
+ }
+
+ @Test
+ public void shouldAnalyseFilesOnlyWhenRegexConfigured() throws IOException {
+ File javaFile1 = new File(baseDir, "src/main/java/Foo.java");
+ File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java");
+ when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList(
+ new InputFileBuilder(javaFile1, Charsets.UTF_8, "src/main/java/Foo.java")
+ .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/main/java/Foo.java")
+ .build(),
+ new InputFileBuilder(javaTestFile1, Charsets.UTF_8, "src/test/java/FooTest.java")
+ .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/test/java/FooTest.java")
+ .build()));
+
+ when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(false);
+
+ scanner.execute();
+
+ verify(inclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java");
+ verify(inclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java");
+ verify(exclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java");
+ verify(exclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java");
+ verifyZeroInteractions(regexpScanner);
+ }
+
+ @Test
+ public void shouldReportFailure() throws IOException {
+ File phpFile1 = new File(baseDir, "src/Foo.php");
+ when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList(
+ new InputFileBuilder(phpFile1, Charsets.UTF_8, "src/Foo.php")
+ .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/Foo.php")
+ .build()));
+
+ when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true);
+ doThrow(new IOException("BUG")).when(regexpScanner).scan("polop:src/Foo.php", phpFile1, UTF_8);
+
+ thrown.expect(SonarException.class);
+ thrown.expectMessage("Unable to read the source file");
+
+ scanner.execute();
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java
new file mode 100644
index 00000000000..d50c3778e32
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java
@@ -0,0 +1,163 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.batch.issue.ignore.scanner;
+
+import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
+import org.sonar.batch.issue.ignore.pattern.IssuePattern;
+import org.sonar.batch.issue.ignore.pattern.LineRange;
+import org.sonar.batch.issue.ignore.pattern.PatternMatcher;
+import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner;
+
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.sonar.test.TestUtils;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Set;
+
+import static com.google.common.base.Charsets.UTF_8;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+public class IssueExclusionsRegexpScannerTest {
+
+ private IssueExclusionsRegexpScanner regexpScanner;
+
+ private String javaFile;
+ @Mock
+ private IssueExclusionPatternInitializer patternsInitializer;
+ @Mock
+ private PatternMatcher patternMatcher;
+ @Mock
+ private IssuePattern allFilePattern;
+ @Mock
+ private IssuePattern blockPattern1;
+ @Mock
+ private IssuePattern blockPattern2;
+
+ @Before
+ public void init() {
+ MockitoAnnotations.initMocks(this);
+
+ when(allFilePattern.getAllFileRegexp()).thenReturn("@SONAR-IGNORE-ALL");
+ when(blockPattern1.getBeginBlockRegexp()).thenReturn("// SONAR-OFF");
+ when(blockPattern1.getEndBlockRegexp()).thenReturn("// SONAR-ON");
+ when(blockPattern2.getBeginBlockRegexp()).thenReturn("// FOO-OFF");
+ when(blockPattern2.getEndBlockRegexp()).thenReturn("// FOO-ON");
+ when(patternsInitializer.getAllFilePatterns()).thenReturn(Arrays.asList(allFilePattern));
+ when(patternsInitializer.getBlockPatterns()).thenReturn(Arrays.asList(blockPattern1, blockPattern2));
+ when(patternsInitializer.getPatternMatcher()).thenReturn(patternMatcher);
+
+ regexpScanner = new IssueExclusionsRegexpScanner(patternsInitializer);
+ verify(patternsInitializer, times(1)).getAllFilePatterns();
+ verify(patternsInitializer, times(1)).getBlockPatterns();
+
+ javaFile = "org.sonar.test.MyFile";
+ }
+
+ @Test
+ public void shouldDoNothing() throws IOException {
+ regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-no-regexp.txt"), UTF_8);
+
+ verifyNoMoreInteractions(patternsInitializer);
+ }
+
+ @Test
+ public void shouldAddPatternToExcludeFile() throws IOException {
+ regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-single-regexp.txt"), UTF_8);
+
+ verify(patternsInitializer).getPatternMatcher();
+ verify(patternMatcher, times(1)).addPatternToExcludeResource(javaFile);
+ verifyNoMoreInteractions(patternsInitializer);
+ }
+
+ @Test
+ public void shouldAddPatternToExcludeFileEvenIfAlsoDoubleRegexps() throws IOException {
+ regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-single-regexp-and-double-regexp.txt"), UTF_8);
+
+ verify(patternsInitializer).getPatternMatcher();
+ verify(patternMatcher, times(1)).addPatternToExcludeResource(javaFile);
+ verifyNoMoreInteractions(patternsInitializer);
+ }
+
+ @Test
+ public void shouldAddPatternToExcludeLines() throws IOException {
+ regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp.txt"), UTF_8);
+
+ Set<LineRange> lineRanges = Sets.newHashSet();
+ lineRanges.add(new LineRange(21, 25));
+ verify(patternsInitializer).getPatternMatcher();
+ verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges);
+ verifyNoMoreInteractions(patternsInitializer);
+ }
+
+ @Test
+ public void shouldAddPatternToExcludeLinesTillTheEnd() throws IOException {
+ regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-unfinished.txt"), UTF_8);
+
+ Set<LineRange> lineRanges = Sets.newHashSet();
+ lineRanges.add(new LineRange(21, 34));
+ verify(patternsInitializer).getPatternMatcher();
+ verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges);
+ verifyNoMoreInteractions(patternsInitializer);
+ }
+
+ @Test
+ public void shouldAddPatternToExcludeSeveralLineRanges() throws IOException {
+ regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-twice.txt"), UTF_8);
+
+ Set<LineRange> lineRanges = Sets.newHashSet();
+ lineRanges.add(new LineRange(21, 25));
+ lineRanges.add(new LineRange(29, 33));
+ verify(patternsInitializer).getPatternMatcher();
+ verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges);
+ verifyNoMoreInteractions(patternsInitializer);
+ }
+
+ @Test
+ public void shouldAddPatternToExcludeLinesWithWrongOrder() throws IOException {
+ regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-wrong-order.txt"), UTF_8);
+
+ Set<LineRange> lineRanges = Sets.newHashSet();
+ lineRanges.add(new LineRange(25, 35));
+ verify(patternsInitializer).getPatternMatcher();
+ verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges);
+ verifyNoMoreInteractions(patternsInitializer);
+ }
+
+ @Test
+ public void shouldAddPatternToExcludeLinesWithMess() throws IOException {
+ regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-mess.txt"), UTF_8);
+
+ Set<LineRange> lineRanges = Sets.newHashSet();
+ lineRanges.add(new LineRange(21, 29));
+ verify(patternsInitializer).getPatternMatcher();
+ verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges);
+ verifyNoMoreInteractions(patternsInitializer);
+ }
+
+}