]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6993 Replace first analysis flag by the project snapshot
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 10 Nov 2015 15:10:01 +0000 (16:10 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 12 Nov 2015 10:01:28 +0000 (11:01 +0100)
13 files changed:
server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java
server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java
server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolderImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java
server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolder.java
server/sonar-server/src/main/java/org/sonar/server/computation/snapshot/Snapshot.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/analysis/AnalysisMetadataHolderImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java
server/sonar-server/src/test/java/org/sonar/server/computation/batch/BatchReportReaderRule.java
server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/snapshot/SnapshotImplTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java

index 260d5edaf8fa86867ce4227f384b539d86e554a8..0a35a0c9c8aa5b827cdb75fc86aa1ddbbe845d13 100644 (file)
@@ -24,7 +24,6 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-
 import org.apache.commons.io.FileUtils;
 import org.junit.Rule;
 import org.junit.Test;
@@ -89,7 +88,7 @@ public class PersistFileSourcesStepTest {
     BatchReportDirectoryHolderImpl batchReportDirectoryHolder = new BatchReportDirectoryHolderImpl();
     batchReportDirectoryHolder.setDirectory(reportDir);
     org.sonar.server.computation.batch.BatchReportReader batchReportReader = new BatchReportReaderImpl(batchReportDirectoryHolder);
-    analysisMetadataHolder.setIsFirstAnalysis(false);
+    analysisMetadataHolder.setBaseProjectSnapshot(null);
     SourceLinesRepositoryImpl sourceLinesRepository = new SourceLinesRepositoryImpl(batchReportReader);
     SourceHashRepositoryImpl sourceHashRepository = new SourceHashRepositoryImpl(sourceLinesRepository);
     ScmInfoRepositoryImpl scmInfoRepository = new ScmInfoRepositoryImpl(batchReportReader, analysisMetadataHolder, dbClient, sourceHashRepository);
index 445fd8a63c81f9acc225babca7b72c3915c68af2..fc634054bc81904f432064031bfb550c465c3197 100644 (file)
@@ -20,6 +20,8 @@
 package org.sonar.server.computation.analysis;
 
 import java.util.Date;
+import javax.annotation.CheckForNull;
+import org.sonar.server.computation.snapshot.Snapshot;
 
 public interface AnalysisMetadataHolder {
   /**
@@ -28,7 +30,19 @@ public interface AnalysisMetadataHolder {
   Date getAnalysisDate();
 
   /**
-   * @throws IllegalStateException if isFirstAnalysis has not been set
+   * Convenience method equivalent to calling {@link #getBaseProjectSnapshot() == null}
+   *
+   * @throws IllegalStateException if baseProjectSnapshot has not been set
    */
   boolean isFirstAnalysis();
+
+  /**
+   * Return the last snapshot of the project.
+   * If it's the first analysis, it will return null.
+   *
+   * @throws IllegalStateException if baseProjectSnapshot has not been set
+   */
+  @CheckForNull
+  Snapshot getBaseProjectSnapshot();
+
 }
index 185732637e2c48bc37fc6cbc433277c2ffc51fbc..a73acbd4adb97869c08a3137868361a7702fc67a 100644 (file)
@@ -21,6 +21,8 @@ package org.sonar.server.computation.analysis;
 
 import java.util.Date;
 import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.server.computation.snapshot.Snapshot;
 
 import static com.google.common.base.Preconditions.checkState;
 
@@ -28,8 +30,10 @@ public class AnalysisMetadataHolderImpl implements MutableAnalysisMetadataHolder
   @CheckForNull
   private Long analysisDate;
 
+  private boolean baseProjectSnapshotInitialized = false;
+
   @CheckForNull
-  private Boolean firstAnalysis;
+  private Snapshot baseProjectSnapshot;
 
   @Override
   public void setAnalysisDate(Date date) {
@@ -44,14 +48,22 @@ public class AnalysisMetadataHolderImpl implements MutableAnalysisMetadataHolder
   }
 
   @Override
-  public void setIsFirstAnalysis(boolean firstAnalysis) {
-    checkState(this.firstAnalysis == null, "firstAnalysis flag has already been set");
-    this.firstAnalysis = firstAnalysis;
+  public boolean isFirstAnalysis() {
+    return getBaseProjectSnapshot() == null;
   }
 
   @Override
-  public boolean isFirstAnalysis() {
-    checkState(firstAnalysis != null, "firstAnalysis flag has not been set");
-    return firstAnalysis;
+  public void setBaseProjectSnapshot(@Nullable Snapshot baseProjectSnapshot) {
+    checkState(!baseProjectSnapshotInitialized, "Base project snapshot has already been set");
+    this.baseProjectSnapshot = baseProjectSnapshot;
+    this.baseProjectSnapshotInitialized = true;
+  }
+
+  @Override
+  @CheckForNull
+  public Snapshot getBaseProjectSnapshot() {
+    checkState(baseProjectSnapshotInitialized, "Base project snapshot has not been set");
+    return baseProjectSnapshot;
   }
+
 }
index e485012782be11a15dc30a335cd033d1b080dbd2..586d152b237140e11a078f95791a4e235a8ccc7c 100644 (file)
@@ -20,6 +20,8 @@
 package org.sonar.server.computation.analysis;
 
 import java.util.Date;
+import javax.annotation.Nullable;
+import org.sonar.server.computation.snapshot.Snapshot;
 
 public interface MutableAnalysisMetadataHolder extends AnalysisMetadataHolder {
 
@@ -30,7 +32,8 @@ public interface MutableAnalysisMetadataHolder extends AnalysisMetadataHolder {
   void setAnalysisDate(Date date);
 
   /**
-   * @throws IllegalStateException if isFirstAnalysis has already been set
+   * @throws IllegalStateException if baseProjectSnapshot has already been set
    */
-  void setIsFirstAnalysis(boolean isFirstAnalysis);
+  void setBaseProjectSnapshot(@Nullable Snapshot baseProjectSnapshot);
+
 }
index f901194dce4a5c24d968497bdc049514ad1b4346..690c9dd203208e964b6334078b1b9bd9b1f6ba1e 100644 (file)
 package org.sonar.server.computation.period;
 
 import java.util.List;
-import org.sonar.api.CoreProperties;
 
 /**
  * Repository of periods used to compute differential measures.
  * Here are the steps to retrieve these periods :
- * - Read the 5 period properties ${@link CoreProperties#TIMEMACHINE_PERIOD_PREFIX}
+ * - Read the 5 period properties ${@link org.sonar.core.config.CorePropertyDefinitions#TIMEMACHINE_PERIOD_PREFIX}
  * - Try to find the matching snapshots from the properties
  * - If a snapshot is found, a new period is added to the repository
  */
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/snapshot/Snapshot.java b/server/sonar-server/src/main/java/org/sonar/server/computation/snapshot/Snapshot.java
new file mode 100644 (file)
index 0000000..65967a5
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation.snapshot;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.concurrent.Immutable;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+@Immutable
+public class Snapshot {
+
+  private long id;
+  private long createdAt;
+
+  private Snapshot(Builder builder) {
+    this.id = builder.id;
+    this.createdAt = builder.createdAt;
+  }
+
+  public long getId() {
+    return id;
+  }
+
+  public long getCreatedAt() {
+    return createdAt;
+  }
+
+  public static final class Builder {
+    @CheckForNull
+    private Long id;
+    @CheckForNull
+    private Long createdAt;
+
+    public Builder setId(long id) {
+      this.id = id;
+      return this;
+    }
+
+    public Builder setCreatedAt(long createdAt) {
+      this.createdAt = createdAt;
+      return this;
+    }
+
+    public Snapshot build() {
+      checkNotNull(id, "id cannot be null");
+      checkNotNull(createdAt, "createdAt cannot be null");
+      return new Snapshot(this);
+    }
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    Snapshot snapshot = (Snapshot) o;
+    return id == snapshot.id;
+  }
+
+  @Override
+  public int hashCode() {
+    return (int) (id ^ (id >>> 32));
+  }
+
+  @Override
+  public String toString() {
+    return "SnapshotImpl{" +
+      "id=" + id +
+      ", createdAt=" + createdAt +
+      '}';
+  }
+}
index 036bce963f4b9a5028870eaf80e25a31fb65e2f0..ab51b2eea6c5a634f3420a7d6c9f9fe057654922 100644 (file)
@@ -29,12 +29,15 @@ import org.sonar.batch.protocol.output.BatchReport;
 import org.sonar.core.component.ComponentKeys;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.component.SnapshotQuery;
 import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolder;
 import org.sonar.server.computation.batch.BatchReportReader;
 import org.sonar.server.computation.component.Component;
 import org.sonar.server.computation.component.ComponentImpl;
 import org.sonar.server.computation.component.MutableTreeRootHolder;
 import org.sonar.server.computation.component.UuidFactory;
+import org.sonar.server.computation.snapshot.Snapshot;
 
 import static com.google.common.collect.Iterables.toArray;
 import static org.sonar.server.computation.component.ComponentImpl.builder;
@@ -65,18 +68,31 @@ public class BuildComponentTreeStep implements ComputationStep {
     UuidFactory uuidFactory = new UuidFactory(dbClient, moduleKey(reportProject, branch));
     Component project = new ComponentRootBuilder(reportProject, uuidFactory, branch).build();
     treeRootHolder.setRoot(project);
-    setIsFirstAnalysis(project.getUuid());
+    setBaseProjectSnapshot(project.getUuid());
   }
 
-  private void setIsFirstAnalysis(String projectUuid){
+  private void setBaseProjectSnapshot(String projectUuid) {
     DbSession dbSession = dbClient.openSession(false);
     try {
-      analysisMetadataHolder.setIsFirstAnalysis(!dbClient.snapshotDao().hasLastSnapshotByComponentUuid(dbSession, projectUuid));
+      SnapshotDto snapshotDto = dbClient.snapshotDao().selectSnapshotByQuery(dbSession,
+        new SnapshotQuery()
+          .setComponentUuid(projectUuid)
+          .setIsLast(true));
+      analysisMetadataHolder.setBaseProjectSnapshot(toSnapshot(snapshotDto));
     } finally {
       dbClient.closeSession(dbSession);
     }
   }
 
+  @CheckForNull
+  private static Snapshot toSnapshot(@Nullable SnapshotDto snapshotDto) {
+    return snapshotDto == null ? null :
+      new Snapshot.Builder()
+        .setId(snapshotDto.getId())
+        .setCreatedAt(snapshotDto.getCreatedAt())
+        .build();
+  }
+
   private class ComponentRootBuilder {
 
     private final BatchReport.Component reportProject;
@@ -110,7 +126,7 @@ public class BuildComponentTreeStep implements ComputationStep {
       }
     }
 
-    private ComponentImpl buildComponent(BatchReport.Component reportComponent, String componentKey, String latestModuleKey){
+    private ComponentImpl buildComponent(BatchReport.Component reportComponent, String componentKey, String latestModuleKey) {
       return builder(reportComponent)
         .addChildren(toArray(buildChildren(reportComponent, latestModuleKey), Component.class))
         .setKey(componentKey)
@@ -127,7 +143,7 @@ public class BuildComponentTreeStep implements ComputationStep {
             return buildComponent(reportReader.readComponent(componentRef), latestModuleKey);
           }
         }
-      );
+        );
     }
   }
 
index 4d114f2fb23b64249fe2c4a4040b4082772ca3d5..8cee2f78e20815f12b17625884bbade69147df08 100644 (file)
@@ -23,26 +23,33 @@ import java.util.Date;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.server.computation.snapshot.Snapshot;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class AnalysisMetadataHolderImplTest {
+
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
 
-  private Date someDate = new Date();
+  static Snapshot BASE_PROJECT_SNAPSHOT = new Snapshot.Builder()
+    .setId(1)
+    .setCreatedAt(123456789L)
+    .build();
+
+  static Date SOME_DATE = new Date();
 
   @Test
   public void getAnalysisDate_returns_date_with_same_time_as_the_one_set_with_setAnalysisDate() throws InterruptedException {
     AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl();
 
-    underTest.setAnalysisDate(someDate);
+    underTest.setAnalysisDate(SOME_DATE);
 
     Thread.sleep(10);
 
     Date analysisDate = underTest.getAnalysisDate();
-    assertThat(analysisDate.getTime()).isEqualTo(someDate.getTime());
-    assertThat(analysisDate).isNotSameAs(someDate);
+    assertThat(analysisDate.getTime()).isEqualTo(SOME_DATE.getTime());
+    assertThat(analysisDate).isNotSameAs(SOME_DATE);
   }
 
   @Test
@@ -55,20 +62,20 @@ public class AnalysisMetadataHolderImplTest {
 
   @Test
   public void setAnalysisDate_throws_ISE_when_called_twice() {
+    AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl();
+    underTest.setAnalysisDate(SOME_DATE);
+
     expectedException.expect(IllegalStateException.class);
     expectedException.expectMessage("Analysis date has already been set");
 
-    AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl();
-
-    underTest.setAnalysisDate(someDate);
-    underTest.setAnalysisDate(someDate);
+    underTest.setAnalysisDate(SOME_DATE);
   }
 
   @Test
   public void isFirstAnalysis_return_true() throws Exception {
     AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl();
 
-    underTest.setIsFirstAnalysis(true);
+    underTest.setBaseProjectSnapshot(null);
     assertThat(underTest.isFirstAnalysis()).isTrue();
   }
 
@@ -76,26 +83,33 @@ public class AnalysisMetadataHolderImplTest {
   public void isFirstAnalysis_return_false() throws Exception {
     AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl();
 
-    underTest.setIsFirstAnalysis(false);
+    underTest.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
     assertThat(underTest.isFirstAnalysis()).isFalse();
   }
 
   @Test
-  public void isFirstAnalysis_throws_ISE_when_holder_is_not_initialized() {
+  public void isFirstAnalysis_throws_ISE_when_base_project_snapshot_is_not_set() {
     expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("firstAnalysis flag has not been set");
+    expectedException.expectMessage("Base project snapshot has not been set");
 
     new AnalysisMetadataHolderImpl().isFirstAnalysis();
   }
 
   @Test
-  public void setIsFirstAnalysis_throws_ISE_when_called_twice() {
+  public void baseProjectSnapshot_throws_ISE_when_base_project_snapshot_is_not_set() {
     expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("firstAnalysis flag has already been set");
+    expectedException.expectMessage("Base project snapshot has not been set");
+
+    new AnalysisMetadataHolderImpl().getBaseProjectSnapshot();
+  }
 
+  @Test
+  public void setBaseProjectSnapshot_throws_ISE_when_called_twice() {
     AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl();
+    underTest.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
 
-    underTest.setIsFirstAnalysis(true);
-    underTest.setIsFirstAnalysis(true);
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Base project snapshot has already been set");
+    underTest.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
   }
 }
index fac659f2a1212af3c0a2e9c5d8ae2c186d05e56e..f97d3e6b6e27bcfe585e71f7a555673b24bf6de5 100644 (file)
 package org.sonar.server.computation.analysis;
 
 import java.util.Date;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import org.junit.rules.ExternalResource;
+import org.sonar.server.computation.snapshot.Snapshot;
 
 public class MutableAnalysisMetadataHolderRule extends ExternalResource implements MutableAnalysisMetadataHolder {
+
   private AnalysisMetadataHolderImpl delegate = new AnalysisMetadataHolderImpl();
 
   @Override
@@ -46,7 +50,13 @@ public class MutableAnalysisMetadataHolderRule extends ExternalResource implemen
   }
 
   @Override
-  public void setIsFirstAnalysis(boolean isFirstAnalysis) {
-    delegate.setIsFirstAnalysis(isFirstAnalysis);
+  @CheckForNull
+  public Snapshot getBaseProjectSnapshot() {
+    return delegate.getBaseProjectSnapshot();
+  }
+
+  @Override
+  public void setBaseProjectSnapshot(@Nullable Snapshot baseProjectSnapshot) {
+    delegate.setBaseProjectSnapshot(baseProjectSnapshot);
   }
 }
index 866e366118ad6929335e19d50d89cd73dd28fa99..579e333d70acb51e1da6bbfd4733e0ed0e3fbedf 100644 (file)
@@ -90,8 +90,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return metadata;
   }
 
-  public void setMetadata(BatchReport.Metadata metadata) {
+  public BatchReportReaderRule setMetadata(BatchReport.Metadata metadata) {
     this.metadata = metadata;
+    return this;
   }
 
   @Override
@@ -102,8 +103,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return CloseableIterator.from(scannerLogs.iterator());
   }
 
-  public void setScannerLogs(@Nullable List<String> logs) {
+  public BatchReportReaderRule setScannerLogs(@Nullable List<String> logs) {
     this.scannerLogs = logs;
+    return this;
   }
 
   @Override
@@ -114,8 +116,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return CloseableIterator.from(activeRules.iterator());
   }
 
-  public void putActiveRules(List<BatchReport.ActiveRule> activeRules) {
+  public BatchReportReaderRule putActiveRules(List<BatchReport.ActiveRule> activeRules) {
     this.activeRules = activeRules;
+    return this;
   }
 
   @Override
@@ -127,8 +130,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return CloseableIterator.from(res.iterator());
   }
 
-  public void putMeasures(int componentRef, List<BatchReport.Measure> measures) {
+  public BatchReportReaderRule putMeasures(int componentRef, List<BatchReport.Measure> measures) {
     this.measures.put(componentRef, measures);
+    return this;
   }
 
   @Override
@@ -137,8 +141,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return changesets.get(componentRef);
   }
 
-  public void putChangesets(BatchReport.Changesets changesets) {
+  public BatchReportReaderRule putChangesets(BatchReport.Changesets changesets) {
     this.changesets.put(changesets.getComponentRef(), changesets);
+    return this;
   }
 
   @Override
@@ -146,8 +151,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return components.get(componentRef);
   }
 
-  public void putComponent(BatchReport.Component component) {
+  public BatchReportReaderRule putComponent(BatchReport.Component component) {
     this.components.put(component.getRef(), component);
+    return this;
   }
 
   @Override
@@ -155,8 +161,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return closeableIterator(issues.get(componentRef));
   }
 
-  public void putIssues(int componentRef, List<BatchReport.Issue> issue) {
+  public BatchReportReaderRule putIssues(int componentRef, List<BatchReport.Issue> issue) {
     this.issues.put(componentRef, issue);
+    return this;
   }
 
   @Override
@@ -164,8 +171,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return closeableIterator(this.duplications.get(componentRef));
   }
 
-  public void putDuplications(int componentRef, BatchReport.Duplication... duplications) {
+  public BatchReportReaderRule putDuplications(int componentRef, BatchReport.Duplication... duplications) {
     this.duplications.put(componentRef, Arrays.asList(duplications));
+    return this;
   }
 
   @Override
@@ -173,8 +181,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return closeableIterator(this.duplicationBlocks.get(componentRef));
   }
 
-  public void putDuplicationBlocks(int componentRef, List<BatchReport.DuplicationBlock> duplicationBlocks) {
+  public BatchReportReaderRule putDuplicationBlocks(int componentRef, List<BatchReport.DuplicationBlock> duplicationBlocks) {
     this.duplicationBlocks.put(componentRef, duplicationBlocks);
+    return this;
   }
 
   @Override
@@ -186,8 +195,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return list == null ? CloseableIterator.<T>emptyCloseableIterator() : CloseableIterator.from(list.iterator());
   }
 
-  public void putSymbols(int componentRef, List<BatchReport.Symbol> symbols) {
+  public BatchReportReaderRule putSymbols(int componentRef, List<BatchReport.Symbol> symbols) {
     this.symbols.put(componentRef, symbols);
+    return this;
   }
 
   @Override
@@ -200,8 +210,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return CloseableIterator.from(res.iterator());
   }
 
-  public void putSyntaxHighlighting(int fileRef, List<BatchReport.SyntaxHighlighting> syntaxHighlightings) {
+  public BatchReportReaderRule putSyntaxHighlighting(int fileRef, List<BatchReport.SyntaxHighlighting> syntaxHighlightings) {
     this.syntaxHighlightings.put(fileRef, syntaxHighlightings);
+    return this;
   }
 
   @Override
@@ -214,8 +225,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return CloseableIterator.from(res.iterator());
   }
 
-  public void putCoverage(int fileRef, List<BatchReport.Coverage> coverages) {
+  public BatchReportReaderRule putCoverage(int fileRef, List<BatchReport.Coverage> coverages) {
     this.coverages.put(fileRef, coverages);
+    return this;
   }
 
   @Override
@@ -228,13 +240,15 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return Optional.of(CloseableIterator.from(lines.iterator()));
   }
 
-  public void putFileSourceLines(int fileRef, @Nullable String... lines) {
+  public BatchReportReaderRule putFileSourceLines(int fileRef, @Nullable String... lines) {
     Preconditions.checkNotNull(lines);
     this.fileSources.put(fileRef, Arrays.asList(lines));
+    return this;
   }
 
-  public void putFileSourceLines(int fileRef, List<String> lines) {
+  public BatchReportReaderRule putFileSourceLines(int fileRef, List<String> lines) {
     this.fileSources.put(fileRef, lines);
+    return this;
   }
 
   @Override
@@ -247,8 +261,9 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return CloseableIterator.from(res.iterator());
   }
 
-  public void putTests(int testFileRed, List<BatchReport.Test> tests) {
+  public BatchReportReaderRule putTests(int testFileRed, List<BatchReport.Test> tests) {
     this.tests.put(testFileRed, tests);
+    return this;
   }
 
   @Override
@@ -261,7 +276,8 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return CloseableIterator.from(res.iterator());
   }
 
-  public void putCoverageDetails(int testFileRef, List<BatchReport.CoverageDetail> coverageDetails) {
+  public BatchReportReaderRule putCoverageDetails(int testFileRef, List<BatchReport.CoverageDetail> coverageDetails) {
     this.coverageDetails.put(testFileRef, coverageDetails);
+    return this;
   }
 }
index 8a784bf904390013459ae903f4b35c6cbff45909..723aac7eeeb42be639acc49215e035e92d4e86ce 100644 (file)
@@ -35,6 +35,7 @@ import org.junit.runner.RunWith;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.core.hash.SourceHashComputer;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.protobuf.DbFileSources;
@@ -46,7 +47,7 @@ import org.sonar.server.computation.batch.BatchReportReaderRule;
 import org.sonar.server.computation.component.Component;
 import org.sonar.server.computation.component.ReportComponent;
 import org.sonar.server.computation.component.ViewsComponent;
-import org.sonar.core.hash.SourceHashComputer;
+import org.sonar.server.computation.snapshot.Snapshot;
 import org.sonar.server.computation.source.SourceHashRepository;
 import org.sonar.server.computation.source.SourceHashRepositoryImpl;
 import org.sonar.server.computation.source.SourceLinesRepositoryImpl;
@@ -61,10 +62,15 @@ import static org.sonar.server.computation.component.ReportComponent.builder;
 @RunWith(DataProviderRunner.class)
 public class ScmInfoRepositoryImplTest {
 
-  private static final int FILE_REF = 1;
-  private static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build();
-  private static final long DATE_1 = 123456789L;
-  private static final long DATE_2 = 1234567810L;
+  static final int FILE_REF = 1;
+  static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build();
+  static final long DATE_1 = 123456789L;
+  static final long DATE_2 = 1234567810L;
+
+  static Snapshot BASE_PROJECT_SNAPSHOT = new Snapshot.Builder()
+    .setId(1)
+    .setCreatedAt(123456789L)
+    .build();
 
   @Rule
   public ExpectedException thrown = ExpectedException.none();
@@ -84,7 +90,7 @@ public class ScmInfoRepositoryImplTest {
 
   @Test
   public void read_from_report() throws Exception {
-    analysisMetadataHolder.setIsFirstAnalysis(false);
+    analysisMetadataHolder.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
     addChangesetInReport("john", DATE_1, "rev-1");
 
     ScmInfo scmInfo = underTest.getScmInfo(FILE).get();
@@ -95,7 +101,7 @@ public class ScmInfoRepositoryImplTest {
 
   @Test
   public void getScmInfo_returns_ScmInfo_from_DB_if_hashes_are_the_same() throws Exception {
-    analysisMetadataHolder.setIsFirstAnalysis(false);
+    analysisMetadataHolder.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
     addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1));
     addFileSourceInReport(1);
 
@@ -107,7 +113,7 @@ public class ScmInfoRepositoryImplTest {
 
   @Test
   public void getScmInfo_returns_absent_if_hash_from_db_does_not_match() throws Exception {
-    analysisMetadataHolder.setIsFirstAnalysis(false);
+    analysisMetadataHolder.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
     addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1) + "_different");
     addFileSourceInReport(1);
 
@@ -118,7 +124,7 @@ public class ScmInfoRepositoryImplTest {
 
   @Test
   public void read_from_report_even_if_data_in_db_exists() throws Exception {
-    analysisMetadataHolder.setIsFirstAnalysis(false);
+    analysisMetadataHolder.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
     addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1));
     addChangesetInReport("john", DATE_2, "rev-2");
 
@@ -132,13 +138,13 @@ public class ScmInfoRepositoryImplTest {
 
   @Test
   public void return_nothing_when_no_data_in_report_and_db() throws Exception {
-    analysisMetadataHolder.setIsFirstAnalysis(false);
+    analysisMetadataHolder.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
     assertThat(underTest.getScmInfo(FILE)).isAbsent();
   }
 
   @Test
   public void return_nothing_when_nothing_in_report_and_db_has_no_scm() throws Exception {
-    analysisMetadataHolder.setIsFirstAnalysis(false);
+    analysisMetadataHolder.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
     addFileSourceInDb(null, null, null, "don't care");
     addFileSourceInReport(1);
 
@@ -147,7 +153,7 @@ public class ScmInfoRepositoryImplTest {
 
   @Test
   public void fail_with_NPE_when_component_is_null() throws Exception {
-    analysisMetadataHolder.setIsFirstAnalysis(false);
+    analysisMetadataHolder.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
 
     thrown.expect(NullPointerException.class);
     thrown.expectMessage("Component cannot be bull");
@@ -186,7 +192,7 @@ public class ScmInfoRepositoryImplTest {
 
   @Test
   public void load_scm_info_from_cache_when_already_read() throws Exception {
-    analysisMetadataHolder.setIsFirstAnalysis(false);
+    analysisMetadataHolder.setBaseProjectSnapshot(BASE_PROJECT_SNAPSHOT);
     addChangesetInReport("john", DATE_1, "rev-1");
     ScmInfo scmInfo = underTest.getScmInfo(FILE).get();
     assertThat(scmInfo.getAllChangesets()).hasSize(1);
@@ -200,7 +206,7 @@ public class ScmInfoRepositoryImplTest {
 
   @Test
   public void not_read_in_db_on_first_analysis() throws Exception {
-    analysisMetadataHolder.setIsFirstAnalysis(true);
+    analysisMetadataHolder.setBaseProjectSnapshot(null);
     addFileSourceInDb("henry", DATE_1, "rev-1", "don't care");
     addFileSourceInReport(1);
 
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/snapshot/SnapshotImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/snapshot/SnapshotImplTest.java
new file mode 100644 (file)
index 0000000..ab4fc3d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.computation.snapshot;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SnapshotImplTest {
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  static final long ID = 10;
+  static final long CREATED_AT = 123456789L;
+
+  @Test
+  public void build_snapshot() throws Exception {
+    Snapshot snapshot = new Snapshot.Builder()
+      .setId(ID)
+      .setCreatedAt(CREATED_AT)
+      .build();
+
+    assertThat(snapshot.getId()).isEqualTo(ID);
+    assertThat(snapshot.getCreatedAt()).isEqualTo(CREATED_AT);
+  }
+
+  @Test
+  public void fail_with_NPE_when_building_snapshot_without_id() throws Exception {
+    thrown.expect(NullPointerException.class);
+    thrown.expectMessage("id cannot be null");
+
+    new Snapshot.Builder()
+      .setCreatedAt(CREATED_AT)
+      .build();
+  }
+
+  @Test
+  public void fail_with_NPE_when_building_snapshot_without_created_at() throws Exception {
+    thrown.expect(NullPointerException.class);
+    thrown.expectMessage("createdAt cannot be null");
+
+    new Snapshot.Builder()
+      .setId(ID)
+      .build();
+  }
+
+  @Test
+  public void test_toString() throws Exception {
+    assertThat(new Snapshot.Builder()
+      .setId(ID)
+      .setCreatedAt(CREATED_AT)
+      .build().toString())
+      .isEqualTo("SnapshotImpl{id=10, createdAt=123456789}");
+  }
+
+  @Test
+  public void test_equals_and_hascode() throws Exception {
+    Snapshot snapshot = new Snapshot.Builder()
+      .setId(ID)
+      .setCreatedAt(CREATED_AT)
+      .build();
+    Snapshot sameSnapshot = new Snapshot.Builder()
+      .setId(ID)
+      .setCreatedAt(CREATED_AT)
+      .build();
+    Snapshot otherSnapshot = new Snapshot.Builder()
+      .setId(11L)
+      .setCreatedAt(CREATED_AT)
+      .build();
+
+    assertThat(snapshot).isEqualTo(snapshot);
+    assertThat(snapshot).isEqualTo(sameSnapshot);
+    assertThat(snapshot).isNotEqualTo(otherSnapshot);
+    assertThat(snapshot).isNotEqualTo(null);
+
+    assertThat(snapshot.hashCode()).isEqualTo(snapshot.hashCode());
+    assertThat(snapshot.hashCode()).isEqualTo(sameSnapshot.hashCode());
+    assertThat(snapshot.hashCode()).isNotEqualTo(otherSnapshot.hashCode());
+  }
+}
index c085483ace5d83f4d8f8625938a52aa563b9f01b..ce6e98476ffe69a53bb78747573f9e6d4d17c789 100644 (file)
@@ -277,7 +277,7 @@ public class BuildComponentTreeStepTest {
   }
 
   @Test
-  public void set_first_analysis_to_true_when_no_snapshot() throws Exception {
+  public void set_no_base_project_snapshot_when_no_snapshot() throws Exception {
     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
     underTest.execute();
 
@@ -285,7 +285,7 @@ public class BuildComponentTreeStepTest {
   }
 
   @Test
-  public void set_first_analysis_to_true_when_no_last_snapshot() throws Exception {
+  public void set_no_base_project_snapshot_when_no_last_snapshot() throws Exception {
     ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
     insertSnapshot(newSnapshotForProject(project).setLast(false));
 
@@ -296,7 +296,7 @@ public class BuildComponentTreeStepTest {
   }
 
   @Test
-  public void set_first_analysis_to_false_when_last_snapshot_exist() throws Exception {
+  public void set_base_project_snapshot_when_last_snapshot_exist() throws Exception {
     ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
     insertSnapshot(newSnapshotForProject(project).setLast(true));