3 * Copyright (C) 2009-2022 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.ce.task.projectanalysis.pushevent;
22 import java.util.Date;
23 import java.util.List;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.sonar.api.rule.RuleKey;
28 import org.sonar.api.rules.RuleType;
29 import org.sonar.api.utils.DateUtils;
30 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
31 import org.sonar.ce.task.projectanalysis.analysis.TestBranch;
32 import org.sonar.ce.task.projectanalysis.component.Component.Type;
33 import org.sonar.ce.task.projectanalysis.component.MutableTreeRootHolderRule;
34 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
35 import org.sonar.ce.task.projectanalysis.locations.flow.FlowGenerator;
36 import org.sonar.core.issue.DefaultIssue;
37 import org.sonar.core.issue.FieldDiffs;
38 import org.sonar.db.protobuf.DbCommons;
39 import org.sonar.db.protobuf.DbIssues;
40 import org.sonar.server.issue.TaintChecker;
42 import static org.assertj.core.api.Assertions.assertThat;
43 import static org.mockito.ArgumentMatchers.any;
44 import static org.mockito.Mockito.mock;
45 import static org.mockito.Mockito.when;
47 public class PushEventFactoryTest {
49 private final TaintChecker taintChecker = mock(TaintChecker.class);
51 public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule();
53 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
54 .setBranch(new TestBranch("develop"));
56 private final FlowGenerator flowGenerator = new FlowGenerator(treeRootHolder);
57 private final PushEventFactory underTest = new PushEventFactory(treeRootHolder, analysisMetadataHolder, taintChecker, flowGenerator);
61 when(taintChecker.getTaintRepositories()).thenReturn(List.of("roslyn.sonaranalyzer.security.cs",
62 "javasecurity", "jssecurity", "tssecurity", "phpsecurity", "pythonsecurity"));
63 when(taintChecker.isTaintVulnerability(any())).thenReturn(true);
68 public void raise_event_to_repository_if_taint_vulnerability_is_new() {
69 DefaultIssue defaultIssue = createDefaultIssue()
72 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue))
74 .hasValueSatisfying(pushEventDto -> {
75 assertThat(pushEventDto.getName()).isEqualTo("TaintVulnerabilityRaised");
76 assertThat(pushEventDto.getPayload()).isNotNull();
77 assertThat(pushEventDto.getLanguage()).isEqualTo("java");
78 assertThat(pushEventDto.getProjectUuid()).isEqualTo("some-project-uuid");
84 public void raise_event_to_repository_if_taint_vulnerability_is_reopened() {
85 DefaultIssue defaultIssue = createDefaultIssue()
89 .setCurrentChange(new FieldDiffs().setDiff("status", "CLOSED", "OPEN"));
91 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue))
93 .hasValueSatisfying(pushEventDto -> {
94 assertThat(pushEventDto.getName()).isEqualTo("TaintVulnerabilityRaised");
95 assertThat(pushEventDto.getPayload()).isNotNull();
100 public void skip_event_if_taint_vulnerability_status_change() {
101 DefaultIssue defaultIssue = createDefaultIssue()
105 .setCurrentChange(new FieldDiffs().setDiff("status", "OPEN", "FIXED"));
107 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty();
111 public void raise_event_to_repository_if_taint_vulnerability_is_copied() {
112 DefaultIssue defaultIssue = createDefaultIssue()
115 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue))
117 .hasValueSatisfying(pushEventDto -> {
118 assertThat(pushEventDto.getName()).isEqualTo("TaintVulnerabilityRaised");
119 assertThat(pushEventDto.getPayload()).isNotNull();
124 public void raise_event_to_repository_if_taint_vulnerability_is_closed() {
125 DefaultIssue defaultIssue = createDefaultIssue()
126 .setComponentUuid("")
129 .setBeingClosed(true);
131 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue))
133 .hasValueSatisfying(pushEventDto -> {
134 assertThat(pushEventDto.getName()).isEqualTo("TaintVulnerabilityClosed");
135 assertThat(pushEventDto.getPayload()).isNotNull();
140 public void skip_issue_if_issue_changed() {
141 DefaultIssue defaultIssue = new DefaultIssue()
142 .setComponentUuid("issue-component-uuid")
146 .setType(RuleType.VULNERABILITY)
147 .setCreationDate(DateUtils.parseDate("2022-01-01"))
148 .setRuleKey(RuleKey.of("javasecurity", "S123"));
150 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty();
154 public void skip_if_issue_not_from_taint_vulnerability_repository() {
155 DefaultIssue defaultIssue = new DefaultIssue()
156 .setComponentUuid("issue-component-uuid")
158 .setType(RuleType.VULNERABILITY)
159 .setRuleKey(RuleKey.of("weirdrepo", "S123"));
161 when(taintChecker.isTaintVulnerability(any())).thenReturn(false);
163 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty();
165 defaultIssue = new DefaultIssue()
166 .setComponentUuid("issue-component-uuid")
169 .setBeingClosed(true)
170 .setType(RuleType.VULNERABILITY)
171 .setRuleKey(RuleKey.of("weirdrepo", "S123"));
173 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty();
177 public void skip_if_issue_is_a_hotspot() {
178 DefaultIssue defaultIssue = new DefaultIssue()
179 .setComponentUuid("issue-component-uuid")
181 .setType(RuleType.SECURITY_HOTSPOT)
182 .setRuleKey(RuleKey.of("javasecurity", "S123"));
184 when(taintChecker.isTaintVulnerability(any())).thenReturn(false);
186 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty();
190 public void skip_if_issue_does_not_have_locations() {
191 DefaultIssue defaultIssue = new DefaultIssue()
192 .setComponentUuid("issue-component-uuid")
194 .setType(RuleType.VULNERABILITY)
195 .setRuleKey(RuleKey.of("javasecurity", "S123"));
197 when(taintChecker.isTaintVulnerability(any())).thenReturn(false);
199 assertThat(underTest.raiseEventOnIssue("some-project-uuid", defaultIssue)).isEmpty();
202 private void buildComponentTree() {
203 treeRootHolder.setRoot(ReportComponent.builder(Type.PROJECT, 1)
205 .addChildren(ReportComponent.builder(Type.FILE, 2)
206 .setUuid("issue-component-uuid")
208 .addChildren(ReportComponent.builder(Type.FILE, 3)
209 .setUuid("location-component-uuid")
214 private DefaultIssue createDefaultIssue() {
215 return new DefaultIssue()
216 .setComponentUuid("issue-component-uuid")
217 .setType(RuleType.VULNERABILITY)
219 .setCreationDate(new Date())
220 .setLocations(DbIssues.Locations.newBuilder()
221 .addFlow(DbIssues.Flow.newBuilder()
222 .addLocation(DbIssues.Location.newBuilder()
223 .setChecksum("checksum")
224 .setComponentId("location-component-uuid")
227 .setTextRange(DbCommons.TextRange.newBuilder()
231 .setRuleKey(RuleKey.of("javasecurity", "S123"));