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.server.duplication.ws;
22 import java.io.StringWriter;
23 import java.util.Collections;
24 import java.util.List;
25 import javax.annotation.Nullable;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.sonar.api.utils.text.JsonWriter;
29 import org.sonar.core.util.ProtobufJsonFormat;
30 import org.sonar.db.DbTester;
31 import org.sonar.db.component.ComponentDto;
32 import org.sonar.test.JsonAssert;
34 import static com.google.common.collect.Lists.newArrayList;
35 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
36 import static org.sonar.db.component.BranchType.PULL_REQUEST;
37 import static org.sonar.db.component.ComponentTesting.newDirectory;
38 import static org.sonar.db.component.ComponentTesting.newFileDto;
40 public class ShowResponseBuilderIT {
43 public DbTester db = DbTester.create();
45 private ShowResponseBuilder underTest = new ShowResponseBuilder(db.getDbClient().componentDao());
48 public void write_duplications() {
49 ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
50 ComponentDto dir = db.components().insertComponent(newDirectory(project, "path"));
51 ComponentDto file1 = db.components().insertComponent(newFileDto(project, dir));
52 ComponentDto file2 = db.components().insertComponent(newFileDto(project, dir));
53 List<DuplicationsParser.Block> blocks = newArrayList();
54 blocks.add(new DuplicationsParser.Block(newArrayList(
55 Duplication.newComponent(file1, 57, 12),
56 Duplication.newComponent(file2, 73, 12))));
58 test(blocks, null, null,
60 " \"duplications\": [\n" +
64 " \"from\": 57, \"size\": 12, \"_ref\": \"1\"\n" +
67 " \"from\": 73, \"size\": 12, \"_ref\": \"2\"\n" +
74 " \"key\": \"" + file1.getKey() + "\",\n" +
75 " \"name\": \"" + file1.longName() + "\",\n" +
76 " \"project\": \"" + project.getKey() + "\",\n" +
77 " \"projectName\": \"" + project.longName() + "\",\n" +
80 " \"key\": \"" + file2.getKey() + "\",\n" +
81 " \"name\": \"" + file2.longName() + "\",\n" +
82 " \"project\": \"" + project.getKey() + "\",\n" +
83 " \"projectName\": \"" + project.longName() + "\",\n" +
90 public void write_duplications_without_sub_project() {
91 ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
92 ComponentDto file1 = db.components().insertComponent(newFileDto(project));
93 ComponentDto file2 = db.components().insertComponent(newFileDto(project));
94 List<DuplicationsParser.Block> blocks = newArrayList();
95 blocks.add(new DuplicationsParser.Block(newArrayList(
96 Duplication.newComponent(file1, 57, 12),
97 Duplication.newComponent(file2, 73, 12))));
99 test(blocks, null, null,
101 " \"duplications\": [\n" +
105 " \"from\": 57, \"size\": 12, \"_ref\": \"1\"\n" +
108 " \"from\": 73, \"size\": 12, \"_ref\": \"2\"\n" +
115 " \"key\": \"" + file1.getKey() + "\",\n" +
116 " \"name\": \"" + file1.longName() + "\",\n" +
117 " \"project\": \"" + project.getKey() + "\",\n" +
118 " \"projectName\": \"" + project.longName() + "\",\n" +
121 " \"key\": \"" + file2.getKey() + "\",\n" +
122 " \"name\": \"" + file2.longName() + "\",\n" +
123 " \"project\": \"" + project.getKey() + "\",\n" +
124 " \"projectName\": \"" + project.longName() + "\",\n" +
131 public void write_duplications_with_a_removed_component() {
132 ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
133 ComponentDto file = db.components().insertComponent(newFileDto(project));
134 List<DuplicationsParser.Block> blocks = newArrayList();
135 blocks.add(new DuplicationsParser.Block(newArrayList(
136 Duplication.newComponent(file, 57, 12),
137 // Duplication on a removed file
138 Duplication.newRemovedComponent("key", 73, 12))));
140 test(blocks, null, null,
142 " \"duplications\": [\n" +
146 " \"from\": 57, \"size\": 12, \"_ref\": \"1\"\n" +
149 " \"from\": 73, \"size\": 12\n" +
156 " \"key\": \"" + file.getKey() + "\",\n" +
157 " \"name\": \"" + file.longName() + "\",\n" +
158 " \"project\": \"" + project.getKey() + "\",\n" +
159 " \"projectName\": \"" + project.longName() + "\",\n" +
166 public void write_duplications_with_a_component_without_details() {
167 ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
168 ComponentDto file = db.components().insertComponent(newFileDto(project));
169 List<DuplicationsParser.Block> blocks = newArrayList();
170 blocks.add(new DuplicationsParser.Block(newArrayList(
171 Duplication.newComponent(file, 57, 12),
172 // Duplication on a file without details
173 Duplication.newTextComponent("project:path/to/file", 73, 12))));
175 test(blocks, null, null,
177 " \"duplications\": [\n" +
181 " \"from\": 57, \"size\": 12, \"_ref\": \"1\"\n" +
184 " \"from\": 73, \"size\": 12\n" +
191 " \"key\": \"" + file.getKey() + "\",\n" +
192 " \"name\": \"" + file.longName() + "\",\n" +
193 " \"project\": \"" + project.getKey() + "\",\n" +
194 " \"projectName\": \"" + project.longName() + "\",\n" +
197 " \"key\": \"project:path/to/file\",\n" +
198 " \"name\": \"path/to/file\",\n" +
205 public void write_duplications_on_branch() {
206 ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
207 String branchName = randomAlphanumeric(248);
208 ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey(branchName));
209 ComponentDto file1 = db.components().insertComponent(newFileDto(branch, project.uuid()));
210 ComponentDto file2 = db.components().insertComponent(newFileDto(branch, project.uuid()));
211 List<DuplicationsParser.Block> blocks = newArrayList();
212 blocks.add(new DuplicationsParser.Block(newArrayList(
213 Duplication.newComponent(file1, 57, 12),
214 Duplication.newComponent(file2, 73, 12))));
216 test(blocks, branchName, null,
218 " \"duplications\": [\n" +
222 " \"from\": 57, \"size\": 12, \"_ref\": \"1\"\n" +
225 " \"from\": 73, \"size\": 12, \"_ref\": \"2\"\n" +
232 " \"key\": \"" + file1.getKey() + "\",\n" +
233 " \"name\": \"" + file1.longName() + "\",\n" +
234 " \"project\": \"" + branch.getKey() + "\",\n" +
235 " \"projectName\": \"" + branch.longName() + "\",\n" +
236 " \"branch\": \"" + branchName + "\",\n" +
239 " \"key\": \"" + file2.getKey() + "\",\n" +
240 " \"name\": \"" + file2.longName() + "\",\n" +
241 " \"project\": \"" + branch.getKey() + "\",\n" +
242 " \"projectName\": \"" + branch.longName() + "\",\n" +
243 " \"branch\": \"" + branchName + "\",\n" +
250 public void write_duplications_on_pull_request() {
251 ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
252 String pullRequestKey = randomAlphanumeric(100);
253 ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(PULL_REQUEST).setKey(pullRequestKey));
254 ComponentDto file1 = db.components().insertComponent(newFileDto(pullRequest));
255 ComponentDto file2 = db.components().insertComponent(newFileDto(pullRequest));
256 List<DuplicationsParser.Block> blocks = newArrayList();
257 blocks.add(new DuplicationsParser.Block(newArrayList(
258 Duplication.newComponent(file1, 57, 12),
259 Duplication.newComponent(file2, 73, 12))));
261 test(blocks, null, pullRequestKey,
263 " \"duplications\": [\n" +
267 " \"from\": 57, \"size\": 12, \"_ref\": \"1\"\n" +
270 " \"from\": 73, \"size\": 12, \"_ref\": \"2\"\n" +
277 " \"key\": \"" + file1.getKey() + "\",\n" +
278 " \"name\": \"" + file1.longName() + "\",\n" +
279 " \"project\": \"" + pullRequest.getKey() + "\",\n" +
280 " \"projectName\": \"" + pullRequest.longName() + "\",\n" +
281 " \"pullRequest\": \"" + pullRequestKey + "\",\n" +
284 " \"key\": \"" + file2.getKey() + "\",\n" +
285 " \"name\": \"" + file2.longName() + "\",\n" +
286 " \"project\": \"" + pullRequest.getKey() + "\",\n" +
287 " \"projectName\": \"" + pullRequest.longName() + "\",\n" +
288 " \"pullRequest\": \"" + pullRequestKey + "\",\n" +
295 public void write_nothing_when_no_data() {
296 test(Collections.emptyList(), null, null, "{\"duplications\": [], \"files\": {}}");
299 private void test(List<DuplicationsParser.Block> blocks, @Nullable String branch, @Nullable String pullRequest, String expected) {
300 StringWriter output = new StringWriter();
301 JsonWriter jsonWriter = JsonWriter.of(output);
302 ProtobufJsonFormat.write(underTest.build(db.getSession(), blocks, branch, pullRequest), jsonWriter);
303 JsonAssert.assertJson(output.toString()).isSimilarTo(expected);