@@ -0,0 +1,14 @@ | |||
#!/bin/bash | |||
# Usage: compile_protobuf <inputDir> <outputDir> | |||
function compile_protobuf { | |||
echo "Compiling [$1] to [$2]..." | |||
mkdir -p $2 | |||
protoc --proto_path=$1 --java_out=$2 $1/*.proto | |||
} | |||
compile_protobuf "sonar-core/src/test/protobuf" "sonar-core/src/test/gen-java" | |||
compile_protobuf "sonar-batch-protocol/src/main/protobuf" "sonar-batch-protocol/src/main/gen-java" | |||
@@ -1,6 +0,0 @@ | |||
#!/bin/sh | |||
OUTPUT_DIR="src/main/gen-java" | |||
mkdir -p ${OUTPUT_DIR} | |||
protoc --proto_path=src/main/protobuf --java_out=${OUTPUT_DIR} src/main/protobuf/*.proto |
@@ -1,121 +0,0 @@ | |||
/* | |||
* 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.batch.protocol; | |||
import com.google.protobuf.InvalidProtocolBufferException; | |||
import com.google.protobuf.Message; | |||
import com.google.protobuf.Parser; | |||
import java.io.BufferedInputStream; | |||
import java.io.BufferedOutputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileNotFoundException; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import org.apache.commons.io.IOUtils; | |||
import org.sonar.core.util.CloseableIterator; | |||
import static java.lang.String.format; | |||
public class ProtobufUtil { | |||
private ProtobufUtil() { | |||
// only static stuff | |||
} | |||
/** | |||
* Returns the message contained in the given file. Throws an unchecked exception | |||
* if the file does not exist or is empty. | |||
*/ | |||
public static <MSG extends Message> MSG readFile(File file, Parser<MSG> parser) { | |||
InputStream input = null; | |||
try { | |||
input = new BufferedInputStream(new FileInputStream(file)); | |||
return parser.parseFrom(input); | |||
} catch (IOException e) { | |||
throw new IllegalStateException(format("Unable to read file %s", file), e); | |||
} finally { | |||
IOUtils.closeQuietly(input); | |||
} | |||
} | |||
/** | |||
* Writes a single message to a file, by replacing existing content. The message is | |||
* NOT appended. | |||
*/ | |||
public static void writeToFile(Message message, File toFile) { | |||
OutputStream out = null; | |||
try { | |||
out = new BufferedOutputStream(new FileOutputStream(toFile, false)); | |||
message.writeTo(out); | |||
} catch (IOException e) { | |||
throw new IllegalStateException(format("Unable to write protobuf message to file %s", toFile), e); | |||
} finally { | |||
IOUtils.closeQuietly(out); | |||
} | |||
} | |||
public static void writeStreamToFile(Iterable<? extends Message> messages, File toFile, boolean append) { | |||
OutputStream out = null; | |||
try { | |||
out = new BufferedOutputStream(new FileOutputStream(toFile, append)); | |||
for (Message message : messages) { | |||
message.writeDelimitedTo(out); | |||
} | |||
} catch (IOException e) { | |||
throw new IllegalStateException(format("Unable to write protobuf messages to file %s", toFile), e); | |||
} finally { | |||
IOUtils.closeQuietly(out); | |||
} | |||
} | |||
public static <MSG extends Message> CloseableIterator<MSG> readStreamFromFile(File file, Parser<MSG> parser) { | |||
try { | |||
return new ProtobufIterator<>(parser, new BufferedInputStream(new FileInputStream(file))); | |||
} catch (FileNotFoundException e) { | |||
throw new IllegalStateException(format("Unable to read protobuf file %s", file), e); | |||
} | |||
} | |||
private static class ProtobufIterator<MSG extends Message> extends CloseableIterator<MSG> { | |||
private final Parser<MSG> parser; | |||
private final InputStream input; | |||
private ProtobufIterator(Parser<MSG> parser, InputStream input) { | |||
this.parser = parser; | |||
this.input = input; | |||
} | |||
@Override | |||
protected MSG doNext() { | |||
try { | |||
return parser.parseDelimitedFrom(input); | |||
} catch (InvalidProtocolBufferException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
@Override | |||
protected void doClose() throws Exception { | |||
IOUtils.closeQuietly(input); | |||
} | |||
} | |||
} |
@@ -21,8 +21,8 @@ package org.sonar.batch.protocol.output; | |||
import java.io.File; | |||
import javax.annotation.CheckForNull; | |||
import org.sonar.batch.protocol.ProtobufUtil; | |||
import org.sonar.core.util.CloseableIterator; | |||
import org.sonar.core.util.Protobuf; | |||
public class BatchReportReader { | |||
@@ -37,7 +37,7 @@ public class BatchReportReader { | |||
if (!fileExists(file)) { | |||
throw new IllegalStateException("Metadata file is missing in analysis report: " + file); | |||
} | |||
return ProtobufUtil.readFile(file, BatchReport.Metadata.PARSER); | |||
return Protobuf.read(file, BatchReport.Metadata.PARSER); | |||
} | |||
public CloseableIterator<BatchReport.ActiveRule> readActiveRules() { | |||
@@ -45,13 +45,13 @@ public class BatchReportReader { | |||
if (!fileExists(file)) { | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} | |||
return ProtobufUtil.readStreamFromFile(file, BatchReport.ActiveRule.PARSER); | |||
return Protobuf.readStream(file, BatchReport.ActiveRule.PARSER); | |||
} | |||
public CloseableIterator<BatchReport.Measure> readComponentMeasures(int componentRef) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.MEASURES, componentRef); | |||
if (fileExists(file)) { | |||
return ProtobufUtil.readStreamFromFile(file, BatchReport.Measure.PARSER); | |||
return Protobuf.readStream(file, BatchReport.Measure.PARSER); | |||
} | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} | |||
@@ -60,7 +60,7 @@ public class BatchReportReader { | |||
public BatchReport.Changesets readChangesets(int componentRef) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.CHANGESETS, componentRef); | |||
if (fileExists(file)) { | |||
return ProtobufUtil.readFile(file, BatchReport.Changesets.PARSER); | |||
return Protobuf.read(file, BatchReport.Changesets.PARSER); | |||
} | |||
return null; | |||
} | |||
@@ -70,13 +70,13 @@ public class BatchReportReader { | |||
if (!fileExists(file)) { | |||
throw new IllegalStateException("Unable to find report for component #" + componentRef + ". File does not exist: " + file); | |||
} | |||
return ProtobufUtil.readFile(file, BatchReport.Component.PARSER); | |||
return Protobuf.read(file, BatchReport.Component.PARSER); | |||
} | |||
public CloseableIterator<BatchReport.Issue> readComponentIssues(int componentRef) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.ISSUES, componentRef); | |||
if (fileExists(file)) { | |||
return ProtobufUtil.readStreamFromFile(file, BatchReport.Issue.PARSER); | |||
return Protobuf.readStream(file, BatchReport.Issue.PARSER); | |||
} | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} | |||
@@ -84,7 +84,7 @@ public class BatchReportReader { | |||
public CloseableIterator<BatchReport.Duplication> readComponentDuplications(int componentRef) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.DUPLICATIONS, componentRef); | |||
if (fileExists(file)) { | |||
return ProtobufUtil.readStreamFromFile(file, BatchReport.Duplication.PARSER); | |||
return Protobuf.readStream(file, BatchReport.Duplication.PARSER); | |||
} | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} | |||
@@ -92,7 +92,7 @@ public class BatchReportReader { | |||
public CloseableIterator<BatchReport.Symbol> readComponentSymbols(int componentRef) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.SYMBOLS, componentRef); | |||
if (fileExists(file)) { | |||
return ProtobufUtil.readStreamFromFile(file, BatchReport.Symbol.PARSER); | |||
return Protobuf.readStream(file, BatchReport.Symbol.PARSER); | |||
} | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} |
@@ -20,7 +20,7 @@ | |||
package org.sonar.batch.protocol.output; | |||
import java.io.File; | |||
import org.sonar.batch.protocol.ProtobufUtil; | |||
import org.sonar.core.util.Protobuf; | |||
public class BatchReportWriter { | |||
@@ -46,72 +46,72 @@ public class BatchReportWriter { | |||
* Metadata is mandatory | |||
*/ | |||
public File writeMetadata(BatchReport.Metadata metadata) { | |||
ProtobufUtil.writeToFile(metadata, fileStructure.metadataFile()); | |||
Protobuf.write(metadata, fileStructure.metadataFile()); | |||
return fileStructure.metadataFile(); | |||
} | |||
public File writeActiveRules(Iterable<BatchReport.ActiveRule> activeRules) { | |||
ProtobufUtil.writeStreamToFile(activeRules, fileStructure.activeRules(), false); | |||
Protobuf.writeStream(activeRules, fileStructure.activeRules(), false); | |||
return fileStructure.metadataFile(); | |||
} | |||
public File writeComponent(BatchReport.Component component) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.COMPONENT, component.getRef()); | |||
ProtobufUtil.writeToFile(component, file); | |||
Protobuf.write(component, file); | |||
return file; | |||
} | |||
public File writeComponentIssues(int componentRef, Iterable<BatchReport.Issue> issues) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.ISSUES, componentRef); | |||
ProtobufUtil.writeStreamToFile(issues, file, false); | |||
Protobuf.writeStream(issues, file, false); | |||
return file; | |||
} | |||
public File writeComponentMeasures(int componentRef, Iterable<BatchReport.Measure> measures) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.MEASURES, componentRef); | |||
ProtobufUtil.writeStreamToFile(measures, file, false); | |||
Protobuf.writeStream(measures, file, false); | |||
return file; | |||
} | |||
public File writeComponentChangesets(BatchReport.Changesets changesets) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.CHANGESETS, changesets.getComponentRef()); | |||
ProtobufUtil.writeToFile(changesets, file); | |||
Protobuf.write(changesets, file); | |||
return file; | |||
} | |||
public File writeComponentDuplications(int componentRef, Iterable<BatchReport.Duplication> duplications) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.DUPLICATIONS, componentRef); | |||
ProtobufUtil.writeStreamToFile(duplications, file, false); | |||
Protobuf.writeStream(duplications, file, false); | |||
return file; | |||
} | |||
public File writeComponentSymbols(int componentRef, Iterable<BatchReport.Symbol> symbols) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.SYMBOLS, componentRef); | |||
ProtobufUtil.writeStreamToFile(symbols, file, false); | |||
Protobuf.writeStream(symbols, file, false); | |||
return file; | |||
} | |||
public File writeComponentSyntaxHighlighting(int componentRef, Iterable<BatchReport.SyntaxHighlighting> syntaxHighlightingRules) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.SYNTAX_HIGHLIGHTINGS, componentRef); | |||
ProtobufUtil.writeStreamToFile(syntaxHighlightingRules, file, false); | |||
Protobuf.writeStream(syntaxHighlightingRules, file, false); | |||
return file; | |||
} | |||
public File writeComponentCoverage(int componentRef, Iterable<BatchReport.Coverage> coverageList) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.COVERAGES, componentRef); | |||
ProtobufUtil.writeStreamToFile(coverageList, file, false); | |||
Protobuf.writeStream(coverageList, file, false); | |||
return file; | |||
} | |||
public File writeTests(int componentRef, Iterable<BatchReport.Test> tests) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.TESTS, componentRef); | |||
ProtobufUtil.writeStreamToFile(tests, file, false); | |||
Protobuf.writeStream(tests, file, false); | |||
return file; | |||
} | |||
public File writeCoverageDetails(int componentRef, Iterable<BatchReport.CoverageDetail> tests) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.COVERAGE_DETAILS, componentRef); | |||
ProtobufUtil.writeStreamToFile(tests, file, false); | |||
Protobuf.writeStream(tests, file, false); | |||
return file; | |||
} | |||
@@ -1,71 +0,0 @@ | |||
/* | |||
* 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.batch.protocol; | |||
import java.io.File; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.batch.protocol.output.BatchReport; | |||
import org.sonar.test.TestUtils; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class ProtobufUtilTest { | |||
@Rule | |||
public ExpectedException thrown = ExpectedException.none(); | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@Test | |||
public void only_utils() { | |||
assertThat(TestUtils.hasOnlyPrivateConstructors(ProtobufUtil.class)); | |||
} | |||
@Test | |||
public void readFile_fails_if_file_does_not_exist() throws Exception { | |||
thrown.expect(IllegalStateException.class); | |||
File file = temp.newFile(); | |||
FileUtils.forceDelete(file); | |||
ProtobufUtil.readFile(file, BatchReport.Metadata.PARSER); | |||
} | |||
@Test | |||
public void readFile_returns_empty_message_if_file_is_empty() throws Exception { | |||
File file = temp.newFile(); | |||
BatchReport.Metadata msg = ProtobufUtil.readFile(file, BatchReport.Metadata.PARSER); | |||
assertThat(msg).isNotNull(); | |||
assertThat(msg.isInitialized()).isTrue(); | |||
} | |||
@Test | |||
public void readFile_returns_message() throws Exception { | |||
File file = temp.newFile(); | |||
ProtobufUtil.writeToFile(BatchReport.Metadata.getDefaultInstance(), file); | |||
BatchReport.Metadata message = ProtobufUtil.readFile(file, BatchReport.Metadata.PARSER); | |||
assertThat(message).isNotNull(); | |||
assertThat(message.isInitialized()).isTrue(); | |||
} | |||
} |
@@ -28,9 +28,9 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.batch.protocol.Constants; | |||
import org.sonar.batch.protocol.ProtobufUtil; | |||
import org.sonar.batch.protocol.output.BatchReport.Range; | |||
import org.sonar.core.util.CloseableIterator; | |||
import org.sonar.core.util.Protobuf; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -63,7 +63,7 @@ public class BatchReportWriterTest { | |||
.setRootComponentRef(1); | |||
underTest.writeMetadata(metadata.build()); | |||
BatchReport.Metadata read = ProtobufUtil.readFile(underTest.getFileStructure().metadataFile(), BatchReport.Metadata.PARSER); | |||
BatchReport.Metadata read = Protobuf.read(underTest.getFileStructure().metadataFile(), BatchReport.Metadata.PARSER); | |||
assertThat(read.getAnalysisDate()).isEqualTo(15000000L); | |||
assertThat(read.getProjectKey()).isEqualTo("PROJECT_A"); | |||
assertThat(read.getRootComponentRef()).isEqualTo(1); | |||
@@ -88,7 +88,7 @@ public class BatchReportWriterTest { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isTrue(); | |||
File file = underTest.getFileStructure().fileFor(FileStructure.Domain.COMPONENT, 1); | |||
assertThat(file).exists().isFile(); | |||
BatchReport.Component read = ProtobufUtil.readFile(file, BatchReport.Component.PARSER); | |||
BatchReport.Component read = Protobuf.read(file, BatchReport.Component.PARSER); | |||
assertThat(read.getRef()).isEqualTo(1); | |||
assertThat(read.getChildRefList()).containsOnly(5, 42); | |||
assertThat(read.hasName()).isFalse(); | |||
@@ -111,7 +111,7 @@ public class BatchReportWriterTest { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.ISSUES, 1)).isTrue(); | |||
File file = underTest.getFileStructure().fileFor(FileStructure.Domain.ISSUES, 1); | |||
assertThat(file).exists().isFile(); | |||
try (CloseableIterator<BatchReport.Issue> read = ProtobufUtil.readStreamFromFile(file, BatchReport.Issue.PARSER)) { | |||
try (CloseableIterator<BatchReport.Issue> read = Protobuf.readStream(file, BatchReport.Issue.PARSER)) { | |||
assertThat(Iterators.size(read)).isEqualTo(1); | |||
} | |||
} | |||
@@ -131,7 +131,7 @@ public class BatchReportWriterTest { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.MEASURES, 1)).isTrue(); | |||
File file = underTest.getFileStructure().fileFor(FileStructure.Domain.MEASURES, 1); | |||
assertThat(file).exists().isFile(); | |||
try (CloseableIterator<BatchReport.Measure> read = ProtobufUtil.readStreamFromFile(file, BatchReport.Measure.PARSER)) { | |||
try (CloseableIterator<BatchReport.Measure> read = Protobuf.readStream(file, BatchReport.Measure.PARSER)) { | |||
assertThat(Iterators.size(read)).isEqualTo(1); | |||
} | |||
} | |||
@@ -154,7 +154,7 @@ public class BatchReportWriterTest { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.CHANGESETS, 1)).isTrue(); | |||
File file = underTest.getFileStructure().fileFor(FileStructure.Domain.CHANGESETS, 1); | |||
assertThat(file).exists().isFile(); | |||
BatchReport.Changesets read = ProtobufUtil.readFile(file, BatchReport.Changesets.PARSER); | |||
BatchReport.Changesets read = Protobuf.read(file, BatchReport.Changesets.PARSER); | |||
assertThat(read.getComponentRef()).isEqualTo(1); | |||
assertThat(read.getChangesetCount()).isEqualTo(1); | |||
assertThat(read.getChangesetList()).hasSize(1); | |||
@@ -184,7 +184,7 @@ public class BatchReportWriterTest { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.DUPLICATIONS, 1)).isTrue(); | |||
File file = underTest.getFileStructure().fileFor(FileStructure.Domain.DUPLICATIONS, 1); | |||
assertThat(file).exists().isFile(); | |||
try (CloseableIterator<BatchReport.Duplication> duplications = ProtobufUtil.readStreamFromFile(file, BatchReport.Duplication.PARSER)) { | |||
try (CloseableIterator<BatchReport.Duplication> duplications = Protobuf.readStream(file, BatchReport.Duplication.PARSER)) { | |||
BatchReport.Duplication dup = duplications.next(); | |||
assertThat(dup.getOriginPosition()).isNotNull(); | |||
assertThat(dup.getDuplicateList()).hasSize(1); | |||
@@ -218,7 +218,7 @@ public class BatchReportWriterTest { | |||
File file = underTest.getFileStructure().fileFor(FileStructure.Domain.SYMBOLS, 1); | |||
assertThat(file).exists().isFile(); | |||
try (CloseableIterator<BatchReport.Symbol> read = ProtobufUtil.readStreamFromFile(file, BatchReport.Symbol.PARSER)) { | |||
try (CloseableIterator<BatchReport.Symbol> read = Protobuf.readStream(file, BatchReport.Symbol.PARSER)) { | |||
assertThat(read).hasSize(1); | |||
} | |||
} | |||
@@ -235,8 +235,7 @@ public class BatchReportWriterTest { | |||
.setEndLine(1) | |||
.build()) | |||
.setType(Constants.HighlightingType.ANNOTATION) | |||
.build() | |||
)); | |||
.build())); | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.SYNTAX_HIGHLIGHTINGS, 1)).isTrue(); | |||
} | |||
@@ -255,8 +254,7 @@ public class BatchReportWriterTest { | |||
.setUtCoveredConditions(1) | |||
.setItCoveredConditions(1) | |||
.setOverallCoveredConditions(1) | |||
.build() | |||
)); | |||
.build())); | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGES, 1)).isTrue(); | |||
} | |||
@@ -266,8 +264,7 @@ public class BatchReportWriterTest { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.TESTS, 1)).isFalse(); | |||
underTest.writeTests(1, Arrays.asList( | |||
BatchReport.Test.getDefaultInstance() | |||
)); | |||
BatchReport.Test.getDefaultInstance())); | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.TESTS, 1)).isTrue(); | |||
@@ -278,8 +275,7 @@ public class BatchReportWriterTest { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGE_DETAILS, 1)).isFalse(); | |||
underTest.writeCoverageDetails(1, Arrays.asList( | |||
BatchReport.CoverageDetail.getDefaultInstance() | |||
)); | |||
BatchReport.CoverageDetail.getDefaultInstance())); | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGE_DETAILS, 1)).isTrue(); | |||
} |
@@ -22,6 +22,7 @@ package org.sonar.batch.report; | |||
import java.io.File; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
import org.apache.commons.lang.exception.ExceptionUtils; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
@@ -42,6 +43,7 @@ import org.sonar.core.util.CloseableIterator; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.Assert.fail; | |||
import static org.mockito.Matchers.any; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
@@ -106,16 +108,18 @@ public class MeasuresPublisherTest { | |||
@Test | |||
public void fail_with_IAE_when_measure_has_no_value() throws Exception { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Measure on metric 'coverage' and component 'foo:src/Foo.php' has no value, but it's not allowed"); | |||
Measure measure = new Measure<>(CoreMetrics.COVERAGE); | |||
when(measureCache.byResource(sampleFile)).thenReturn(Collections.singletonList(measure)); | |||
File outputDir = temp.newFolder(); | |||
BatchReportWriter writer = new BatchReportWriter(outputDir); | |||
publisher.publish(writer); | |||
try { | |||
publisher.publish(writer); | |||
fail(); | |||
} catch (RuntimeException e) { | |||
assertThat(ExceptionUtils.getFullStackTrace(e)).contains("Measure on metric 'coverage' and component 'foo:src/Foo.php' has no value, but it's not allowed"); | |||
} | |||
} | |||
} |
@@ -27,6 +27,10 @@ | |||
<groupId>org.picocontainer</groupId> | |||
<artifactId>picocontainer</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.google.protobuf</groupId> | |||
<artifactId>protobuf-java</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.codehaus.sonar</groupId> | |||
<artifactId>sonar-classloader</artifactId> | |||
@@ -106,6 +110,25 @@ | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.codehaus.mojo</groupId> | |||
<artifactId>build-helper-maven-plugin</artifactId> | |||
<executions> | |||
<execution> | |||
<id>add-test-source</id> | |||
<phase>generate-test-sources</phase> | |||
<goals> | |||
<goal>add-test-source</goal> | |||
</goals> | |||
<configuration> | |||
<sources> | |||
<source>src/test/gen-java</source> | |||
</sources> | |||
</configuration> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-dependency-plugin</artifactId> |
@@ -0,0 +1,162 @@ | |||
/* | |||
* 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.core.util; | |||
import com.google.protobuf.InvalidProtocolBufferException; | |||
import com.google.protobuf.Message; | |||
import com.google.protobuf.Parser; | |||
import java.io.BufferedInputStream; | |||
import java.io.BufferedOutputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import org.apache.commons.io.IOUtils; | |||
/** | |||
* Utility to read and write Protocol Buffers messages | |||
*/ | |||
public class Protobuf { | |||
private Protobuf() { | |||
// only static stuff | |||
} | |||
/** | |||
* Returns the message contained in {@code file}. Throws an unchecked exception | |||
* if the file does not exist, is empty or does not contain message with the | |||
* expected type. | |||
*/ | |||
public static <MSG extends Message> MSG read(File file, Parser<MSG> parser) { | |||
InputStream input = null; | |||
try { | |||
input = new BufferedInputStream(new FileInputStream(file)); | |||
return parser.parseFrom(input); | |||
} catch (Exception e) { | |||
throw ContextException.of("Unable to read message", e).addContext("file", file); | |||
} finally { | |||
IOUtils.closeQuietly(input); | |||
} | |||
} | |||
/** | |||
* Writes a single message to {@code file}. Existing content is replaced, the message is not | |||
* appended. | |||
*/ | |||
public static void write(Message message, File toFile) { | |||
OutputStream out = null; | |||
try { | |||
out = new BufferedOutputStream(new FileOutputStream(toFile, false)); | |||
message.writeTo(out); | |||
} catch (Exception e) { | |||
throw ContextException.of("Unable to write message", e).addContext("file", toFile); | |||
} finally { | |||
IOUtils.closeQuietly(out); | |||
} | |||
} | |||
/** | |||
* Streams multiple messages to {@code file}. Reading the messages back requires to | |||
* call methods {@code readStream(...)}. | |||
* <p> | |||
* See https://developers.google.com/protocol-buffers/docs/techniques#streaming | |||
* </p> | |||
*/ | |||
public static <MSG extends Message> void writeStream(Iterable<MSG> messages, File toFile, boolean append) { | |||
OutputStream out = null; | |||
try { | |||
out = new BufferedOutputStream(new FileOutputStream(toFile, append)); | |||
writeStream(messages, out); | |||
} catch (Exception e) { | |||
throw ContextException.of("Unable to write messages", e).addContext("file", toFile); | |||
} finally { | |||
IOUtils.closeQuietly(out); | |||
} | |||
} | |||
/** | |||
* Streams multiple messages to {@code output}. Reading the messages back requires to | |||
* call methods {@code readStream(...)}. | |||
* <p> | |||
* See https://developers.google.com/protocol-buffers/docs/techniques#streaming | |||
* </p> | |||
*/ | |||
public static <MSG extends Message> void writeStream(Iterable<MSG> messages, OutputStream output) { | |||
try { | |||
for (Message message : messages) { | |||
message.writeDelimitedTo(output); | |||
} | |||
} catch (Exception e) { | |||
throw ContextException.of("Unable to write messages", e); | |||
} | |||
} | |||
/** | |||
* Reads a stream of messages. This method returns an empty iterator if there are no messages. An | |||
* exception is raised on IO error, if file does not exist or if messages have a | |||
* different type than {@code parser}. | |||
*/ | |||
public static <MSG extends Message> CloseableIterator<MSG> readStream(File file, Parser<MSG> parser) { | |||
try { | |||
// the input stream is closed by the CloseableIterator | |||
BufferedInputStream input = new BufferedInputStream(new FileInputStream(file)); | |||
return readStream(input, parser); | |||
} catch (Exception e) { | |||
throw ContextException.of("Unable to read messages", e).addContext("file", file); | |||
} | |||
} | |||
/** | |||
* Reads a stream of messages. This method returns an empty iterator if there are no messages. An | |||
* exception is raised on IO error or if messages have a different type than {@code parser}. | |||
* <p> | |||
* The stream is not closed by this method. It is closed when {@link CloseableIterator} traverses | |||
* all messages or when {@link CloseableIterator#close()} is called. | |||
* </p> | |||
*/ | |||
public static <MSG extends Message> CloseableIterator<MSG> readStream(InputStream input, Parser<MSG> parser) { | |||
// the stream is closed by the CloseableIterator | |||
return new StreamIterator<>(parser, input); | |||
} | |||
private static class StreamIterator<MSG extends Message> extends CloseableIterator<MSG> { | |||
private final Parser<MSG> parser; | |||
private final InputStream input; | |||
private StreamIterator(Parser<MSG> parser, InputStream input) { | |||
this.parser = parser; | |||
this.input = input; | |||
} | |||
@Override | |||
protected MSG doNext() { | |||
try { | |||
return parser.parsePartialDelimitedFrom(input); | |||
} catch (InvalidProtocolBufferException e) { | |||
throw ContextException.of(e); | |||
} | |||
} | |||
@Override | |||
protected void doClose() { | |||
IOUtils.closeQuietly(input); | |||
} | |||
} | |||
} |
@@ -0,0 +1,603 @@ | |||
// Generated by the protocol buffer compiler. DO NOT EDIT! | |||
// source: test.proto | |||
package org.sonar.core.test; | |||
public final class Test { | |||
private Test() {} | |||
public static void registerAllExtensions( | |||
com.google.protobuf.ExtensionRegistry registry) { | |||
} | |||
public interface FakeOrBuilder extends | |||
// @@protoc_insertion_point(interface_extends:Fake) | |||
com.google.protobuf.MessageOrBuilder { | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
boolean hasKey(); | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
java.lang.String getKey(); | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
com.google.protobuf.ByteString | |||
getKeyBytes(); | |||
/** | |||
* <code>optional int32 line = 2;</code> | |||
*/ | |||
boolean hasLine(); | |||
/** | |||
* <code>optional int32 line = 2;</code> | |||
*/ | |||
int getLine(); | |||
} | |||
/** | |||
* Protobuf type {@code Fake} | |||
*/ | |||
public static final class Fake extends | |||
com.google.protobuf.GeneratedMessage implements | |||
// @@protoc_insertion_point(message_implements:Fake) | |||
FakeOrBuilder { | |||
// Use Fake.newBuilder() to construct. | |||
private Fake(com.google.protobuf.GeneratedMessage.Builder<?> builder) { | |||
super(builder); | |||
this.unknownFields = builder.getUnknownFields(); | |||
} | |||
private Fake(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } | |||
private static final Fake defaultInstance; | |||
public static Fake getDefaultInstance() { | |||
return defaultInstance; | |||
} | |||
public Fake getDefaultInstanceForType() { | |||
return defaultInstance; | |||
} | |||
private final com.google.protobuf.UnknownFieldSet unknownFields; | |||
@java.lang.Override | |||
public final com.google.protobuf.UnknownFieldSet | |||
getUnknownFields() { | |||
return this.unknownFields; | |||
} | |||
private Fake( | |||
com.google.protobuf.CodedInputStream input, | |||
com.google.protobuf.ExtensionRegistryLite extensionRegistry) | |||
throws com.google.protobuf.InvalidProtocolBufferException { | |||
initFields(); | |||
int mutable_bitField0_ = 0; | |||
com.google.protobuf.UnknownFieldSet.Builder unknownFields = | |||
com.google.protobuf.UnknownFieldSet.newBuilder(); | |||
try { | |||
boolean done = false; | |||
while (!done) { | |||
int tag = input.readTag(); | |||
switch (tag) { | |||
case 0: | |||
done = true; | |||
break; | |||
default: { | |||
if (!parseUnknownField(input, unknownFields, | |||
extensionRegistry, tag)) { | |||
done = true; | |||
} | |||
break; | |||
} | |||
case 10: { | |||
com.google.protobuf.ByteString bs = input.readBytes(); | |||
bitField0_ |= 0x00000001; | |||
key_ = bs; | |||
break; | |||
} | |||
case 16: { | |||
bitField0_ |= 0x00000002; | |||
line_ = input.readInt32(); | |||
break; | |||
} | |||
} | |||
} | |||
} catch (com.google.protobuf.InvalidProtocolBufferException e) { | |||
throw e.setUnfinishedMessage(this); | |||
} catch (java.io.IOException e) { | |||
throw new com.google.protobuf.InvalidProtocolBufferException( | |||
e.getMessage()).setUnfinishedMessage(this); | |||
} finally { | |||
this.unknownFields = unknownFields.build(); | |||
makeExtensionsImmutable(); | |||
} | |||
} | |||
public static final com.google.protobuf.Descriptors.Descriptor | |||
getDescriptor() { | |||
return org.sonar.core.test.Test.internal_static_Fake_descriptor; | |||
} | |||
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable | |||
internalGetFieldAccessorTable() { | |||
return org.sonar.core.test.Test.internal_static_Fake_fieldAccessorTable | |||
.ensureFieldAccessorsInitialized( | |||
org.sonar.core.test.Test.Fake.class, org.sonar.core.test.Test.Fake.Builder.class); | |||
} | |||
public static com.google.protobuf.Parser<Fake> PARSER = | |||
new com.google.protobuf.AbstractParser<Fake>() { | |||
public Fake parsePartialFrom( | |||
com.google.protobuf.CodedInputStream input, | |||
com.google.protobuf.ExtensionRegistryLite extensionRegistry) | |||
throws com.google.protobuf.InvalidProtocolBufferException { | |||
return new Fake(input, extensionRegistry); | |||
} | |||
}; | |||
@java.lang.Override | |||
public com.google.protobuf.Parser<Fake> getParserForType() { | |||
return PARSER; | |||
} | |||
private int bitField0_; | |||
public static final int KEY_FIELD_NUMBER = 1; | |||
private java.lang.Object key_; | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
public boolean hasKey() { | |||
return ((bitField0_ & 0x00000001) == 0x00000001); | |||
} | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
public java.lang.String getKey() { | |||
java.lang.Object ref = key_; | |||
if (ref instanceof java.lang.String) { | |||
return (java.lang.String) ref; | |||
} else { | |||
com.google.protobuf.ByteString bs = | |||
(com.google.protobuf.ByteString) ref; | |||
java.lang.String s = bs.toStringUtf8(); | |||
if (bs.isValidUtf8()) { | |||
key_ = s; | |||
} | |||
return s; | |||
} | |||
} | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
public com.google.protobuf.ByteString | |||
getKeyBytes() { | |||
java.lang.Object ref = key_; | |||
if (ref instanceof java.lang.String) { | |||
com.google.protobuf.ByteString b = | |||
com.google.protobuf.ByteString.copyFromUtf8( | |||
(java.lang.String) ref); | |||
key_ = b; | |||
return b; | |||
} else { | |||
return (com.google.protobuf.ByteString) ref; | |||
} | |||
} | |||
public static final int LINE_FIELD_NUMBER = 2; | |||
private int line_; | |||
/** | |||
* <code>optional int32 line = 2;</code> | |||
*/ | |||
public boolean hasLine() { | |||
return ((bitField0_ & 0x00000002) == 0x00000002); | |||
} | |||
/** | |||
* <code>optional int32 line = 2;</code> | |||
*/ | |||
public int getLine() { | |||
return line_; | |||
} | |||
private void initFields() { | |||
key_ = ""; | |||
line_ = 0; | |||
} | |||
private byte memoizedIsInitialized = -1; | |||
public final boolean isInitialized() { | |||
byte isInitialized = memoizedIsInitialized; | |||
if (isInitialized == 1) return true; | |||
if (isInitialized == 0) return false; | |||
memoizedIsInitialized = 1; | |||
return true; | |||
} | |||
public void writeTo(com.google.protobuf.CodedOutputStream output) | |||
throws java.io.IOException { | |||
getSerializedSize(); | |||
if (((bitField0_ & 0x00000001) == 0x00000001)) { | |||
output.writeBytes(1, getKeyBytes()); | |||
} | |||
if (((bitField0_ & 0x00000002) == 0x00000002)) { | |||
output.writeInt32(2, line_); | |||
} | |||
getUnknownFields().writeTo(output); | |||
} | |||
private int memoizedSerializedSize = -1; | |||
public int getSerializedSize() { | |||
int size = memoizedSerializedSize; | |||
if (size != -1) return size; | |||
size = 0; | |||
if (((bitField0_ & 0x00000001) == 0x00000001)) { | |||
size += com.google.protobuf.CodedOutputStream | |||
.computeBytesSize(1, getKeyBytes()); | |||
} | |||
if (((bitField0_ & 0x00000002) == 0x00000002)) { | |||
size += com.google.protobuf.CodedOutputStream | |||
.computeInt32Size(2, line_); | |||
} | |||
size += getUnknownFields().getSerializedSize(); | |||
memoizedSerializedSize = size; | |||
return size; | |||
} | |||
private static final long serialVersionUID = 0L; | |||
@java.lang.Override | |||
protected java.lang.Object writeReplace() | |||
throws java.io.ObjectStreamException { | |||
return super.writeReplace(); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseFrom( | |||
com.google.protobuf.ByteString data) | |||
throws com.google.protobuf.InvalidProtocolBufferException { | |||
return PARSER.parseFrom(data); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseFrom( | |||
com.google.protobuf.ByteString data, | |||
com.google.protobuf.ExtensionRegistryLite extensionRegistry) | |||
throws com.google.protobuf.InvalidProtocolBufferException { | |||
return PARSER.parseFrom(data, extensionRegistry); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseFrom(byte[] data) | |||
throws com.google.protobuf.InvalidProtocolBufferException { | |||
return PARSER.parseFrom(data); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseFrom( | |||
byte[] data, | |||
com.google.protobuf.ExtensionRegistryLite extensionRegistry) | |||
throws com.google.protobuf.InvalidProtocolBufferException { | |||
return PARSER.parseFrom(data, extensionRegistry); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseFrom(java.io.InputStream input) | |||
throws java.io.IOException { | |||
return PARSER.parseFrom(input); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseFrom( | |||
java.io.InputStream input, | |||
com.google.protobuf.ExtensionRegistryLite extensionRegistry) | |||
throws java.io.IOException { | |||
return PARSER.parseFrom(input, extensionRegistry); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseDelimitedFrom(java.io.InputStream input) | |||
throws java.io.IOException { | |||
return PARSER.parseDelimitedFrom(input); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseDelimitedFrom( | |||
java.io.InputStream input, | |||
com.google.protobuf.ExtensionRegistryLite extensionRegistry) | |||
throws java.io.IOException { | |||
return PARSER.parseDelimitedFrom(input, extensionRegistry); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseFrom( | |||
com.google.protobuf.CodedInputStream input) | |||
throws java.io.IOException { | |||
return PARSER.parseFrom(input); | |||
} | |||
public static org.sonar.core.test.Test.Fake parseFrom( | |||
com.google.protobuf.CodedInputStream input, | |||
com.google.protobuf.ExtensionRegistryLite extensionRegistry) | |||
throws java.io.IOException { | |||
return PARSER.parseFrom(input, extensionRegistry); | |||
} | |||
public static Builder newBuilder() { return Builder.create(); } | |||
public Builder newBuilderForType() { return newBuilder(); } | |||
public static Builder newBuilder(org.sonar.core.test.Test.Fake prototype) { | |||
return newBuilder().mergeFrom(prototype); | |||
} | |||
public Builder toBuilder() { return newBuilder(this); } | |||
@java.lang.Override | |||
protected Builder newBuilderForType( | |||
com.google.protobuf.GeneratedMessage.BuilderParent parent) { | |||
Builder builder = new Builder(parent); | |||
return builder; | |||
} | |||
/** | |||
* Protobuf type {@code Fake} | |||
*/ | |||
public static final class Builder extends | |||
com.google.protobuf.GeneratedMessage.Builder<Builder> implements | |||
// @@protoc_insertion_point(builder_implements:Fake) | |||
org.sonar.core.test.Test.FakeOrBuilder { | |||
public static final com.google.protobuf.Descriptors.Descriptor | |||
getDescriptor() { | |||
return org.sonar.core.test.Test.internal_static_Fake_descriptor; | |||
} | |||
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable | |||
internalGetFieldAccessorTable() { | |||
return org.sonar.core.test.Test.internal_static_Fake_fieldAccessorTable | |||
.ensureFieldAccessorsInitialized( | |||
org.sonar.core.test.Test.Fake.class, org.sonar.core.test.Test.Fake.Builder.class); | |||
} | |||
// Construct using org.sonar.core.test.Test.Fake.newBuilder() | |||
private Builder() { | |||
maybeForceBuilderInitialization(); | |||
} | |||
private Builder( | |||
com.google.protobuf.GeneratedMessage.BuilderParent parent) { | |||
super(parent); | |||
maybeForceBuilderInitialization(); | |||
} | |||
private void maybeForceBuilderInitialization() { | |||
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { | |||
} | |||
} | |||
private static Builder create() { | |||
return new Builder(); | |||
} | |||
public Builder clear() { | |||
super.clear(); | |||
key_ = ""; | |||
bitField0_ = (bitField0_ & ~0x00000001); | |||
line_ = 0; | |||
bitField0_ = (bitField0_ & ~0x00000002); | |||
return this; | |||
} | |||
public Builder clone() { | |||
return create().mergeFrom(buildPartial()); | |||
} | |||
public com.google.protobuf.Descriptors.Descriptor | |||
getDescriptorForType() { | |||
return org.sonar.core.test.Test.internal_static_Fake_descriptor; | |||
} | |||
public org.sonar.core.test.Test.Fake getDefaultInstanceForType() { | |||
return org.sonar.core.test.Test.Fake.getDefaultInstance(); | |||
} | |||
public org.sonar.core.test.Test.Fake build() { | |||
org.sonar.core.test.Test.Fake result = buildPartial(); | |||
if (!result.isInitialized()) { | |||
throw newUninitializedMessageException(result); | |||
} | |||
return result; | |||
} | |||
public org.sonar.core.test.Test.Fake buildPartial() { | |||
org.sonar.core.test.Test.Fake result = new org.sonar.core.test.Test.Fake(this); | |||
int from_bitField0_ = bitField0_; | |||
int to_bitField0_ = 0; | |||
if (((from_bitField0_ & 0x00000001) == 0x00000001)) { | |||
to_bitField0_ |= 0x00000001; | |||
} | |||
result.key_ = key_; | |||
if (((from_bitField0_ & 0x00000002) == 0x00000002)) { | |||
to_bitField0_ |= 0x00000002; | |||
} | |||
result.line_ = line_; | |||
result.bitField0_ = to_bitField0_; | |||
onBuilt(); | |||
return result; | |||
} | |||
public Builder mergeFrom(com.google.protobuf.Message other) { | |||
if (other instanceof org.sonar.core.test.Test.Fake) { | |||
return mergeFrom((org.sonar.core.test.Test.Fake)other); | |||
} else { | |||
super.mergeFrom(other); | |||
return this; | |||
} | |||
} | |||
public Builder mergeFrom(org.sonar.core.test.Test.Fake other) { | |||
if (other == org.sonar.core.test.Test.Fake.getDefaultInstance()) return this; | |||
if (other.hasKey()) { | |||
bitField0_ |= 0x00000001; | |||
key_ = other.key_; | |||
onChanged(); | |||
} | |||
if (other.hasLine()) { | |||
setLine(other.getLine()); | |||
} | |||
this.mergeUnknownFields(other.getUnknownFields()); | |||
return this; | |||
} | |||
public final boolean isInitialized() { | |||
return true; | |||
} | |||
public Builder mergeFrom( | |||
com.google.protobuf.CodedInputStream input, | |||
com.google.protobuf.ExtensionRegistryLite extensionRegistry) | |||
throws java.io.IOException { | |||
org.sonar.core.test.Test.Fake parsedMessage = null; | |||
try { | |||
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); | |||
} catch (com.google.protobuf.InvalidProtocolBufferException e) { | |||
parsedMessage = (org.sonar.core.test.Test.Fake) e.getUnfinishedMessage(); | |||
throw e; | |||
} finally { | |||
if (parsedMessage != null) { | |||
mergeFrom(parsedMessage); | |||
} | |||
} | |||
return this; | |||
} | |||
private int bitField0_; | |||
private java.lang.Object key_ = ""; | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
public boolean hasKey() { | |||
return ((bitField0_ & 0x00000001) == 0x00000001); | |||
} | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
public java.lang.String getKey() { | |||
java.lang.Object ref = key_; | |||
if (!(ref instanceof java.lang.String)) { | |||
com.google.protobuf.ByteString bs = | |||
(com.google.protobuf.ByteString) ref; | |||
java.lang.String s = bs.toStringUtf8(); | |||
if (bs.isValidUtf8()) { | |||
key_ = s; | |||
} | |||
return s; | |||
} else { | |||
return (java.lang.String) ref; | |||
} | |||
} | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
public com.google.protobuf.ByteString | |||
getKeyBytes() { | |||
java.lang.Object ref = key_; | |||
if (ref instanceof String) { | |||
com.google.protobuf.ByteString b = | |||
com.google.protobuf.ByteString.copyFromUtf8( | |||
(java.lang.String) ref); | |||
key_ = b; | |||
return b; | |||
} else { | |||
return (com.google.protobuf.ByteString) ref; | |||
} | |||
} | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
public Builder setKey( | |||
java.lang.String value) { | |||
if (value == null) { | |||
throw new NullPointerException(); | |||
} | |||
bitField0_ |= 0x00000001; | |||
key_ = value; | |||
onChanged(); | |||
return this; | |||
} | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
public Builder clearKey() { | |||
bitField0_ = (bitField0_ & ~0x00000001); | |||
key_ = getDefaultInstance().getKey(); | |||
onChanged(); | |||
return this; | |||
} | |||
/** | |||
* <code>optional string key = 1;</code> | |||
*/ | |||
public Builder setKeyBytes( | |||
com.google.protobuf.ByteString value) { | |||
if (value == null) { | |||
throw new NullPointerException(); | |||
} | |||
bitField0_ |= 0x00000001; | |||
key_ = value; | |||
onChanged(); | |||
return this; | |||
} | |||
private int line_ ; | |||
/** | |||
* <code>optional int32 line = 2;</code> | |||
*/ | |||
public boolean hasLine() { | |||
return ((bitField0_ & 0x00000002) == 0x00000002); | |||
} | |||
/** | |||
* <code>optional int32 line = 2;</code> | |||
*/ | |||
public int getLine() { | |||
return line_; | |||
} | |||
/** | |||
* <code>optional int32 line = 2;</code> | |||
*/ | |||
public Builder setLine(int value) { | |||
bitField0_ |= 0x00000002; | |||
line_ = value; | |||
onChanged(); | |||
return this; | |||
} | |||
/** | |||
* <code>optional int32 line = 2;</code> | |||
*/ | |||
public Builder clearLine() { | |||
bitField0_ = (bitField0_ & ~0x00000002); | |||
line_ = 0; | |||
onChanged(); | |||
return this; | |||
} | |||
// @@protoc_insertion_point(builder_scope:Fake) | |||
} | |||
static { | |||
defaultInstance = new Fake(true); | |||
defaultInstance.initFields(); | |||
} | |||
// @@protoc_insertion_point(class_scope:Fake) | |||
} | |||
private static final com.google.protobuf.Descriptors.Descriptor | |||
internal_static_Fake_descriptor; | |||
private static | |||
com.google.protobuf.GeneratedMessage.FieldAccessorTable | |||
internal_static_Fake_fieldAccessorTable; | |||
public static com.google.protobuf.Descriptors.FileDescriptor | |||
getDescriptor() { | |||
return descriptor; | |||
} | |||
private static com.google.protobuf.Descriptors.FileDescriptor | |||
descriptor; | |||
static { | |||
java.lang.String[] descriptorData = { | |||
"\n\ntest.proto\"!\n\004Fake\022\013\n\003key\030\001 \001(\t\022\014\n\004lin" + | |||
"e\030\002 \001(\005B\027\n\023org.sonar.core.testH\001" | |||
}; | |||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = | |||
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { | |||
public com.google.protobuf.ExtensionRegistry assignDescriptors( | |||
com.google.protobuf.Descriptors.FileDescriptor root) { | |||
descriptor = root; | |||
return null; | |||
} | |||
}; | |||
com.google.protobuf.Descriptors.FileDescriptor | |||
.internalBuildGeneratedFileFrom(descriptorData, | |||
new com.google.protobuf.Descriptors.FileDescriptor[] { | |||
}, assigner); | |||
internal_static_Fake_descriptor = | |||
getDescriptor().getMessageTypes().get(0); | |||
internal_static_Fake_fieldAccessorTable = new | |||
com.google.protobuf.GeneratedMessage.FieldAccessorTable( | |||
internal_static_Fake_descriptor, | |||
new java.lang.String[] { "Key", "Line", }); | |||
} | |||
// @@protoc_insertion_point(outer_class_scope) | |||
} |
@@ -0,0 +1,120 @@ | |||
/* | |||
* 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.core.util; | |||
import java.io.File; | |||
import java.util.Arrays; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.test.TestUtils; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.core.test.Test.Fake; | |||
public class ProtobufTest { | |||
@Rule | |||
public ExpectedException thrown = ExpectedException.none(); | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@Test | |||
public void only_utils() { | |||
assertThat(TestUtils.hasOnlyPrivateConstructors(Protobuf.class)); | |||
} | |||
@Test | |||
public void read_file_fails_if_file_does_not_exist() throws Exception { | |||
thrown.expect(ContextException.class); | |||
thrown.expectMessage("Unable to read message"); | |||
File file = temp.newFile(); | |||
FileUtils.forceDelete(file); | |||
Protobuf.read(file, Fake.PARSER); | |||
} | |||
@Test | |||
public void read_file_returns_empty_message_if_file_is_empty() throws Exception { | |||
File file = temp.newFile(); | |||
Fake msg = Protobuf.read(file, Fake.PARSER); | |||
assertThat(msg).isNotNull(); | |||
assertThat(msg.isInitialized()).isTrue(); | |||
} | |||
@Test | |||
public void read_file_returns_message() throws Exception { | |||
File file = temp.newFile(); | |||
Protobuf.write(Fake.getDefaultInstance(), file); | |||
Fake message = Protobuf.read(file, Fake.PARSER); | |||
assertThat(message).isNotNull(); | |||
assertThat(message.isInitialized()).isTrue(); | |||
} | |||
@Test | |||
public void fail_to_write_single_message() throws Exception { | |||
thrown.expect(ContextException.class); | |||
thrown.expectMessage("Unable to write message"); | |||
File dir = temp.newFolder(); | |||
Protobuf.write(Fake.getDefaultInstance(), dir); | |||
} | |||
@Test | |||
public void write_and_read_streams() throws Exception { | |||
File file = temp.newFile(); | |||
Fake item1 = Fake.newBuilder().setKey("one").setLine(1).build(); | |||
Fake item2 = Fake.newBuilder().setKey("two").build(); | |||
Protobuf.writeStream(asList(item1, item2), file, false); | |||
CloseableIterator<Fake> it = Protobuf.readStream(file, Fake.PARSER); | |||
Fake read = it.next(); | |||
assertThat(read.getKey()).isEqualTo("one"); | |||
assertThat(read.getLine()).isEqualTo(1); | |||
read = it.next(); | |||
assertThat(read.getKey()).isEqualTo("two"); | |||
assertThat(read.hasLine()).isFalse(); | |||
assertThat(it.hasNext()).isFalse(); | |||
} | |||
@Test | |||
public void fail_to_read_stream() throws Exception { | |||
thrown.expect(ContextException.class); | |||
thrown.expectMessage("Unable to read messages"); | |||
File dir = temp.newFolder(); | |||
Protobuf.readStream(dir, Fake.PARSER); | |||
} | |||
@Test | |||
public void read_empty_stream() throws Exception { | |||
File file = temp.newFile(); | |||
CloseableIterator<Fake> it = Protobuf.readStream(file, Fake.PARSER); | |||
assertThat(it).isNotNull(); | |||
assertThat(it.hasNext()).isFalse(); | |||
} | |||
// TODO test in-moemry file | |||
} |
@@ -0,0 +1,28 @@ | |||
/* | |||
SonarQube, open source software quality management tool. | |||
Copyright (C) 2008-2015 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. | |||
*/ | |||
option java_package = "org.sonar.core.test"; | |||
option optimize_for = SPEED; | |||
message Fake { | |||
optional string key = 1; | |||
optional int32 line = 2; | |||
} |