summaryrefslogtreecommitdiffstats
path: root/server/sonar-db-dao
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2018-08-17 15:52:09 +0200
committerSonarTech <sonartech@sonarsource.com>2018-08-21 20:21:06 +0200
commit80549d03acb65a59bce2867a16509c5420cf488e (patch)
tree089f5116f9c759fa2f40359b36da821f113b97b9 /server/sonar-db-dao
parent82204700a1bed3ed769d86b8c17e318b21a6a5a9 (diff)
downloadsonarqube-80549d03acb65a59bce2867a16509c5420cf488e.tar.gz
sonarqube-80549d03acb65a59bce2867a16509c5420cf488e.zip
SONAR-8368 reopen only closed issues closed less than 30 days ago
Diffstat (limited to 'server/sonar-db-dao')
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java2
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml6
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueMapperTest.java120
3 files changed, 107 insertions, 21 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java
index 9098c986d15..90655308f90 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java
@@ -44,7 +44,7 @@ public interface IssueMapper {
void scrollNonClosedByComponentUuid(@Param("componentUuid") String componentUuid, ResultHandler<IssueDto> handler);
- void scrollClosedByComponentUuid(@Param("componentUuid") String componentUuid, ResultHandler<IssueDto> handler);
+ void scrollClosedByComponentUuid(@Param("componentUuid") String componentUuid, @Param("closeDateAfter") long closeDateAfter, ResultHandler<IssueDto> handler);
List<IssueDto> selectNonClosedByComponentUuidExcludingExternals(@Param("componentUuid") String componentUuid);
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml
index 2aac0a6344b..90f2ccfaf03 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml
@@ -216,7 +216,7 @@
i.issue_type &lt;&gt; 4 and (i.from_hotspot is NULL or i.from_hotspot = ${_false})
</select>
- <select id="scrollClosedByComponentUuid" parameterType="String" resultType="Issue" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
+ <select id="scrollClosedByComponentUuid" resultType="Issue" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
select
<include refid="issueColumns"/>,
ic.change_data as closedChangeData
@@ -234,8 +234,10 @@
where
i.component_uuid = #{componentUuid,jdbcType=VARCHAR}
and i.status = 'CLOSED'
+ and i.issue_close_date is not null
+ and i.issue_close_date >= #{closeDateAfter,jdbcType=BIGINT}
and i.issue_type &lt;&gt; 4
- and (i.from_hotspot is NULL or i.from_hotspot = ${_false})
+ and (i.from_hotspot is null or i.from_hotspot = ${_false})
order by
i.kee, ic.issue_change_creation_date desc
</select>
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueMapperTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueMapperTest.java
index ac887d764ff..5666e194c0c 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueMapperTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueMapperTest.java
@@ -39,6 +39,7 @@ import org.sonar.api.issue.Issue;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
import org.sonar.core.issue.FieldDiffs;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.DbSession;
@@ -57,6 +58,8 @@ import static org.assertj.core.api.Assertions.tuple;
@RunWith(DataProviderRunner.class)
public class IssueMapperTest {
+ private static final long NO_FILTERING_ON_CLOSE_DATE = 1L;
+
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@@ -67,6 +70,7 @@ public class IssueMapperTest {
private ComponentDto project, file, file2;
private RuleDto rule;
private Random random = new Random();
+ private System2 system2 = new AlwaysIncreasingSystem2();
@Before
public void setUp() throws Exception {
@@ -241,7 +245,7 @@ public class IssueMapperTest {
String componentUuid = randomAlphabetic(10);
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(componentUuid, resultHandler);
+ underTest.scrollClosedByComponentUuid(componentUuid, new Date().getTime(), resultHandler);
assertThat(resultHandler.issues).isEmpty();
}
@@ -255,7 +259,7 @@ public class IssueMapperTest {
IssueChangeDto changeDto = insertToClosedDiff(expected);
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(component.uuid(), resultHandler);
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
assertThat(resultHandler.issues).hasSize(1);
IssueDto issue = resultHandler.issues.iterator().next();
@@ -274,7 +278,7 @@ public class IssueMapperTest {
insertToClosedDiff(issueWithoutRule);
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(component.uuid(), resultHandler);
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
assertThat(resultHandler.issues)
.extracting(IssueDto::getKey, t -> t.getClosedChangeData().get())
@@ -294,7 +298,7 @@ public class IssueMapperTest {
insertToClosedDiff(issueMissingProject);
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(component.uuid(), resultHandler);
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
assertThat(resultHandler.issues)
.extracting(IssueDto::getKey, t -> t.getClosedChangeData().get())
@@ -311,7 +315,7 @@ public class IssueMapperTest {
insertNewClosedIssue(component, ruleType);
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(component.uuid(), resultHandler);
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
assertThat(resultHandler.issues)
.extracting(IssueDto::getKey, t -> t.getClosedChangeData().get())
@@ -319,8 +323,8 @@ public class IssueMapperTest {
}
@Test
- @UseDataProvider("closedIssuesSupportedRuleTypes")
- public void scrollClosedByComponentUuid_does_not_return_closed_issues_of_type_SECURITY_HOTSPOT(RuleType ruleType) {
+ public void scrollClosedByComponentUuid_does_not_return_closed_issues_of_type_SECURITY_HOTSPOT() {
+ RuleType ruleType = randomSupportedRuleType();
OrganizationDto organization = dbTester.organizations().insert();
ComponentDto component = randomComponent(organization);
IssueDto securityHotspotIssue = insertNewClosedIssue(component, RuleType.SECURITY_HOTSPOT);
@@ -329,7 +333,7 @@ public class IssueMapperTest {
IssueChangeDto issueChange = insertToClosedDiff(issue);
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(component.uuid(), resultHandler);
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
assertThat(resultHandler.issues)
.extracting(IssueDto::getKey, t -> t.getClosedChangeData().get())
@@ -337,8 +341,8 @@ public class IssueMapperTest {
}
@Test
- @UseDataProvider("closedIssuesSupportedRuleTypes")
- public void scrollClosedByComponentUuid_return_closed_issues_without_isHotspot_flag(RuleType ruleType) {
+ public void scrollClosedByComponentUuid_returns_closed_issues_without_isHotspot_flag() {
+ RuleType ruleType = randomSupportedRuleType();
OrganizationDto organization = dbTester.organizations().insert();
ComponentDto component = randomComponent(organization);
IssueDto noHotspotFlagIssue = insertNewClosedIssue(component, ruleType);
@@ -348,7 +352,7 @@ public class IssueMapperTest {
IssueChangeDto issueChange = insertToClosedDiff(issue);
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(component.uuid(), resultHandler);
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
assertThat(resultHandler.issues)
.extracting(IssueDto::getKey, t -> t.getClosedChangeData().get())
@@ -357,6 +361,73 @@ public class IssueMapperTest {
tuple(noHotspotFlagIssue.getKey(), noFlagIssueChange.getChangeData()));
}
+ @Test
+ public void scrollClosedByComponentUuid_does_not_return_closed_issues_without_close_date() {
+ RuleType ruleType = randomSupportedRuleType();
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto component = randomComponent(organization);
+ IssueDto issueWithoutCloseDate = insertNewClosedIssue(component, ruleType, t -> t.setIssueCloseDate(null));
+ insertToClosedDiff(issueWithoutCloseDate);
+ IssueDto issueCloseDate = insertNewClosedIssue(component, ruleType);
+ IssueChangeDto changeDto = insertToClosedDiff(issueCloseDate);
+
+ RecorderResultHandler resultHandler = new RecorderResultHandler();
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
+
+ assertThat(resultHandler.issues).hasSize(1);
+ IssueDto issue = resultHandler.issues.iterator().next();
+ assertThat(issue.getKey()).isEqualTo(issue.getKey());
+ assertThat(issue.getClosedChangeData()).contains(changeDto.getChangeData());
+ }
+
+ @Test
+ public void scrollClosedByComponentUuid_returns_closed_issues_which_close_date_is_greater_or_equal_to_requested() {
+ RuleType ruleType = randomSupportedRuleType();
+ OrganizationDto organization = dbTester.organizations().insert();
+ ComponentDto component = randomComponent(organization);
+ RuleDefinitionDto rule1 = dbTester.rules().insert(t -> t.setType(ruleType));
+ IssueDto[] issues = new IssueDto[] {
+ insertNewClosedIssue(component, rule1, 1_999_999L),
+ insertNewClosedIssue(component, rule1, 3_999_999L),
+ insertNewClosedIssue(component, rule1, 2_999_999L),
+ insertNewClosedIssue(component, rule1, 10_999_999L)
+ };
+ Arrays.stream(issues).forEach(this::insertToClosedDiff);
+
+ RecorderResultHandler resultHandler = new RecorderResultHandler();
+ underTest.scrollClosedByComponentUuid(component.uuid(), 4_000_000L, resultHandler);
+
+ assertThat(resultHandler.issues)
+ .extracting(IssueDto::getKey)
+ .containsOnly(issues[3].getKey());
+
+ resultHandler = new RecorderResultHandler();
+ underTest.scrollClosedByComponentUuid(component.uuid(), 11_999_999L, resultHandler);
+
+ assertThat(resultHandler.issues).isEmpty();
+
+ resultHandler = new RecorderResultHandler();
+ underTest.scrollClosedByComponentUuid(component.uuid(), 3_999_999L, resultHandler);
+
+ assertThat(resultHandler.issues)
+ .extracting(IssueDto::getKey)
+ .containsOnly(issues[3].getKey(), issues[1].getKey());
+
+ resultHandler = new RecorderResultHandler();
+ underTest.scrollClosedByComponentUuid(component.uuid(), 2_999_999L, resultHandler);
+
+ assertThat(resultHandler.issues)
+ .extracting(IssueDto::getKey)
+ .containsOnly(issues[3].getKey(), issues[1].getKey(), issues[2].getKey());
+
+ resultHandler = new RecorderResultHandler();
+ underTest.scrollClosedByComponentUuid(component.uuid(), 1L, resultHandler);
+
+ assertThat(resultHandler.issues)
+ .extracting(IssueDto::getKey)
+ .containsOnly(issues[3].getKey(), issues[1].getKey(), issues[2].getKey(), issues[0].getKey());
+ }
+
private void manuallySetToNullFromHotpotsColumn(IssueDto fromHostSpotIssue) {
dbTester.executeUpdateSql("update issues set from_hotspot = null where kee = '" + fromHostSpotIssue.getKey() + "'");
dbTester.commit();
@@ -373,7 +444,7 @@ public class IssueMapperTest {
IssueChangeDto issueChange = insertToClosedDiff(issue);
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(component.uuid(), resultHandler);
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
assertThat(resultHandler.issues)
.extracting(IssueDto::getKey, t -> t.getClosedChangeData().get())
@@ -395,7 +466,7 @@ public class IssueMapperTest {
};
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(component.uuid(), resultHandler);
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
assertThat(resultHandler.issues)
.hasSize(4)
@@ -422,7 +493,7 @@ public class IssueMapperTest {
};
RecorderResultHandler resultHandler = new RecorderResultHandler();
- underTest.scrollClosedByComponentUuid(component.uuid(), resultHandler);
+ underTest.scrollClosedByComponentUuid(component.uuid(), NO_FILTERING_ON_CLOSE_DATE, resultHandler);
assertThat(resultHandler.issues)
.hasSize(3)
@@ -460,32 +531,45 @@ public class IssueMapperTest {
@SafeVarargs
private final IssueDto insertNewClosedIssue(ComponentDto component, RuleType ruleType, Consumer<IssueDto>... consumers) {
RuleDefinitionDto rule = dbTester.rules().insert(t -> t.setType(ruleType));
- return insertNewClosedIssue(component, rule, consumers);
+ return insertNewClosedIssue(component, rule, system2.now(), consumers);
}
@SafeVarargs
private final IssueDto insertNewClosedIssue(ComponentDto component, RuleDefinitionDto rule, Consumer<IssueDto>... consumers) {
+ return insertNewClosedIssue(component, rule, system2.now(), consumers);
+ }
+
+ @SafeVarargs
+ private final IssueDto insertNewClosedIssue(ComponentDto component, RuleDefinitionDto rule, long issueCloseTime, Consumer<IssueDto>... consumers) {
IssueDto res = new IssueDto()
.setKee(UuidFactoryFast.getInstance().create())
.setRuleId(rule.getId())
.setType(rule.getType())
.setComponentUuid(component.uuid())
.setProjectUuid(component.projectUuid())
- .setStatus(Issue.STATUS_CLOSED);
+ .setStatus(Issue.STATUS_CLOSED)
+ .setIssueCloseTime(issueCloseTime);
Arrays.asList(consumers).forEach(c -> c.accept(res));
underTest.insert(res);
dbSession.commit();
return res;
}
+ private static final RuleType[] SUPPORTED_RULE_TYPES = Arrays.stream(RuleType.values())
+ .filter(t -> t != RuleType.SECURITY_HOTSPOT)
+ .toArray(RuleType[]::new);
+
@DataProvider
public static Object[][] closedIssuesSupportedRuleTypes() {
- return Arrays.stream(RuleType.values())
- .filter(t -> t != RuleType.SECURITY_HOTSPOT)
+ return Arrays.stream(SUPPORTED_RULE_TYPES)
.map(t -> new Object[] {t})
.toArray(Object[][]::new);
}
+ private static RuleType randomSupportedRuleType() {
+ return SUPPORTED_RULE_TYPES[new Random().nextInt(SUPPORTED_RULE_TYPES.length)];
+ }
+
private ComponentDto randomComponent(OrganizationDto organization) {
ComponentDto project = dbTester.components().insertPublicProject(organization);
ComponentDto module = dbTester.components().insertComponent(ComponentTesting.newModuleDto(project));