3 * Copyright (C) 2009-2024 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.projectexport.file;
22 import com.sonarsource.governance.projectdump.protobuf.ProjectDump;
23 import java.util.List;
24 import org.junit.After;
25 import org.junit.Before;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.mockito.ArgumentCaptor;
29 import org.slf4j.event.Level;
30 import org.sonar.api.testfixtures.log.LogTester;
31 import org.sonar.api.utils.System2;
32 import org.sonar.ce.task.projectexport.component.ComponentRepositoryImpl;
33 import org.sonar.ce.task.projectexport.component.MutableComponentRepository;
34 import org.sonar.ce.task.projectexport.steps.DumpElement;
35 import org.sonar.ce.task.projectexport.steps.FakeDumpWriter;
36 import org.sonar.ce.task.step.TestComputationStepContext;
37 import org.sonar.core.util.Uuids;
38 import org.sonar.db.DbClient;
39 import org.sonar.db.DbSession;
40 import org.sonar.db.DbTester;
41 import org.sonar.db.MyBatis;
42 import org.sonar.db.source.FileSourceDto;
44 import static org.assertj.core.api.Assertions.assertThat;
45 import static org.mockito.ArgumentMatchers.any;
46 import static org.mockito.Mockito.doCallRealMethod;
47 import static org.mockito.Mockito.spy;
48 import static org.mockito.Mockito.verifyNoInteractions;
49 import static org.mockito.Mockito.when;
51 public class ExportLineHashesStepIT {
52 private static final String PROJECT_MASTER_UUID = "project uuid";
53 private static final String PROJECT_BRANCH_UUID = "branch-uuid";
54 private static final String FILE_UUID = "file uuid";
55 private static final String FILE_UUID_2 = "file-2-uuid";
58 public DbTester dbTester = DbTester.create(System2.INSTANCE);
60 public LogTester logTester = new LogTester();
62 private final DbClient dbClient = dbTester.getDbClient();
63 private final DbSession dbSession = dbClient.openSession(false);
64 private final FakeDumpWriter dumpWriter = new FakeDumpWriter();
65 private final MutableComponentRepository componentRepository = new ComponentRepositoryImpl();
66 private final ExportLineHashesStep underTest = new ExportLineHashesStep(dbClient, dumpWriter, componentRepository);
69 public void before() {
70 logTester.setLevel(Level.DEBUG);
74 public void tearDown() {
79 public void getDescription_is_set() {
80 assertThat(underTest.getDescription()).isEqualTo("Export line hashes");
84 public void execute_does_not_create_a_session_when_there_is_no_file_in_ComponentRepository() {
85 DbClient spy = spy(dbClient);
86 new ExportLineHashesStep(spy, dumpWriter, componentRepository)
87 .execute(new TestComputationStepContext());
89 verifyNoInteractions(spy);
91 assertThat(dumpWriter.getWrittenMessagesOf(DumpElement.LINES_HASHES)).isEmpty();
95 public void execute_relies_only_on_file_uuid_and_does_not_check_project_uuid() {
96 componentRepository.register(1, FILE_UUID, true);
98 insertFileSource(createDto(FILE_UUID, "blabla", "A"));
99 insertFileSource(createDto(FILE_UUID_2, "blabla", "B"));
101 underTest.execute(new TestComputationStepContext());
103 assertThat(dumpWriter.getWrittenMessagesOf(DumpElement.LINES_HASHES)).hasSize(1);
107 public void execute_maps_ref_of_component_and_hashes_from_fileSources() {
108 int fileRef = 984615;
109 componentRepository.register(fileRef, FILE_UUID, true);
110 FileSourceDto dto = createDto(FILE_UUID, PROJECT_MASTER_UUID, "B");
111 insertFileSource(dto);
113 underTest.execute(new TestComputationStepContext());
115 List<ProjectDump.LineHashes> messages = dumpWriter.getWrittenMessagesOf(DumpElement.LINES_HASHES);
116 assertThat(messages).hasSize(1);
117 ProjectDump.LineHashes lineHashes = messages.iterator().next();
118 assertThat(lineHashes.getHashes()).isEqualTo(dto.getRawLineHashes());
119 assertThat(lineHashes.getComponentRef()).isEqualTo(fileRef);
123 public void execute_does_one_SQL_request_by_1000_items_per_IN_clause() {
124 for (int i = 0; i < 2500; i++) {
125 componentRepository.register(i, "uuid_" + i, true);
128 DbClient spyDbClient = spy(dbClient);
129 MyBatis spyMyBatis = spy(dbClient.getMyBatis());
130 when(spyDbClient.getMyBatis()).thenReturn(spyMyBatis);
131 ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);
132 doCallRealMethod().when(spyMyBatis).newScrollingSelectStatement(any(DbSession.class), stringCaptor.capture());
134 new ExportLineHashesStep(spyDbClient, dumpWriter, componentRepository)
135 .execute(new TestComputationStepContext());
137 List<String> statements = stringCaptor.getAllValues();
138 assertThat(statements).hasSize(3);
140 assertThat(statements.get(0).split("\\?")).hasSize(1001);
141 assertThat(statements.get(1).split("\\?")).hasSize(1001);
142 assertThat(statements.get(2).split("\\?")).hasSize(501);
146 public void execute_exports_lines_hashes_of_file_sources() {
147 componentRepository.register(1, FILE_UUID, true);
148 insertFileSource(FILE_UUID, "A");
150 underTest.execute(new TestComputationStepContext());
152 assertThat(dumpWriter.getWrittenMessagesOf(DumpElement.LINES_HASHES))
153 .extracting(ProjectDump.LineHashes::getHashes)
158 public void execute_logs_number_of_filesource_exported_and_export_by_order_of_id() {
159 componentRepository.register(1, FILE_UUID, true);
160 componentRepository.register(2, "file-2", true);
161 componentRepository.register(3, "file-3", true);
162 componentRepository.register(4, "file-4", true);
164 insertFileSource(createDto(FILE_UUID, PROJECT_MASTER_UUID, "A"));
165 insertFileSource(createDto("file-2", PROJECT_MASTER_UUID, "C"));
166 insertFileSource(createDto("file-3", PROJECT_MASTER_UUID, "D"));
167 insertFileSource(createDto("file-4", PROJECT_BRANCH_UUID, "E"));
169 underTest.execute(new TestComputationStepContext());
171 assertThat(dumpWriter.getWrittenMessagesOf(DumpElement.LINES_HASHES))
172 .extracting(ProjectDump.LineHashes::getHashes)
173 .containsExactly("A", "C", "D", "E");
175 assertThat(logTester.logs(Level.DEBUG)).contains("Lines hashes of 4 files exported");
178 private FileSourceDto insertFileSource(String fileUuid, String hashes) {
179 FileSourceDto dto = createDto(fileUuid, PROJECT_MASTER_UUID, hashes);
180 return insertFileSource(dto);
183 private FileSourceDto insertFileSource(FileSourceDto dto) {
184 dbClient.fileSourceDao().insert(dbSession, dto);
189 private FileSourceDto createDto(String fileUuid, String componentUuid, String hashes) {
190 FileSourceDto fileSourceDto = new FileSourceDto()
191 .setUuid(Uuids.createFast())
192 .setFileUuid(fileUuid)
193 .setProjectUuid(componentUuid);
194 fileSourceDto.setRawLineHashes(hashes);
195 return fileSourceDto;