diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-07-22 14:17:06 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-07-22 14:17:16 +0200 |
commit | c98aca6054048d0293fdb713910b4fa98beaa524 (patch) | |
tree | 2335acba0b9ecab3115dc6a49e67db4431dcd53b /sonar-core | |
parent | 5539cfffd327697a49278361901335e2d4d6e075 (diff) | |
download | sonarqube-c98aca6054048d0293fdb713910b4fa98beaa524.tar.gz sonarqube-c98aca6054048d0293fdb713910b4fa98beaa524.zip |
Improve utility org.sonar.core.util.Protobuf
Diffstat (limited to 'sonar-core')
-rw-r--r-- | sonar-core/pom.xml | 23 | ||||
-rw-r--r-- | sonar-core/src/main/java/org/sonar/core/util/Protobuf.java | 162 | ||||
-rw-r--r-- | sonar-core/src/test/gen-java/org/sonar/core/test/Test.java | 603 | ||||
-rw-r--r-- | sonar-core/src/test/java/org/sonar/core/util/ProtobufTest.java | 120 | ||||
-rw-r--r-- | sonar-core/src/test/protobuf/test.proto | 28 |
5 files changed, 936 insertions, 0 deletions
diff --git a/sonar-core/pom.xml b/sonar-core/pom.xml index 2f9a09ab9d8..010524b4614 100644 --- a/sonar-core/pom.xml +++ b/sonar-core/pom.xml @@ -28,6 +28,10 @@ <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> </dependency> @@ -107,6 +111,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> <executions> diff --git a/sonar-core/src/main/java/org/sonar/core/util/Protobuf.java b/sonar-core/src/main/java/org/sonar/core/util/Protobuf.java new file mode 100644 index 00000000000..7b8b25c6e73 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/util/Protobuf.java @@ -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); + } + } +} diff --git a/sonar-core/src/test/gen-java/org/sonar/core/test/Test.java b/sonar-core/src/test/gen-java/org/sonar/core/test/Test.java new file mode 100644 index 00000000000..9797ed15898 --- /dev/null +++ b/sonar-core/src/test/gen-java/org/sonar/core/test/Test.java @@ -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) +} diff --git a/sonar-core/src/test/java/org/sonar/core/util/ProtobufTest.java b/sonar-core/src/test/java/org/sonar/core/util/ProtobufTest.java new file mode 100644 index 00000000000..5b30c2b9a7c --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/util/ProtobufTest.java @@ -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 +} diff --git a/sonar-core/src/test/protobuf/test.proto b/sonar-core/src/test/protobuf/test.proto new file mode 100644 index 00000000000..c449a6a0596 --- /dev/null +++ b/sonar-core/src/test/protobuf/test.proto @@ -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; +} |