]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-1450: Add support for incremental review of incoming violations
authorGodin <mandrikov@gmail.com>
Mon, 29 Nov 2010 15:31:20 +0000 (15:31 +0000)
committerGodin <mandrikov@gmail.com>
Mon, 29 Nov 2010 15:31:20 +0000 (15:31 +0000)
* Move getPreviousLastSnapshot from UpdateStatusJob to DefaultResourcePersister
* ViolationPersister should allow load and update of violations

13 files changed:
sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
sonar-batch/src/main/java/org/sonar/batch/index/DefaultPersistenceManager.java
sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java
sonar-batch/src/main/java/org/sonar/batch/index/PersistenceManager.java
sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java
sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java
sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java
sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java
sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shared.xml
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml [new file with mode: 0644]
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldSaveViolations-result.xml [deleted file]
sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldUpdateViolation-result.xml [new file with mode: 0644]

index 927177d553e1a5a16d6deda76640f4a01b2d9b24..55dbfa90c6426df9b3c52ae0774d2d80eef9c3f8 100644 (file)
@@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.Event;
 import org.sonar.api.batch.SonarIndex;
 import org.sonar.api.database.model.ResourceModel;
+import org.sonar.api.database.model.RuleFailureModel;
 import org.sonar.api.design.Dependency;
 import org.sonar.api.measures.*;
 import org.sonar.api.profiles.RulesProfile;
