You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FlowGeneratorTest.java 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2024 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.ce.task.projectanalysis.locations.flow;
  21. import java.security.SecureRandom;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.Random;
  25. import org.junit.Test;
  26. import org.junit.runner.RunWith;
  27. import org.mockito.InjectMocks;
  28. import org.mockito.Mock;
  29. import org.mockito.junit.MockitoJUnitRunner;
  30. import org.sonar.ce.task.projectanalysis.component.Component;
  31. import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
  32. import org.sonar.db.protobuf.DbCommons;
  33. import org.sonar.db.protobuf.DbIssues;
  34. import static java.util.function.Function.identity;
  35. import static java.util.stream.Collectors.toMap;
  36. import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
  37. import static org.assertj.core.api.Assertions.assertThat;
  38. import static org.mockito.Mockito.mock;
  39. import static org.mockito.Mockito.when;
  40. @RunWith(MockitoJUnitRunner.class)
  41. public class FlowGeneratorTest {
  42. private static final String COMPONENT_NAME = "test_comp";
  43. private final Random random = new SecureRandom();
  44. @Mock
  45. private TreeRootHolder treeRootHolder;
  46. @InjectMocks
  47. private FlowGenerator flowGenerator;
  48. @Test
  49. public void convertFlows_withNullDbLocations_returnsEmptyList() {
  50. assertThat(flowGenerator.convertFlows(COMPONENT_NAME, null)).isEmpty();
  51. }
  52. @Test
  53. public void convertFlows_withEmptyDbLocations_returnsEmptyList() {
  54. DbIssues.Locations issueLocations = DbIssues.Locations.newBuilder().build();
  55. assertThat(flowGenerator.convertFlows(COMPONENT_NAME, issueLocations)).isEmpty();
  56. }
  57. @Test
  58. public void convertFlows_withSingleDbLocations_returnsCorrectFlow() {
  59. DbIssues.Location location = createDbLocation("comp_id_1");
  60. DbIssues.Locations issueLocations = DbIssues.Locations.newBuilder()
  61. .addFlow(createFlow(location))
  62. .build();
  63. List<Flow> flows = flowGenerator.convertFlows(COMPONENT_NAME, issueLocations);
  64. assertThat(flows).hasSize(1);
  65. Flow singleFlow = flows.iterator().next();
  66. assertThat(singleFlow.getLocations()).hasSize(1);
  67. Location singleLocation = singleFlow.getLocations().iterator().next();
  68. assertLocationMatches(singleLocation, location);
  69. }
  70. @Test
  71. public void convertFlows_with2FlowsSingleDbLocations_returnsCorrectFlow() {
  72. DbIssues.Location location1 = createDbLocation("comp_id_1");
  73. DbIssues.Location location2 = createDbLocation("comp_id_2");
  74. DbIssues.Locations issueLocations = DbIssues.Locations.newBuilder()
  75. .addFlow(createFlow(location1))
  76. .addFlow(createFlow(location2))
  77. .build();
  78. List<Flow> flows = flowGenerator.convertFlows(COMPONENT_NAME, issueLocations);
  79. assertThat(flows).hasSize(2).extracting(f -> f.getLocations().size()).containsExactly(1, 1);
  80. Map<String, DbIssues.Location> toDbLocation = Map.of(
  81. "file_path_" + location1.getComponentId(), location1,
  82. "file_path_" + location2.getComponentId(), location2);
  83. flows.stream()
  84. .map(actualFlow -> actualFlow.getLocations().iterator().next())
  85. .forEach(l -> assertLocationMatches(l, toDbLocation.get(l.getFilePath())));
  86. }
  87. @Test
  88. public void convertFlows_with2DbLocations_returns() {
  89. DbIssues.Location location1 = createDbLocation("comp_id_1");
  90. DbIssues.Location location2 = createDbLocation("comp_id_2");
  91. DbIssues.Locations issueLocations = DbIssues.Locations.newBuilder()
  92. .addFlow(createFlow(location1, location2))
  93. .build();
  94. List<Flow> flows = flowGenerator.convertFlows(COMPONENT_NAME, issueLocations);
  95. assertThat(flows).hasSize(1);
  96. Flow singleFlow = flows.iterator().next();
  97. assertThat(singleFlow.getLocations()).hasSize(2);
  98. Map<String, Location> pathToLocations = singleFlow.getLocations()
  99. .stream()
  100. .collect(toMap(Location::getFilePath, identity()));
  101. assertLocationMatches(pathToLocations.get("file_path_comp_id_1"), location1);
  102. assertLocationMatches(pathToLocations.get("file_path_comp_id_2"), location2);
  103. }
  104. private DbIssues.Location createDbLocation(String componentId) {
  105. org.sonar.db.protobuf.DbCommons.TextRange textRange = org.sonar.db.protobuf.DbCommons.TextRange.newBuilder()
  106. .setStartLine(random.nextInt(Integer.MAX_VALUE))
  107. .setEndLine(random.nextInt(Integer.MAX_VALUE))
  108. .setStartOffset(random.nextInt(Integer.MAX_VALUE))
  109. .setEndOffset(random.nextInt(Integer.MAX_VALUE))
  110. .build();
  111. Component component = mock(Component.class);
  112. when(component.getName()).thenReturn("file_path_" + componentId);
  113. when(treeRootHolder.getComponentByUuid(componentId)).thenReturn(component);
  114. return DbIssues.Location.newBuilder()
  115. .setComponentId(componentId)
  116. .setChecksum("hash" + randomAlphanumeric(10))
  117. .setTextRange(textRange)
  118. .setMsg("msg" + randomAlphanumeric(15))
  119. .build();
  120. }
  121. private static DbIssues.Flow createFlow(DbIssues.Location ... locations) {
  122. return DbIssues.Flow.newBuilder()
  123. .addAllLocation(List.of(locations))
  124. .build();
  125. }
  126. private static void assertLocationMatches(Location actualLocation, DbIssues.Location sourceLocation) {
  127. assertThat(actualLocation.getMessage()).isEqualTo(sourceLocation.getMsg());
  128. DbCommons.TextRange textRange = sourceLocation.getTextRange();
  129. assertThat(actualLocation.getTextRange().getStartLine()).isEqualTo(textRange.getStartLine());
  130. assertThat(actualLocation.getTextRange().getEndLine()).isEqualTo(textRange.getEndLine());
  131. assertThat(actualLocation.getTextRange().getStartLineOffset()).isEqualTo(textRange.getStartOffset());
  132. assertThat(actualLocation.getTextRange().getEndLineOffset()).isEqualTo(textRange.getEndOffset());
  133. assertThat(actualLocation.getTextRange().getHash()).isEqualTo(sourceLocation.getChecksum());
  134. }
  135. }