/* * SonarQube * Copyright (C) 2009-2017 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonar.server.duplication.ws; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.io.Files; import com.google.common.io.Resources; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; import javax.annotation.Nullable; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.sonar.api.utils.System2; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDao; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; import org.sonar.db.organization.OrganizationDto; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.db.component.ComponentTesting.newFileDto; public class DuplicationsParserTest { @Rule public DbTester db = DbTester.create(System2.INSTANCE); final DbSession dbSession = db.getSession(); ComponentDao componentDao = db.getDbClient().componentDao(); OrganizationDto organizationDto; ComponentDto currentFile; ComponentDto fileOnSameProject; ComponentDto fileOnDifferentProject; ComponentDto project1; ComponentDto project2; DuplicationsParser parser = new DuplicationsParser(componentDao); @Before public void setUp() { organizationDto = db.organizations().insert(); project1 = ComponentTesting.newPrivateProjectDto(organizationDto) .setName("SonarQube") .setLongName("SonarQube") .setKey("org.codehaus.sonar:sonar"); project2 = ComponentTesting.newPrivateProjectDto(organizationDto); componentDao.insert(dbSession, project1, project2); // Current file String key1 = "org.codehaus.sonar:sonar-plugin-api:src/main/java/org/sonar/api/utils/command/CommandExecutor.java"; currentFile = newFileDto(project1, null).setKey(key1).setLongName("CommandExecutor"); // File on same project String key2 = "org.codehaus.sonar:sonar-plugin-api:src/main/java/com/sonar/orchestrator/util/CommandExecutor.java"; fileOnSameProject = newFileDto(project1, null).setKey(key2).setLongName("CommandExecutor"); // File on different project String key3 = "com.sonarsource.orchestrator:sonar-orchestrator:src/main/java/com/sonar/orchestrator/util/CommandExecutor.java"; fileOnDifferentProject = newFileDto(project2, null).setKey(key3).setLongName("CommandExecutor"); componentDao.insert(dbSession, currentFile, fileOnSameProject, fileOnDifferentProject); dbSession.commit(); } @Test public void empty_list_when_no_data() { assertThat(parser.parse(currentFile, null, dbSession)).isEmpty(); } @Test public void duplication_on_same_file() throws Exception { List<DuplicationsParser.Block> blocks = parser.parse(currentFile, getData("duplication_on_same_file.xml"), dbSession); assertThat(blocks).hasSize(1); List<DuplicationsParser.Duplication> duplications = blocks.get(0).getDuplications(); assertThat(duplications).hasSize(2); // Smallest line comes first DuplicationsParser.Duplication duplication1 = duplications.get(0); assertThat(duplication1.file()).isEqualTo(currentFile); assertThat(duplication1.from()).isEqualTo(20); assertThat(duplication1.size()).isEqualTo(5); DuplicationsParser.Duplication duplication2 = duplications.get(1); assertThat(duplication2.file()).isEqualTo(currentFile); assertThat(duplication2.from()).isEqualTo(31); assertThat(duplication2.size()).isEqualTo(5); } @Test public void duplication_on_same_project() throws Exception { List<DuplicationsParser.Block> blocks = parser.parse(currentFile, getData("duplication_on_same_project.xml"), dbSession); assertThat(blocks).hasSize(1); List<DuplicationsParser.Duplication> duplications = blocks.get(0).getDuplications(); assertThat(duplications).hasSize(2); // Current file comes first DuplicationsParser.Duplication duplication1 = duplications.get(0); assertThat(duplication1.file()).isEqualTo(currentFile); assertThat(duplication1.from()).isEqualTo(31); assertThat(duplication1.size()).isEqualTo(5); DuplicationsParser.Duplication duplication2 = duplications.get(1); assertThat(duplication2.file()).isEqualTo(fileOnSameProject); assertThat(duplication2.from()).isEqualTo(20); assertThat(duplication2.size()).isEqualTo(5); } @Test public void duplications_on_different_project() throws Exception { List<DuplicationsParser.Block> blocks = parser.parse(currentFile, getData("duplications_on_different_project.xml"), dbSession); assertThat(blocks).hasSize(1); List<DuplicationsParser.Duplication> duplications = blocks.get(0).getDuplications(); assertThat(duplications).hasSize(3); // Current file's project comes first DuplicationsParser.Duplication duplication1 = duplications.get(0); assertThat(duplication1.file()).isEqualTo(currentFile); assertThat(duplication1.from()).isEqualTo(148); assertThat(duplication1.size()).isEqualTo(24); DuplicationsParser.Duplication duplication2 = duplications.get(1); assertThat(duplication2.file()).isEqualTo(fileOnSameProject); assertThat(duplication2.from()).isEqualTo(111); assertThat(duplication2.size()).isEqualTo(24); // Other project comes last DuplicationsParser.Duplication duplication3 = duplications.get(2); assertThat(duplication3.file()).isEqualTo(fileOnDifferentProject); assertThat(duplication3.from()).isEqualTo(137); assertThat(duplication3.size()).isEqualTo(24); } @Test public void duplications_on_many_blocks() throws Exception { List<DuplicationsParser.Block> blocks = parser.parse(currentFile, getData("duplications_on_many_blocks.xml"), dbSession); assertThat(blocks).hasSize(2); // Block with smaller line should come first assertThat(blocks.get(0).getDuplications().get(0).from()).isEqualTo(38); assertThat(blocks.get(0).getDuplications().get(1).from()).isEqualTo(29); assertThat(blocks.get(1).getDuplications().get(0).from()).isEqualTo(94); assertThat(blocks.get(1).getDuplications().get(1).from()).isEqualTo(83); } @Test public void duplication_on_removed_file() throws Exception { List<DuplicationsParser.Block> blocks = parser.parse(currentFile, getData("duplication_on_removed_file.xml"), dbSession); assertThat(blocks).hasSize(1); List<DuplicationsParser.Duplication> duplications = blocks.get(0).getDuplications(); assertThat(duplications).hasSize(2); // Duplications on removed file DuplicationsParser.Duplication duplication1 = duplication(duplications, null); assertThat(duplication1.file()).isNull(); assertThat(duplication1.from()).isEqualTo(31); assertThat(duplication1.size()).isEqualTo(5); DuplicationsParser.Duplication duplication2 = duplication(duplications, fileOnSameProject.key()); assertThat(duplication2.file()).isEqualTo(fileOnSameProject); assertThat(duplication2.from()).isEqualTo(20); assertThat(duplication2.size()).isEqualTo(5); } @Test public void compare_duplications() { ComponentDto currentFile = newFileDto(project1, null).setId(11L); ComponentDto fileOnSameProject = newFileDto(project1, null).setId(12L); ComponentDto fileOnDifferentProject = newFileDto(project2, null).setId(13L); DuplicationsParser.DuplicationComparator comparator = new DuplicationsParser.DuplicationComparator(currentFile.uuid(), currentFile.projectUuid()); // On same file assertThat(comparator.compare(new DuplicationsParser.Duplication(currentFile, 2, 2), new DuplicationsParser.Duplication(currentFile, 5, 2))).isEqualTo(-1); // Different files on same project assertThat(comparator.compare(new DuplicationsParser.Duplication(currentFile, 2, 2), new DuplicationsParser.Duplication(fileOnSameProject, 5, 2))).isEqualTo(-1); assertThat(comparator.compare(new DuplicationsParser.Duplication(fileOnSameProject, 2, 2), new DuplicationsParser.Duplication(currentFile, 5, 2))).isEqualTo(1); // Different files on different projects assertThat(comparator.compare(new DuplicationsParser.Duplication(fileOnSameProject, 5, 2), new DuplicationsParser.Duplication(fileOnDifferentProject, 2, 2))).isEqualTo(-1); assertThat(comparator.compare(new DuplicationsParser.Duplication(fileOnDifferentProject, 5, 2), new DuplicationsParser.Duplication(fileOnSameProject, 2, 2))).isEqualTo(1); // Files on 2 different projects ComponentDto project3 = ComponentTesting.newPrivateProjectDto(organizationDto).setId(3L); assertThat(comparator.compare(new DuplicationsParser.Duplication(fileOnDifferentProject, 5, 2), new DuplicationsParser.Duplication(project3, 2, 2))).isEqualTo(1); // With null duplications assertThat(comparator.compare(null, new DuplicationsParser.Duplication(fileOnSameProject, 2, 2))).isEqualTo(-1); assertThat(comparator.compare(new DuplicationsParser.Duplication(fileOnSameProject, 2, 2), null)).isEqualTo(-1); assertThat(comparator.compare(null, null)).isEqualTo(-1); // On some removed file assertThat(comparator.compare(new DuplicationsParser.Duplication(currentFile, 2, 2), new DuplicationsParser.Duplication(null, 5, 2))).isEqualTo(-1); assertThat(comparator.compare(new DuplicationsParser.Duplication(null, 2, 2), new DuplicationsParser.Duplication(currentFile, 5, 2))).isEqualTo(-1); } private String getData(String file) throws IOException { return Files.toString(new File(Resources.getResource(this.getClass(), "DuplicationsParserTest/" + file).getFile()), StandardCharsets.UTF_8); } private static DuplicationsParser.Duplication duplication(List<DuplicationsParser.Duplication> duplications, @Nullable final String componentKey) { return Iterables.find(duplications, new Predicate<DuplicationsParser.Duplication>() { @Override public boolean apply(@Nullable DuplicationsParser.Duplication input) { return input != null && (componentKey == null ? input.file() == null : input.file() != null && componentKey.equals(input.file().key())); } }); } }