@@ -64,6 +65,7 @@ public final class DefaultIndex extends SonarIndex {
   private Set<Dependency> dependencies = Sets.newHashSet();
   private Map<Resource, Map<Resource, Dependency>> outgoingDependenciesByResource = Maps.newHashMap();
   private Map<Resource, Map<Resource, Dependency>> incomingDependenciesByResource = Maps.newHashMap();
+  private Map<Resource, List<RuleFailureModel>> violationsByResource = Maps.newHashMap();
   private ProjectTree projectTree;
 
   public DefaultIndex(PersistenceManager persistence, DefaultResourceCreationLock lock, ProjectTree projectTree, MetricFinder metricFinder) {
@@ -131,7 +133,6 @@ public final class DefaultIndex extends SonarIndex {
     lock.unlock();
   }
 
-
   /**
    * Does nothing if the resource is already registered.
    */
@@ -196,7 +197,6 @@ public final class DefaultIndex extends SonarIndex {
     return excluded;
   }
 
-
   public List<Resource> getChildren(Resource resource) {
     List<Resource> children = Lists.newArrayList();
     Bucket bucket = buckets.get(resource);
@@ -262,7 +262,6 @@ public final class DefaultIndex extends SonarIndex {
     }
   }
 
-
   //
   //
   //
@@ -270,6 +269,7 @@ public final class DefaultIndex extends SonarIndex {
   //
   //
   //
+
   public Dependency addDependency(Dependency dependency) {
     Dependency existingDep = getEdge(dependency.getFrom(), dependency.getTo());
     if (existingDep != null) {
@@ -356,7 +356,6 @@ public final class DefaultIndex extends SonarIndex {
     return result;
   }
 
-
   //
   //
   //
@@ -402,8 +401,21 @@ public final class DefaultIndex extends SonarIndex {
   }
 
   private void doAddViolation(Violation violation, Bucket bucket) {
+    Resource resource = violation.getResource();
+    if (!violationsByResource.containsKey(resource)) {
+      violationsByResource.put(resource, persistence.loadPreviousViolations(resource));
+    }
+    RuleFailureModel found = null;
+    List<RuleFailureModel> pastViolations = violationsByResource.get(resource);
+    for (RuleFailureModel pastViolation : pastViolations) {
+      // TODO Compare pastViolation to violation
+      if (pastViolation.getLine() == violation.getLineId() && StringUtils.equals(pastViolation.getMessage(), violation.getMessage())) {
+        found = pastViolation;
+        break;
+      }
+    }
     bucket.addViolation(violation);
-    persistence.saveViolation(currentProject, violation);
+    persistence.saveOrUpdateViolation(currentProject, violation, found);
   }
 
   //
@@ -413,6 +425,7 @@ public final class DefaultIndex extends SonarIndex {
   //
   //
   //
+
   public void addLink(ProjectLink link) {
     persistence.saveLink(currentProject, link);
   }
@@ -421,7 +434,6 @@ public final class DefaultIndex extends SonarIndex {
     persistence.deleteLink(currentProject, key);
   }
 
-
   //
   //
   //
index f03147a4ede54d63a0ed40250c177856b2c6d92e..2bf06968097992f1aa86a152aabd2dce91be08cd 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.batch.index;
 
 import org.sonar.api.batch.Event;
+import org.sonar.api.database.model.RuleFailureModel;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.design.Dependency;
 import org.sonar.api.measures.Measure;
@@ -86,8 +87,12 @@ public final class DefaultPersistenceManager implements PersistenceManager {
     dependencyPersister.saveDependency(project, dependency, parentDependency);
   }
 
-  public void saveViolation(Project project, Violation violation) {
-    violationPersister.saveViolation(project, violation);
+  public List<RuleFailureModel> loadPreviousViolations(Resource resource) {
+    return violationPersister.getPreviousViolations(resource);
+  }
+
+  public void saveOrUpdateViolation(Project project, Violation violation, RuleFailureModel oldModel) {
+    violationPersister.saveOrUpdateViolation(project, violation, oldModel);
   }
 
   public void saveLink(Project project, ProjectLink link) {
index e4215524033d8bd0d88b4ec055d254cfc5cf7755..05f5ef188031a7571ab87b84e87e56a05ae1a924 100644 (file)
@@ -33,6 +33,7 @@ import org.sonar.api.utils.SonarException;
 
 import javax.persistence.NonUniqueResultException;
 import javax.persistence.Query;
+
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -159,7 +160,7 @@ public final class DefaultResourcePersister implements ResourcePersister {
     model = session.save(model);
     resource.setId(model.getId()); // TODO to be removed
 
-    Snapshot parentSnapshot = (Snapshot)ObjectUtils.defaultIfNull(getSnapshot(resource.getParent()), projectSnapshot);
+    Snapshot parentSnapshot = (Snapshot) ObjectUtils.defaultIfNull(getSnapshot(resource.getParent()), projectSnapshot);
     Snapshot snapshot = new Snapshot(model, parentSnapshot);
     snapshot = session.save(snapshot);
     session.commit();
@@ -167,17 +168,24 @@ public final class DefaultResourcePersister implements ResourcePersister {
     return snapshot;
   }
 
+  public Snapshot getPreviousLastSnapshot(Snapshot snapshot) {
+    Query query = session.createQuery(
+        "SELECT s FROM " + Snapshot.class.getSimpleName() + " s " +
+            "WHERE s.last=true AND s.resourceId=:resourceId");
+    query.setParameter("resourceId", snapshot.getResourceId());
+    return session.getSingleResult(query, null);
+  }
+
   public void clear() {
     // we keep cache of projects
     for (Iterator<Map.Entry<Resource, Snapshot>> it = snapshotsByResource.entrySet().iterator(); it.hasNext();) {
       Map.Entry<Resource, Snapshot> entry = it.next();
-      if (!ResourceUtils.isSet(entry.getKey())) {
+      if ( !ResourceUtils.isSet(entry.getKey())) {
         it.remove();
       }
     }
   }
 
-
   private ResourceModel findOrCreateModel(Resource resource) {
     ResourceModel model;
     try {
@@ -225,7 +233,7 @@ public final class DefaultResourcePersister implements ResourcePersister {
     if (StringUtils.isNotBlank(resource.getDescription())) {
       model.setDescription(resource.getDescription());
     }
-    if (!ResourceUtils.isLibrary(resource)) {
+    if ( !ResourceUtils.isLibrary(resource)) {
       model.setScope(resource.getScope());
       model.setQualifier(resource.getQualifier());
     }
index f53248feff2f9592bb6c368a16ca9bbe7f8abdd1..ebb3d2ea1522ce5a4c6d9fe51001fe97acb911b4 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.batch.index;
 
 import org.sonar.api.batch.Event;
+import org.sonar.api.database.model.RuleFailureModel;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.design.Dependency;
 import org.sonar.api.measures.Measure;
@@ -47,7 +48,9 @@ public interface PersistenceManager {
 
   void saveDependency(Project project, Dependency dependency, Dependency parentDependency);
 
-  void saveViolation(Project project, Violation violation);
+  List<RuleFailureModel> loadPreviousViolations(Resource resource);
+
+  void saveOrUpdateViolation(Project project, Violation violation, RuleFailureModel oldModel);
 
   void saveLink(Project project, ProjectLink link);
 
index 94660c451c4dce569d7400ca434dc2bac54c57a4..6a332562cd3e96606984c098c4c6335b6a2bb237 100644 (file)
@@ -30,5 +30,7 @@ public interface ResourcePersister {
 
   Snapshot saveResource(Project project, Resource resource);
 
+  Snapshot getPreviousLastSnapshot(Snapshot snapshot);
+
   void clear();
 }
index caf426f0cfd816e62b5986d54378c84a15675c77..f5d2e9661c8b36ffca070732d941b6616030b184 100644 (file)
@@ -24,10 +24,13 @@ import org.sonar.api.database.DatabaseSession;
 import org.sonar.api.database.model.RuleFailureModel;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.Violation;
 import org.sonar.api.utils.SonarException;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 public final class ViolationPersister {
@@ -41,22 +44,44 @@ public final class ViolationPersister {
     this.resourcePersister = resourcePersister;
   }
 
-  public void saveViolation(Project project, Violation violation) {
-    Snapshot snapshot = resourcePersister.saveResource(project, violation.getResource());
-    if (snapshot != null) {
-      session.save(toModel(snapshot, violation));
+  public List<RuleFailureModel> getPreviousViolations(Resource resource) {
+    Snapshot snapshot = resourcePersister.getSnapshot(resource);
+    Snapshot previousLastSnapshot = resourcePersister.getPreviousLastSnapshot(snapshot);
+    if (previousLastSnapshot == null) {
+      return Collections.emptyList();
     }
+    return session.getResults(RuleFailureModel.class, "snapshotId", previousLastSnapshot.getId());
   }
 
-  private RuleFailureModel toModel(Snapshot snapshot, Violation violation) {
-    RuleFailureModel model = new RuleFailureModel();
-    model.setRuleId(getRuleId(violation.getRule()));
-    model.setPriority(violation.getPriority());
-    model.setLine(violation.getLineId());
-    model.setMessage(violation.getMessage());
-    model.setCost(violation.getCost());
+  public void saveOrUpdateViolation(Project project, Violation violation, RuleFailureModel oldModel) {
+    Snapshot snapshot = resourcePersister.saveResource(project, violation.getResource());
+    if (snapshot == null) {
+      return; // TODO Godin why ? when?
+    }
+    RuleFailureModel model;
+    if (oldModel != null) {
+      // update
+      model = session.reattach(RuleFailureModel.class, oldModel.getId());
+      model = mergeModel(violation, oldModel);
+    } else {
+      // insert
+      model = createModel(violation);
+    }
     model.setSnapshotId(snapshot.getId());
-    return model;
+    session.save(model);
+  }
+
+  private RuleFailureModel createModel(Violation violation) {
+    return mergeModel(violation, new RuleFailureModel());
+  }
+
+  private RuleFailureModel mergeModel(Violation violation, RuleFailureModel merge) {
+    merge.setRuleId(getRuleId(violation.getRule()));
+    merge.setPriority(violation.getPriority());
+    merge.setLine(violation.getLineId());
+    merge.setMessage(violation.getMessage());
+    merge.setCost(violation.getCost());
+    return merge;
   }
 
   private Integer getRuleId(Rule rule) {
@@ -64,7 +89,8 @@ public final class ViolationPersister {
     if (ruleId == null) {
       ruleId = rule.getId();
       if (ruleId == null) {
-        Rule persistedRule = session.getSingleResult(Rule.class, "pluginName", rule.getRepositoryKey(), "key", rule.getKey(), "enabled", true);
+        Rule persistedRule = session.getSingleResult(Rule.class,
+          "pluginName", rule.getRepositoryKey(), "key", rule.getKey(), "enabled", true);
         if (persistedRule == null) {
           throw new SonarException("Rule not found: " + rule);
         }
index 57d5d3b56f585b5c9d706a3754e51e4bb0092d90..80c3368816b006a37d7804ac3a01147cb1e44069 100644 (file)
@@ -24,6 +24,7 @@ import org.sonar.api.BatchComponent;
 import org.sonar.api.database.DatabaseSession;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.batch.ServerMetadata;
+import org.sonar.batch.index.ResourcePersister;
 
 import javax.persistence.Query;
 
@@ -32,27 +33,20 @@ public class UpdateStatusJob implements BatchComponent {
   private DatabaseSession session;
   private ServerMetadata server;
   private Snapshot snapshot; // TODO remove this component
+  private ResourcePersister resourcePersister;
 
-  public UpdateStatusJob(ServerMetadata server, DatabaseSession session, Snapshot snapshot) {
+  public UpdateStatusJob(ServerMetadata server, DatabaseSession session, ResourcePersister resourcePersister, Snapshot snapshot) {
     this.session = session;
     this.server = server;
+    this.resourcePersister = resourcePersister;
     this.snapshot = snapshot;
   }
 
   public void execute() {
-    Snapshot previousLastSnapshot = getPreviousLastSnapshot(snapshot);
+    Snapshot previousLastSnapshot = resourcePersister.getPreviousLastSnapshot(snapshot);
     updateFlags(snapshot, previousLastSnapshot);
   }
 
-  private Snapshot getPreviousLastSnapshot(Snapshot snapshot) {
-    Query query = session.createQuery(
-        "SELECT s FROM " + Snapshot.class.getSimpleName() + " s " +
-            "WHERE s.last=true AND s.resourceId=:resourceId");
-    query.setParameter("resourceId", snapshot.getResourceId());
-    return session.getSingleResult(query, null);
-  }
-
-
   private void updateFlags(Snapshot rootSnapshot, Snapshot previousLastSnapshot) {
     if (previousLastSnapshot != null && previousLastSnapshot.getCreatedAt().before(rootSnapshot.getCreatedAt())) {
       setFlags(previousLastSnapshot, false, null);
index 307295c2e29070cb0466548e6eeaa3ebb073014a..0c6b898813df3c389979e0272bed38473bbf4189 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.batch.index;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.database.model.RuleFailureModel;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.JavaFile;
 import org.sonar.api.resources.Project;
@@ -29,6 +30,11 @@ import org.sonar.api.rules.RulePriority;
 import org.sonar.api.rules.Violation;
 import org.sonar.jpa.test.AbstractDbUnitTestCase;
 
+import java.util.List;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.notNullValue;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
@@ -47,9 +53,19 @@ public class ViolationPersisterTest extends AbstractDbUnitTestCase {
     Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", 1000);
     ResourcePersister resourcePersister = mock(ResourcePersister.class);
     when(resourcePersister.saveResource((Project) anyObject(), eq(javaFile))).thenReturn(snapshot);
+    when(resourcePersister.getPreviousLastSnapshot(snapshot)).thenReturn(snapshot);
+    when(resourcePersister.getSnapshot(javaFile)).thenReturn(snapshot);
     violationPersister = new ViolationPersister(getSession(), resourcePersister);
   }
 
+  @Test
+  public void shouldLoadViolations() {
+    List<RuleFailureModel> models = violationPersister.getPreviousViolations(javaFile);
+
+    assertThat(models, notNullValue());
+    assertThat(models.size(), greaterThan(0));
+  }
+
   @Test
   public void shouldSaveViolations() {
     Violation violation1a = Violation.create(rule1, javaFile)
@@ -60,10 +76,21 @@ public class ViolationPersisterTest extends AbstractDbUnitTestCase {
     Violation violation2 = Violation.create(rule2, javaFile)
         .setPriority(RulePriority.MINOR);
 
-    violationPersister.saveViolation(new Project("project"), violation1a);
-    violationPersister.saveViolation(new Project("project"), violation1b);
-    violationPersister.saveViolation(new Project("project"), violation2);
+    violationPersister.saveOrUpdateViolation(new Project("project"), violation1a, null);
+    violationPersister.saveOrUpdateViolation(new Project("project"), violation1b, null);
+    violationPersister.saveOrUpdateViolation(new Project("project"), violation2, null);
+
+    checkTables("shouldInsertViolations", "rule_failures");
+  }
+
+  @Test
+  public void shouldUpdateViolation() {
+    Violation violation = Violation.create(rule1, javaFile)
+      .setPriority(RulePriority.CRITICAL).setLineId(20).setCost(55.6);
+    RuleFailureModel oldModel = violationPersister.getPreviousViolations(javaFile).iterator().next();
+
+    violationPersister.saveOrUpdateViolation(new Project("project"), violation, oldModel);
 
-    checkTables("shouldSaveViolations", "rule_failures");
+    checkTables("shouldUpdateViolation", "rule_failures");
   }
 }
index b83c32eafb0adb30ba47433f403bf0b0b9d31647..e6f1e78d657ca201ca01ea12025d53dbf99a12d0 100644 (file)
 package org.sonar.batch.phases;
 
 import org.junit.Test;
+import org.sonar.api.database.DatabaseSession;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.batch.ServerMetadata;
+import org.sonar.batch.index.DefaultResourcePersister;
 import org.sonar.jpa.test.AbstractDbUnitTestCase;
 
 import javax.persistence.Query;
@@ -47,15 +49,14 @@ public class UpdateStatusJobTest extends AbstractDbUnitTestCase {
 
   private void assertAnalysis(int snapshotId, String fixture) {
     setupData("sharedFixture", fixture);
-
-    UpdateStatusJob sensor = new UpdateStatusJob(mock(ServerMetadata.class), getSession(), loadSnapshot(snapshotId));
+    DatabaseSession session = getSession();
+    UpdateStatusJob sensor = new UpdateStatusJob(mock(ServerMetadata.class), session, new DefaultResourcePersister(session), loadSnapshot(snapshotId));
     sensor.execute();
 
     getSession().stop();
     checkTables(fixture, "snapshots");
   }
 
-
   private Snapshot loadSnapshot(int id) {
     Query query = getSession().createQuery("SELECT s FROM Snapshot s WHERE s.id=:id");
     query.setParameter("id", id);
index b9678a48fcc6d4d0a35577a8f1c1a54107da8efd..0d7a84ff870fffb994c92966800a91d276109884 100644 (file)
@@ -19,4 +19,5 @@
              scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
              status="U" islast="false" depth="3" />
 
+  <RULE_FAILURES ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="[null]"/>
 </dataset>
\ No newline at end of file
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldInsertViolations-result.xml
new file mode 100644 (file)
index 0000000..c28d5fd
--- /dev/null
@@ -0,0 +1,25 @@
+<dataset>
+  <rules_categories id="1" name="Efficiency" description="[null]"/>
+  <rules_categories id="6" name="Usability" description="[null]"/>
+
+  <rules id="30" name="Check Header" rules_category_id="6" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <rules id="31" name="Equals Avoid Null" rules_category_id="6" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+            name="Bar" long_name="org.foo.Bar" description="[null]"
+            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
+
+  <snapshots id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
+             status="U" islast="false" depth="3" />
+
+  <RULE_FAILURES ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="[null]"/>
+  <RULE_FAILURES ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="55.6"/>
+  <RULE_FAILURES ID="3" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="[null]" LINE="50" COST="80"/>
+  <RULE_FAILURES ID="4" SNAPSHOT_ID="1000" RULE_ID="31" FAILURE_LEVEL="1" MESSAGE="[null]" LINE="[null]" COST="[null]"/>
+</dataset>
\ No newline at end of file
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldSaveViolations-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldSaveViolations-result.xml
deleted file mode 100644 (file)
index 1e78b98..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<dataset>
-  <rules_categories id="1" name="Efficiency" description="[null]"/>
-  <rules_categories id="6" name="Usability" description="[null]"/>
-
-  <rules id="30" name="Check Header" rules_category_id="6" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
-         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
-         cardinality="SINGLE" parent_id="[null]"/>
-
-  <rules id="31" name="Equals Avoid Null" rules_category_id="6" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
-         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
-         cardinality="SINGLE" parent_id="[null]"/>
-
-  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
-            name="Bar" long_name="org.foo.Bar" description="[null]"
-            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
-
-  <snapshots id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
-             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
-             status="U" islast="false" depth="3" />
-
-  <RULE_FAILURES ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="55.6"/>
-  <RULE_FAILURES ID="2" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="[null]" LINE="50" COST="80"/>
-  <RULE_FAILURES ID="3" SNAPSHOT_ID="1000" RULE_ID="31" FAILURE_LEVEL="1" MESSAGE="[null]" LINE="[null]" COST="[null]"/>
-</dataset>
\ No newline at end of file
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldUpdateViolation-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/ViolationPersisterTest/shouldUpdateViolation-result.xml
new file mode 100644 (file)
index 0000000..150433b
--- /dev/null
@@ -0,0 +1,22 @@
+<dataset>
+  <rules_categories id="1" name="Efficiency" description="[null]"/>
+  <rules_categories id="6" name="Usability" description="[null]"/>
+
+  <rules id="30" name="Check Header" rules_category_id="6" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+         plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <rules id="31" name="Equals Avoid Null" rules_category_id="6" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+         plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" enabled="true"
+         cardinality="SINGLE" parent_id="[null]"/>
+
+  <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+            name="Bar" long_name="org.foo.Bar" description="[null]"
+            enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>
+
+  <snapshots id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+             scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
+             status="U" islast="false" depth="3" />
+
+  <RULE_FAILURES ID="1" SNAPSHOT_ID="1000" RULE_ID="30" FAILURE_LEVEL="3" MESSAGE="the message" LINE="20" COST="55.6"/>
+</dataset>
\ No newline at end of file