]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6959 Performance improvements
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Mon, 2 Oct 2017 08:28:58 +0000 (10:28 +0200)
committerGitHub <noreply@github.com>
Mon, 2 Oct 2017 08:28:58 +0000 (10:28 +0200)
* Avoid creation of intermediary array

* SONAR-6959 Speed-up copy of custom measures in Compute Engine

* Use light object to get key/uuid map of components

* Avoid always formatting string

* Minor refactoring

* Avoid cost of hash

* Ajust perf tests

20 files changed:
server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/KeyWithUuidDto.java [new file with mode: 0644]
server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilder.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentUuidFactory.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/filemove/FileMoveDetectionStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ComponentIssuesRepositoryImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/measure/MapBasedRawMeasureRepository.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/source/SymbolsLineReader.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/CustomMeasuresCopyStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistMeasuresStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/CustomMeasuresCopyStepTest.java
sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
sonar-plugin-api/src/main/java/org/sonar/api/ce/measure/RangeDistributionBuilder.java
tests/src/test/java/org/sonarqube/tests/performance/scanner/MemoryTest.java

index 6e7db16ec98836ee2e37320f6dcbf6b3f08e0571..b8ee31f72e716d4dc0492eed9222a90c10403bd9 100644 (file)
@@ -43,6 +43,7 @@ import org.sonar.db.component.ComponentLinkDto;
 import org.sonar.db.component.ComponentLinkMapper;
 import org.sonar.db.component.ComponentMapper;
 import org.sonar.db.component.FilePathWithHashDto;
+import org.sonar.db.component.KeyWithUuidDto;
 import org.sonar.db.component.ResourceDto;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.component.SnapshotMapper;
