From d1b0098d7fc9ef5d386b7aa71b883891c8e489ce Mon Sep 17 00:00:00 2001 From: Stephane Gamard Date: Sun, 31 Aug 2014 19:02:27 +0200 Subject: [PATCH] SONAR-5529 - Basic Issue Normalization with MediumTests --- .../sonar/server/issue/index/IssueDoc.java | 47 +++++++++++----- .../server/issue/index/IssueNormalizer.java | 56 ++++++++++++++++++- .../issue/db/IssueBackendMediumTest.java | 45 ++++++++++++--- .../org/sonar/core/issue/db/IssueDto.java | 33 +++++++++++ 4 files changed, 154 insertions(+), 27 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java index 991fba0dd9e..7bd9a77cb05 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java @@ -23,6 +23,9 @@ import org.sonar.api.issue.Issue; import org.sonar.api.issue.IssueComment; import org.sonar.api.rule.RuleKey; import org.sonar.server.search.BaseDoc; +import org.sonar.server.search.IndexUtils; + +import javax.annotation.CheckForNull; import java.util.Date; import java.util.List; @@ -41,70 +44,82 @@ public class IssueDoc extends BaseDoc implements Issue { @Override public String componentKey() { - return null; + return getField(IssueNormalizer.IssueField.COMPONENT.field()); } @Override public RuleKey ruleKey() { - return null; + return RuleKey.of( + (String) getField(IssueNormalizer.IssueField.REPOSITORY.field()), + (String) getField(IssueNormalizer.IssueField.RULE.field())); } @Override public String severity() { - return null; + return getField(IssueNormalizer.IssueField.SEVERITY.field()); } @Override + @CheckForNull public String message() { - return null; + return getNullableField(IssueNormalizer.IssueField.MESSAGE.field()); } @Override + @CheckForNull public Integer line() { - return null; + return getNullableField(IssueNormalizer.IssueField.LINE.field()); } @Override + @CheckForNull public Double effortToFix() { - return null; + return getNullableField(IssueNormalizer.IssueField.EFFORT.field()); } @Override public String status() { - return null; + return getField(IssueNormalizer.IssueField.STATUS.field()); } @Override + @CheckForNull public String resolution() { - return null; + return getNullableField(IssueNormalizer.IssueField.RESOLUTION.field()); } @Override + @CheckForNull public String reporter() { - return null; + return getNullableField(IssueNormalizer.IssueField.REPORTER.field()); } @Override + @CheckForNull public String assignee() { - return null; + return getNullableField(IssueNormalizer.IssueField.ASSIGNEE.field()); } @Override public Date creationDate() { - return null; + return IndexUtils.parseDateTime((String) getField(IssueNormalizer.IssueField.ISSUE_CREATED_AT.field())); } @Override public Date updateDate() { - return null; + return IndexUtils.parseDateTime((String) getField(IssueNormalizer.IssueField.ISSUE_UPDATED_AT.field())); } @Override + @CheckForNull public Date closeDate() { - return null; + return getNullableField(IssueNormalizer.IssueField.ISSUE_CLOSE_DATE.field()) != null ? + IndexUtils.parseDateTime((String) getNullableField(IssueNormalizer.IssueField.ISSUE_CLOSE_DATE.field())) : + null; } @Override + @CheckForNull public String attribute(String key) { return null; } @@ -115,13 +130,15 @@ public class IssueDoc extends BaseDoc implements Issue { } @Override + @CheckForNull public String authorLogin() { - return null; + return getNullableField(IssueNormalizer.IssueField.AUTHOR_LOGIN.field()); } @Override + @CheckForNull public String actionPlanKey() { - return null; + return getNullableField(IssueNormalizer.IssueField.ACTION_PLAN.field()); } @Override diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java index 6932cb9f40e..38ae9d97635 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java @@ -44,6 +44,26 @@ public class IssueNormalizer extends BaseNormalizer { public static final class IssueField extends Indexable { public static final IndexField KEY = addSortable(IndexField.Type.STRING, "key"); + public static final IndexField CREATED_AT = add(IndexField.Type.DATE, "createdAt"); + public static final IndexField UPDATED_AT = add(IndexField.Type.DATE, "updatedAt"); + + public static final IndexField ACTION_PLAN = add(IndexField.Type.STRING, "actionPlan"); + public static final IndexField ASSIGNEE = add(IndexField.Type.STRING, "assignee"); + public static final IndexField AUTHOR_LOGIN = add(IndexField.Type.STRING, "authorLogin"); + public static final IndexField ISSUE_CREATED_AT = add(IndexField.Type.DATE, "issueCreatedAt"); + public static final IndexField ISSUE_UPDATED_AT = add(IndexField.Type.DATE, "issueUpdatedAt"); + public static final IndexField ISSUE_CLOSE_DATE = add(IndexField.Type.DATE, "issueClosedAt"); + public static final IndexField COMPONENT = add(IndexField.Type.STRING, "component"); + public static final IndexField EFFORT = add(IndexField.Type.NUMERIC, "effort"); + public static final IndexField RESOLUTION = add(IndexField.Type.STRING, "resolution"); + public static final IndexField LINE = add(IndexField.Type.NUMERIC, "line"); + public static final IndexField MESSAGE = add(IndexField.Type.STRING, "message"); + public static final IndexField REPORTER = add(IndexField.Type.STRING, "reporter"); + public static final IndexField STATUS = add(IndexField.Type.STRING, "status"); + public static final IndexField SEVERITY = add(IndexField.Type.STRING, "severity"); + + public static final IndexField RULE = addSearchable(IndexField.Type.STRING, "rule"); + public static final IndexField REPOSITORY = addSearchable(IndexField.Type.STRING, "repository"); public static final Set ALL_FIELDS = getAllFields(); @@ -74,14 +94,44 @@ public class IssueNormalizer extends BaseNormalizer { @Override public List normalize(IssueDto dto) { Map update = new HashMap(); - Map upsert = new HashMap(); update.put(IssueField.KEY.field(), dto.getKey()); + update.put(IssueField.UPDATED_AT.field(), dto.getUpdatedAt()); + update.put(IssueField.CREATED_AT.field(), dto.getCreatedAt()); + + update.put(IssueField.ACTION_PLAN.field(), dto.getActionPlanKey()); + update.put(IssueField.ASSIGNEE.field(), dto.getAssignee()); + update.put(IssueField.AUTHOR_LOGIN.field(), dto.getAuthorLogin()); + update.put(IssueField.ISSUE_CLOSE_DATE.field(), dto.getIssueCloseDate()); + update.put(IssueField.COMPONENT.field(), dto.getComponentKey()); + update.put(IssueField.ISSUE_CREATED_AT.field(), dto.getIssueCreationDate()); + update.put(IssueField.ISSUE_UPDATED_AT.field(), dto.getIssueUpdateDate()); + update.put(IssueField.EFFORT.field(), dto.getEffortToFix()); + update.put(IssueField.RESOLUTION.field(), dto.getResolution()); + update.put(IssueField.LINE.field(), dto.getLine()); + update.put(IssueField.MESSAGE.field(), dto.getMessage()); + update.put(IssueField.REPORTER.field(), dto.getReporter()); + update.put(IssueField.STATUS.field(), dto.getStatus()); + update.put(IssueField.SEVERITY.field(), dto.getSeverity()); + + // issueDoc.ruleKey(); + update.put(IssueField.RULE.field(), dto.getRule()); + update.put(IssueField.REPOSITORY.field(), dto.getRuleRepo()); + + // TODO Not yet normalized + // IssueDoc issueDoc = new IssueDoc(null); + // issueDoc.isNew(); + // issueDoc.comments(); + // issueDoc.attributes(); + + /** Upsert elements */ + Map upsert = getUpsertFor(IssueField.ALL_FIELDS, update); + upsert.put(IssueField.KEY.field(), dto.getKey().toString()); return ImmutableList.of( new UpdateRequest() .id(dto.getKey().toString()) .doc(update) - .upsert(update)); - } + .upsert(upsert)); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java index 9b7e9d8829b..a3c970fdfc9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java @@ -23,6 +23,7 @@ import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; +import org.sonar.api.rule.RuleKey; import org.sonar.core.component.ComponentDto; import org.sonar.core.issue.db.IssueDto; import org.sonar.core.persistence.DbSession; @@ -45,7 +46,8 @@ import static org.fest.assertions.Assertions.assertThat; public class IssueBackendMediumTest { @ClassRule - public static ServerTester tester = new ServerTester(); + public static ServerTester tester = new ServerTester() + .setProperty("sonar.log.profilingLevel", "FULL"); DbClient dbClient; IndexClient indexClient; @@ -74,25 +76,29 @@ public class IssueBackendMediumTest { tester.get(RuleDao.class).insert(dbSession, rule); ComponentDto project = new ComponentDto() - .setId(1L) + .setKey("MyProject") + .setId(1L) .setProjectId(1L); tester.get(ComponentDao.class).insert(dbSession, project); ComponentDto resource = new ComponentDto() + .setKey("MyComponent") .setProjectId(1L) .setId(2L); tester.get(ComponentDao.class).insert(dbSession, resource); - IssueDto issue = new IssueDto().setId(1L).setRuleId(50).setComponentId(123l).setRootComponentId(100l) - .setRuleId(rule.getId()) - .setRootComponentId(project.getId()) - .setComponentId(resource.getId()) + IssueDto issue = new IssueDto() + .setIssueCreationDate(new Date()) + .setIssueUpdateDate(new Date()) + .setRule(rule) + .setRootComponent(project) + .setComponent(resource) .setStatus("OPEN").setResolution("OPEN") - .setKee(UUID.randomUUID().toString()); + .setKee(UUID.randomUUID().toString()) + .setSeverity("MAJOR"); dbClient.issueDao().insert(dbSession, issue); dbSession.commit(); - assertThat(issue.getId()).isNotNull(); // Check that Issue is in Index assertThat(indexClient.get(IssueIndex.class).countAll()).isEqualTo(1); @@ -100,11 +106,32 @@ public class IssueBackendMediumTest { // should find by key IssueDoc issueDoc = indexClient.get(IssueIndex.class).getByKey(issue.getKey()); assertThat(issueDoc).isNotNull(); + + // Check all normalized fields + assertThat(issueDoc.actionPlanKey()).isEqualTo(issue.getActionPlanKey()); + assertThat(issueDoc.assignee()).isEqualTo(issue.getAssignee()); + assertThat(issueDoc.authorLogin()).isEqualTo(issue.getAuthorLogin()); + assertThat(issueDoc.closeDate()).isEqualTo(issue.getIssueCloseDate()); + assertThat(issueDoc.componentKey()).isEqualTo(issue.getComponentKey()); + assertThat(issueDoc.creationDate()).isEqualTo(issue.getCreatedAt()); + assertThat(issueDoc.effortToFix()).isEqualTo(issue.getEffortToFix()); + assertThat(issueDoc.resolution()).isEqualTo(issue.getResolution()); + assertThat(issueDoc.ruleKey()).isEqualTo(RuleKey.of(issue.getRuleRepo(), issue.getRule())); + assertThat(issueDoc.line()).isEqualTo(issue.getLine()); + assertThat(issueDoc.message()).isEqualTo(issue.getMessage()); + assertThat(issueDoc.reporter()).isEqualTo(issue.getReporter()); assertThat(issueDoc.key()).isEqualTo(issue.getKey()); + assertThat(issueDoc.updateDate()).isEqualTo(issue.getIssueUpdateDate()); + assertThat(issueDoc.status()).isEqualTo(issue.getStatus()); + assertThat(issueDoc.severity()).isEqualTo(issue.getSeverity()); + + // assertThat(issueDoc.attributes()).isEqualTo(issue.getIssueAttributes()); + // assertThat(issueDoc.isNew()).isEqualTo(issue.isN()); + // assertThat(issueDoc.comments()).isEqualTo(issue.()); } @Test - public void insert_and_find_after_date() throws Exception { + public void insert_and_find_after_date() throws Exception { RuleDto rule = RuleTesting.newXooX1(); tester.get(RuleDao.class).insert(dbSession, rule); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java index 355652afb99..47daf0b7871 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java @@ -28,6 +28,7 @@ import org.sonar.api.resources.Project; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.Duration; import org.sonar.api.utils.KeyValueFormat; +import org.sonar.core.component.ComponentDto; import org.sonar.core.persistence.Dto; import org.sonar.core.rule.RuleDto; @@ -108,6 +109,16 @@ public final class IssueDto extends Dto implements Serializable { return componentId; } + public IssueDto setComponent(ComponentDto component) { + this.componentId = component.getId(); + this.componentKey = component.getKey(); + return this; + } + + /** + * @deprecated please use setComponent(ComponentDto component) + */ + @Deprecated public IssueDto setComponentId(Long componentId) { this.componentId = componentId; return this; @@ -117,6 +128,16 @@ public final class IssueDto extends Dto implements Serializable { return rootComponentId; } + public IssueDto setRootComponent(ComponentDto rootComponent) { + this.rootComponentId = rootComponent.getId(); + this.rootComponentKey = rootComponent.getKey(); + return this; + } + + /** + * @deprecated please use setRootComponent; + */ + @Deprecated public IssueDto setRootComponentId(Long rootComponentId) { this.rootComponentId = rootComponentId; return this; @@ -126,6 +147,18 @@ public final class IssueDto extends Dto implements Serializable { return ruleId; } + public IssueDto setRule(RuleDto rule) { + Preconditions.checkNotNull(rule.getId(), "Rule must be persisted."); + this.ruleId = rule.getId(); + this.ruleKey = rule.getRuleKey(); + this.ruleRepo = rule.getRepositoryKey(); + return this; + } + + /** + * @deprecated please use setRule(RuleDto rule) + */ + @Deprecated public IssueDto setRuleId(Integer ruleId) { this.ruleId = ruleId; return this; -- 2.39.5