aboutsummaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-12-18 02:11:36 +0000
committerkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-12-18 02:11:36 +0000
commitfccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9 (patch)
tree9f2d9fe0267d96a54e541377ffeada3d0bff0d1d /java
parentd5cf7b55a6a1f959d1646785f63ca2b62da78079 (diff)
downloadprotobuf-fccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9.tar.gz
protobuf-fccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9.tar.bz2
protobuf-fccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9.zip
Massive roll-up of changes. See CHANGES.txt.
Diffstat (limited to 'java')
-rw-r--r--java/pom.xml1
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java35
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessageLite.java28
-rw-r--r--java/src/main/java/com/google/protobuf/ByteString.java18
-rw-r--r--java/src/main/java/com/google/protobuf/CodedInputStream.java27
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java118
-rw-r--r--java/src/main/java/com/google/protobuf/ExtensionRegistry.java5
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessage.java4
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java31
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java4
-rw-r--r--java/src/main/java/com/google/protobuf/MessageLite.java8
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java2
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSet.java20
-rw-r--r--java/src/main/java/com/google/protobuf/WireFormat.java18
-rw-r--r--java/src/test/java/com/google/protobuf/AbstractMessageTest.java38
-rw-r--r--java/src/test/java/com/google/protobuf/CodedInputStreamTest.java14
-rw-r--r--java/src/test/java/com/google/protobuf/DescriptorsTest.java51
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java35
-rw-r--r--java/src/test/java/com/google/protobuf/ServiceTest.java47
-rw-r--r--java/src/test/java/com/google/protobuf/TestUtil.java92
-rw-r--r--java/src/test/java/com/google/protobuf/TextFormatTest.java22
-rw-r--r--java/src/test/java/com/google/protobuf/WireFormatTest.java3
22 files changed, 510 insertions, 111 deletions
diff --git a/java/pom.xml b/java/pom.xml
index 849ef5da..307bc0b7 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -113,6 +113,7 @@
<arg value="../src/google/protobuf/unittest_import_lite.proto" />
<arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
<arg value="../src/google/protobuf/unittest_enormous_descriptor.proto" />
+ <arg value="../src/google/protobuf/unittest_no_generic_services.proto" />
</exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index e5bdefe3..b059bc98 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -311,6 +311,12 @@ public abstract class AbstractMessage extends AbstractMessageLite
} else {
field = extension.descriptor;
defaultInstance = extension.defaultInstance;
+ if (defaultInstance == null &&
+ field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ throw new IllegalStateException(
+ "Message-typed extension lacked default instance: " +
+ field.getFullName());
+ }
}
} else {
field = null;
@@ -319,15 +325,28 @@ public abstract class AbstractMessage extends AbstractMessageLite
field = type.findFieldByNumber(fieldNumber);
}
- if (field == null || wireType !=
- FieldSet.getWireFormatForFieldType(
- field.getLiteType(),
- field.getOptions().getPacked())) {
- // Unknown field or wrong wire type. Skip.
+ boolean unknown = false;
+ boolean packed = false;
+ if (field == null) {
+ unknown = true; // Unknown field.
+ } else if (wireType == FieldSet.getWireFormatForFieldType(
+ field.getLiteType(),
+ false /* isPacked */)) {
+ packed = false;
+ } else if (field.isPackable() &&
+ wireType == FieldSet.getWireFormatForFieldType(
+ field.getLiteType(),
+ true /* isPacked */)) {
+ packed = true;
+ } else {
+ unknown = true; // Unknown wire type.
+ }
+
+ if (unknown) { // Unknown field or wrong wire type. Skip.
return unknownFields.mergeFieldFrom(tag, input);
}
- if (field.getOptions().getPacked()) {
+ if (packed) {
final int length = input.readRawVarint32();
final int limit = input.pushLimit(length);
if (field.getLiteType() == WireFormat.FieldType.ENUM) {
@@ -673,13 +692,13 @@ public abstract class AbstractMessage extends AbstractMessageLite
}
@Override
- public BuilderType mergeDelimitedFrom(final InputStream input)
+ public boolean mergeDelimitedFrom(final InputStream input)
throws IOException {
return super.mergeDelimitedFrom(input);
}
@Override
- public BuilderType mergeDelimitedFrom(
+ public boolean mergeDelimitedFrom(
final InputStream input,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
index 86bf02d8..9210d853 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -86,7 +86,7 @@ public abstract class AbstractMessageLite implements MessageLite {
CodedOutputStream.computeRawVarint32Size(serialized) + serialized);
final CodedOutputStream codedOutput =
CodedOutputStream.newInstance(output, bufferSize);
- codedOutput.writeRawVarint32(getSerializedSize());
+ codedOutput.writeRawVarint32(serialized);
writeTo(codedOutput);
codedOutput.flush();
}
@@ -105,13 +105,7 @@ public abstract class AbstractMessageLite implements MessageLite {
public BuilderType mergeFrom(final CodedInputStream input)
throws IOException {
- // TODO(kenton): Don't use null here. Currently we have to because
- // using ExtensionRegistry.getEmptyRegistry() would imply a dependency
- // on ExtensionRegistry. However, AbstractMessage overrides this with
- // a correct implementation, and lite messages don't yet support
- // extensions, so it ends up not mattering for now. It will matter
- // once lite messages support extensions.
- return mergeFrom(input, null);
+ return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
}
// Re-defined here for return type covariance.
@@ -275,20 +269,24 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
- public BuilderType mergeDelimitedFrom(
+ public boolean mergeDelimitedFrom(
final InputStream input,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
- final int size = CodedInputStream.readRawVarint32(input);
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ return false;
+ }
+ final int size = CodedInputStream.readRawVarint32(firstByte, input);
final InputStream limitedInput = new LimitedInputStream(input, size);
- return mergeFrom(limitedInput, extensionRegistry);
+ mergeFrom(limitedInput, extensionRegistry);
+ return true;
}
- public BuilderType mergeDelimitedFrom(final InputStream input)
+ public boolean mergeDelimitedFrom(final InputStream input)
throws IOException {
- final int size = CodedInputStream.readRawVarint32(input);
- final InputStream limitedInput = new LimitedInputStream(input, size);
- return mergeFrom(limitedInput);
+ return mergeDelimitedFrom(input,
+ ExtensionRegistryLite.getEmptyRegistry());
}
/**
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index c83c335c..c043df8b 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -99,6 +99,24 @@ public final class ByteString {
}
/**
+ * Copies {@code size} bytes from a {@code java.nio.ByteBuffer} into
+ * a {@code ByteString}.
+ */
+ public static ByteString copyFrom(final ByteBuffer bytes, final int size) {
+ final byte[] copy = new byte[size];
+ bytes.get(copy);
+ return new ByteString(copy);
+ }
+
+ /**
+ * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into
+ * a {@code ByteString}.
+ */
+ public static ByteString copyFrom(final ByteBuffer bytes) {
+ return copyFrom(bytes, bytes.remaining());
+ }
+
+ /**
* Encodes {@code text} into a sequence of bytes using the named charset
* and returns the result as a {@code ByteString}.
*/
diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java
index f339c00e..f0c1051d 100644
--- a/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -84,8 +84,9 @@ public final class CodedInputStream {
}
lastTag = readRawVarint32();
- if (lastTag == 0) {
- // If we actually read zero, that's not a valid tag.
+ if (WireFormat.getTagFieldNumber(lastTag) == 0) {
+ // If we actually read zero (or any tag number corresponding to field
+ // number zero), that's not a valid tag.
throw InvalidProtocolBufferException.invalidTag();
}
return lastTag;
@@ -355,8 +356,26 @@ public final class CodedInputStream {
* CodedInputStream buffers its input.
*/
static int readRawVarint32(final InputStream input) throws IOException {
- int result = 0;
- int offset = 0;
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return readRawVarint32(firstByte, input);
+ }
+
+ /**
+ * Like {@link #readRawVarint32(InputStream)}, but expects that the caller
+ * has already read one byte. This allows the caller to determine if EOF
+ * has been reached before attempting to read.
+ */
+ static int readRawVarint32(final int firstByte,
+ final InputStream input) throws IOException {
+ if ((firstByte & 0x80) == 0) {
+ return firstByte;
+ }
+
+ int result = firstByte & 0x7f;
+ int offset = 7;
for (; offset < 32; offset += 7) {
final int b = input.read();
if (b == -1) {
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index 0c162d5d..c5e9a04b 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -48,7 +48,7 @@ import java.io.UnsupportedEncodingException;
* (given a message object of the type) {@code message.getDescriptorForType()}.
*
* Descriptors are built from DescriptorProtos, as defined in
- * {@code net/proto2/proto/descriptor.proto}.
+ * {@code google/protobuf/descriptor.proto}.
*
* @author kenton@google.com Kenton Varda
*/
@@ -699,6 +699,11 @@ public final class Descriptors {
return getOptions().getPacked();
}
+ /** Can this field be packed? i.e. is it a repeated primitive field? */
+ public boolean isPackable() {
+ return isRepeated() && getLiteType().isPackable();
+ }
+
/** Returns true if the field had an explicitly-defined default value. */
public boolean hasDefaultValue() { return proto.hasDefaultValue(); }
@@ -810,39 +815,34 @@ public final class Descriptors {
private Object defaultValue;
public enum Type {
- DOUBLE (FieldDescriptorProto.Type.TYPE_DOUBLE , JavaType.DOUBLE ),
- FLOAT (FieldDescriptorProto.Type.TYPE_FLOAT , JavaType.FLOAT ),
- INT64 (FieldDescriptorProto.Type.TYPE_INT64 , JavaType.LONG ),
- UINT64 (FieldDescriptorProto.Type.TYPE_UINT64 , JavaType.LONG ),
- INT32 (FieldDescriptorProto.Type.TYPE_INT32 , JavaType.INT ),
- FIXED64 (FieldDescriptorProto.Type.TYPE_FIXED64 , JavaType.LONG ),
- FIXED32 (FieldDescriptorProto.Type.TYPE_FIXED32 , JavaType.INT ),
- BOOL (FieldDescriptorProto.Type.TYPE_BOOL , JavaType.BOOLEAN ),
- STRING (FieldDescriptorProto.Type.TYPE_STRING , JavaType.STRING ),
- GROUP (FieldDescriptorProto.Type.TYPE_GROUP , JavaType.MESSAGE ),
- MESSAGE (FieldDescriptorProto.Type.TYPE_MESSAGE , JavaType.MESSAGE ),
- BYTES (FieldDescriptorProto.Type.TYPE_BYTES , JavaType.BYTE_STRING),
- UINT32 (FieldDescriptorProto.Type.TYPE_UINT32 , JavaType.INT ),
- ENUM (FieldDescriptorProto.Type.TYPE_ENUM , JavaType.ENUM ),
- SFIXED32(FieldDescriptorProto.Type.TYPE_SFIXED32, JavaType.INT ),
- SFIXED64(FieldDescriptorProto.Type.TYPE_SFIXED64, JavaType.LONG ),
- SINT32 (FieldDescriptorProto.Type.TYPE_SINT32 , JavaType.INT ),
- SINT64 (FieldDescriptorProto.Type.TYPE_SINT64 , JavaType.LONG );
-
- Type(final FieldDescriptorProto.Type proto, final JavaType javaType) {
- this.proto = proto;
+ DOUBLE (JavaType.DOUBLE ),
+ FLOAT (JavaType.FLOAT ),
+ INT64 (JavaType.LONG ),
+ UINT64 (JavaType.LONG ),
+ INT32 (JavaType.INT ),
+ FIXED64 (JavaType.LONG ),
+ FIXED32 (JavaType.INT ),
+ BOOL (JavaType.BOOLEAN ),
+ STRING (JavaType.STRING ),
+ GROUP (JavaType.MESSAGE ),
+ MESSAGE (JavaType.MESSAGE ),
+ BYTES (JavaType.BYTE_STRING),
+ UINT32 (JavaType.INT ),
+ ENUM (JavaType.ENUM ),
+ SFIXED32(JavaType.INT ),
+ SFIXED64(JavaType.LONG ),
+ SINT32 (JavaType.INT ),
+ SINT64 (JavaType.LONG );
+
+ Type(final JavaType javaType) {
this.javaType = javaType;
-
- if (ordinal() != proto.getNumber() - 1) {
- throw new RuntimeException(
- "descriptor.proto changed but Desrciptors.java wasn't updated.");
- }
}
- private FieldDescriptorProto.Type proto;
private JavaType javaType;
- public FieldDescriptorProto.Type toProto() { return proto; }
+ public FieldDescriptorProto.Type toProto() {
+ return FieldDescriptorProto.Type.valueOf(ordinal() + 1);
+ }
public JavaType getJavaType() { return javaType; }
public static Type valueOf(final FieldDescriptorProto.Type type) {
@@ -902,16 +902,10 @@ public final class Descriptors {
}
// Only repeated primitive fields may be packed.
- if (proto.getOptions().getPacked()) {
- if (proto.getLabel() != FieldDescriptorProto.Label.LABEL_REPEATED ||
- proto.getType() == FieldDescriptorProto.Type.TYPE_STRING ||
- proto.getType() == FieldDescriptorProto.Type.TYPE_GROUP ||
- proto.getType() == FieldDescriptorProto.Type.TYPE_MESSAGE ||
- proto.getType() == FieldDescriptorProto.Type.TYPE_BYTES) {
- throw new DescriptorValidationException(this,
- "[packed = true] can only be specified for repeated primitive " +
- "fields.");
- }
+ if (proto.getOptions().getPacked() && !isPackable()) {
+ throw new DescriptorValidationException(this,
+ "[packed = true] can only be specified for repeated primitive " +
+ "fields.");
}
if (isExtension) {
@@ -1030,10 +1024,26 @@ public final class Descriptors {
defaultValue = TextFormat.parseUInt64(proto.getDefaultValue());
break;
case FLOAT:
- defaultValue = Float.valueOf(proto.getDefaultValue());
+ if (proto.getDefaultValue().equals("inf")) {
+ defaultValue = Float.POSITIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("-inf")) {
+ defaultValue = Float.NEGATIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("nan")) {
+ defaultValue = Float.NaN;
+ } else {
+ defaultValue = Float.valueOf(proto.getDefaultValue());
+ }
break;
case DOUBLE:
- defaultValue = Double.valueOf(proto.getDefaultValue());
+ if (proto.getDefaultValue().equals("inf")) {
+ defaultValue = Double.POSITIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("-inf")) {
+ defaultValue = Double.NEGATIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("nan")) {
+ defaultValue = Double.NaN;
+ } else {
+ defaultValue = Double.valueOf(proto.getDefaultValue());
+ }
break;
case BOOL:
defaultValue = Boolean.valueOf(proto.getDefaultValue());
@@ -1064,12 +1074,9 @@ public final class Descriptors {
"Message type had default value.");
}
} catch (NumberFormatException e) {
- final DescriptorValidationException validationException =
- new DescriptorValidationException(this,
- "Could not parse default value: \"" +
- proto.getDefaultValue() + '\"');
- validationException.initCause(e);
- throw validationException;
+ throw new DescriptorValidationException(this,
+ "Could not parse default value: \"" +
+ proto.getDefaultValue() + '\"', e);
}
} else {
// Determine the default default for this field.
@@ -1536,14 +1543,7 @@ public final class Descriptors {
private DescriptorValidationException(
final GenericDescriptor problemDescriptor,
final String description) {
- this(problemDescriptor, description, null);
- }
-
- private DescriptorValidationException(
- final GenericDescriptor problemDescriptor,
- final String description,
- final Throwable cause) {
- super(problemDescriptor.getFullName() + ": " + description, cause);
+ super(problemDescriptor.getFullName() + ": " + description);
// Note that problemDescriptor may be partially uninitialized, so we
// don't want to expose it directly to the user. So, we only provide
@@ -1554,6 +1554,14 @@ public final class Descriptors {
}
private DescriptorValidationException(
+ final GenericDescriptor problemDescriptor,
+ final String description,
+ final Throwable cause) {
+ this(problemDescriptor, description);
+ initCause(cause);
+ }
+
+ private DescriptorValidationException(
final FileDescriptor problemDescriptor,
final String description) {
super(problemDescriptor.getName() + ": " + description);
diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
index 87bbd6eb..d4f6ba9e 100644
--- a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
+++ b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
@@ -157,6 +157,11 @@ public final class ExtensionRegistry extends ExtensionRegistryLite {
public void add(final GeneratedMessage.GeneratedExtension<?, ?> extension) {
if (extension.getDescriptor().getJavaType() ==
FieldDescriptor.JavaType.MESSAGE) {
+ if (extension.getMessageDefaultInstance() == null) {
+ throw new IllegalStateException(
+ "Registered message-type extension had null default instance: " +
+ extension.getDescriptor().getFullName());
+ }
add(new ExtensionInfo(extension.getDescriptor(),
extension.getMessageDefaultInstance()));
} else {
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 4994faad..b5583ba3 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -789,6 +789,10 @@ public abstract class GeneratedMessage extends AbstractMessage {
messageDefaultInstance =
(Message) invokeOrDie(getMethodOrDie(type, "getDefaultInstance"),
null);
+ if (messageDefaultInstance == null) {
+ throw new IllegalStateException(
+ type.getName() + ".getDefaultInstance() returned null.");
+ }
break;
case ENUM:
enumValueOf = getMethodOrDie(type, "valueOf",
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index c68414bd..e327f745 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -303,7 +303,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite {
final ExtensionRegistryLite extensionRegistry,
final int tag) throws IOException {
final FieldSet<ExtensionDescriptor> extensions =
- internalGetResult().extensions;
+ ((ExtendableMessage) internalGetResult()).extensions;
final int wireType = WireFormat.getTagWireType(tag);
final int fieldNumber = WireFormat.getTagFieldNumber(tag);
@@ -312,15 +312,29 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite {
extensionRegistry.findLiteExtensionByNumber(
getDefaultInstanceForType(), fieldNumber);
- if (extension == null || wireType !=
- FieldSet.getWireFormatForFieldType(
- extension.descriptor.getLiteType(),
- extension.descriptor.isPacked())) {
- // Unknown field or wrong wire type. Skip.
+ boolean unknown = false;
+ boolean packed = false;
+ if (extension == null) {
+ unknown = true; // Unknown field.
+ } else if (wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ false /* isPacked */)) {
+ packed = false; // Normal, unpacked value.
+ } else if (extension.descriptor.isRepeated &&
+ extension.descriptor.type.isPackable() &&
+ wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ true /* isPacked */)) {
+ packed = true; // Packed value.
+ } else {
+ unknown = true; // Wrong wire type.
+ }
+
+ if (unknown) { // Unknown field or wrong wire type. Skip.
return input.skipField(tag);
}
- if (extension.descriptor.isPacked()) {
+ if (packed) {
final int length = input.readRawVarint32();
final int limit = input.pushLimit(length);
if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
@@ -396,7 +410,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite {
}
protected final void mergeExtensionFields(final MessageType other) {
- internalGetResult().extensions.mergeFrom(other.extensions);
+ ((ExtendableMessage) internalGetResult()).extensions.mergeFrom(
+ ((ExtendableMessage) other).extensions);
}
}
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index c11abdc5..8c29e212 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -296,9 +296,9 @@ public interface Message extends MessageLite {
Builder mergeFrom(InputStream input,
ExtensionRegistryLite extensionRegistry)
throws IOException;
- Builder mergeDelimitedFrom(InputStream input)
+ boolean mergeDelimitedFrom(InputStream input)
throws IOException;
- Builder mergeDelimitedFrom(InputStream input,
+ boolean mergeDelimitedFrom(InputStream input,
ExtensionRegistryLite extensionRegistry)
throws IOException;
}
diff --git a/java/src/main/java/com/google/protobuf/MessageLite.java b/java/src/main/java/com/google/protobuf/MessageLite.java
index 3ebe9bba..cf7f39e2 100644
--- a/java/src/main/java/com/google/protobuf/MessageLite.java
+++ b/java/src/main/java/com/google/protobuf/MessageLite.java
@@ -317,14 +317,18 @@ public interface MessageLite {
* then the message data. Use
* {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
* this format.
+ *
+ * @returns True if successful, or false if the stream is at EOF when the
+ * method starts. Any other error (including reaching EOF during
+ * parsing) will cause an exception to be thrown.
*/
- Builder mergeDelimitedFrom(InputStream input)
+ boolean mergeDelimitedFrom(InputStream input)
throws IOException;
/**
* Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
*/
- Builder mergeDelimitedFrom(InputStream input,
+ boolean mergeDelimitedFrom(InputStream input,
ExtensionRegistryLite extensionRegistry)
throws IOException;
}
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index a855720b..698992f0 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -426,7 +426,7 @@ public final class TextFormat {
Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
private static final Pattern TOKEN = Pattern.compile(
"[a-zA-Z_][0-9a-zA-Z_+-]*+|" + // an identifier
- "[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number
+ "[.]?[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number
"\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" + // a double-quoted string
"\'([^\"\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string
Pattern.MULTILINE);
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 7f7e4939..26a15d00 100644
--- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -30,6 +30,8 @@
package com.google.protobuf;
+import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -551,19 +553,23 @@ public final class UnknownFieldSet implements MessageLite {
return this;
}
- public Builder mergeDelimitedFrom(InputStream input)
+ public boolean mergeDelimitedFrom(InputStream input)
throws IOException {
- final int size = CodedInputStream.readRawVarint32(input);
- final InputStream limitedInput =
- new AbstractMessage.Builder.LimitedInputStream(input, size);
- return mergeFrom(limitedInput, null);
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ return false;
+ }
+ final int size = CodedInputStream.readRawVarint32(firstByte, input);
+ final InputStream limitedInput = new LimitedInputStream(input, size);
+ mergeFrom(limitedInput);
+ return true;
}
- public Builder mergeDelimitedFrom(
+ public boolean mergeDelimitedFrom(
InputStream input,
ExtensionRegistryLite extensionRegistry) throws IOException {
// UnknownFieldSet has no extensions.
- return mergeFrom(input);
+ return mergeDelimitedFrom(input);
}
public Builder mergeFrom(
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index 3b0bdcd0..c46f7b0a 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -113,10 +113,18 @@ public final class WireFormat {
FIXED64 (JavaType.LONG , WIRETYPE_FIXED64 ),
FIXED32 (JavaType.INT , WIRETYPE_FIXED32 ),
BOOL (JavaType.BOOLEAN , WIRETYPE_VARINT ),
- STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED),
- GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ),
- MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED),
- BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED),
+ STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED) {
+ public boolean isPackable() { return false; }
+ },
+ GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ) {
+ public boolean isPackable() { return false; }
+ },
+ MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED) {
+ public boolean isPackable() { return false; }
+ },
+ BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) {
+ public boolean isPackable() { return false; }
+ },
UINT32 (JavaType.INT , WIRETYPE_VARINT ),
ENUM (JavaType.ENUM , WIRETYPE_VARINT ),
SFIXED32(JavaType.INT , WIRETYPE_FIXED32 ),
@@ -134,6 +142,8 @@ public final class WireFormat {
public JavaType getJavaType() { return javaType; }
public int getWireType() { return wireType; }
+
+ public boolean isPackable() { return true; }
}
// Field numbers for feilds in MessageSet wire format.
diff --git a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
index 2c59fd0d..c44d6605 100644
--- a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -38,6 +38,7 @@ import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestPackedTypes;
import protobuf_unittest.UnittestProto.TestRequired;
import protobuf_unittest.UnittestProto.TestRequiredForeign;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
import junit.framework.TestCase;
@@ -238,6 +239,43 @@ public class AbstractMessageTest extends TestCase {
TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
}
+ public void testUnpackedSerialization() throws Exception {
+ Message abstractMessage =
+ new AbstractMessageWrapper(TestUtil.getUnpackedSet());
+
+ TestUtil.assertUnpackedFieldsSet(
+ TestUnpackedTypes.parseFrom(abstractMessage.toByteString()));
+
+ assertEquals(TestUtil.getUnpackedSet().toByteString(),
+ abstractMessage.toByteString());
+ }
+
+ public void testParsePackedToUnpacked() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(
+ (TestUnpackedTypes) message.wrappedMessage);
+ }
+
+ public void testParseUnpackedToPacked() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
+ }
+
+ public void testUnpackedParsing() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(
+ (TestUnpackedTypes) message.wrappedMessage);
+ }
+
public void testOptimizedForSize() throws Exception {
// We're mostly only checking that this class was compiled successfully.
TestOptimizedForSize message =
diff --git a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index a75a400b..6acd3223 100644
--- a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -490,4 +490,18 @@ public class CodedInputStreamTest extends TestCase {
assertEquals(0, in.readTag());
assertEquals(5, in.getTotalBytesRead());
}
+
+ public void testInvalidTag() throws Exception {
+ // Any tag number which corresponds to field number zero is invalid and
+ // should throw InvalidProtocolBufferException.
+ for (int i = 0; i < 8; i++) {
+ try {
+ CodedInputStream.newInstance(bytes(i)).readTag();
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(InvalidProtocolBufferException.invalidTag().getMessage(),
+ e.getMessage());
+ }
+ }
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index c5c38b27..f41d070e 100644
--- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -30,6 +30,10 @@
package com.google.protobuf;
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.Descriptors.DescriptorValidationException;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
@@ -63,6 +67,22 @@ import java.util.Collections;
* @author kenton@google.com Kenton Varda
*/
public class DescriptorsTest extends TestCase {
+
+ // Regression test for bug where referencing a FieldDescriptor.Type value
+ // before a FieldDescriptorProto.Type value would yield a
+ // ExceptionInInitializerError.
+ private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
+
+ public void testFieldTypeEnumMapping() throws Exception {
+ assertEquals(FieldDescriptor.Type.values().length,
+ FieldDescriptorProto.Type.values().length);
+ for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
+ FieldDescriptorProto.Type protoType = type.toProto();
+ assertEquals("TYPE_" + type.name(), protoType.name());
+ assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
+ }
+ }
+
public void testFileDescriptor() throws Exception {
FileDescriptor file = UnittestProto.getDescriptor();
@@ -405,4 +425,35 @@ public class DescriptorsTest extends TestCase {
UnittestEnormousDescriptor.getDescriptor()
.toProto().getSerializedSize() > 65536);
}
+
+ /**
+ * Tests that the DescriptorValidationException works as intended.
+ */
+ public void testDescriptorValidatorException() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setType(FieldDescriptorProto.Type.TYPE_INT32)
+ .setName("foo")
+ .setNumber(1)
+ .setDefaultValue("invalid")
+ .build())
+ .build())
+ .build();
+ try {
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ new FileDescriptor[0]);
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ // Expected; check that the error message contains some useful hints
+ assertTrue(e.getMessage().indexOf("foo") != -1);
+ assertTrue(e.getMessage().indexOf("Foo") != -1);
+ assertTrue(e.getMessage().indexOf("invalid") != -1);
+ assertTrue(e.getCause() instanceof NumberFormatException);
+ assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
+ }
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index cdf60c5e..73c71f31 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -39,6 +39,8 @@ import protobuf_unittest.UnittestProto.ForeignEnum;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
import protobuf_unittest.MultipleFilesTestProto;
import protobuf_unittest.MessageWithNoOuter;
import protobuf_unittest.EnumWithNoOuter;
@@ -303,8 +305,15 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.assertClear(TestAllTypes.getDefaultInstance());
TestUtil.assertClear(TestAllTypes.newBuilder().build());
- assertEquals("\u1234",
- TestExtremeDefaultValues.getDefaultInstance().getUtf8String());
+ TestExtremeDefaultValues message =
+ TestExtremeDefaultValues.getDefaultInstance();
+ assertEquals("\u1234", message.getUtf8String());
+ assertEquals(Double.POSITIVE_INFINITY, message.getInfDouble());
+ assertEquals(Double.NEGATIVE_INFINITY, message.getNegInfDouble());
+ assertTrue(Double.isNaN(message.getNanDouble()));
+ assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat());
+ assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat());
+ assertTrue(Float.isNaN(message.getNanFloat()));
}
public void testReflectionGetters() throws Exception {
@@ -361,6 +370,20 @@ public class GeneratedMessageTest extends TestCase {
assertTrue(map.findValueByNumber(12345) == null);
}
+ public void testParsePackedToUnpacked() throws Exception {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ TestUnpackedTypes message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(message);
+ }
+
+ public void testParseUnpackedToPacked() throws Exception {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ TestPackedTypes message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet(message);
+ }
+
// =================================================================
// Extensions.
@@ -615,4 +638,12 @@ public class GeneratedMessageTest extends TestCase {
UnittestProto.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48);
assertEquals(UnittestProto.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51);
}
+
+ public void testRecursiveMessageDefaultInstance() throws Exception {
+ UnittestProto.TestRecursiveMessage message =
+ UnittestProto.TestRecursiveMessage.getDefaultInstance();
+ assertTrue(message != null);
+ assertTrue(message.getA() != null);
+ assertTrue(message.getA() == message);
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/ServiceTest.java b/java/src/test/java/com/google/protobuf/ServiceTest.java
index d8523ea3..e10322dc 100644
--- a/java/src/test/java/com/google/protobuf/ServiceTest.java
+++ b/java/src/test/java/com/google/protobuf/ServiceTest.java
@@ -30,7 +30,9 @@
package com.google.protobuf;
+import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.MethodDescriptor;
+import google.protobuf.no_generic_services_test.UnittestNoGenericServices;
import protobuf_unittest.MessageWithNoOuter;
import protobuf_unittest.ServiceWithNoOuter;
import protobuf_unittest.UnittestProto.TestAllTypes;
@@ -44,6 +46,9 @@ import org.easymock.classextension.EasyMock;
import org.easymock.classextension.IMocksControl;
import org.easymock.IArgumentMatcher;
+import java.util.HashSet;
+import java.util.Set;
+
import junit.framework.TestCase;
/**
@@ -220,6 +225,48 @@ public class ServiceTest extends TestCase {
control.verify();
}
+ public void testNoGenericServices() throws Exception {
+ // Non-services should be usable.
+ UnittestNoGenericServices.TestMessage message =
+ UnittestNoGenericServices.TestMessage.newBuilder()
+ .setA(123)
+ .setExtension(UnittestNoGenericServices.testExtension, 456)
+ .build();
+ assertEquals(123, message.getA());
+ assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber());
+
+ // Build a list of the class names nested in UnittestNoGenericServices.
+ String outerName = "google.protobuf.no_generic_services_test." +
+ "UnittestNoGenericServices";
+ Class<?> outerClass = Class.forName(outerName);
+
+ Set<String> innerClassNames = new HashSet<String>();
+ for (Class<?> innerClass : outerClass.getClasses()) {
+ String fullName = innerClass.getName();
+ // Figure out the unqualified name of the inner class.
+ // Note: Surprisingly, the full name of an inner class will be separated
+ // from the outer class name by a '$' rather than a '.'. This is not
+ // mentioned in the documentation for java.lang.Class. I don't want to
+ // make assumptions, so I'm just going to accept any character as the
+ // separator.
+ assertTrue(fullName.startsWith(outerName));
+ innerClassNames.add(fullName.substring(outerName.length() + 1));
+ }
+
+ // No service class should have been generated.
+ assertTrue(innerClassNames.contains("TestMessage"));
+ assertTrue(innerClassNames.contains("TestEnum"));
+ assertFalse(innerClassNames.contains("TestService"));
+
+ // But descriptors are there.
+ FileDescriptor file = UnittestNoGenericServices.getDescriptor();
+ assertEquals(1, file.getServices().size());
+ assertEquals("TestService", file.getServices().get(0).getName());
+ assertEquals(1, file.getServices().get(0).getMethods().size());
+ assertEquals("Foo",
+ file.getServices().get(0).getMethods().get(0).getName());
+ }
+
// =================================================================
/**
diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java
index 805c42ae..db6acb07 100644
--- a/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -217,6 +217,7 @@ import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestPackedExtensions;
import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.ForeignEnum;
import com.google.protobuf.test.UnittestImport.ImportMessage;
@@ -289,6 +290,12 @@ class TestUtil {
return builder.build();
}
+ public static TestUnpackedTypes getUnpackedSet() {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ setUnpackedFields(builder);
+ return builder.build();
+ }
+
public static TestPackedExtensions getPackedExtensionsSet() {
TestPackedExtensions.Builder builder = TestPackedExtensions.newBuilder();
setPackedExtensions(builder);
@@ -956,6 +963,42 @@ class TestUtil {
}
/**
+ * Set every field of {@code message} to a unique value. Must correspond with
+ * the values applied by {@code setPackedFields}.
+ */
+ public static void setUnpackedFields(TestUnpackedTypes.Builder message) {
+ message.addUnpackedInt32 (601);
+ message.addUnpackedInt64 (602);
+ message.addUnpackedUint32 (603);
+ message.addUnpackedUint64 (604);
+ message.addUnpackedSint32 (605);
+ message.addUnpackedSint64 (606);
+ message.addUnpackedFixed32 (607);
+ message.addUnpackedFixed64 (608);
+ message.addUnpackedSfixed32(609);
+ message.addUnpackedSfixed64(610);
+ message.addUnpackedFloat (611);
+ message.addUnpackedDouble (612);
+ message.addUnpackedBool (true);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addUnpackedInt32 (701);
+ message.addUnpackedInt64 (702);
+ message.addUnpackedUint32 (703);
+ message.addUnpackedUint64 (704);
+ message.addUnpackedSint32 (705);
+ message.addUnpackedSint64 (706);
+ message.addUnpackedFixed32 (707);
+ message.addUnpackedFixed64 (708);
+ message.addUnpackedSfixed32(709);
+ message.addUnpackedSfixed64(710);
+ message.addUnpackedFloat (711);
+ message.addUnpackedDouble (712);
+ message.addUnpackedBool (false);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAZ);
+ }
+
+ /**
* Assert (using {@code junit.framework.Assert}} that all fields of
* {@code message} are set to the values assigned by {@code setPackedFields}.
*/
@@ -1004,6 +1047,55 @@ class TestUtil {
Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
}
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setUnpackedFields}.
+ */
+ public static void assertUnpackedFieldsSet(TestUnpackedTypes message) {
+ Assert.assertEquals(2, message.getUnpackedInt32Count ());
+ Assert.assertEquals(2, message.getUnpackedInt64Count ());
+ Assert.assertEquals(2, message.getUnpackedUint32Count ());
+ Assert.assertEquals(2, message.getUnpackedUint64Count ());
+ Assert.assertEquals(2, message.getUnpackedSint32Count ());
+ Assert.assertEquals(2, message.getUnpackedSint64Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed32Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed64Count ());
+ Assert.assertEquals(2, message.getUnpackedSfixed32Count());
+ Assert.assertEquals(2, message.getUnpackedSfixed64Count());
+ Assert.assertEquals(2, message.getUnpackedFloatCount ());
+ Assert.assertEquals(2, message.getUnpackedDoubleCount ());
+ Assert.assertEquals(2, message.getUnpackedBoolCount ());
+ Assert.assertEquals(2, message.getUnpackedEnumCount ());
+ Assert.assertEquals(601 , message.getUnpackedInt32 (0));
+ Assert.assertEquals(602 , message.getUnpackedInt64 (0));
+ Assert.assertEquals(603 , message.getUnpackedUint32 (0));
+ Assert.assertEquals(604 , message.getUnpackedUint64 (0));
+ Assert.assertEquals(605 , message.getUnpackedSint32 (0));
+ Assert.assertEquals(606 , message.getUnpackedSint64 (0));
+ Assert.assertEquals(607 , message.getUnpackedFixed32 (0));
+ Assert.assertEquals(608 , message.getUnpackedFixed64 (0));
+ Assert.assertEquals(609 , message.getUnpackedSfixed32(0));
+ Assert.assertEquals(610 , message.getUnpackedSfixed64(0));
+ Assert.assertEquals(611 , message.getUnpackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getUnpackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getUnpackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getUnpackedEnum(0));
+ Assert.assertEquals(701 , message.getUnpackedInt32 (1));
+ Assert.assertEquals(702 , message.getUnpackedInt64 (1));
+ Assert.assertEquals(703 , message.getUnpackedUint32 (1));
+ Assert.assertEquals(704 , message.getUnpackedUint64 (1));
+ Assert.assertEquals(705 , message.getUnpackedSint32 (1));
+ Assert.assertEquals(706 , message.getUnpackedSint64 (1));
+ Assert.assertEquals(707 , message.getUnpackedFixed32 (1));
+ Assert.assertEquals(708 , message.getUnpackedFixed64 (1));
+ Assert.assertEquals(709 , message.getUnpackedSfixed32(1));
+ Assert.assertEquals(710 , message.getUnpackedSfixed64(1));
+ Assert.assertEquals(711 , message.getUnpackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getUnpackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getUnpackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getUnpackedEnum(1));
+ }
+
// ===================================================================
// Like above, but for extensions
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 1d73165e..3ea7b2cf 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -68,7 +68,7 @@ public class TextFormatTest extends TestCase {
private static String allExtensionsSetText = TestUtil.readTextFromFile(
"text_format_unittest_extensions_data.txt");
- private String exoticText =
+ private static String exoticText =
"repeated_int32: -1\n" +
"repeated_int32: -2147483648\n" +
"repeated_int64: -1\n" +
@@ -80,7 +80,13 @@ public class TextFormatTest extends TestCase {
"repeated_double: 123.0\n" +
"repeated_double: 123.5\n" +
"repeated_double: 0.125\n" +
+ "repeated_double: .125\n" +
+ "repeated_double: -.125\n" +
"repeated_double: 1.23E17\n" +
+ "repeated_double: 1.23E+17\n" +
+ "repeated_double: -1.23e-17\n" +
+ "repeated_double: .23e+17\n" +
+ "repeated_double: -.23E17\n" +
"repeated_double: 1.235E22\n" +
"repeated_double: 1.235E-18\n" +
"repeated_double: 123.456789\n" +
@@ -91,6 +97,10 @@ public class TextFormatTest extends TestCase {
"\\341\\210\\264\"\n" +
"repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
+ private static String canonicalExoticText =
+ exoticText.replace(": .", ": 0.").replace(": -.", ": -0.") // short-form double
+ .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16");
+
private String messageSetText =
"[protobuf_unittest.TestMessageSetExtension1] {\n" +
" i: 123\n" +
@@ -231,7 +241,13 @@ public class TextFormatTest extends TestCase {
.addRepeatedDouble(123)
.addRepeatedDouble(123.5)
.addRepeatedDouble(0.125)
+ .addRepeatedDouble(.125)
+ .addRepeatedDouble(-.125)
+ .addRepeatedDouble(123e15)
.addRepeatedDouble(123e15)
+ .addRepeatedDouble(-1.23e-17)
+ .addRepeatedDouble(.23e17)
+ .addRepeatedDouble(-23e15)
.addRepeatedDouble(123.5e20)
.addRepeatedDouble(123.5e-20)
.addRepeatedDouble(123.456789)
@@ -244,7 +260,7 @@ public class TextFormatTest extends TestCase {
.addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe"))
.build();
- assertEquals(exoticText, message.toString());
+ assertEquals(canonicalExoticText, message.toString());
}
public void testPrintMessageSet() throws Exception {
@@ -319,7 +335,7 @@ public class TextFormatTest extends TestCase {
// Too lazy to check things individually. Don't try to debug this
// if testPrintExotic() is failing.
- assertEquals(exoticText, builder.build().toString());
+ assertEquals(canonicalExoticText, builder.build().toString());
}
public void testParseMessageSet() throws Exception {
diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 6a5bd5de..5ea1dd6a 100644
--- a/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -235,6 +235,9 @@ public class WireFormatTest extends TestCase {
TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
assertEquals(34, input.read());
assertEquals(-1, input.read());
+
+ // We're at EOF, so parsing again should return null.
+ assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
}
private void assertFieldsInOrder(ByteString data) throws Exception {