@Test
  public void nothing_to_do_when_no_events_in_report() throws Exception {
    dbTester.prepareDbUnit(getClass(), "nothing_to_do_when_no_events_in_report.xml");

    File reportDir = temp.newFolder();
    BatchReportWriter writer = new BatchReportWriter(reportDir);
    writer.writeMetadata(
        BatchReport.Metadata.newBuilder()
            .setRootComponentRef(1)
            .setProjectKey("PROJECT_KEY")
            .setAnalysisDate(150000000L)
            .build());

    writer.writeComponent(
        BatchReport.Component.newBuilder()
            .setRef(1)
            .setType(Constants.ComponentType.PROJECT)
            .setUuid("ABCD")
            .build());

    step.execute(
        new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));

    dbTester.assertDbUnit(getClass(), "nothing_to_do_when_no_events_in_report.xml", "events");
  }
  private BatchReportWriter initReport() {
    BatchReportWriter writer = new BatchReportWriter(reportDir);
    writer.writeMetadata(
        BatchReport.Metadata.newBuilder()
            .setRootComponentRef(1)
            .setProjectKey("PROJECT_KEY")
            .setAnalysisDate(150000000L)
            .build());

    writer.writeComponent(
        BatchReport.Component.newBuilder()
            .setRef(1)
            .setType(Constants.ComponentType.PROJECT)
            .setUuid("PROJECT_A")
            .addChildRef(2)
            .build());
    writer.writeComponent(
        BatchReport.Component.newBuilder()
            .setRef(2)
            .setType(Constants.ComponentType.MODULE)
            .setUuid("BCDE")
            .addChildRef(FILE_REF)
            .build());
    writer.writeComponent(
        BatchReport.Component.newBuilder()
            .setRef(FILE_REF)
            .setType(Constants.ComponentType.FILE)
            .setUuid("FILE_A")
            .build());
    return writer;
  }
  @Test
  public void compute_syntax_highlighting() throws Exception {
    BatchReportWriter writer = initReport();

    writer.writeComponentSyntaxHighlighting(
        FILE_REF,
        newArrayList(
            BatchReport.SyntaxHighlighting.HighlightingRule.newBuilder()
                .setRange(
                    BatchReport.Range.newBuilder()
                        .setStartLine(1)
                        .setStartOffset(3)
                        .setEndLine(1)
                        .setEndOffset(5)
                        .build())
                .setType(Constants.HighlightingType.ANNOTATION)
                .build(),
            BatchReport.SyntaxHighlighting.HighlightingRule.newBuilder()
                .setRange(
                    BatchReport.Range.newBuilder()
                        .setStartLine(3)
                        .setStartOffset(6)
                        .setEndLine(3)
                        .setEndOffset(7)
                        .build())
                .setType(Constants.HighlightingType.COMMENT)
                .build()));

    step.execute(
        new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));

    assertThat(step.getSyntaxHighlightingByLine()).hasSize(2);
    assertThat(step.getSyntaxHighlightingByLine().get(1).toString()).isEqualTo("3,5,ANNOTATION");
    assertThat(step.getSyntaxHighlightingByLine().get(3).toString()).isEqualTo("6,7,COMMENT");
  }
  @Test
  public void keep_one_event_by_version() throws Exception {
    dbTester.prepareDbUnit(getClass(), "keep_one_event_by_version.xml");

    File reportDir = temp.newFolder();
    BatchReportWriter writer = new BatchReportWriter(reportDir);
    writer.writeMetadata(
        BatchReport.Metadata.newBuilder()
            .setRootComponentRef(1)
            .setProjectKey("PROJECT_KEY")
            .setAnalysisDate(150000000L)
            .build());

    writer.writeComponent(
        BatchReport.Component.newBuilder()
            .setRef(1)
            .setType(Constants.ComponentType.PROJECT)
            .setUuid("ABCD")
            .setSnapshotId(1001L)
            .setVersion("1.5-SNAPSHOT")
            .build());

    step.execute(
        new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));

    dbTester.assertDbUnit(getClass(), "keep_one_event_by_version-result.xml", "events");
  }
  @Test
  public void persist_report_events_with_component_children() throws Exception {
    dbTester.prepareDbUnit(getClass(), "empty.xml");

    File reportDir = temp.newFolder();
    BatchReportWriter writer = new BatchReportWriter(reportDir);
    writer.writeMetadata(
        BatchReport.Metadata.newBuilder()
            .setRootComponentRef(1)
            .setProjectKey("PROJECT_KEY")
            .setAnalysisDate(150000000L)
            .build());

    writer.writeComponent(
        BatchReport.Component.newBuilder()
            .setRef(1)
            .setType(Constants.ComponentType.PROJECT)
            .setUuid("ABCD")
            .setSnapshotId(1000L)
            .addEvent(
                BatchReport.Event.newBuilder()
                    .setName("Red (was Orange)")
                    .setCategory(Constants.EventCategory.ALERT)
                    .setDescription("Open issues > 0")
                    .build())
            .addChildRef(2)
            .build());

    writer.writeComponent(
        BatchReport.Component.newBuilder()
            .setRef(2)
            .setType(Constants.ComponentType.MODULE)
            .setUuid("BCDE")
            .setSnapshotId(1001L)
            .addEvent(
                BatchReport.Event.newBuilder()
                    .setName("Red (was Orange)")
                    .setCategory(Constants.EventCategory.ALERT)
                    .setDescription("Open issues > 0")
                    .build())
            .build());

    step.execute(
        new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));

    dbTester.assertDbUnit(
        getClass(), "persist_report_events_with_component_children-result.xml", "events");
  }
  @Test
  public void readComponentMeasures_is_not_cached() {
    writer.writeComponentMeasures(COMPONENT_REF, of(MEASURE));

    assertThat(underTest.readComponentMeasures(COMPONENT_REF))
        .isNotSameAs(underTest.readComponentMeasures(COMPONENT_REF));
  }
  @Test
  public void readComponentSymbols_it_not_cached() {
    writer.writeComponentSymbols(COMPONENT_REF, of(SYMBOL));

    assertThat(underTest.readComponentSymbols(COMPONENT_REF))
        .isNotSameAs(underTest.readComponentSymbols(COMPONENT_REF));
  }
  @Test
  public void readComponentDuplicationBlocks_is_not_cached() {
    writer.writeCpdTextBlocks(COMPONENT_REF, of(DUPLICATION_BLOCK));

    assertThat(underTest.readCpdTextBlocks(COMPONENT_REF))
        .isNotSameAs(underTest.readCpdTextBlocks(COMPONENT_REF));
  }
  @Test
  public void readComponentDuplications_it_not_cached() {
    writer.writeComponentDuplications(COMPONENT_REF, of(DUPLICATION));

    assertThat(underTest.readComponentDuplications(COMPONENT_REF))
        .isNotSameAs(underTest.readComponentDuplications(COMPONENT_REF));
  }
  @Test
  public void readComponentIssues_it_not_cached() {
    writer.writeComponentIssues(COMPONENT_REF, of(ISSUE));

    assertThat(underTest.readComponentIssues(COMPONENT_REF))
        .isNotSameAs(underTest.readComponentIssues(COMPONENT_REF));
  }
  @Test
  public void readComponent_is_not_cached() {
    writer.writeComponent(COMPONENT);

    assertThat(underTest.readComponent(COMPONENT_REF))
        .isNotSameAs(underTest.readComponent(COMPONENT_REF));
  }
  @Test
  public void readChangesets_is_not_cached() {
    writer.writeComponentChangesets(CHANGESETS);

    assertThat(underTest.readChangesets(COMPONENT_REF))
        .isNotSameAs(underTest.readChangesets(COMPONENT_REF));
  }
  @Test
  public void verify_readChangesets_returns_changesets() {
    writer.writeComponentChangesets(CHANGESETS);

    BatchReport.Changesets res = underTest.readChangesets(COMPONENT_REF);
    assertThat(res).isEqualTo(CHANGESETS);
  }
  @Override
  public void publish(BatchReportWriter writer) {
    for (final BatchResource resource : resourceCache.all()) {
      Iterable<Measure> batchMeasures = measureCache.byResource(resource.resource());
      batchMeasures =
          Iterables.filter(
              batchMeasures,
              new Predicate<Measure>() {
                @Override
                public boolean apply(Measure input) {
                  // Reload Metric to have all Hibernate fields populated
                  input.setMetric(metricFinder.findByKey(input.getMetricKey()));
                  return shouldPersistMeasure(resource.resource(), input);
                }
              });
      Iterable<org.sonar.batch.protocol.output.BatchReport.Measure> reportMeasures =
          Iterables.transform(
              batchMeasures,
              new Function<Measure, BatchReport.Measure>() {
                private final BatchReport.Measure.Builder builder =
                    BatchReport.Measure.newBuilder();

                @Override
                public BatchReport.Measure apply(Measure input) {
                  return toReportMeasure(builder, input);
                }
              });
      writer.writeComponentMeasures(resource.batchId(), reportMeasures);
    }
  }
  @Test
  public void verify_readTests() {
    writer.writeTests(COMPONENT_REF, of(TEST_1, TEST_2));

    CloseableIterator<BatchReport.Test> res = underTest.readTests(COMPONENT_REF);
    assertThat(res).containsExactly(TEST_1, TEST_2);
    res.close();
  }
  @Test
  public void verify_readComponentCoverage() {
    writer.writeComponentCoverage(COMPONENT_REF, of(COVERAGE_1, COVERAGE_2));

    CloseableIterator<BatchReport.Coverage> res = underTest.readComponentCoverage(COMPONENT_REF);
    assertThat(res).containsExactly(COVERAGE_1, COVERAGE_2);
    res.close();
  }
  @Test
  public void readScannerLogs() throws IOException {
    File scannerLogFile = writer.getFileStructure().analysisLog();
    FileUtils.write(scannerLogFile, "log1\nlog2");

    CloseableIterator<String> logs = underTest.readScannerLogs();
    assertThat(logs).containsExactly("log1", "log2");
  }
  @Test
  public void verify_readComponentIssues_returns_Issues() {
    writer.writeComponentIssues(COMPONENT_REF, of(ISSUE));

    try (CloseableIterator<BatchReport.Issue> res = underTest.readComponentIssues(COMPONENT_REF)) {
      assertThat(res.next()).isEqualTo(ISSUE);
      assertThat(res.hasNext()).isFalse();
    }
  }
  @Test
  public void verify_readFileSource() throws IOException {
    File file = writer.getSourceFile(COMPONENT_REF);
    FileUtils.writeLines(file, of("1", "2", "3"));

    CloseableIterator<String> res = underTest.readFileSource(COMPONENT_REF).get();
    assertThat(res).containsExactly("1", "2", "3");
    res.close();
  }
  @Test
  public void verify_readComponentMeasures_returns_measures() {
    writer.writeComponentMeasures(COMPONENT_REF, of(MEASURE));

    try (CloseableIterator<BatchReport.Measure> measures =
        underTest.readComponentMeasures(COMPONENT_REF)) {
      assertThat(measures.next()).isEqualTo(MEASURE);
      assertThat(measures.hasNext()).isFalse();
    }
  }
  @Test
  public void verify_readComponentDuplicationBlocks_returns_Issues() {
    writer.writeCpdTextBlocks(COMPONENT_REF, of(DUPLICATION_BLOCK));

    try (CloseableIterator<BatchReport.CpdTextBlock> res =
        underTest.readCpdTextBlocks(COMPONENT_REF)) {
      assertThat(res.next()).isEqualTo(DUPLICATION_BLOCK);
      assertThat(res.hasNext()).isFalse();
    }
  }
  @Test
  public void verify_readComponentSyntaxHighlighting() {
    writer.writeComponentSyntaxHighlighting(
        COMPONENT_REF, of(SYNTAX_HIGHLIGHTING_1, SYNTAX_HIGHLIGHTING_2));

    CloseableIterator<BatchReport.SyntaxHighlighting> res =
        underTest.readComponentSyntaxHighlighting(COMPONENT_REF);
    assertThat(res).containsExactly(SYNTAX_HIGHLIGHTING_1, SYNTAX_HIGHLIGHTING_2);
    res.close();
  }
  @Test
  public void readMetadata_result_is_cached() {
    BatchReport.Metadata metadata = BatchReport.Metadata.newBuilder().build();

    writer.writeMetadata(metadata);

    BatchReport.Metadata res = underTest.readMetadata();
    assertThat(res).isEqualTo(metadata);
    assertThat(underTest.readMetadata()).isSameAs(res);
  }
  @Test(expected = IllegalStateException.class)
  public void fail_when_range_is_defined_on_different_line() throws Exception {
    BatchReportWriter writer = initReport();

    writer.writeComponentSyntaxHighlighting(
        FILE_REF,
        newArrayList(
            BatchReport.SyntaxHighlighting.HighlightingRule.newBuilder()
                .setRange(
                    BatchReport.Range.newBuilder()
                        .setStartLine(1)
                        .setStartOffset(3)
                        .setEndLine(2)
                        .setEndOffset(2)
                        .build())
                .setType(Constants.HighlightingType.ANNOTATION)
                .build()));

    step.execute(
        new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));
  }
  @Test
  public void persist_report_events() throws Exception {
    dbTester.prepareDbUnit(getClass(), "empty.xml");

    File reportDir = temp.newFolder();
    BatchReportWriter writer = new BatchReportWriter(reportDir);
    writer.writeMetadata(
        BatchReport.Metadata.newBuilder()
            .setRootComponentRef(1)
            .setProjectKey("PROJECT_KEY")
            .setAnalysisDate(150000000L)
            .build());

    writer.writeComponent(
        BatchReport.Component.newBuilder()
            .setRef(1)
            .setType(Constants.ComponentType.PROJECT)
            .setUuid("ABCD")
            .setSnapshotId(1000L)
            .addEvent(
                BatchReport.Event.newBuilder()
                    .setName("Red (was Orange)")
                    .setCategory(Constants.EventCategory.ALERT)
                    .setDescription("Open issues > 0")
                    .build())
            .addEvent(
                BatchReport.Event.newBuilder()
                    .setName("Changes in 'Default' (Java)")
                    .setCategory(Constants.EventCategory.PROFILE)
                    .setEventData(
                        "from=2014-10-12T08:36:25+0000;key=java-default;to=2014-10-12T10:36:25+0000")
                    .build())
            .build());

    step.execute(
        new ComputationContext(new BatchReportReader(reportDir), mock(ComponentDto.class)));

    dbTester.assertDbUnit(getClass(), "add_events-result.xml", "events");
  }
  @Override
  public synchronized void blameResult(InputFile file, List<BlameLine> lines) {
    Preconditions.checkNotNull(file);
    Preconditions.checkNotNull(lines);
    Preconditions.checkArgument(
        allFilesToBlame.contains(file),
        "It was not expected to blame file %s",
        file.relativePath());

    if (lines.size() != file.lines()) {
      LOG.debug(
          "Ignoring blame result since provider returned {} blame lines but file {} has {} lines",
          lines.size(),
          file.relativePath(),
          file.lines());
      return;
    }

    BatchComponent batchComponent = componentCache.get(file);
    Builder scmBuilder = BatchReport.Changesets.newBuilder();
    scmBuilder.setComponentRef(batchComponent.batchId());
    Map<String, Integer> changesetsIdByRevision = new HashMap<>();

    int lineId = 1;
    for (BlameLine line : lines) {
      validateLine(line, lineId, file);
      Integer changesetId = changesetsIdByRevision.get(line.revision());
      if (changesetId == null) {
        addChangeset(scmBuilder, line);
        changesetId = scmBuilder.getChangesetCount() - 1;
        changesetsIdByRevision.put(line.revision(), changesetId);
      }
      scmBuilder.addChangesetIndexByLine(changesetId);
      lineId++;
    }
    writer.writeComponentChangesets(scmBuilder.build());
    allFilesToBlame.remove(file);
    count++;
    progressReport.message(count + "/" + total + " files analyzed");
  }
  @Test
  public void verify_readComponent_returns_Component() {
    writer.writeComponent(COMPONENT);

    assertThat(underTest.readComponent(COMPONENT_REF)).isEqualTo(COMPONENT);
  }