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