]> source.dussan.org Git - sonarqube.git/blob
a5160407b37f6e77964b16e5fc7eeb1bfed0d34b
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.duplication.ws;
21
22 import com.google.common.collect.Iterables;
23 import java.util.List;
24 import javax.annotation.Nullable;
25 import org.apache.commons.lang.RandomStringUtils;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.sonar.db.DbTester;
29 import org.sonar.db.component.BranchType;
30 import org.sonar.db.component.ComponentDto;
31
32 import static java.lang.String.format;
33 import static org.assertj.core.api.Assertions.assertThat;
34 import static org.sonar.db.component.ComponentTesting.newFileDto;
35
36 public class DuplicationsParserTest {
37
38   @Rule
39   public DbTester db = DbTester.create();
40
41   private DuplicationsParser parser = new DuplicationsParser(db.getDbClient().componentDao());
42
43   @Test
44   public void empty_list_when_no_data() {
45     ComponentDto project = db.components().insertPrivateProject();
46     ComponentDto file = db.components().insertComponent(newFileDto(project));
47
48     assertThat(parser.parse(db.getSession(), file, null, null, null)).isEmpty();
49   }
50
51   @Test
52   public void duplication_on_same_file() {
53     ComponentDto project = db.components().insertPrivateProject();
54     ComponentDto file = db.components().insertComponent(newFileDto(project));
55     List<DuplicationsParser.Block> blocks = parser.parse(db.getSession(), file, null, null,
56       format("<duplications>\n" +
57         "  <g>\n" +
58         "    <b s=\"31\" l=\"5\" r=\"%s\"/>\n" +
59         "    <b s=\"20\" l=\"5\" r=\"%s\"/>\n" +
60         "  </g>\n" +
61         "</duplications>", file.getKey(), file.getKey()));
62     assertThat(blocks).hasSize(1);
63
64     List<Duplication> duplications = blocks.get(0).getDuplications();
65     assertThat(duplications).hasSize(2);
66
67     // Smallest line comes first
68     Duplication duplication1 = duplications.get(0);
69     assertThat(duplication1.componentDto()).isEqualTo(file);
70     assertThat(duplication1.from()).isEqualTo(20);
71     assertThat(duplication1.size()).isEqualTo(5);
72
73     Duplication duplication2 = duplications.get(1);
74     assertThat(duplication2.componentDto()).isEqualTo(file);
75     assertThat(duplication2.from()).isEqualTo(31);
76     assertThat(duplication2.size()).isEqualTo(5);
77   }
78
79   @Test
80   public void duplication_on_same_project() {
81     ComponentDto project = db.components().insertPrivateProject();
82     ComponentDto file1 = db.components().insertComponent(newFileDto(project));
83     ComponentDto file2 = db.components().insertComponent(newFileDto(project));
84     List<DuplicationsParser.Block> blocks = parser.parse(db.getSession(), file1, null, null,
85       format("<duplications>\n" +
86         "  <g>\n" +
87         "    <b s=\"20\" l=\"5\" r=\"%s\"/>\n" +
88         "    <b s=\"31\" l=\"5\" r=\"%s\"/>\n" +
89         "  </g>\n" +
90         "</duplications>", file2.getKey(), file1.getKey()));
91     assertThat(blocks).hasSize(1);
92
93     List<Duplication> duplications = blocks.get(0).getDuplications();
94     assertThat(duplications).hasSize(2);
95
96     // Current file comes first
97     Duplication duplication1 = duplications.get(0);
98     assertThat(duplication1.componentDto()).isEqualTo(file1);
99     assertThat(duplication1.from()).isEqualTo(31);
100     assertThat(duplication1.size()).isEqualTo(5);
101
102     Duplication duplication2 = duplications.get(1);
103     assertThat(duplication2.componentDto()).isEqualTo(file2);
104     assertThat(duplication2.from()).isEqualTo(20);
105     assertThat(duplication2.size()).isEqualTo(5);
106   }
107
108   @Test
109   public void duplications_on_different_project() {
110     ComponentDto project1 = db.components().insertPrivateProject();
111     ComponentDto file1 = db.components().insertComponent(newFileDto(project1));
112     ComponentDto file2 = db.components().insertComponent(newFileDto(project1));
113     ComponentDto project2 = db.components().insertPrivateProject();
114     ComponentDto fileOnProject2 = db.components().insertComponent(newFileDto(project2));
115     List<DuplicationsParser.Block> blocks = parser.parse(db.getSession(), file1, null, null,
116       format("<duplications>\n" +
117         "  <g>\n" +
118         "    <b s=\"148\" l=\"24\" r=\"%s\"/>\n" +
119         "    <b s=\"137\" l=\"24\" r=\"%s\"/>\n" +
120         "    <b s=\"111\" l=\"24\" r=\"%s\"/>\n" +
121         "  </g>\n" +
122         "</duplications>", file1.getKey(), fileOnProject2.getKey(), file2.getKey()));
123     assertThat(blocks).hasSize(1);
124
125     List<Duplication> duplications = blocks.get(0).getDuplications();
126     assertThat(duplications).hasSize(3);
127
128     // Current file's project comes first
129
130     Duplication duplication1 = duplications.get(0);
131     assertThat(duplication1.componentDto()).isEqualTo(file1);
132     assertThat(duplication1.from()).isEqualTo(148);
133     assertThat(duplication1.size()).isEqualTo(24);
134
135     Duplication duplication2 = duplications.get(1);
136     assertThat(duplication2.componentDto()).isEqualTo(file2);
137     assertThat(duplication2.from()).isEqualTo(111);
138     assertThat(duplication2.size()).isEqualTo(24);
139
140     // Other project comes last
141
142     Duplication duplication3 = duplications.get(2);
143     assertThat(duplication3.componentDto()).isEqualTo(fileOnProject2);
144     assertThat(duplication3.from()).isEqualTo(137);
145     assertThat(duplication3.size()).isEqualTo(24);
146   }
147
148   @Test
149   public void duplications_on_many_blocks() {
150     ComponentDto project1 = db.components().insertPrivateProject();
151     ComponentDto file1 = db.components().insertComponent(newFileDto(project1)
152       .setKey("org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/utils/command/CommandExecutor.java")
153       .setLongName("CommandExecutor"));
154     ComponentDto project2 = db.components().insertPrivateProject();
155     ComponentDto file2 = db.components().insertComponent(newFileDto(project2)
156       .setKey("com.sonarsource.orchestrator:sonar-orchestrator:src/main/java/com/sonar/orchestrator/util/CommandExecutor.java")
157       .setLongName("CommandExecutor"));
158     List<DuplicationsParser.Block> blocks = parser.parse(db.getSession(), file1, null, null,
159       format("<duplications>\n" +
160         "  <g>\n" +
161         "    <b s=\"94\" l=\"101\" r=\"%s\"/>\n" +
162         "    <b s=\"83\" l=\"101\" r=\"%s\"/>\n" +
163         "  </g>\n" +
164         "  <g>\n" +
165         "    <b s=\"38\" l=\"40\" r=\"%s\"/>\n" +
166         "    <b s=\"29\" l=\"39\" r=\"%s\"/>\n" +
167         "  </g>\n" +
168         "</duplications>\n", file2.getKey(), file1.getKey(), file2.getKey(), file1.getKey()));
169     assertThat(blocks).hasSize(2);
170
171     // Block with smaller line should come first
172
173     assertThat(blocks.get(0).getDuplications().get(0).from()).isEqualTo(29);
174     assertThat(blocks.get(0).getDuplications().get(1).from()).isEqualTo(38);
175
176     assertThat(blocks.get(1).getDuplications().get(0).from()).isEqualTo(83);
177     assertThat(blocks.get(1).getDuplications().get(1).from()).isEqualTo(94);
178   }
179
180   @Test
181   public void duplication_on_not_existing_file() {
182     ComponentDto project = db.components().insertPrivateProject();
183     ComponentDto file = db.components().insertComponent(newFileDto(project));
184     List<DuplicationsParser.Block> blocks = parser.parse(db.getSession(), file, null, null,
185       format("<duplications>\n" +
186         "  <g>\n" +
187         "    <b s=\"20\" l=\"5\" r=\"%s\"/>\n" +
188         "    <b s=\"31\" l=\"5\" r=\"%s\"/>\n" +
189         "  </g>\n" +
190         "</duplications>", file.getKey(), "not_existing"));
191     assertThat(blocks).hasSize(1);
192
193     List<Duplication> duplications = blocks.get(0).getDuplications();
194     assertThat(duplications).hasSize(2);
195
196     // Duplications on removed file
197     Duplication duplication1 = duplication(duplications, null);
198     assertThat(duplication1.componentDto()).isNull();
199     assertThat(duplication1.from()).isEqualTo(31);
200     assertThat(duplication1.size()).isEqualTo(5);
201
202     Duplication duplication2 = duplication(duplications, file.getKey());
203     assertThat(duplication2.componentDto()).isEqualTo(file);
204     assertThat(duplication2.from()).isEqualTo(20);
205     assertThat(duplication2.size()).isEqualTo(5);
206   }
207
208   @Test
209   public void compare_duplications() {
210     ComponentDto project1 = db.components().insertPrivateProject();
211     ComponentDto project2 = db.components().insertPrivateProject();
212     ComponentDto currentFile = db.components().insertComponent(newFileDto(project1, null));
213     ComponentDto fileOnSameProject = db.components().insertComponent(newFileDto(project1, null));
214     ComponentDto fileOnDifferentProject = db.components().insertComponent(newFileDto(project2, null));
215
216     DuplicationsParser.DuplicationComparator comparator = new DuplicationsParser.DuplicationComparator(currentFile.uuid(), currentFile.branchUuid());
217
218     // On same file
219     assertThat(comparator.compare(Duplication.newComponent(currentFile, 2, 2),
220       Duplication.newComponent(currentFile, 5, 2))).isEqualTo(-1);
221     // Different files on same project
222     assertThat(comparator.compare(Duplication.newComponent(currentFile, 2, 2),
223       Duplication.newComponent(fileOnSameProject, 5, 2))).isEqualTo(-1);
224     assertThat(comparator.compare(Duplication.newComponent(fileOnSameProject, 2, 2),
225       Duplication.newComponent(currentFile, 5, 2))).isOne();
226     // Different files on different projects
227     assertThat(comparator.compare(Duplication.newComponent(fileOnSameProject, 5, 2),
228       Duplication.newComponent(fileOnDifferentProject, 2, 2))).isEqualTo(-1);
229     assertThat(comparator.compare(Duplication.newComponent(fileOnDifferentProject, 5, 2),
230       Duplication.newComponent(fileOnSameProject, 2, 2))).isOne();
231     // Files on 2 different projects
232     ComponentDto project3 = db.components().insertPrivateProject();
233     assertThat(comparator.compare(Duplication.newComponent(fileOnDifferentProject, 5, 2),
234       Duplication.newComponent(project3, 2, 2))).isOne();
235
236     // With null duplications
237     assertThat(comparator.compare(null, Duplication.newComponent(fileOnSameProject, 2, 2))).isEqualTo(-1);
238     assertThat(comparator.compare(Duplication.newComponent(fileOnSameProject, 2, 2), null)).isEqualTo(-1);
239     assertThat(comparator.compare(null, null)).isEqualTo(-1);
240
241     // On some removed file
242     assertThat(comparator.compare(Duplication.newComponent(currentFile, 2, 2),
243       Duplication.newRemovedComponent("key1", 5, 2))).isEqualTo(-1);
244     assertThat(comparator.compare(Duplication.newRemovedComponent("key2", 2, 2),
245       Duplication.newComponent(currentFile, 5, 2))).isOne();
246   }
247
248   @Test
249   public void duplication_on_branch() {
250     ComponentDto project = db.components().insertPublicProject();
251     ComponentDto branch = db.components().insertProjectBranch(project);
252     ComponentDto file1 = db.components().insertComponent(newFileDto(branch));
253     ComponentDto file2 = db.components().insertComponent(newFileDto(branch));
254     List<DuplicationsParser.Block> blocks = parser.parse(db.getSession(), file1, branch.getBranch(), null,
255       format("<duplications>\n" +
256         "  <g>\n" +
257         "    <b s=\"20\" l=\"5\" r=\"%s\"/>\n" +
258         "    <b s=\"31\" l=\"5\" r=\"%s\"/>\n" +
259         "  </g>\n" +
260         "</duplications>", file2.getKey(), file1.getKey()));
261     assertThat(blocks).hasSize(1);
262
263     List<Duplication> duplications = blocks.get(0).getDuplications();
264     assertThat(duplications).hasSize(2);
265
266     // Current file comes first
267     Duplication duplication1 = duplications.get(0);
268     assertThat(duplication1.componentDto()).isEqualTo(file1);
269     assertThat(duplication1.componentDto().getKey()).isEqualTo(file1.getKey());
270     assertThat(duplication1.from()).isEqualTo(31);
271     assertThat(duplication1.size()).isEqualTo(5);
272
273     Duplication duplication2 = duplications.get(1);
274     assertThat(duplication2.componentDto()).isEqualTo(file2);
275     assertThat(duplication2.componentDto().getKey()).isEqualTo(file2.getKey());
276     assertThat(duplication2.from()).isEqualTo(20);
277     assertThat(duplication2.size()).isEqualTo(5);
278   }
279
280   @Test
281   public void duplication_on_pull_request() {
282     ComponentDto project = db.components().insertPublicProject();
283     String pullRequestKey = RandomStringUtils.randomAlphanumeric(100);
284     ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST).setKey(pullRequestKey));
285     ComponentDto file1 = db.components().insertComponent(newFileDto(pullRequest));
286     ComponentDto file2 = db.components().insertComponent(newFileDto(pullRequest));
287     List<DuplicationsParser.Block> blocks = parser.parse(db.getSession(), file1, null, pullRequestKey,
288       format("<duplications>\n" +
289         "  <g>\n" +
290         "    <b s=\"20\" l=\"5\" r=\"%s\"/>\n" +
291         "    <b s=\"31\" l=\"5\" r=\"%s\"/>\n" +
292         "  </g>\n" +
293         "</duplications>", file2.getKey(), file1.getKey()));
294     assertThat(blocks).hasSize(1);
295
296     List<Duplication> duplications = blocks.get(0).getDuplications();
297     assertThat(duplications).hasSize(2);
298
299     // Current file comes first
300     Duplication duplication1 = duplications.get(0);
301     assertThat(duplication1.componentDto()).isEqualTo(file1);
302     assertThat(duplication1.componentDto().getKey()).isEqualTo(file1.getKey());
303     assertThat(duplication1.from()).isEqualTo(31);
304     assertThat(duplication1.size()).isEqualTo(5);
305
306     Duplication duplication2 = duplications.get(1);
307     assertThat(duplication2.componentDto()).isEqualTo(file2);
308     assertThat(duplication2.componentDto().getKey()).isEqualTo(file2.getKey());
309     assertThat(duplication2.from()).isEqualTo(20);
310     assertThat(duplication2.size()).isEqualTo(5);
311   }
312
313   private static Duplication duplication(List<Duplication> duplications, @Nullable final String componentKey) {
314     return Iterables.find(duplications, input -> input != null && (componentKey == null ? input.componentDto() == null
315       : input.componentDto() != null && componentKey.equals(input.componentDto().getKey())));
316   }
317
318 }