diff options
author | Daniel Schwarz <daniel.schwarz@sonarsource.com> | 2017-02-06 12:42:34 +0100 |
---|---|---|
committer | Daniel Schwarz <bartfastiel@users.noreply.github.com> | 2017-02-13 11:08:03 +0100 |
commit | e7c02f7fec37c6c7c16af8759d313ad81d807ffa (patch) | |
tree | dc258730e1b2c9eebb65598a2d9ccaa8468e83da | |
parent | e6ef4e2eb6e853e0edd6a58f05cb3e6c99e7bc58 (diff) | |
download | sonarqube-e7c02f7fec37c6c7c16af8759d313ad81d807ffa.tar.gz sonarqube-e7c02f7fec37c6c7c16af8759d313ad81d807ffa.zip |
SONAR-8736 it test for issue creation date
21 files changed, 514 insertions, 4 deletions
diff --git a/it/it-projects/issue/creationDateSampleChanged/sonar-project.properties b/it/it-projects/issue/creationDateSampleChanged/sonar-project.properties new file mode 100644 index 00000000000..3a25a96024f --- /dev/null +++ b/it/it-projects/issue/creationDateSampleChanged/sonar-project.properties @@ -0,0 +1,5 @@ +sonar.projectKey=creation-date-sample +sonar.projectName=Creation date sample +sonar.projectVersion=SNAPSHOT +sonar.sources=src/main/xoo +sonar.language=xoo diff --git a/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndModified.xoo b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndModified.xoo new file mode 100644 index 00000000000..2e3e81d8300 --- /dev/null +++ b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndModified.xoo @@ -0,0 +1,7 @@ +/**/package sample; +/**/ +/**/public class ForeverAndModified { +/**/ +/**/ private String myMethod() { +/**/ } +/**/} diff --git a/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndModified.xoo.scm b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndModified.xoo.scm new file mode 100644 index 00000000000..f8c205d4d68 --- /dev/null +++ b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndModified.xoo.scm @@ -0,0 +1,8 @@ +2,jhenry,2004-01-01T00:00:00+0000 +2,jhenry,2004-01-01T00:00:00+0000 +2,jhenry,2004-01-01T00:00:00+0000 +2,jhenry,2004-01-01T00:00:00+0000 +2,jhenry,2004-01-01T00:00:00+0000 +2,jhenry,2004-01-01T00:00:00+0000 +2,jhenry,2004-01-01T00:00:00+0000 +2,jhenry,2004-01-01T00:00:00+0000 diff --git a/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndUnmodified.xoo b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndUnmodified.xoo new file mode 100644 index 00000000000..3d80cf8da75 --- /dev/null +++ b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndUnmodified.xoo @@ -0,0 +1,7 @@ +package sample; + +public class ForeverAndUnmodified { + + private String myMethod() { + } +} diff --git a/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndUnmodified.xoo.scm b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndUnmodified.xoo.scm new file mode 100644 index 00000000000..3272e3e6ed8 --- /dev/null +++ b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/ForeverAndUnmodified.xoo.scm @@ -0,0 +1,8 @@ +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 diff --git a/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/OnlyInChanged.xoo b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/OnlyInChanged.xoo new file mode 100644 index 00000000000..0a96b5c9ddb --- /dev/null +++ b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/OnlyInChanged.xoo @@ -0,0 +1,7 @@ +/**/package sample; +/**/ +/**/public class OnlyInChanged { +/**/ +/**/ private String anotherMethod() { +/**/ } +/**/} diff --git a/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/OnlyInChanged.xoo.scm b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/OnlyInChanged.xoo.scm new file mode 100644 index 00000000000..59c11db6b3b --- /dev/null +++ b/it/it-projects/issue/creationDateSampleChanged/src/main/xoo/sample/OnlyInChanged.xoo.scm @@ -0,0 +1,8 @@ +1,jhenry,2005-01-01T00:00:00+0000 +1,jhenry,2005-01-01T00:00:00+0000 +1,jhenry,2005-01-01T00:00:00+0000 +1,jhenry,2005-01-01T00:00:00+0000 +1,jhenry,2005-01-01T00:00:00+0000 +1,jhenry,2005-01-01T00:00:00+0000 +1,jhenry,2005-01-01T00:00:00+0000 +1,jhenry,2005-01-01T00:00:00+0000 diff --git a/it/it-projects/issue/creationDateSampleInitial/sonar-project.properties b/it/it-projects/issue/creationDateSampleInitial/sonar-project.properties new file mode 100644 index 00000000000..3a25a96024f --- /dev/null +++ b/it/it-projects/issue/creationDateSampleInitial/sonar-project.properties @@ -0,0 +1,5 @@ +sonar.projectKey=creation-date-sample +sonar.projectName=Creation date sample +sonar.projectVersion=SNAPSHOT +sonar.sources=src/main/xoo +sonar.language=xoo diff --git a/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndModified.xoo b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndModified.xoo new file mode 100644 index 00000000000..4b6e8b8d818 --- /dev/null +++ b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndModified.xoo @@ -0,0 +1,7 @@ +package sample; + +public class ForeverAndModified { + + private String myMethod() { + } +} diff --git a/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndModified.xoo.scm b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndModified.xoo.scm new file mode 100644 index 00000000000..654a775e4ef --- /dev/null +++ b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndModified.xoo.scm @@ -0,0 +1,8 @@ +1,jhenry,2003-01-01T00:00:00+0000 +1,jhenry,2003-01-01T00:00:00+0000 +1,jhenry,2003-01-01T00:00:00+0000 +1,jhenry,2003-01-01T00:00:00+0000 +1,jhenry,2003-01-01T00:00:00+0000 +1,jhenry,2003-01-01T00:00:00+0000 +1,jhenry,2003-01-01T00:00:00+0000 +1,jhenry,2003-01-01T00:00:00+0000 diff --git a/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndUnmodified.xoo b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndUnmodified.xoo new file mode 100644 index 00000000000..3d80cf8da75 --- /dev/null +++ b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndUnmodified.xoo @@ -0,0 +1,7 @@ +package sample; + +public class ForeverAndUnmodified { + + private String myMethod() { + } +} diff --git a/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndUnmodified.xoo.scm b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndUnmodified.xoo.scm new file mode 100644 index 00000000000..3272e3e6ed8 --- /dev/null +++ b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/ForeverAndUnmodified.xoo.scm @@ -0,0 +1,8 @@ +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 +1,jhenry,2002-01-01T00:00:00+0000 diff --git a/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/OnlyInInitial.xoo b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/OnlyInInitial.xoo new file mode 100644 index 00000000000..969fc44abfe --- /dev/null +++ b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/OnlyInInitial.xoo @@ -0,0 +1,7 @@ +package sample; + +public class IsBuggyThenChangesAndBecomesClean { + + private String myMethod() { + } +} diff --git a/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/OnlyInInitial.xoo.scm b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/OnlyInInitial.xoo.scm new file mode 100644 index 00000000000..65099dbec9b --- /dev/null +++ b/it/it-projects/issue/creationDateSampleInitial/src/main/xoo/sample/OnlyInInitial.xoo.scm @@ -0,0 +1,8 @@ +1,jhenry,2001-01-01T00:00:00+0000 +1,jhenry,2001-01-01T00:00:00+0000 +1,jhenry,2001-01-01T00:00:00+0000 +1,jhenry,2001-01-01T00:00:00+0000 +1,jhenry,2001-01-01T00:00:00+0000 +1,jhenry,2001-01-01T00:00:00+0000 +1,jhenry,2001-01-01T00:00:00+0000 +1,jhenry,2001-01-01T00:00:00+0000 diff --git a/it/it-tests/src/test/java/it/issue/IssueCreationDateTest.java b/it/it-tests/src/test/java/it/issue/IssueCreationDateTest.java new file mode 100644 index 00000000000..0caa3db8687 --- /dev/null +++ b/it/it-tests/src/test/java/it/issue/IssueCreationDateTest.java @@ -0,0 +1,379 @@ +/* + * 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 it.issue; + +import com.sonar.orchestrator.build.SonarScanner; +import com.sonar.orchestrator.container.Server; +import com.sonar.orchestrator.locator.FileLocation; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Stream; +import org.junit.Before; +import org.junit.Test; +import org.sonar.wsclient.issue.Issue; +import org.sonar.wsclient.issue.IssueQuery; +import org.sonarqube.ws.ProjectAnalyses; +import org.sonarqube.ws.client.projectanalysis.SearchRequest; +import util.ItUtils; + +import static org.assertj.core.api.Assertions.assertThat; +import static util.ItUtils.projectDir; + +/** + * @see <a href="https://jira.sonarsource.com/browse/MMF-567">MMF-567</a> + */ +public class IssueCreationDateTest extends AbstractIssueTest { + + private static final String ISSUE_STATUS_OPEN = "OPEN"; + + private static final String LANGUAGE_XOO = "xoo"; + + private static final String DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ"; + private static final String DATE_FORMAT = "yyyy-MM-dd"; + + private static final String SAMPLE_PROJECT_KEY = "creation-date-sample"; + private static final String SAMPLE_PROJECT_NAME = "Creation date sample"; + private static final String SAMPLE_QUALITY_PROFILE_NAME = "creation-date-quality-profile"; + private static final String SAMPLE_EXPLICIT_DATE_1 = todayMinusDays(2); + private static final String SAMPLE_EXPLICIT_DATE_2 = todayMinusDays(1); + + private Server server = ORCHESTRATOR.getServer(); + + @Before + public void resetData() { + ORCHESTRATOR.resetData(); + server.provisionProject(SAMPLE_PROJECT_KEY, SAMPLE_PROJECT_NAME); + } + + @Test + public void should_use_scm_date_for_new_issues_if_scm_is_available() { + analysis(QProfile.ONE_RULE, SourceCode.INITIAL, ScannerFeature.SCM); + + assertNumberOfIssues(3); + assertIssueCreationDate(Component.OnlyInInitial, IssueCreationDate.OnlyInInitial_R1); + assertIssueCreationDate(Component.ForeverAndModified, IssueCreationDate.ForeverAndModified_R1); + assertIssueCreationDate(Component.ForeverAndUnmodified, IssueCreationDate.ForeverAndUnmodified_R1); + } + + @Test + public void should_use_analysis_date_for_new_issues_if_scm_is_not_available() { + analysis(QProfile.ONE_RULE, SourceCode.INITIAL); + + assertNumberOfIssues(3); + assertIssueCreationDates(COMPONENTS_OF_SOURCE_INITIAL, IssueCreationDate.FIRST_ANALYSIS); + } + + @Test + public void use_explicit_project_date_if_scm_is_not_available() { + analysis(QProfile.ONE_RULE, SourceCode.INITIAL, ScannerFeature.EXPLICIT_DATE_1); + + assertNumberOfIssues(3); + assertIssueCreationDates(COMPONENTS_OF_SOURCE_INITIAL, IssueCreationDate.EXPLICIT_DATE_1); + } + + @Test + public void use_scm_date_even_if_explicit_project_date_is_set() { + analysis(QProfile.ONE_RULE, SourceCode.INITIAL, ScannerFeature.SCM, ScannerFeature.EXPLICIT_DATE_1); + + assertNumberOfIssues(3); + assertIssueCreationDate(Component.OnlyInInitial, IssueCreationDate.OnlyInInitial_R1); + assertIssueCreationDate(Component.ForeverAndModified, IssueCreationDate.ForeverAndModified_R1); + assertIssueCreationDate(Component.ForeverAndUnmodified, IssueCreationDate.ForeverAndUnmodified_R1); + } + + @Test + public void no_rules_no_issues_if_scm_is_available() { + analysis(QProfile.NO_RULES, SourceCode.INITIAL, ScannerFeature.SCM); + + assertNoIssue(); + } + + @Test + public void no_rules_no_issues_if_scm_is_not_available() { + analysis(QProfile.NO_RULES, SourceCode.INITIAL); + + assertNoIssue(); + } + + @Test + public void use_scm_date_for_issues_raised_by_new_rules_if_scm_is_newly_available() { + analysis(QProfile.NO_RULES, SourceCode.INITIAL); + analysis(QProfile.ONE_RULE, SourceCode.CHANGED, ScannerFeature.SCM); + + assertNumberOfIssues(3); + assertIssueCreationDate(Component.ForeverAndModified, IssueCreationDate.ForeverAndModified_R2); + assertIssueCreationDate(Component.ForeverAndUnmodified, IssueCreationDate.ForeverAndUnmodified_R1); + assertIssueCreationDate(Component.OnlyInChanged, IssueCreationDate.OnlyInChanged_R1); + } + + @Test + public void use_scm_date_for_issues_raised_by_new_rules_if_scm_is_available_and_ever_has_been_available() { + analysis(QProfile.NO_RULES, SourceCode.INITIAL, ScannerFeature.SCM); + analysis(QProfile.ONE_RULE, SourceCode.CHANGED, ScannerFeature.SCM); + + assertNumberOfIssues(3); + assertIssueCreationDate(Component.ForeverAndModified, IssueCreationDate.ForeverAndModified_R2); + assertIssueCreationDate(Component.ForeverAndUnmodified, IssueCreationDate.ForeverAndUnmodified_R1); + assertIssueCreationDate(Component.OnlyInChanged, IssueCreationDate.OnlyInChanged_R1); + } + + @Test + public void use_analysis_date_for_issues_raised_by_new_rules_if_scm_is_not_available() { + analysis(QProfile.NO_RULES, SourceCode.INITIAL); + analysis(QProfile.ONE_RULE, SourceCode.CHANGED); + + assertNumberOfIssues(3); + Stream.of(COMPONENTS_OF_SOURCE_CHANGED) + .forEach(component -> { + assertIssueCreationDate(component, IssueCreationDate.LATEST_ANALYSIS); + }); + } + + @Test + public void keep_the_date_of_an_existing_issue_even_if_the_blame_information_changes() { + analysis(QProfile.ONE_RULE, SourceCode.INITIAL, ScannerFeature.SCM); + analysis(QProfile.ONE_RULE, SourceCode.CHANGED, ScannerFeature.SCM); + + assertNumberOfIssues(3); + assertIssueCreationDate(Component.ForeverAndModified, IssueCreationDate.ForeverAndModified_R1); + assertIssueCreationDate(Component.ForeverAndUnmodified, IssueCreationDate.ForeverAndUnmodified_R1); + + // this file is new to the second analysis + assertIssueCreationDate(Component.OnlyInChanged, IssueCreationDate.LATEST_ANALYSIS); + } + + @Test + public void ignore_explicit_date_for_issues_related_to_new_rules_if_scm_is_available() { + analysis(QProfile.NO_RULES, SourceCode.INITIAL, ScannerFeature.SCM, ScannerFeature.EXPLICIT_DATE_1); + analysis(QProfile.ONE_RULE, SourceCode.CHANGED, ScannerFeature.SCM, ScannerFeature.EXPLICIT_DATE_2); + + assertNumberOfIssues(3); + assertIssueCreationDate(Component.ForeverAndModified, IssueCreationDate.ForeverAndModified_R2); + assertIssueCreationDate(Component.ForeverAndUnmodified, IssueCreationDate.ForeverAndUnmodified_R1); + assertIssueCreationDate(Component.OnlyInChanged, IssueCreationDate.OnlyInChanged_R1); + } + + @Test + public void use_explicit_date_for_issues_related_to_new_rules_if_scm_is_not_available() { + analysis(QProfile.NO_RULES, SourceCode.INITIAL, ScannerFeature.EXPLICIT_DATE_1); + analysis(QProfile.ONE_RULE, SourceCode.CHANGED, ScannerFeature.EXPLICIT_DATE_2); + + assertNumberOfIssues(3); + assertIssueCreationDates(COMPONENTS_OF_SOURCE_CHANGED, IssueCreationDate.EXPLICIT_DATE_2); + } + + private void analysis(QProfile qProfile, SourceCode sourceCode, ScannerFeature... scm) { + server.restoreProfile(FileLocation.ofClasspath(qProfile.path)); + server.associateProjectToQualityProfile(SAMPLE_PROJECT_KEY, LANGUAGE_XOO, SAMPLE_QUALITY_PROFILE_NAME); + + SonarScanner scanner = SonarScanner.create(projectDir(sourceCode.path)); + Arrays.stream(scm).forEach(s -> s.configure(scanner)); + ORCHESTRATOR.executeBuild(scanner); + } + + private static void assertNoIssue() { + assertNumberOfIssues(0); + } + + private static void assertNumberOfIssues(int number) { + assertThat(getIssues(issueQuery())).hasSize(number); + } + + private static void assertIssueCreationDate(Component component, IssueCreationDate expectedDate) { + assertIssueCreationDates(new Component[] {component}, expectedDate); + } + + private static void assertIssueCreationDates(Component[] components, IssueCreationDate expectedDate) { + String[] keys = Arrays.stream(components).map(Component::getKey).toArray(String[]::new); + List<Issue> issues = getIssues(issueQuery().components(keys)); + Date[] dates = Arrays.stream(components).map(x -> expectedDate.getDate()).toArray(Date[]::new); + + assertThat(issues) + .extracting(Issue::creationDate) + .containsExactly(dates); + } + + private static List<Issue> getIssues(IssueQuery query) { + return issueClient().find(query).list(); + } + + private static IssueQuery issueQuery() { + return IssueQuery.create().statuses(ISSUE_STATUS_OPEN); + } + + private static Date dateTimeParse(String expectedDate) { + try { + return new SimpleDateFormat(DATETIME_FORMAT).parse(expectedDate); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + private static Date dateParse(String expectedDate) { + try { + return new SimpleDateFormat(DATE_FORMAT).parse(expectedDate); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + private static String todayMinusDays(int numberOfDays) { + return DateTimeFormatter.ofPattern(DATE_FORMAT).format(LocalDate.now().atStartOfDay().minusDays(numberOfDays)); + } + + private enum SourceCode { + INITIAL("issue/creationDateSampleInitial"), + CHANGED("issue/creationDateSampleChanged"), + ; + + private final String path; + + private SourceCode(String path) { + this.path = path; + } + } + + private enum Component { + OnlyInInitial("creation-date-sample:src/main/xoo/sample/OnlyInInitial.xoo"), + ForeverAndModified("creation-date-sample:src/main/xoo/sample/ForeverAndModified.xoo"), + ForeverAndUnmodified("creation-date-sample:src/main/xoo/sample/ForeverAndUnmodified.xoo"), + OnlyInChanged("creation-date-sample:src/main/xoo/sample/OnlyInChanged.xoo"), + ; + private final String key; + + private Component(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + } + + private static final Component[] COMPONENTS_OF_SOURCE_INITIAL = {Component.OnlyInInitial, Component.ForeverAndModified, Component.ForeverAndUnmodified}; + private static final Component[] COMPONENTS_OF_SOURCE_CHANGED = {Component.ForeverAndModified, Component.ForeverAndUnmodified, Component.OnlyInChanged}; + + private enum QProfile { + ONE_RULE("/issue/IssueCreationDateTest/one-rule.xml"), + NO_RULES("/issue/IssueCreationDateTest/no-rules.xml"), + ; + + private final String path; + + private QProfile(String path) { + this.path = path; + } + } + + private enum ScannerFeature { + SCM { + @Override + void configure(SonarScanner scanner) { + scanner + .setProperty("sonar.scm.provider", "xoo") + .setProperty("sonar.scm.disabled", "false"); + } + }, + EXPLICIT_DATE_1 { + @Override + void configure(SonarScanner scanner) { + scanner + .setProperty("sonar.projectDate", SAMPLE_EXPLICIT_DATE_1); + } + }, + EXPLICIT_DATE_2 { + @Override + void configure(SonarScanner scanner) { + scanner + .setProperty("sonar.projectDate", SAMPLE_EXPLICIT_DATE_2); + } + }, + ; + + void configure(SonarScanner scanner) { + } + } + + private enum IssueCreationDate { + OnlyInInitial_R1(dateTimeParse("2001-01-01T00:00:00+0000")), + ForeverAndUnmodified_R1(dateTimeParse("2002-01-01T00:00:00+0000")), + ForeverAndModified_R1(dateTimeParse("2003-01-01T00:00:00+0000")), + ForeverAndModified_R2(dateTimeParse("2004-01-01T00:00:00+0000")), + OnlyInChanged_R1(dateTimeParse("2005-01-01T00:00:00+0000")), + EXPLICIT_DATE_1(dateParse(SAMPLE_EXPLICIT_DATE_1)), + EXPLICIT_DATE_2(dateParse(SAMPLE_EXPLICIT_DATE_2)), + FIRST_ANALYSIS { + @Override + Date getDate() { + return getAnalysisDate(l -> { + if (l.isEmpty()) { + return Optional.empty(); + } + return Optional.of(l.get(l.size() - 1)); + }); + } + }, + LATEST_ANALYSIS { + @Override + Date getDate() { + return getAnalysisDate(l -> { + if (l.size() > 0) { + return Optional.of(l.get(0)); + } + return Optional.empty(); + }); + } + }, + ; + + private final Date date; + + private IssueCreationDate() { + this.date = null; + } + + private IssueCreationDate(Date date) { + this.date = date; + } + + Date getDate() { + return date; + } + + private static Date getAnalysisDate(Function<List<ProjectAnalyses.Analysis>, Optional<ProjectAnalyses.Analysis>> chooseItem) { + return Optional.of( + ItUtils.newWsClient(ORCHESTRATOR) + .projectAnanlysis() + .search(SearchRequest.builder().setProject(SAMPLE_PROJECT_KEY).build()) + .getAnalysesList()) + .flatMap(chooseItem) + .map(ProjectAnalyses.Analysis::getDate) + .map(IssueCreationDateTest::dateTimeParse) + .orElseThrow(() -> new IllegalStateException("There is no analysis")); + } + } +} diff --git a/it/it-tests/src/test/resources/issue/IssueCreationDateTest/no-rules.xml b/it/it-tests/src/test/resources/issue/IssueCreationDateTest/no-rules.xml new file mode 100644 index 00000000000..62ec52d9d10 --- /dev/null +++ b/it/it-tests/src/test/resources/issue/IssueCreationDateTest/no-rules.xml @@ -0,0 +1,6 @@ +<profile> + <name>creation-date-quality-profile</name> + <language>xoo</language> + <rules> + </rules> +</profile> diff --git a/it/it-tests/src/test/resources/issue/IssueCreationDateTest/one-rule.xml b/it/it-tests/src/test/resources/issue/IssueCreationDateTest/one-rule.xml new file mode 100644 index 00000000000..c1d7d44f02c --- /dev/null +++ b/it/it-tests/src/test/resources/issue/IssueCreationDateTest/one-rule.xml @@ -0,0 +1,11 @@ +<profile> + <name>creation-date-quality-profile</name> + <language>xoo</language> + <rules> + <rule> + <repositoryKey>xoo</repositoryKey> + <key>OneIssuePerFile</key> + <priority>MAJOR</priority> + </rule> + </rules> +</profile> diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java index 253f3636cff..26137cbe6a8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java @@ -1,7 +1,7 @@ /* * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com + * 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 diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java index c66decbf774..1e2ffcfd40d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java @@ -1,7 +1,7 @@ /* * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com + * 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 diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java index a905aee8f20..6f80e6b66e5 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java @@ -27,6 +27,7 @@ import org.sonarqube.ws.client.measure.MeasuresService; import org.sonarqube.ws.client.organization.OrganizationService; import org.sonarqube.ws.client.permission.PermissionsService; import org.sonarqube.ws.client.project.ProjectsService; +import org.sonarqube.ws.client.projectanalysis.ProjectAnalysisService; import org.sonarqube.ws.client.projectlinks.ProjectLinksService; import org.sonarqube.ws.client.qualitygate.QualityGatesService; import org.sonarqube.ws.client.qualityprofile.QualityProfilesService; @@ -65,6 +66,7 @@ class DefaultWsClient implements WsClient { private final SettingsService settingsService; private final RootsService rootsService; private final WebhooksService webhooksService; + private final ProjectAnalysisService projectAnalysisService; DefaultWsClient(WsConnector wsConnector) { this.wsConnector = wsConnector; @@ -86,6 +88,7 @@ class DefaultWsClient implements WsClient { this.settingsService = new SettingsService(wsConnector); this.rootsService = new RootsService(wsConnector); this.webhooksService = new WebhooksService(wsConnector); + this.projectAnalysisService = new ProjectAnalysisService(wsConnector); } @Override @@ -182,4 +185,9 @@ class DefaultWsClient implements WsClient { public WebhooksService webhooks() { return webhooksService; } + + @Override + public ProjectAnalysisService projectAnanlysis() { + return projectAnalysisService; + } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java index 4a1cb95a0ba..9220614689f 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java @@ -27,6 +27,7 @@ import org.sonarqube.ws.client.measure.MeasuresService; import org.sonarqube.ws.client.organization.OrganizationService; import org.sonarqube.ws.client.permission.PermissionsService; import org.sonarqube.ws.client.project.ProjectsService; +import org.sonarqube.ws.client.projectanalysis.ProjectAnalysisService; import org.sonarqube.ws.client.projectlinks.ProjectLinksService; import org.sonarqube.ws.client.qualitygate.QualityGatesService; import org.sonarqube.ws.client.qualityprofile.QualityProfilesService; @@ -109,4 +110,9 @@ public interface WsClient { * @since 6.2 */ WebhooksService webhooks(); + + /** + * @since 6.3 + */ + ProjectAnalysisService projectAnanlysis(); } |