3 * Copyright (C) 2009-2023 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.step;
22 import java.util.Collections;
23 import java.util.Date;
24 import java.util.List;
25 import org.junit.Before;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.sonar.api.utils.System2;
29 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
30 import org.sonar.ce.task.projectanalysis.component.Component;
31 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
32 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
33 import org.sonar.ce.task.projectanalysis.event.Event;
34 import org.sonar.ce.task.projectanalysis.event.EventRepository;
35 import org.sonar.ce.task.step.ComputationStep;
36 import org.sonar.ce.task.step.TestComputationStepContext;
37 import org.sonar.core.util.UuidFactory;
38 import org.sonar.core.util.UuidFactoryImpl;
39 import org.sonar.db.DbTester;
40 import org.sonar.db.component.ComponentDto;
41 import org.sonar.db.event.EventDto;
43 import static org.assertj.core.api.Assertions.assertThat;
44 import static org.assertj.core.api.Assertions.fail;
45 import static org.mockito.Mockito.mock;
46 import static org.mockito.Mockito.when;
47 import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
48 import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
49 import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT;
50 import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
51 import static org.sonar.db.event.EventDto.CATEGORY_ALERT;
52 import static org.sonar.db.event.EventDto.CATEGORY_ISSUE_DETECTION;
53 import static org.sonar.db.event.EventDto.CATEGORY_PROFILE;
54 import static org.sonar.db.event.EventDto.CATEGORY_VERSION;
56 public class PersistEventsStepIT extends BaseStepTest {
58 private static final long NOW = 1225630680000L;
59 private static final ReportComponent ROOT = builder(PROJECT, 1)
61 .setProjectVersion("version_1")
75 private static final String ANALYSIS_UUID = "uuid_1";
77 System2 system2 = mock(System2.class);
80 public DbTester dbTester = DbTester.create(system2);
82 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
84 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
86 private final Date someDate = new Date(150000000L);
88 private final EventRepository eventRepository = mock(EventRepository.class);
89 private final UuidFactory uuidFactory = UuidFactoryImpl.INSTANCE;
91 private PersistEventsStep underTest;
95 analysisMetadataHolder.setAnalysisDate(someDate.getTime()).setUuid(ANALYSIS_UUID);
96 underTest = new PersistEventsStep(dbTester.getDbClient(), system2, treeRootHolder, analysisMetadataHolder, eventRepository, uuidFactory);
97 when(eventRepository.getEvents()).thenReturn(Collections.emptyList());
101 protected ComputationStep step() {
106 public void create_version_event() {
107 when(system2.now()).thenReturn(NOW);
108 Component project = builder(PROJECT, 1)
110 .setProjectVersion("1.0")
112 builder(DIRECTORY, 2)
115 builder(DIRECTORY, 3)
124 treeRootHolder.setRoot(project);
126 underTest.execute(new TestComputationStepContext());
128 assertThat(dbTester.countRowsOfTable(dbTester.getSession(), "events")).isOne();
129 List<EventDto> eventDtos = dbTester.getDbClient().eventDao().selectByComponentUuid(dbTester.getSession(), ROOT.getUuid());
130 assertThat(eventDtos).hasSize(1);
131 EventDto eventDto = eventDtos.iterator().next();
132 assertThat(eventDto.getComponentUuid()).isEqualTo(ROOT.getUuid());
133 assertThat(eventDto.getName()).isEqualTo("1.0");
134 assertThat(eventDto.getDescription()).isNull();
135 assertThat(eventDto.getCategory()).isEqualTo(CATEGORY_VERSION);
136 assertThat(eventDto.getData()).isNull();
137 assertThat(eventDto.getDate()).isEqualTo(analysisMetadataHolder.getAnalysisDate());
138 assertThat(eventDto.getCreatedAt()).isEqualTo(NOW);
142 public void persist_alert_events_on_root() {
143 when(system2.now()).thenReturn(NOW);
144 treeRootHolder.setRoot(ROOT);
145 Event alert = Event.createAlert("Failed", null, "Open issues > 0");
146 when(eventRepository.getEvents()).thenReturn(List.of(alert));
148 underTest.execute(new TestComputationStepContext());
150 assertThat(dbTester.countRowsOfTable(dbTester.getSession(), "events")).isEqualTo(2);
151 List<EventDto> eventDtos = dbTester.getDbClient().eventDao().selectByComponentUuid(dbTester.getSession(), ROOT.getUuid());
152 assertThat(eventDtos)
153 .extracting(EventDto::getCategory)
154 .containsOnly(CATEGORY_ALERT, CATEGORY_VERSION);
155 EventDto eventDto = eventDtos.stream().filter(t -> CATEGORY_ALERT.equals(t.getCategory())).findAny().get();
156 assertThat(eventDto.getComponentUuid()).isEqualTo(ROOT.getUuid());
157 assertThat(eventDto.getName()).isEqualTo(alert.getName());
158 assertThat(eventDto.getDescription()).isEqualTo(alert.getDescription());
159 assertThat(eventDto.getCategory()).isEqualTo(CATEGORY_ALERT);
160 assertThat(eventDto.getData()).isNull();
161 assertThat(eventDto.getDate()).isEqualTo(analysisMetadataHolder.getAnalysisDate());
162 assertThat(eventDto.getCreatedAt()).isEqualTo(NOW);
166 public void persist_profile_events_on_root() {
167 when(system2.now()).thenReturn(NOW);
168 treeRootHolder.setRoot(ROOT);
169 Event profile = Event.createProfile("foo", null, "bar");
170 when(eventRepository.getEvents()).thenReturn(List.of(profile));
172 underTest.execute(new TestComputationStepContext());
174 assertThat(dbTester.countRowsOfTable(dbTester.getSession(), "events")).isEqualTo(2);
175 List<EventDto> eventDtos = dbTester.getDbClient().eventDao().selectByComponentUuid(dbTester.getSession(), ROOT.getUuid());
176 assertThat(eventDtos)
177 .extracting(EventDto::getCategory)
178 .containsOnly(CATEGORY_PROFILE, CATEGORY_VERSION);
179 EventDto eventDto = eventDtos.stream().filter(t -> CATEGORY_PROFILE.equals(t.getCategory())).findAny().get();
180 assertThat(eventDto.getComponentUuid()).isEqualTo(ROOT.getUuid());
181 assertThat(eventDto.getName()).isEqualTo(profile.getName());
182 assertThat(eventDto.getDescription()).isEqualTo(profile.getDescription());
183 assertThat(eventDto.getCategory()).isEqualTo(EventDto.CATEGORY_PROFILE);
184 assertThat(eventDto.getData()).isNull();
185 assertThat(eventDto.getDate()).isEqualTo(analysisMetadataHolder.getAnalysisDate());
186 assertThat(eventDto.getCreatedAt()).isEqualTo(NOW);
190 public void execute_whenIssueDetectionEventRaised_shouldPersist() {
191 when(system2.now()).thenReturn(NOW);
192 treeRootHolder.setRoot(ROOT);
193 Event issueDetection = Event.createIssueDetection("Capabilities have changed (Xoo)");
194 when(eventRepository.getEvents()).thenReturn(List.of(issueDetection));
196 underTest.execute(new TestComputationStepContext());
198 assertThat(dbTester.countRowsOfTable(dbTester.getSession(), "events")).isEqualTo(2);
199 List<EventDto> eventDtos = dbTester.getDbClient().eventDao().selectByComponentUuid(dbTester.getSession(), ROOT.getUuid());
200 assertThat(eventDtos)
201 .extracting(EventDto::getCategory)
202 .containsOnly(CATEGORY_ISSUE_DETECTION, CATEGORY_VERSION);
203 EventDto eventDto = eventDtos.stream()
204 .filter(t -> CATEGORY_ISSUE_DETECTION.equals(t.getCategory()))
206 .orElseGet(() -> fail("Issue detection event not found"));
207 assertThat(eventDto.getComponentUuid()).isEqualTo(ROOT.getUuid());
208 assertThat(eventDto.getName()).isEqualTo(issueDetection.getName());
209 assertThat(eventDto.getDescription()).isEqualTo(issueDetection.getDescription());
210 assertThat(eventDto.getCategory()).isEqualTo(CATEGORY_ISSUE_DETECTION);
211 assertThat(eventDto.getData()).isNull();
212 assertThat(eventDto.getDate()).isEqualTo(analysisMetadataHolder.getAnalysisDate());
213 assertThat(eventDto.getCreatedAt()).isEqualTo(NOW);
217 public void keep_one_event_by_version() {
218 ComponentDto projectDto = dbTester.components().insertPublicProject().getMainBranchComponent();
219 EventDto[] existingEvents = new EventDto[] {
220 dbTester.events().insertEvent(newVersionEventDto(projectDto, 120_000_000L, "1.3-SNAPSHOT")),
221 dbTester.events().insertEvent(newVersionEventDto(projectDto, 130_000_000L, "1.4")),
222 dbTester.events().insertEvent(newVersionEventDto(projectDto, 140_000_000L, "1.5-SNAPSHOT"))
225 Component project = builder(PROJECT, 1)
226 .setUuid(projectDto.uuid())
227 .setProjectVersion("1.5-SNAPSHOT")
229 builder(DIRECTORY, 2)
232 builder(DIRECTORY, 3)
241 treeRootHolder.setRoot(project);
243 underTest.execute(new TestComputationStepContext());
245 assertThat(dbTester.countRowsOfTable(dbTester.getSession(), "events")).isEqualTo(3);
246 List<EventDto> eventDtos = dbTester.getDbClient().eventDao().selectByComponentUuid(dbTester.getSession(), projectDto.uuid());
247 assertThat(eventDtos).hasSize(3);
248 assertThat(eventDtos)
249 .extracting(EventDto::getName)
250 .containsOnly("1.3-SNAPSHOT", "1.4", "1.5-SNAPSHOT");
251 assertThat(eventDtos)
252 .extracting(EventDto::getUuid)
253 .contains(existingEvents[0].getUuid(), existingEvents[1].getUuid())
254 .doesNotContain(existingEvents[2].getUuid());
257 private EventDto newVersionEventDto(ComponentDto project, long date, String name) {
258 return new EventDto().setUuid(uuidFactory.create()).setComponentUuid(project.uuid())
259 .setAnalysisUuid("analysis_uuid")
260 .setCategory(CATEGORY_VERSION)
261 .setName(name).setDate(date).setCreatedAt(date);