@@ -150,6 +151,7 @@ public class MyBatis implements Startable {
     confBuilder.loadAlias("DuplicationUnit", DuplicationUnitDto.class);
     confBuilder.loadAlias("Event", EventDto.class);
     confBuilder.loadAlias("FilePathWithHash", FilePathWithHashDto.class);
+    confBuilder.loadAlias("KeyWithUuid", KeyWithUuidDto.class);
     confBuilder.loadAlias("Group", GroupDto.class);
     confBuilder.loadAlias("GroupMembership", GroupMembershipDto.class);
     confBuilder.loadAlias("GroupPermission", GroupPermissionDto.class);
index e3b3b556c6b2f98212387d717bbf13b03ae6ef56..9e11072f09e915d4423456407d9708ca474d345c 100644 (file)
@@ -164,6 +164,10 @@ public class ComponentDao implements Dao {
     return mapper(session).selectComponentsFromProjectKeyAndScope(projectKey, null, false);
   }
 
+  public List<KeyWithUuidDto> selectUuidsByKeyFromProjectKey(DbSession session, String projectKey) {
+    return mapper(session).selectUuidsByKeyFromProjectKey(projectKey);
+  }
+
   public List<ComponentDto> selectEnabledModulesFromProjectKey(DbSession session, String projectKey) {
     return mapper(session).selectComponentsFromProjectKeyAndScope(projectKey, Scopes.PROJECT, true);
   }
@@ -174,7 +178,7 @@ public class ComponentDao implements Dao {
 
   public List<ComponentDto> selectByKeysAndBranch(DbSession session, Collection<String> keys, String branch) {
     List<String> dbKeys = keys.stream().map(k -> generateBranchKey(k, branch)).collect(toList());
-    List<String> allKeys = Stream.of(keys, dbKeys) .flatMap(Collection::stream) .collect(toList());
+    List<String> allKeys = Stream.of(keys, dbKeys).flatMap(Collection::stream).collect(toList());
     return executeLargeInputs(allKeys, subKeys -> mapper(session).selectByKeysAndBranch(subKeys, branch));
   }
 
index ca7da22e6456c698ad6ef9fe75b1232591bdcb3c..c99bab08f13f56c50c620eebeae6abd5af6fb950 100644 (file)
@@ -116,6 +116,11 @@ public interface ComponentMapper {
   List<ComponentDto> selectComponentsFromProjectKeyAndScope(@Param("projectKey") String projectKey, @Nullable @Param("scope") String scope,
     @Param(value = "excludeDisabled") boolean excludeDisabled);
 
+  /**
+   * Return keys and UUIDs of all components belonging to a project
+   */
+  List<KeyWithUuidDto> selectUuidsByKeyFromProjectKey(@Param("projectKey") String projectKey);
+
   /**
    * Return technical projects from a view or a sub-view
    */
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/KeyWithUuidDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/KeyWithUuidDto.java
new file mode 100644 (file)
index 0000000..e141306
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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 org.sonar.db.component;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+public class KeyWithUuidDto {
+
+  private final String kee;
+  private final String uuid;
+
+  public KeyWithUuidDto(String kee, String uuid) {
+    this.kee = kee;
+    this.uuid = uuid;
+  }
+
+  public String key() {
+    return kee;
+  }
+
+  public String uuid() {
+    return uuid;
+  }
+}
index feaa6661866429562726fc54b0ae992b3c9d9695..2aaadf4d956fa666a362c80e1e8d5226ee881e56 100644 (file)
       </if>
     </where>
   </select>
+  
+  <select id="selectUuidsByKeyFromProjectKey" parameterType="string" resultType="KeyWithUuid">
+    SELECT
+     p.kee, p.uuid
+    FROM 
+      projects p
+    INNER JOIN 
+      projects root ON root.uuid=p.project_uuid AND root.kee=#{projectKey,jdbcType=VARCHAR}
+  </select>
 
   <select id="selectGhostProjects" parameterType="map" resultType="Component">
     select distinct
index f37b5e0c2fcca4bc1490231bdadf49493a3fe7cf..140a3a0bfd3d2ba784afb429e56389c825ffe942 100644 (file)
@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 import javax.annotation.Nullable;
 import org.assertj.core.api.ListAssert;
 import org.junit.Rule;
@@ -47,6 +48,7 @@ import static java.util.Collections.emptyList;
 import static java.util.Collections.emptySet;
 import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
 import static org.assertj.core.api.Assertions.tuple;
 import static org.assertj.guava.api.Assertions.assertThat;
 import static org.sonar.db.component.ComponentTesting.newDirectory;
@@ -580,6 +582,34 @@ public class ComponentDaoTest {
     assertThat(underTest.selectAllComponentsFromProjectKey(dbSession, "UNKNOWN")).isEmpty();
   }
 
+  @Test
+  public void select_uuids_by_key_from_project() {
+    ComponentDto project = db.components().insertPrivateProject();
+    ComponentDto removedProject = db.components().insertPrivateProject(p -> p.setEnabled(false));
+    ComponentDto module = db.components().insertComponent(newModuleDto(project));
+    ComponentDto removedModule = db.components().insertComponent(newModuleDto(project).setEnabled(false));
+    ComponentDto subModule = db.components().insertComponent(newModuleDto(module));
+    ComponentDto removedSubModule = db.components().insertComponent(newModuleDto(module).setEnabled(false));
+    ComponentDto directory = db.components().insertComponent(newDirectory(subModule, "src"));
+    ComponentDto removedDirectory = db.components().insertComponent(newDirectory(subModule, "src2").setEnabled(false));
+    ComponentDto file = db.components().insertComponent(newFileDto(subModule, directory));
+    ComponentDto removedFile = db.components().insertComponent(newFileDto(subModule, directory).setEnabled(false));
+
+    Map<String, String> uuidsByKey = underTest.selectUuidsByKeyFromProjectKey(dbSession, project.getDbKey())
+      .stream().collect(Collectors.toMap(KeyWithUuidDto::key, KeyWithUuidDto::uuid));
+
+    assertThat(uuidsByKey).containsOnly(
+      entry(project.getDbKey(), project.uuid()),
+      entry(module.getDbKey(), module.uuid()),
+      entry(removedModule.getDbKey(), removedModule.uuid()),
+      entry(subModule.getDbKey(), subModule.uuid()),
+      entry(removedSubModule.getDbKey(), removedSubModule.uuid()),
+      entry(directory.getDbKey(), directory.uuid()),
+      entry(removedDirectory.getDbKey(), removedDirectory.uuid()),
+      entry(file.getDbKey(), file.uuid()),
+      entry(removedFile.getDbKey(), removedFile.uuid()));
+  }
+
   @Test
   public void select_enabled_modules_from_project() {
     ComponentDto project = db.components().insertPrivateProject();
index 100c92cdae99e787c22d72e7e2a69f18b05ab30f..6b46eba027d40c44e019ea2c625722d13445dce0 100644 (file)
@@ -28,7 +28,6 @@ import javax.annotation.concurrent.Immutable;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
-import static java.util.Arrays.asList;
 import static java.util.Objects.requireNonNull;
 import static org.apache.commons.lang.StringUtils.trimToNull;
 
@@ -66,7 +65,7 @@ public class ComponentImpl implements Component {
   public Type getType() {
     return type;
   }
-  
+
   @Override
   public Status getStatus() {
     return status;
@@ -140,7 +139,7 @@ public class ComponentImpl implements Component {
     private static final String REPORT_ATTRIBUTES_CANNOT_BE_NULL = "reportAttributes can't be null";
     private static final String NAME_CANNOT_BE_NULL = "name can't be null";
     private static final String STATUS_CANNOT_BE_NULL = "status can't be null";
-    
+
     private final Type type;
     private Status status;
     private ReportAttributes reportAttributes;
@@ -170,7 +169,7 @@ public class ComponentImpl implements Component {
     public String getUuid() {
       return uuid;
     }
-    
+
     public Builder setStatus(Status status) {
       this.status = requireNonNull(status, STATUS_CANNOT_BE_NULL);
       return this;
@@ -201,11 +200,11 @@ public class ComponentImpl implements Component {
       return this;
     }
 
-    public Builder addChildren(Component... c) {
-      for (Component component : c) {
+    public Builder addChildren(List<Component> components) {
+      for (Component component : components) {
         checkArgument(component.getType().isReportType());
       }
-      this.children.addAll(asList(c));
+      this.children.addAll(components);
       return this;
     }
 
index 275bc96e7b79f5eff20bffbbf7ca9c3c0af92239..0581d636b865bfae4e39bdeadcbee47ccd521186 100644 (file)
@@ -19,7 +19,9 @@
  */
 package org.sonar.server.computation.task.projectanalysis.component;
 
+import java.util.List;
 import java.util.function.Function;
+import java.util.stream.Collectors;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.sonar.db.component.SnapshotDto;
@@ -80,12 +82,12 @@ public class ComponentTreeBuilder {
     return buildComponent(project, project);
   }
 
-  private Component[] buildChildren(ScannerReport.Component component, ScannerReport.Component parentModule) {
+  private List<Component> buildChildren(ScannerReport.Component component, ScannerReport.Component parentModule) {
     return component.getChildRefList()
       .stream()
       .map(scannerComponentSupplier::apply)
       .map(c -> buildComponent(c, parentModule))
-      .toArray(Component[]::new);
+      .collect(Collectors.toList());
   }
 
   private ComponentImpl buildComponent(ScannerReport.Component component, ScannerReport.Component closestModule) {
index 6cf3c218706d35a6de1bf30865e01161a7b11793..4319130a253cc4db505757261303a812040f00e1 100644 (file)
@@ -25,16 +25,16 @@ import java.util.Map;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.KeyWithUuidDto;
 
 public class ComponentUuidFactory {
 
   private final Map<String, String> uuidsByKey = new HashMap<>();
 
   public ComponentUuidFactory(DbClient dbClient, DbSession dbSession, String rootKey) {
-    List<ComponentDto> components = dbClient.componentDao().selectAllComponentsFromProjectKey(dbSession, rootKey);
-    for (ComponentDto dto : components) {
-      uuidsByKey.put(dto.getDbKey(), dto.uuid());
+    List<KeyWithUuidDto> keys = dbClient.componentDao().selectUuidsByKeyFromProjectKey(dbSession, rootKey);
+    for (KeyWithUuidDto dto : keys) {
+      uuidsByKey.put(dto.key(), dto.uuid());
     }
   }
 
index 6e6341dad9b6524a06c01084c1c5646595802dd0..985b0d510500f52fe61be7c8053426d270c31789 100644 (file)
@@ -45,7 +45,6 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTreeQuery;
 import org.sonar.db.component.ComponentTreeQuery.Strategy;
 import org.sonar.db.source.FileSourceDto;
-import org.sonar.server.computation.task.projectanalysis.analysis.Analysis;
 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
 import org.sonar.server.computation.task.projectanalysis.component.Component;
 import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
@@ -93,8 +92,7 @@ public class FileMoveDetectionStep implements ComputationStep {
   @Override
   public void execute() {
     // do nothing if no files in db (first analysis)
-    Analysis baseProjectAnalysis = analysisMetadataHolder.getBaseAnalysis();
-    if (baseProjectAnalysis == null) {
+    if (analysisMetadataHolder.isFirstAnalysis()) {
       LOG.debug("First analysis. Do nothing.");
       return;
     }
index 4322f60869431157e103f5f642c9fc4d58142aa8..685d537813ffbdc2c526cba09cae2a92aa7b3bdc 100644 (file)
@@ -46,8 +46,8 @@ public class ComponentIssuesRepositoryImpl implements MutableComponentIssuesRepo
   public List<DefaultIssue> getIssues(Component component) {
     checkState(this.component != null && this.issues != null, "Issues have not been initialized");
     checkArgument(component.equals(this.component),
-      String.format("Only issues from component '%s' are available, but wanted component is '%s'.",
-        this.component.getReportAttributes().getRef(), component.getReportAttributes().getRef()));
+      "Only issues from component '%s' are available, but wanted component is '%s'.",
+      this.component.getReportAttributes().getRef(), component.getReportAttributes().getRef());
     return issues;
   }
 }
index 7392ff616f819a1b656a9e9a0ae7718aacbc4f06..751a962bf2042d9acb06fd2bb6fe04898ffad81d 100644 (file)
  */
 package org.sonar.server.computation.task.projectanalysis.measure;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.FluentIterable.from;
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.SetMultimap;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-
 import org.sonar.server.computation.task.projectanalysis.component.Component;
 import org.sonar.server.computation.task.projectanalysis.metric.Metric;
 
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.SetMultimap;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.FluentIterable.from;
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
 
 /**
  * Map based implementation of MeasureRepository which supports only raw measures.
@@ -112,9 +109,8 @@ public final class MapBasedRawMeasureRepository<T> implements MeasureRepository
   private static void checkValueTypeConsistency(Metric metric, Measure measure) {
     checkArgument(
       measure.getValueType() == Measure.ValueType.NO_VALUE || measure.getValueType() == metric.getType().getValueType(),
-      format(
-        "Measure's ValueType (%s) is not consistent with the Metric's ValueType (%s)",
-        measure.getValueType(), metric.getType().getValueType()));
+      "Measure's ValueType (%s) is not consistent with the Metric's ValueType (%s)",
+      measure.getValueType(), metric.getType().getValueType());
   }
 
   @Override
index a78b4914b0d0b040074052deb8b01a9b116a51cf..d569478ce9aeabac350242b7687664e6e57cac59 100644 (file)
@@ -25,7 +25,7 @@ import com.google.common.collect.SetMultimap;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -115,7 +115,7 @@ public class SymbolsLineReader implements LineReader {
   }
 
   private static Map<ScannerReport.Symbol, Integer> createIdsBySymbolMap(List<ScannerReport.Symbol> symbols) {
-    Map<ScannerReport.Symbol, Integer> map = new HashMap<>(symbols.size());
+    Map<ScannerReport.Symbol, Integer> map = new IdentityHashMap<>(symbols.size());
     int symbolId = 1;
     for (ScannerReport.Symbol symbol : symbols) {
       map.put(symbol, symbolId);
index 15a9fe732d8178ba96a5a2ec6aab2395cacead50..9621e30f871027d2c69c4d8ae12fec87f4087239 100644 (file)
@@ -54,17 +54,21 @@ public class CustomMeasuresCopyStep implements ComputationStep {
 
   @Override
   public void execute() {
-    new DepthTraversalTypeAwareCrawler(
-      new TypeAwareVisitorAdapter(CrawlerDepthLimit.LEAVES, ComponentVisitor.Order.PRE_ORDER) {
-        @Override
-        public void visitAny(Component component) {
-          copy(component);
-        }
-      }).visit(treeRootHolder.getRoot());
+    try (DbSession session = dbClient.openSession(false)) {
+      CrawlerDepthLimit depthLimit = new CrawlerDepthLimit.Builder(Component.Type.MODULE)
+        .withViewsMaxDepth(Component.Type.PROJECT_VIEW);
+      new DepthTraversalTypeAwareCrawler(
+        new TypeAwareVisitorAdapter(depthLimit, ComponentVisitor.Order.PRE_ORDER) {
+          @Override
+          public void visitAny(Component component) {
+            copy(component, session);
+          }
+        }).visit(treeRootHolder.getRoot());
+    }
   }
 
-  private void copy(Component component) {
-    for (CustomMeasureDto dto : loadCustomMeasures(component)) {
+  private void copy(Component component, DbSession session) {
+    for (CustomMeasureDto dto : loadCustomMeasures(component, session)) {
       Metric metric = metricRepository.getById(dto.getMetricId());
       // else metric is not found and an exception is raised
       Measure measure = dtoToMeasure(dto, metric);
@@ -72,10 +76,8 @@ public class CustomMeasuresCopyStep implements ComputationStep {
     }
   }
 
-  private List<CustomMeasureDto> loadCustomMeasures(Component component) {
-    try (DbSession session = dbClient.openSession(false)) {
-      return dbClient.customMeasureDao().selectByComponentUuid(session, component.getUuid());
-    }
+  private List<CustomMeasureDto> loadCustomMeasures(Component component, DbSession session) {
+    return dbClient.customMeasureDao().selectByComponentUuid(session, component.getUuid());
   }
 
   @VisibleForTesting
index a20e36e22f2f803654c7db2d162d2049222d2d9e..69d107476455afe0f3e6980f8aadc20cf8939fb5 100644 (file)
@@ -82,12 +82,9 @@ public class PersistMeasuresStep implements ComputationStep {
 
   @Override
   public void execute() {
-    DbSession dbSession = dbClient.openSession(true);
-    try {
+    try (DbSession dbSession = dbClient.openSession(true)) {
       new DepthTraversalTypeAwareCrawler(new MeasureVisitor(dbSession)).visit(treeRootHolder.getRoot());
       dbSession.commit();
-    } finally {
-      dbSession.close();
     }
   }
 
index df3d214802313c30e761c266c565b53f83c760e9..780df24568e0ec569bb324e29ff00484d8709f1f 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.computation.task.projectanalysis.component;
 
 import java.util.Arrays;
+import java.util.Collections;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -183,7 +184,7 @@ public class ComponentImplTest {
       .setUuid(UUID)
       .setStatus(Status.UNAVAILABLE)
       .setReportAttributes(ReportAttributes.newBuilder(1).build())
-      .addChildren(child)
+      .addChildren(Collections.singletonList(child))
       .build();
 
     assertThat(componentImpl.getChildren()).hasSize(1);
index d0abe802756f1740eeb830d24d71ee80eb9bf07b..2203c13b121f358124c0f54b45356d08cb9e9b58 100644 (file)
@@ -52,11 +52,11 @@ import static org.sonar.server.computation.task.projectanalysis.measure.MeasureR
 import static org.sonar.server.computation.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
 import static org.sonar.server.computation.task.projectanalysis.step.CustomMeasuresCopyStep.dtoToMeasure;
 
-
 public class CustomMeasuresCopyStepTest {
 
   private static final int PROJECT_REF = 1;
   private static final int MODULE_REF = 11;
+  private static final int MODULE2_REF = 12;
   private static final int SUB_MODULE_REF = 111;
   private static final int DIR_REF = 1111;
   private static final int FILE1_REF = 11111;
@@ -64,6 +64,7 @@ public class CustomMeasuresCopyStepTest {
 
   private static final String PROJECT_UUID = "PROJECT";
   private static final String MODULE_UUID = "MODULE";
+  private static final String MODULE2_UUID = "MODULE2";
   private static final String SUB_MODULE_UUID = "SUB_MODULE";
   private static final String DIR_UUID = "DIR";
   private static final String FILE1_UUID = "FILE1";
@@ -102,12 +103,12 @@ public class CustomMeasuresCopyStepTest {
 
   @Test
   public void copy_custom_measures_on_report() {
-    // File2 has no custom measure
     insertCustomMeasure(FILE1_UUID, FLOAT_METRIC, 3.14);
     insertCustomMeasure(DIR_UUID, FLOAT_METRIC, 123d);
     insertCustomMeasure(SUB_MODULE_UUID, STRING_METRIC, "sub-module");
     insertCustomMeasure(MODULE_UUID, STRING_METRIC, "module");
     insertCustomMeasure(PROJECT_UUID, STRING_METRIC, "project");
+    // Module2 has no custom measure
 
     treeRootHolder.setRoot(
       builder(PROJECT, PROJECT_REF).setUuid(PROJECT_UUID)
@@ -119,23 +120,23 @@ public class CustomMeasuresCopyStepTest {
                   ReportComponent.builder(DIRECTORY, DIR_REF).setUuid(DIR_UUID)
                     .addChildren(
                       ReportComponent.builder(FILE, FILE1_REF).setUuid(FILE1_UUID).build(),
-                      ReportComponent.builder(FILE, FILE2_REF).setUuid(FILE2_UUID).build()
-                    )
-                    .build()
-                )
-                .build()
-            )
-            .build())
+                      ReportComponent.builder(FILE, FILE2_REF).setUuid(FILE2_UUID).build())
+                    .build())
+                .build())
+            .build(),
+          ReportComponent.builder(MODULE, MODULE2_REF).setUuid(MODULE2_UUID).build())
         .build());
 
     underTest.execute();
 
-    assertRawMeasureValue(FILE1_REF, FLOAT_METRIC.getKey(), 3.1d);
+    assertNoRawMeasureValue(FILE1_REF);
     assertNoRawMeasureValue(FILE2_REF);
-    assertRawMeasureValue(DIR_REF, FLOAT_METRIC.getKey(), 123d);
+    assertNoRawMeasureValue(DIR_REF);
     assertRawMeasureValue(SUB_MODULE_REF, STRING_METRIC.getKey(), "sub-module");
     assertRawMeasureValue(MODULE_REF, STRING_METRIC.getKey(), "module");
     assertRawMeasureValue(PROJECT_REF, STRING_METRIC.getKey(), "project");
+    assertNoRawMeasureValue(MODULE2_REF);
+
   }
 
   @Test
@@ -148,8 +149,7 @@ public class CustomMeasuresCopyStepTest {
       ViewsComponent.builder(VIEW, VIEW_REF).setUuid("VIEW")
         .addChildren(
           ViewsComponent.builder(SUBVIEW, SUBVIEW_REF).setUuid("SUBVIEW").build(),
-          ViewsComponent.builder(PROJECT_VIEW, PROJECT_VIEW_REF).setUuid("PROJECT_VIEW").build()
-        )
+          ViewsComponent.builder(PROJECT_VIEW, PROJECT_VIEW_REF).setUuid("PROJECT_VIEW").build())
         .build());
 
     underTest.execute();
index 9685a49bb06d665444b6a2ce215ed14d94fa240c..198515da6d05355d9bd806865b9305b279287ce8 100644 (file)
@@ -48,7 +48,6 @@ import org.sonar.api.rules.RuleType;
 import org.sonar.api.utils.Duration;
 import org.sonar.core.issue.tracking.Trackable;
 
-import static java.lang.String.format;
 import static org.sonar.api.utils.DateUtils.truncateToSeconds;
 
 public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.Issue {
@@ -258,7 +257,7 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.
   }
 
   public DefaultIssue setLine(@Nullable Integer l) {
-    Preconditions.checkArgument(l == null || l > 0, format("Line must be null or greater than zero (got %d)", l));
+    Preconditions.checkArgument(l == null || l > 0, "Line must be null or greater than zero (got %d)", l);
     this.line = l;
     return this;
   }
@@ -280,7 +279,7 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.
   }
 
   public DefaultIssue setGap(@Nullable Double d) {
-    Preconditions.checkArgument(d == null || d >= 0, format("Gap must be greater than or equal 0 (got %s)", d));
+    Preconditions.checkArgument(d == null || d >= 0, "Gap must be greater than or equal 0 (got %s)", d);
     this.gap = d;
     return this;
   }
index 3a16537d376b16eb26ac6b4024d7872a3ee03b06..2a069017f1b2ca81d16f0c904fcc74ab80e990d2 100644 (file)
@@ -93,8 +93,8 @@ public class RangeDistributionBuilder {
    */
   public RangeDistributionBuilder add(String data) {
     Map<Double, Double> map = KeyValueFormat.parse(data, KeyValueFormat.newDoubleConverter(), KeyValueFormat.newDoubleConverter());
-    Number[] limits = map.keySet().toArray(new Number[map.size()]);
     if (bottomLimits == null) {
+      Number[] limits = map.keySet().toArray(new Number[map.size()]);
       init(limits);
 
     } else if (!areSameLimits(bottomLimits, map.keySet())) {
@@ -118,16 +118,14 @@ public class RangeDistributionBuilder {
   }
 
   private void changeDoublesToInts() {
-    boolean onlyInts = true;
     for (Number bottomLimit : bottomLimits) {
       if (NumberComparator.INSTANCE.compare(bottomLimit.intValue(), bottomLimit.doubleValue()) != 0) {
-        onlyInts = false;
+        // it's not only ints
+        return;
       }
     }
-    if (onlyInts) {
-      for (int i = 0; i < bottomLimits.length; i++) {
-        bottomLimits[i] = bottomLimits[i].intValue();
-      }
+    for (int i = 0; i < bottomLimits.length; i++) {
+      bottomLimits[i] = bottomLimits[i].intValue();
     }
   }
 
@@ -204,7 +202,7 @@ public class RangeDistributionBuilder {
 
     @Override
     public int compare(Number n1, Number n2) {
-      return ((Double) n1.doubleValue()).compareTo(n2.doubleValue());
+      return Double.compare(n1.doubleValue(), n2.doubleValue());
     }
   }
 
index 1ddf3b9bbacda47b23ba6822499f2a284bbfe27d..577f2dfe3f0e32dd6696e11e286c7e8dce695f19 100644 (file)
@@ -89,7 +89,7 @@ public class MemoryTest extends AbstractPerfTest {
       .setProjectDir(baseDir);
 
     BuildResult result = orchestrator.executeBuild(scanner);
-    perfRule.assertDurationAround(MavenLogs.extractTotalTime(result.getLogs()), 8950);
+    perfRule.assertDurationAround(MavenLogs.extractTotalTime(result.getLogs()), 8200);
 
     // Second execution with a property on server side
     orchestrator.getServer().newHttpCall("/api/settings/set")