From 357f6627467938ee4e16f644b79de0e8fa9d8eef Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Wed, 4 Nov 2015 14:13:57 +0100 Subject: [PATCH] SONAR-6988 Add cross project duplication info in batch report Add duplication blocks Add isCrossProjectDuplicationActivated boolen in metada --- .../protocol/output/BatchReportReader.java | 8 +++ .../protocol/output/BatchReportWriter.java | 6 +++ .../batch/protocol/output/FileStructure.java | 1 + .../src/main/protobuf/batch_report.proto | 13 ++++- .../output/BatchReportReaderTest.java | 52 +++++++++++++++---- .../output/BatchReportWriterTest.java | 46 ++++++++++++---- 6 files changed, 105 insertions(+), 21 deletions(-) diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportReader.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportReader.java index b8d1fb2d42e..cdb1d542fe7 100644 --- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportReader.java +++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportReader.java @@ -91,6 +91,14 @@ public class BatchReportReader { return emptyCloseableIterator(); } + public CloseableIterator readComponentDuplicationBlocks(int componentRef) { + File file = fileStructure.fileFor(FileStructure.Domain.DUPLICATION_BLOCKS, componentRef); + if (fileExists(file)) { + return Protobuf.readStream(file, BatchReport.DuplicationBlock.parser()); + } + return emptyCloseableIterator(); + } + public CloseableIterator readComponentSymbols(int componentRef) { File file = fileStructure.fileFor(FileStructure.Domain.SYMBOLS, componentRef); if (fileExists(file)) { diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java index 8c68fa7fce5..224bfdd6935 100644 --- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java +++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java @@ -98,6 +98,12 @@ public class BatchReportWriter { return file; } + public File writeDuplicationBlocks(int componentRef, Iterable duplicationBlocks) { + File file = fileStructure.fileFor(FileStructure.Domain.DUPLICATION_BLOCKS, componentRef); + Protobuf.writeStream(duplicationBlocks, file, false); + return file; + } + public File writeComponentSymbols(int componentRef, Iterable symbols) { File file = fileStructure.fileFor(FileStructure.Domain.SYMBOLS, componentRef); Protobuf.writeStream(symbols, file, false); diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java index 967a6e39fe3..23575dcdec6 100644 --- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java +++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java @@ -31,6 +31,7 @@ public class FileStructure { COMPONENT("component-", Domain.PB), MEASURES("measures-", Domain.PB), DUPLICATIONS("duplications-", Domain.PB), + DUPLICATION_BLOCKS("duplication-blocks-", Domain.PB), SYNTAX_HIGHLIGHTINGS("syntax-highlightings-", Domain.PB), CHANGESETS("changesets-", Domain.PB), SYMBOLS("symbols-", Domain.PB), diff --git a/sonar-batch-protocol/src/main/protobuf/batch_report.proto b/sonar-batch-protocol/src/main/protobuf/batch_report.proto index ffb4f241b9f..bd5b8727821 100644 --- a/sonar-batch-protocol/src/main/protobuf/batch_report.proto +++ b/sonar-batch-protocol/src/main/protobuf/batch_report.proto @@ -40,6 +40,7 @@ message Metadata { optional string project_key = 2; optional string branch = 3; optional int32 root_component_ref = 4; + optional bool cross_project_duplication_activated = 5; } message ActiveRule { @@ -144,11 +145,21 @@ message Duplication { repeated Duplicate duplicate = 2; } +// Used for cross project duplication +message DuplicationBlock { + repeated int32 hash = 1; + optional int32 index_in_file = 2; + optional int32 start_line = 3; + optional int32 end_line = 4; + optional int32 start_token_index = 5; + optional int32 end_token_index = 6; +} + // Lines start at 1 and line offsets start at 0 message TextRange { // Should never be null optional int32 start_line = 1; - // End line (inclusive). Null means it is same as start line + // End line (inclusive) optional int32 end_line = 2; // If null it means range starts at the first offset of start line optional int32 start_offset = 3; diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportReaderTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportReaderTest.java index c1545c9aae9..50dfd49d6c3 100644 --- a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportReaderTest.java +++ b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportReaderTest.java @@ -23,7 +23,6 @@ import com.google.common.collect.Lists; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; -import java.util.Arrays; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.junit.Before; @@ -33,6 +32,8 @@ import org.junit.rules.TemporaryFolder; import org.sonar.batch.protocol.Constants; import org.sonar.core.util.CloseableIterator; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; public class BatchReportReaderTest { @@ -58,13 +59,15 @@ public class BatchReportReaderTest { BatchReport.Metadata.Builder metadata = BatchReport.Metadata.newBuilder() .setAnalysisDate(15000000L) .setProjectKey("PROJECT_A") - .setRootComponentRef(1); + .setRootComponentRef(1) + .setCrossProjectDuplicationActivated(true); writer.writeMetadata(metadata.build()); BatchReport.Metadata readMetadata = underTest.readMetadata(); assertThat(readMetadata.getAnalysisDate()).isEqualTo(15000000L); assertThat(readMetadata.getProjectKey()).isEqualTo("PROJECT_A"); assertThat(readMetadata.getRootComponentRef()).isEqualTo(1); + assertThat(readMetadata.getCrossProjectDuplicationActivated()).isTrue(); } @Test(expected = IllegalStateException.class) @@ -94,7 +97,7 @@ public class BatchReportReaderTest { BatchReport.Issue issue = BatchReport.Issue.newBuilder() .setLine(50) .build(); - writer.writeComponentIssues(1, Arrays.asList(issue)); + writer.writeComponentIssues(1, asList(issue)); assertThat(underTest.readComponentIssues(1)).hasSize(1); assertThat(underTest.readComponentIssues(200)).isEmpty(); @@ -110,7 +113,7 @@ public class BatchReportReaderTest { BatchReportWriter writer = new BatchReportWriter(dir); BatchReport.Measure.Builder measure = BatchReport.Measure.newBuilder() .setStringValue("value_a"); - writer.writeComponentMeasures(1, Arrays.asList(measure.build())); + writer.writeComponentMeasures(1, asList(measure.build())); assertThat(underTest.readComponentMeasures(1)).hasSize(1); } @@ -159,7 +162,7 @@ public class BatchReportReaderTest { .build()) .build()) .build(); - writer.writeComponentDuplications(1, Arrays.asList(duplication)); + writer.writeComponentDuplications(1, asList(duplication)); BatchReportReader sut = new BatchReportReader(dir); assertThat(sut.readComponentDuplications(1)).hasSize(1); @@ -170,6 +173,33 @@ public class BatchReportReaderTest { assertThat(underTest.readComponentDuplications(UNKNOWN_COMPONENT_REF)).isEmpty(); } + @Test + public void read_duplication_blocks() { + BatchReportWriter writer = new BatchReportWriter(dir); + writer.writeMetadata(BatchReport.Metadata.newBuilder() + .setRootComponentRef(1).build()); + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(1).build()); + + BatchReport.DuplicationBlock duplicationBlock = BatchReport.DuplicationBlock.newBuilder() + .setIndexInFile(1) + .addAllHash(asList(1, 2, 3, 5, 7)) + .setStartLine(1) + .setEndLine(2) + .setStartTokenIndex(10) + .setEndTokenIndex(15) + .build(); + writer.writeDuplicationBlocks(1, singletonList(duplicationBlock)); + + BatchReportReader sut = new BatchReportReader(dir); + assertThat(sut.readComponentDuplicationBlocks(1)).hasSize(1); + } + + @Test + public void empty_list_if_no_duplication_block_found() { + assertThat(underTest.readComponentDuplications(UNKNOWN_COMPONENT_REF)).isEmpty(); + } + @Test public void read_syntax_highlighting() throws Exception { BatchReportWriter writer = new BatchReportWriter(dir); @@ -179,7 +209,7 @@ public class BatchReportReaderTest { writer.writeComponent(BatchReport.Component.newBuilder() .setRef(1).build()); - writer.writeComponentSyntaxHighlighting(1, Arrays.asList( + writer.writeComponentSyntaxHighlighting(1, asList( BatchReport.SyntaxHighlighting.newBuilder() .setRange(BatchReport.TextRange.newBuilder() .setStartLine(1) @@ -211,7 +241,7 @@ public class BatchReportReaderTest { writer.writeComponent(BatchReport.Component.newBuilder() .setRef(1).build()); - writer.writeComponentSymbols(1, Arrays.asList(BatchReport.Symbol.newBuilder() + writer.writeComponentSymbols(1, asList(BatchReport.Symbol.newBuilder() .setDeclaration(BatchReport.TextRange.newBuilder() .setStartLine(1) .setStartOffset(3) @@ -244,7 +274,7 @@ public class BatchReportReaderTest { writer.writeComponent(BatchReport.Component.newBuilder() .setRef(1).build()); - writer.writeComponentCoverage(1, Arrays.asList( + writer.writeComponentCoverage(1, asList( BatchReport.Coverage.newBuilder() .setLine(1) .setConditions(1) @@ -295,7 +325,7 @@ public class BatchReportReaderTest { @Test public void read_tests() throws Exception { BatchReportWriter writer = new BatchReportWriter(dir); - writer.writeTests(1, Arrays.asList( + writer.writeTests(1, asList( BatchReport.Test.newBuilder() .setDurationInMs(60_000) .setStacktrace("stacktrace") @@ -320,11 +350,11 @@ public class BatchReportReaderTest { @Test public void read_coverage_details() throws Exception { BatchReportWriter writer = new BatchReportWriter(dir); - writer.writeCoverageDetails(1, Arrays.asList( + writer.writeCoverageDetails(1, asList( BatchReport.CoverageDetail.newBuilder() .setTestName("test-name") .addCoveredFile(BatchReport.CoverageDetail.CoveredFile.newBuilder() - .addAllCoveredLine(Arrays.asList(1, 2, 3, 5, 7)) + .addAllCoveredLine(asList(1, 2, 3, 5, 7)) .setFileRef(2)) .build())); diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportWriterTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportWriterTest.java index 93a394a59cd..eda7000899b 100644 --- a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportWriterTest.java +++ b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchReportWriterTest.java @@ -21,7 +21,6 @@ package org.sonar.batch.protocol.output; import com.google.common.collect.Iterators; import java.io.File; -import java.util.Arrays; import org.apache.commons.io.FileUtils; import org.junit.Before; import org.junit.Rule; @@ -31,6 +30,7 @@ import org.sonar.batch.protocol.Constants; import org.sonar.core.util.CloseableIterator; import org.sonar.core.util.Protobuf; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; public class BatchReportWriterTest { @@ -105,7 +105,7 @@ public class BatchReportWriterTest { .setMsg("the message") .build(); - underTest.writeComponentIssues(1, Arrays.asList(issue)); + underTest.writeComponentIssues(1, asList(issue)); assertThat(underTest.hasComponentData(FileStructure.Domain.ISSUES, 1)).isTrue(); File file = underTest.getFileStructure().fileFor(FileStructure.Domain.ISSUES, 1); @@ -125,7 +125,7 @@ public class BatchReportWriterTest { .setValueType(Constants.MeasureValueType.DOUBLE) .build(); - underTest.writeComponentMeasures(1, Arrays.asList(measure)); + underTest.writeComponentMeasures(1, asList(measure)); assertThat(underTest.hasComponentData(FileStructure.Domain.MEASURES, 1)).isTrue(); File file = underTest.getFileStructure().fileFor(FileStructure.Domain.MEASURES, 1); @@ -178,7 +178,7 @@ public class BatchReportWriterTest { .build()) .build()) .build(); - underTest.writeComponentDuplications(1, Arrays.asList(duplication)); + underTest.writeComponentDuplications(1, asList(duplication)); assertThat(underTest.hasComponentData(FileStructure.Domain.DUPLICATIONS, 1)).isTrue(); File file = underTest.getFileStructure().fileFor(FileStructure.Domain.DUPLICATIONS, 1); @@ -190,6 +190,34 @@ public class BatchReportWriterTest { } } + @Test + public void write_duplication_blocks() { + assertThat(underTest.hasComponentData(FileStructure.Domain.DUPLICATION_BLOCKS, 1)).isFalse(); + + BatchReport.DuplicationBlock duplicationBlock = BatchReport.DuplicationBlock.newBuilder() + .setIndexInFile(1) + .addAllHash(asList(1, 2, 3, 5, 7)) + .setStartLine(1) + .setEndLine(2) + .setStartTokenIndex(10) + .setEndTokenIndex(15) + .build(); + underTest.writeDuplicationBlocks(1, asList(duplicationBlock)); + + assertThat(underTest.hasComponentData(FileStructure.Domain.DUPLICATION_BLOCKS, 1)).isTrue(); + File file = underTest.getFileStructure().fileFor(FileStructure.Domain.DUPLICATION_BLOCKS, 1); + assertThat(file).exists().isFile(); + try (CloseableIterator duplicationBlocks = Protobuf.readStream(file, BatchReport.DuplicationBlock.parser())) { + BatchReport.DuplicationBlock duplicationBlockResult = duplicationBlocks.next(); + assertThat(duplicationBlockResult.getIndexInFile()).isEqualTo(1); + assertThat(duplicationBlockResult.getHashList()).containsOnly(1, 2, 3, 5, 7); + assertThat(duplicationBlockResult.getStartLine()).isEqualTo(1); + assertThat(duplicationBlockResult.getEndLine()).isEqualTo(2); + assertThat(duplicationBlockResult.getStartTokenIndex()).isEqualTo(10); + assertThat(duplicationBlockResult.getEndTokenIndex()).isEqualTo(15); + } + } + @Test public void write_symbols() { // no data yet @@ -211,7 +239,7 @@ public class BatchReportWriterTest { .build()) .build(); - underTest.writeComponentSymbols(1, Arrays.asList(symbol)); + underTest.writeComponentSymbols(1, asList(symbol)); assertThat(underTest.hasComponentData(FileStructure.Domain.SYMBOLS, 1)).isTrue(); @@ -227,7 +255,7 @@ public class BatchReportWriterTest { // no data yet assertThat(underTest.hasComponentData(FileStructure.Domain.SYNTAX_HIGHLIGHTINGS, 1)).isFalse(); - underTest.writeComponentSyntaxHighlighting(1, Arrays.asList( + underTest.writeComponentSyntaxHighlighting(1, asList( BatchReport.SyntaxHighlighting.newBuilder() .setRange(BatchReport.TextRange.newBuilder() .setStartLine(1) @@ -244,7 +272,7 @@ public class BatchReportWriterTest { // no data yet assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGES, 1)).isFalse(); - underTest.writeComponentCoverage(1, Arrays.asList( + underTest.writeComponentCoverage(1, asList( BatchReport.Coverage.newBuilder() .setLine(1) .setConditions(1) @@ -262,7 +290,7 @@ public class BatchReportWriterTest { public void write_tests() { assertThat(underTest.hasComponentData(FileStructure.Domain.TESTS, 1)).isFalse(); - underTest.writeTests(1, Arrays.asList( + underTest.writeTests(1, asList( BatchReport.Test.getDefaultInstance())); assertThat(underTest.hasComponentData(FileStructure.Domain.TESTS, 1)).isTrue(); @@ -273,7 +301,7 @@ public class BatchReportWriterTest { public void write_coverage_details() { assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGE_DETAILS, 1)).isFalse(); - underTest.writeCoverageDetails(1, Arrays.asList( + underTest.writeCoverageDetails(1, asList( BatchReport.CoverageDetail.getDefaultInstance())); assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGE_DETAILS, 1)).isTrue(); -- 2.39.5