]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7844 ScannerContextDao => CeScannerContextDao
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 25 Aug 2016 09:33:31 +0000 (11:33 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 29 Aug 2016 07:48:22 +0000 (09:48 +0200)
20 files changed:
server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskAction.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistScannerContextStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationSteps.java
server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistScannerContextStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ReportComputationStepsTest.java
sonar-db/src/main/java/org/sonar/db/DaoModule.java
sonar-db/src/main/java/org/sonar/db/DbClient.java
sonar-db/src/main/java/org/sonar/db/ce/CeScannerContextDao.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/ce/LogsIteratorInputStream.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/scannercontext/LogsIteratorInputStream.java [deleted file]
sonar-db/src/main/java/org/sonar/db/scannercontext/ScannerContextDao.java [deleted file]
sonar-db/src/main/java/org/sonar/db/scannercontext/package-info.java [deleted file]
sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml
sonar-db/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java
sonar-db/src/test/java/org/sonar/db/ce/CeScannerContextDaoTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/ce/LogsIteratorInputStreamTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
sonar-db/src/test/java/org/sonar/db/scannercontext/LogsIteratorInputStreamTest.java [deleted file]
sonar-db/src/test/java/org/sonar/db/scannercontext/ScannerContextDaoTest.java [deleted file]

index c421665c0b37c705bc5dcb0d2680c6eb0a65be24..77c95e66084744484af401ee799f9a25bba60027 100644 (file)
@@ -130,7 +130,7 @@ public class TaskAction implements CeWsAction {
   @CheckForNull
   private String extractScannerContext(DbSession dbSession, CeActivityDto activityDto, Set<AdditionalField> additionalFields) {
     if (additionalFields.contains(AdditionalField.SCANNER_CONTEXT)) {
-      return dbClient.scannerContextDao().selectScannerContext(dbSession, activityDto.getAnalysisUuid())
+      return dbClient.ceScannerContextDao().selectScannerContext(dbSession, activityDto.getUuid())
         .orElse(null);
     }
     return null;
index 5a49cff1e884ff4040e0f0adbf1da818eab535a2..3d9e98232211e4cffc1b6fcc0b51a7afc7c28cf2 100644 (file)
  */
 package org.sonar.server.computation.task.projectanalysis.step;
 
+import org.sonar.ce.queue.CeTask;
 import org.sonar.core.util.CloseableIterator;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader;
 import org.sonar.server.computation.task.step.ComputationStep;
 
 public class PersistScannerContextStep implements ComputationStep {
   private final BatchReportReader reportReader;
-  private final AnalysisMetadataHolder analysisMetadataHolder;
   private final DbClient dbClient;
+  private final CeTask ceTask;
 
-  public PersistScannerContextStep(BatchReportReader reportReader, AnalysisMetadataHolder analysisMetadataHolder, DbClient dbClient) {
+  public PersistScannerContextStep(BatchReportReader reportReader, DbClient dbClient, CeTask ceTask) {
     this.reportReader = reportReader;
-    this.analysisMetadataHolder = analysisMetadataHolder;
     this.dbClient = dbClient;
+    this.ceTask = ceTask;
+  }
+
+  @Override
+  public String getDescription() {
+    return "Persist scanner context";
   }
 
   @Override
@@ -42,15 +47,10 @@ public class PersistScannerContextStep implements ComputationStep {
     try (CloseableIterator<String> logsIterator = reportReader.readScannerLogs()) {
       if (logsIterator.hasNext()) {
         try (DbSession dbSession = dbClient.openSession(false)) {
-          dbClient.scannerContextDao().insert(dbSession, analysisMetadataHolder.getUuid(), logsIterator);
+          dbClient.ceScannerContextDao().insert(dbSession, ceTask.getUuid(), logsIterator);
           dbSession.commit();
         }
       }
     }
   }
-
-  @Override
-  public String getDescription() {
-    return "Persist scanner context";
-  }
 }
index 217d4cc45058289cae8a2ab42ff555cd13b00428..30e36ec75887ee0f9af2dca7bac74ca1dd19ec7d 100644 (file)
@@ -38,6 +38,7 @@ public class ReportComputationSteps extends AbstractComputationSteps {
 
   private static final List<Class<? extends ComputationStep>> STEPS = Arrays.asList(
     ExtractReportStep.class,
+    PersistScannerContextStep.class,
     GenerateAnalysisUuid.class,
 
     // Builds Component tree
@@ -96,7 +97,6 @@ public class ReportComputationSteps extends AbstractComputationSteps {
     PersistFileSourcesStep.class,
     PersistTestsStep.class,
     PersistCrossProjectDuplicationIndexStep.class,
-    PersistScannerContextStep.class,
     EnableAnalysisStep.class,
 
     UpdateQualityProfilesLastUsedDateStep.class,
index cb06586a61ae02979094595380657f83dd540b04..8fb215893de448611581f55ff27a8a767b8ded04 100644 (file)
@@ -174,8 +174,8 @@ public class TaskActionTest {
     userSession.login("john").setGlobalPermissions(SYSTEM_ADMIN);
 
     String scannerContext = "this is some scanner context, yeah!";
-    CeActivityDto activityDto = persist(createActivityDto(SOME_TASK_UUID));
-    persistScannerContext(activityDto.getAnalysisUuid(), scannerContext);
+    persist(createActivityDto(SOME_TASK_UUID));
+    persistScannerContext(SOME_TASK_UUID, scannerContext);
 
     TestResponse wsResponse = ws.newRequest()
         .setMediaType(PROTOBUF)
@@ -194,8 +194,8 @@ public class TaskActionTest {
     userSession.login("john").setGlobalPermissions(SYSTEM_ADMIN);
 
     String scannerContext = "this is some scanner context, yeah!";
-    CeActivityDto activityDto = persist(createActivityDto(SOME_TASK_UUID));
-    persistScannerContext(activityDto.getAnalysisUuid(), scannerContext);
+    persist(createActivityDto(SOME_TASK_UUID));
+    persistScannerContext(SOME_TASK_UUID, scannerContext);
 
     TestResponse wsResponse = ws.newRequest()
         .setMediaType(PROTOBUF)
@@ -342,8 +342,8 @@ public class TaskActionTest {
     return activityDto;
   }
 
-  private void persistScannerContext(String analysisUuid, String scannerContext) {
-    dbTester.getDbClient().scannerContextDao().insert(dbTester.getSession(), analysisUuid, CloseableIterator.from(singleton(scannerContext).iterator()));
+  private void persistScannerContext(String taskUuid, String scannerContext) {
+    dbTester.getDbClient().ceScannerContextDao().insert(dbTester.getSession(), taskUuid, CloseableIterator.from(singleton(scannerContext).iterator()));
     dbTester.commit();
   }
 
index be31c20ea6b038f856cce537f6af90c6e00f0b54..2a8f9d73592dc69a74f980676283fd778a3e0ce0 100644 (file)
@@ -23,6 +23,7 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
+import org.sonar.ce.queue.CeTask;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
@@ -31,6 +32,8 @@ import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader
 import static java.util.Arrays.asList;
 import static java.util.Collections.emptyList;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class PersistScannerContextStepTest {
   private static final String ANALYSIS_UUID = "UUID";
@@ -45,7 +48,8 @@ public class PersistScannerContextStepTest {
     .setUuid(ANALYSIS_UUID);
 
   private DbClient dbClient = dbTester.getDbClient();
-  private PersistScannerContextStep underTest = new PersistScannerContextStep(reportReader, analysisMetadataHolder, dbClient);
+  private CeTask ceTask = mock(CeTask.class);
+  private PersistScannerContextStep underTest = new PersistScannerContextStep(reportReader, dbClient, ceTask);
 
   @Test
   public void getDescription() {
@@ -54,21 +58,23 @@ public class PersistScannerContextStepTest {
 
   @Test
   public void executes_persist_lines_of_reportReader() {
+    String taskUuid = "task uuid";
+    when(ceTask.getUuid()).thenReturn(taskUuid);
     reportReader.setScannerLogs(asList("log1", "log2"));
 
     underTest.execute();
 
-    assertThat(dbClient.scannerContextDao().selectScannerContext(dbTester.getSession(), ANALYSIS_UUID))
+    assertThat(dbClient.ceScannerContextDao().selectScannerContext(dbTester.getSession(), taskUuid))
       .contains("log1" + '\n' + "log2");
   }
 
   @Test
-  public void executes_persist_does_not_persit_any_scanner_context_if_iterator_is_empty() {
+  public void executes_persist_does_not_persist_any_scanner_context_if_iterator_is_empty() {
     reportReader.setScannerLogs(emptyList());
 
     underTest.execute();
 
-    assertThat(dbClient.scannerContextDao().selectScannerContext(dbTester.getSession(), ANALYSIS_UUID))
+    assertThat(dbClient.ceScannerContextDao().selectScannerContext(dbTester.getSession(), ANALYSIS_UUID))
       .isEmpty();
   }
 
index f8ff545f980ebef7915f7e6f054194bb5d25a1f3..b76473ac2828de7a1d37e9e224b1b9fd7c835523 100644 (file)
@@ -52,7 +52,7 @@ public class ReportComputationStepsTest {
   @Test
   public void instances_throws_ISE_if_container_does_not_have_second_step() throws Exception {
     expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Component not found: class org.sonar.server.computation.task.projectanalysis.step.GenerateAnalysisUuid");
+    expectedException.expectMessage("Component not found: class org.sonar.server.computation.task.projectanalysis.step.PersistScannerContextStep");
 
     final ExtractReportStep reportExtractionStep = mock(ExtractReportStep.class);
     ComponentContainer componentContainer = new ComponentContainer() {
index d18f35a86dde52ff2e7b4f7c003b1dadfad4a8ed..e17fc4911fca24a6c4401628e0ec0c6561d9fe07 100644 (file)
@@ -60,7 +60,7 @@ import org.sonar.db.qualitygate.QualityGateDao;
 import org.sonar.db.qualityprofile.ActiveRuleDao;
 import org.sonar.db.qualityprofile.QualityProfileDao;
 import org.sonar.db.rule.RuleDao;
-import org.sonar.db.scannercontext.ScannerContextDao;
+import org.sonar.db.ce.CeScannerContextDao;
 import org.sonar.db.source.FileSourceDao;
 import org.sonar.db.user.AuthorDao;
 import org.sonar.db.user.AuthorizationDao;
@@ -108,7 +108,7 @@ public class DaoModule extends Module {
     QualityGateDao.class,
     QualityGateConditionDao.class,
     QualityProfileDao.class,
-    ScannerContextDao.class,
+    CeScannerContextDao.class,
     RuleDao.class,
     ActiveRuleDao.class,
     ResourceIndexDao.class,
index 929813bfd66d6c368de726bacbe37a9896dd28d5..48761c376d822a220ea3081cd088fb9588f620fa 100644 (file)
@@ -60,7 +60,7 @@ import org.sonar.db.qualitygate.QualityGateDao;
 import org.sonar.db.qualityprofile.ActiveRuleDao;
 import org.sonar.db.qualityprofile.QualityProfileDao;
 import org.sonar.db.rule.RuleDao;
-import org.sonar.db.scannercontext.ScannerContextDao;
+import org.sonar.db.ce.CeScannerContextDao;
 import org.sonar.db.source.FileSourceDao;
 import org.sonar.db.user.AuthorDao;
 import org.sonar.db.user.AuthorizationDao;
@@ -102,6 +102,7 @@ public class DbClient {
   private final CeActivityDao ceActivityDao;
   private final CeQueueDao ceQueueDao;
   private final CeTaskInputDao ceTaskInputDao;
+  private final CeScannerContextDao ceScannerContextDao;
   private final DashboardDao dashboardDao;
   private final ActiveDashboardDao activeDashboardDao;
   private final WidgetDao widgetDao;
@@ -122,7 +123,6 @@ public class DbClient {
   private final GroupDao groupDao;
   private final RuleDao ruleDao;
   private final ActiveRuleDao activeRuleDao;
-  private final ScannerContextDao scannerContextDao;
 
   public DbClient(Database database, MyBatis myBatis, Dao... daos) {
     this.database = database;
@@ -159,6 +159,7 @@ public class DbClient {
     ceActivityDao = getDao(map, CeActivityDao.class);
     ceQueueDao = getDao(map, CeQueueDao.class);
     ceTaskInputDao = getDao(map, CeTaskInputDao.class);
+    ceScannerContextDao = getDao(map, CeScannerContextDao.class);
     dashboardDao = getDao(map, DashboardDao.class);
     activeDashboardDao = getDao(map, ActiveDashboardDao.class);
     widgetDao = getDao(map, WidgetDao.class);
@@ -179,7 +180,6 @@ public class DbClient {
     groupDao = getDao(map, GroupDao.class);
     ruleDao = getDao(map, RuleDao.class);
     activeRuleDao = getDao(map, ActiveRuleDao.class);
-    scannerContextDao = getDao(map, ScannerContextDao.class);
     doOnLoad(map);
   }
 
@@ -308,6 +308,10 @@ public class DbClient {
     return ceTaskInputDao;
   }
 
+  public CeScannerContextDao ceScannerContextDao() {
+    return ceScannerContextDao;
+  }
+
   public DashboardDao dashboardDao() {
     return dashboardDao;
   }
@@ -388,10 +392,6 @@ public class DbClient {
     return activeRuleDao;
   }
 
-  public ScannerContextDao scannerContextDao() {
-    return scannerContextDao;
-  }
-
   protected <K extends Dao> K getDao(Map<Class, Dao> map, Class<K> clazz) {
     return (K) map.get(clazz);
   }
diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeScannerContextDao.java b/sonar-db/src/main/java/org/sonar/db/ce/CeScannerContextDao.java
new file mode 100644 (file)
index 0000000..946eea5
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.ce;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Optional;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.CloseableIterator;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class CeScannerContextDao implements Dao {
+
+  private static final Charset UTF_8 = Charset.forName("UTF-8");
+
+  private final System2 system;
+
+  public CeScannerContextDao(System2 system) {
+    this.system = system;
+  }
+
+  /**
+   * @throws IllegalArgumentException if {@code scannerContextLines} is empty or fully read.
+   */
+  public void insert(DbSession dbSession, String taskUuid, CloseableIterator<String> scannerContextLines) {
+    checkArgument(scannerContextLines.hasNext(), "Scanner context can not be empty");
+    long now = system.now();
+    Connection connection = dbSession.getConnection();
+    try (PreparedStatement stmt = connection.prepareStatement(
+        "INSERT INTO ce_scanner_context (task_uuid, created_at, updated_at, data) VALUES (?, ?, ?, ?)");
+      InputStream inputStream = new LogsIteratorInputStream(scannerContextLines, UTF_8)) {
+      stmt.setString(1, taskUuid);
+      stmt.setLong(2, now);
+      stmt.setLong(3, now);
+      stmt.setBinaryStream(4, inputStream);
+      stmt.executeUpdate();
+      connection.commit();
+    } catch (SQLException | IOException e) {
+      throw new IllegalStateException("Fail to insert scanner context for task " + taskUuid, e);
+    }
+  }
+
+  /**
+   * The scanner context is very likely to contain lines, which are forcefully separated by {@code \n} characters,
+   * whichever the platform SQ is running on ({@see LogsIteratorInputStream}).
+   */
+  public Optional<String> selectScannerContext(DbSession dbSession, String taskUuid) {
+    try (PreparedStatement stmt = dbSession.getConnection().prepareStatement("select data from ce_scanner_context where task_uuid=?")) {
+      stmt.setString(1, taskUuid);
+      try (ResultSet rs = stmt.executeQuery()) {
+        if (rs.next()) {
+          return Optional.of(IOUtils.toString(rs.getBinaryStream(1), UTF_8));
+        }
+        return Optional.empty();
+      }
+    } catch (SQLException | IOException e) {
+      throw new IllegalStateException("Fail to retrieve scanner context of task " + taskUuid, e);
+    }
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/ce/LogsIteratorInputStream.java b/sonar-db/src/main/java/org/sonar/db/ce/LogsIteratorInputStream.java
new file mode 100644 (file)
index 0000000..6eb239a
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.ce;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import org.sonar.core.util.CloseableIterator;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * An {@link InputStream} that will read from a {@link CloseableIterator} of {@link String}, inserting {@code \n} between
+ * each element of the Iterator.
+ */
+final class LogsIteratorInputStream extends InputStream {
+  private static final int UNSET = -1;
+  private static final int END_OF_STREAM = -1;
+
+  private final Charset charset;
+  private final byte[] lineFeed;
+  private CloseableIterator<String> logsIterator;
+  private byte[] buf;
+  private int nextChar = UNSET;
+
+  LogsIteratorInputStream(CloseableIterator<String> logsIterator, Charset charset) {
+    checkArgument(logsIterator.hasNext(), "LogsIterator can't be empty or already read");
+    this.charset = charset;
+    this.lineFeed = "\n".getBytes(charset);
+    this.logsIterator = logsIterator;
+  }
+
+  @Override
+  public int read() throws IOException {
+    if (nextChar == UNSET || nextChar >= buf.length) {
+      fill();
+      if (nextChar == UNSET) {
+        return END_OF_STREAM;
+      }
+    }
+    return buf[nextChar++];
+  }
+
+  private void fill() {
+    if (logsIterator.hasNext()) {
+      byte[] line = logsIterator.next().getBytes(charset);
+      boolean hasNextLine = logsIterator.hasNext();
+      int bufLength = hasNextLine ? (line.length + lineFeed.length) : line.length;
+      // empty last line
+      if (bufLength == 0) {
+        this.buf = null;
+        this.nextChar = UNSET;
+      } else {
+        this.buf = new byte[bufLength];
+        System.arraycopy(line, 0, buf, 0, line.length);
+        if (hasNextLine) {
+          System.arraycopy(lineFeed, 0, buf, line.length, lineFeed.length);
+        }
+        this.nextChar = 0;
+      }
+    } else {
+      this.buf = null;
+      this.nextChar = UNSET;
+    }
+  }
+
+  @Override
+  public void close() throws IOException {
+    this.logsIterator.close();
+    this.buf = null;
+
+    super.close();
+  }
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/scannercontext/LogsIteratorInputStream.java b/sonar-db/src/main/java/org/sonar/db/scannercontext/LogsIteratorInputStream.java
deleted file mode 100644 (file)
index ab55e46..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.scannercontext;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import org.sonar.core.util.CloseableIterator;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-/**
- * An {@link InputStream} that will read from a {@link CloseableIterator} of {@link String}, inserting {@code \n} between
- * each element of the Iterator.
- */
-final class LogsIteratorInputStream extends InputStream {
-  private static final int UNSET = -1;
-  private static final int END_OF_STREAM = -1;
-
-  private final Charset charset;
-  private final byte[] lineFeed;
-  private CloseableIterator<String> logsIterator;
-  private byte[] buf;
-  private int nextChar = UNSET;
-
-  LogsIteratorInputStream(CloseableIterator<String> logsIterator, Charset charset) {
-    checkArgument(logsIterator.hasNext(), "LogsIterator can't be empty or already read");
-    this.charset = charset;
-    this.lineFeed = "\n".getBytes(charset);
-    this.logsIterator = logsIterator;
-  }
-
-  @Override
-  public int read() throws IOException {
-    if (nextChar == UNSET || nextChar >= buf.length) {
-      fill();
-      if (nextChar == UNSET) {
-        return END_OF_STREAM;
-      }
-    }
-    return buf[nextChar++];
-  }
-
-  private void fill() {
-    if (logsIterator.hasNext()) {
-      byte[] line = logsIterator.next().getBytes(charset);
-      boolean hasNextLine = logsIterator.hasNext();
-      int bufLength = hasNextLine ? (line.length + lineFeed.length) : line.length;
-      // empty last line
-      if (bufLength == 0) {
-        this.buf = null;
-        this.nextChar = UNSET;
-      } else {
-        this.buf = new byte[bufLength];
-        System.arraycopy(line, 0, buf, 0, line.length);
-        if (hasNextLine) {
-          System.arraycopy(lineFeed, 0, buf, line.length, lineFeed.length);
-        }
-        this.nextChar = 0;
-      }
-    } else {
-      this.buf = null;
-      this.nextChar = UNSET;
-    }
-  }
-
-  @Override
-  public void close() throws IOException {
-    this.logsIterator.close();
-    this.buf = null;
-
-    super.close();
-  }
-}
diff --git a/sonar-db/src/main/java/org/sonar/db/scannercontext/ScannerContextDao.java b/sonar-db/src/main/java/org/sonar/db/scannercontext/ScannerContextDao.java
deleted file mode 100644 (file)
index 7d81688..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.scannercontext;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Optional;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.CloseableIterator;
-import org.sonar.db.Dao;
-import org.sonar.db.DbSession;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-public class ScannerContextDao implements Dao {
-
-  private static final Charset UTF_8 = Charset.forName("UTF-8");
-
-  private final System2 system;
-
-  public ScannerContextDao(System2 system) {
-    this.system = system;
-  }
-
-  /**
-   * @throws IllegalArgumentException if {@code scannerContextLines} is empty or fully read.
-   */
-  public void insert(DbSession dbSession, String analysisUuid, CloseableIterator<String> scannerContextLines) {
-    checkArgument(scannerContextLines.hasNext(), "Scanner context can not be empty");
-    long now = system.now();
-    Connection connection = dbSession.getConnection();
-    try (PreparedStatement stmt = connection.prepareStatement(
-        "INSERT INTO scanner_context (analysis_uuid, created_at, updated_at, data) VALUES (?, ?, ?, ?)");
-      InputStream inputStream = new LogsIteratorInputStream(scannerContextLines, UTF_8)) {
-      stmt.setString(1, analysisUuid);
-      stmt.setLong(2, now);
-      stmt.setLong(3, now);
-      stmt.setBinaryStream(4, inputStream);
-      stmt.executeUpdate();
-      connection.commit();
-    } catch (SQLException | IOException e) {
-      throw new IllegalStateException("Fail to insert scanner context for analysis " + analysisUuid, e);
-    }
-  }
-
-  /**
-   * The scanner context is very likely to contain lines, which are forcefully separated by {@code \n} characters,
-   * whichever the platform SQ is running on ({@see LogsIteratorInputStream}).
-   */
-  public Optional<String> selectScannerContext(DbSession dbSession, String analysisUuid) {
-    try (PreparedStatement stmt = dbSession.getConnection().prepareStatement("select data from scanner_context where analysis_uuid=?")) {
-      stmt.setString(1, analysisUuid);
-      try (ResultSet rs = stmt.executeQuery()) {
-        if (rs.next()) {
-          return Optional.of(IOUtils.toString(rs.getBinaryStream(1), UTF_8));
-        }
-        return Optional.empty();
-      }
-    } catch (SQLException | IOException e) {
-      throw new IllegalStateException("Fail to retrieve scanner context of analysis " + analysisUuid, e);
-    }
-  }
-
-}
diff --git a/sonar-db/src/main/java/org/sonar/db/scannercontext/package-info.java b/sonar-db/src/main/java/org/sonar/db/scannercontext/package-info.java
deleted file mode 100644 (file)
index de8b739..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.db.scannercontext;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
index 27b3df87f2cbb8672c914a8f7d30d0795ebee107..77d2ccd60f51ac466afabcdc5d5dec2c6cc55e2a 100644 (file)
@@ -4,15 +4,15 @@
 <mapper namespace="org.sonar.db.ce.CeActivityMapper">
 
 
-  <!--assumes query includes an left left outer join on table scanner_context with alias ct -->
+  <!--assumes query includes an left left outer join on table ce_scanner_context with alias csc -->
   <sql id="hasScannerContextColumn" databaseId="mssql">
-    cast(case when ct.analysis_uuid is null then 0 else 1 end as bit) as hasScannerContext
+    cast(case when csc.task_uuid is null then 0 else 1 end as bit) as hasScannerContext
   </sql>
   <sql id="hasScannerContextColumn" databaseId="oracle">
-    case when ct.analysis_uuid is null then 0 else 1 end as hasScannerContext
+    case when csc.task_uuid is null then 0 else 1 end as hasScannerContext
   </sql>
   <sql id="hasScannerContextColumn">
-    ct.analysis_uuid is not null as hasScannerContext
+    csc.task_uuid is not null as hasScannerContext
   </sql>
 
   <sql id="columns">
@@ -40,7 +40,7 @@
     <include refid="columns"/>,
     ca.error_stacktrace as errorStacktrace
     from ce_activity ca
-    left outer join scanner_context ct on ca.analysis_uuid = ct.analysis_uuid
+    left outer join ce_scanner_context csc on ca.uuid = csc.task_uuid
     where ca.uuid=#{uuid}
   </select>
 
@@ -84,7 +84,7 @@
 
   <sql id="sqlSelectByQuery">
     from ce_activity ca
-    left outer join scanner_context ct on ct.analysis_uuid = ca.analysis_uuid
+    left outer join ce_scanner_context csc on csc.task_uuid = ca.uuid
     <where>
       <if test="query.onlyCurrents">
         and ca.is_last=${_true}
     select
       <include refid="columns"/>
     from ce_activity ca
-    left outer join scanner_context ct on ct.analysis_uuid = ca.analysis_uuid
+    left outer join ce_scanner_context csc on csc.task_uuid = ca.uuid
     where
       ca.created_at &lt; #{beforeDate,jdbcType=BIGINT}
   </select>
index 7b49b1d5a119aa34ec6f799da4da227cd05a7b79..45b8b41271abaa1372667def1df6bf88ce8596fa 100644 (file)
@@ -41,8 +41,6 @@ import static org.sonar.db.ce.CeTaskTypes.REPORT;
 
 public class CeActivityDaoTest {
 
-  private static final String AN_ANALYSIS_UUID = "U1";
-
   private TestSystem2 system2 = new TestSystem2().setNow(1_450_000_000_000L);
 
   @Rule
@@ -196,7 +194,7 @@ public class CeActivityDaoTest {
   public void selectByQuery_populates_hasScannerContext_flag() {
     insert("TASK_1", REPORT, "PROJECT_1", SUCCESS);
     CeActivityDto dto2 = insert("TASK_2", REPORT, "PROJECT_2", SUCCESS);
-    insertScannerContext(dto2.getAnalysisUuid());
+    insertScannerContext(dto2.getUuid());
 
     CeActivityDto dto = underTest.selectByQuery(db.getSession(), new CeTaskQuery().setComponentUuid("PROJECT_1"), 0, 100).iterator().next();
     assertThat(dto.isHasScannerContext()).isFalse();
@@ -275,7 +273,7 @@ public class CeActivityDaoTest {
   public void selectOlder_populates_hasScannerContext_flag() {
     insertWithCreationDate("TASK_1", 1_450_000_000_000L);
     CeActivityDto dto2 = insertWithCreationDate("TASK_2", 1_450_000_000_000L);
-    insertScannerContext(dto2.getAnalysisUuid());
+    insertScannerContext(dto2.getUuid());
 
     List<CeActivityDto> dtos = underTest.selectOlderThan(db.getSession(), 1_465_000_000_000L);
     assertThat(dtos).hasSize(2);
@@ -369,8 +367,9 @@ public class CeActivityDaoTest {
     return dto;
   }
 
-  private void insertScannerContext(String analysisUuid) {
-    db.getDbClient().scannerContextDao().insert(dbSession, analysisUuid, CloseableIterator.from(singletonList("scanner context of " + analysisUuid).iterator()));
+  private void insertScannerContext(String taskUuid) {
+    db.getDbClient().ceScannerContextDao().insert(dbSession, taskUuid, CloseableIterator.from(singletonList("scanner context of " + taskUuid).iterator()));
+    dbSession.commit();
   }
 
   private List<String> selectPageOfUuids(int offset, int pageSize) {
diff --git a/sonar-db/src/test/java/org/sonar/db/ce/CeScannerContextDaoTest.java b/sonar-db/src/test/java/org/sonar/db/ce/CeScannerContextDaoTest.java
new file mode 100644 (file)
index 0000000..e270a94
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.ce;
+
+import java.util.Collections;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.CloseableIterator;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+
+import static java.lang.System.lineSeparator;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class CeScannerContextDaoTest {
+
+  private static final String TABLE_NAME = "ce_scanner_context";
+  private static final String SOME_UUID = "some UUID";
+
+  @Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private System2 system = mock(System2.class);
+  private DbSession dbSession = dbTester.getSession();
+
+  private CeScannerContextDao underTest = new CeScannerContextDao(system);
+
+  @Test
+  public void selectScannerContext_returns_empty_on_empty_table() {
+    assertThat(underTest.selectScannerContext(dbSession, SOME_UUID)).isEmpty();
+  }
+
+  @Test
+  public void selectScannerContext_returns_empty_when_no_row_exist_for_taskUuid() {
+    String data = "some data";
+    underTest.insert(dbSession, SOME_UUID, scannerContextInputStreamOf(data));
+    dbSession.commit();
+
+    assertThat(underTest.selectScannerContext(dbSession, "OTHER_uuid")).isEmpty();
+    assertThat(underTest.selectScannerContext(dbSession, SOME_UUID)).contains(data);
+  }
+
+  @Test
+  public void insert_fails_with_IAE_if_data_is_empty() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Scanner context can not be empty");
+
+    underTest.insert(dbSession, SOME_UUID, CloseableIterator.emptyCloseableIterator());
+  }
+
+  @Test
+  public void insert_fails_with_IAE_if_data_is_fully_read() {
+    CloseableIterator<String> iterator = scannerContextInputStreamOf("aa");
+    iterator.next();
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Scanner context can not be empty");
+
+    underTest.insert(dbSession, SOME_UUID, iterator);
+  }
+
+  @Test
+  public void insert_fails_if_row_already_exists_for_taskUuid() {
+    underTest.insert(dbSession, SOME_UUID, scannerContextInputStreamOf("bla"));
+    dbSession.commit();
+
+    assertThat(dbTester.countRowsOfTable(dbSession, TABLE_NAME)).isEqualTo(1);
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Fail to insert scanner context for task " + SOME_UUID);
+
+    underTest.insert(dbSession, SOME_UUID, scannerContextInputStreamOf("blo"));
+  }
+
+  @Test
+  public void insert_and_select_line_reader() {
+    String scannerContext = "line 1" + lineSeparator() + "line 2" + lineSeparator() + "line 3";
+    underTest.insert(dbSession, SOME_UUID, scannerContextInputStreamOf(scannerContext));
+    dbSession.commit(true);
+
+    assertThat(underTest.selectScannerContext(dbSession, SOME_UUID)).contains(scannerContext);
+  }
+
+  private static CloseableIterator<String> scannerContextInputStreamOf(String data) {
+    return CloseableIterator.from(Collections.singleton(data).iterator());
+  }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/ce/LogsIteratorInputStreamTest.java b/sonar-db/src/test/java/org/sonar/db/ce/LogsIteratorInputStreamTest.java
new file mode 100644 (file)
index 0000000..1e259ce
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.ce;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import org.apache.commons.io.IOUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.core.util.CloseableIterator;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class LogsIteratorInputStreamTest {
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void read_from_ClosableIterator_with_several_lines() throws IOException {
+    assertThat(read(create("line1", "line2", "line3"))).isEqualTo("line1" + '\n' + "line2" + '\n' + "line3");
+  }
+
+  @Test
+  public void read_from_ClosableIterator_with_single_line() throws IOException {
+    assertThat(read(create("line1"))).isEqualTo("line1");
+  }
+
+  @Test
+  public void read_from_ClosableIterator_with_single_empty_line() throws IOException {
+    assertThat(read(create(""))).isEqualTo("");
+  }
+
+  @Test
+  public void read_from_ClosableIterator_with_several_empty_lines() throws IOException {
+    assertThat(read(create("", "line2", "", "line4", "", "", "", "line8", "")))
+      .isEqualTo('\n' + "line2" + '\n' + '\n' + "line4" + '\n' + '\n' + '\n' + '\n' + "line8" + '\n');
+  }
+
+  @Test
+  public void constructor_throws_IAE_when_ClosableIterator_is_empty() throws IOException {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("LogsIterator can't be empty or already read");
+
+    create();
+  }
+
+  @Test
+  public void constructor_throws_IAE_when_ClosableIterator_has_already_been_read() throws IOException {
+    CloseableIterator<String> iterator = CloseableIterator.from(Arrays.asList("line1").iterator());
+
+    // read iterator to the end
+    iterator.next();
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("LogsIterator can't be empty or already read");
+
+    new LogsIteratorInputStream(iterator, Charset.forName("UTF-8"));
+  }
+
+  private static LogsIteratorInputStream create(String... lines) {
+    return new LogsIteratorInputStream(CloseableIterator.from(Arrays.asList(lines).iterator()), Charset.forName("UTF-8"));
+  }
+
+  private static String read(LogsIteratorInputStream logsIteratorInputStream) throws IOException {
+    return IOUtils.toString(logsIteratorInputStream, "UTF-8");
+  }
+}
index 55dd7318bdc222f8b3383f12f71815bffe4b4c11..ee48762f5a25a798e9cb1e874eb00c465ef5f0c3 100644 (file)
@@ -254,7 +254,7 @@ public class PurgeDaoTest {
   }
 
   private void insertScannerContext(String analysisUuid, String scannerContext) {
-    dbTester.getDbClient().scannerContextDao().insert(dbSession, analysisUuid, CloseableIterator.from(singleton(scannerContext).iterator()));
+    dbTester.getDbClient().ceScannerContextDao().insert(dbSession, analysisUuid, CloseableIterator.from(singleton(scannerContext).iterator()));
     dbTester.commit();
   }
 
diff --git a/sonar-db/src/test/java/org/sonar/db/scannercontext/LogsIteratorInputStreamTest.java b/sonar-db/src/test/java/org/sonar/db/scannercontext/LogsIteratorInputStreamTest.java
deleted file mode 100644 (file)
index 06d6e1b..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.scannercontext;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import org.apache.commons.io.IOUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.core.util.CloseableIterator;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class LogsIteratorInputStreamTest {
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Test
-  public void read_from_ClosableIterator_with_several_lines() throws IOException {
-    assertThat(read(create("line1", "line2", "line3"))).isEqualTo("line1" + '\n' + "line2" + '\n' + "line3");
-  }
-
-  @Test
-  public void read_from_ClosableIterator_with_single_line() throws IOException {
-    assertThat(read(create("line1"))).isEqualTo("line1");
-  }
-
-  @Test
-  public void read_from_ClosableIterator_with_single_empty_line() throws IOException {
-    assertThat(read(create(""))).isEqualTo("");
-  }
-
-  @Test
-  public void read_from_ClosableIterator_with_several_empty_lines() throws IOException {
-    assertThat(read(create("", "line2", "", "line4", "", "", "", "line8", "")))
-      .isEqualTo('\n' + "line2" + '\n' + '\n' + "line4" + '\n' + '\n' + '\n' + '\n' + "line8" + '\n');
-  }
-
-  @Test
-  public void constructor_throws_IAE_when_ClosableIterator_is_empty() throws IOException {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("LogsIterator can't be empty or already read");
-
-    create();
-  }
-
-  @Test
-  public void constructor_throws_IAE_when_ClosableIterator_has_already_been_read() throws IOException {
-    CloseableIterator<String> iterator = CloseableIterator.from(Arrays.asList("line1").iterator());
-
-    // read iterator to the end
-    iterator.next();
-
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("LogsIterator can't be empty or already read");
-
-    new LogsIteratorInputStream(iterator, Charset.forName("UTF-8"));
-  }
-
-  private static LogsIteratorInputStream create(String... lines) {
-    return new LogsIteratorInputStream(CloseableIterator.from(Arrays.asList(lines).iterator()), Charset.forName("UTF-8"));
-  }
-
-  private static String read(LogsIteratorInputStream logsIteratorInputStream) throws IOException {
-    return IOUtils.toString(logsIteratorInputStream, "UTF-8");
-  }
-}
diff --git a/sonar-db/src/test/java/org/sonar/db/scannercontext/ScannerContextDaoTest.java b/sonar-db/src/test/java/org/sonar/db/scannercontext/ScannerContextDaoTest.java
deleted file mode 100644 (file)
index ef635a5..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.scannercontext;
-
-import java.util.Collections;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.CloseableIterator;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-
-import static java.lang.System.lineSeparator;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class ScannerContextDaoTest {
-
-  private static final String TABLE_NAME = "scanner_context";
-  private static final String SOME_UUID = "some UUID";
-
-  @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  private System2 system = mock(System2.class);
-  private DbSession dbSession = dbTester.getSession();
-
-  private ScannerContextDao underTest = new ScannerContextDao(system);
-
-  @Test
-  public void selectScannerContext_returns_empty_on_empty_table() {
-    assertThat(underTest.selectScannerContext(dbSession, SOME_UUID)).isEmpty();
-  }
-
-  @Test
-  public void selectScannerContext_returns_empty_when_no_row_exist_for_analysisUuid() {
-    String data = "some data";
-    underTest.insert(dbSession, SOME_UUID, scannerContextInputStreamOf(data));
-    dbSession.commit();
-
-    assertThat(underTest.selectScannerContext(dbSession, "OTHER_uuid")).isEmpty();
-    assertThat(underTest.selectScannerContext(dbSession, SOME_UUID)).contains(data);
-  }
-
-  @Test
-  public void insert_fails_with_IAE_if_data_is_empty() {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Scanner context can not be empty");
-
-    underTest.insert(dbSession, SOME_UUID, CloseableIterator.emptyCloseableIterator());
-  }
-
-  @Test
-  public void insert_fails_with_IAE_if_data_is_fully_read() {
-    CloseableIterator<String> iterator = scannerContextInputStreamOf("aa");
-    iterator.next();
-
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Scanner context can not be empty");
-
-    underTest.insert(dbSession, SOME_UUID, iterator);
-  }
-
-  @Test
-  public void insert_fails_if_row_already_exists_for_analysis_uuid() {
-    underTest.insert(dbSession, SOME_UUID, scannerContextInputStreamOf("bla"));
-    dbSession.commit();
-
-    assertThat(dbTester.countRowsOfTable(dbSession, TABLE_NAME)).isEqualTo(1);
-
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Fail to insert scanner context for analysis " + SOME_UUID);
-
-    underTest.insert(dbSession, SOME_UUID, scannerContextInputStreamOf("blo"));
-  }
-
-  @Test
-  public void insert_and_select_line_reader() {
-    String scannerContext = "line 1" + lineSeparator() + "line 2" + lineSeparator() + "line 3";
-    underTest.insert(dbSession, SOME_UUID, scannerContextInputStreamOf(scannerContext));
-    dbSession.commit(true);
-
-    assertThat(underTest.selectScannerContext(dbSession, SOME_UUID)).contains(scannerContext);
-  }
-
-  private static CloseableIterator<String> scannerContextInputStreamOf(String data) {
-    return CloseableIterator.from(Collections.singleton(data).iterator());
-  }
-
-}