aboutsummaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorFeng Xiao <xfxyjwf@gmail.com>2018-08-08 17:00:41 -0700
committerFeng Xiao <xfxyjwf@gmail.com>2018-08-08 17:00:41 -0700
commit6bbe197e9c1b6fc38cbdc45e3bf83fa7ced792a3 (patch)
treee575738adf52d24b883cca5e8928a5ded31caba1 /java
parente7746f487cb9cca685ffb1b3d7dccc5554b618a4 (diff)
downloadprotobuf-6bbe197e9c1b6fc38cbdc45e3bf83fa7ced792a3.tar.gz
protobuf-6bbe197e9c1b6fc38cbdc45e3bf83fa7ced792a3.tar.bz2
protobuf-6bbe197e9c1b6fc38cbdc45e3bf83fa7ced792a3.zip
Down-integrate from google3.
Diffstat (limited to 'java')
-rw-r--r--java/core/src/main/java/com/google/protobuf/AbstractMessage.java6
-rw-r--r--java/core/src/main/java/com/google/protobuf/BooleanArrayList.java3
-rw-r--r--java/core/src/main/java/com/google/protobuf/ByteString.java90
-rw-r--r--java/core/src/main/java/com/google/protobuf/CodedInputStream.java118
-rw-r--r--java/core/src/main/java/com/google/protobuf/DoubleArrayList.java3
-rw-r--r--java/core/src/main/java/com/google/protobuf/DynamicMessage.java8
-rw-r--r--java/core/src/main/java/com/google/protobuf/FloatArrayList.java3
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java3
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java107
-rw-r--r--java/core/src/main/java/com/google/protobuf/IntArrayList.java3
-rw-r--r--java/core/src/main/java/com/google/protobuf/Internal.java5
-rw-r--r--java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java32
-rw-r--r--java/core/src/main/java/com/google/protobuf/LongArrayList.java3
-rw-r--r--java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java18
-rw-r--r--java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java12
-rw-r--r--java/core/src/main/java/com/google/protobuf/TextFormat.java4
-rw-r--r--java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java17
-rw-r--r--java/core/src/main/java/com/google/protobuf/UnsafeUtil.java11
-rw-r--r--java/core/src/main/java/com/google/protobuf/Utf8.java5
-rw-r--r--java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java4
-rw-r--r--java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java8
-rw-r--r--java/core/src/test/java/com/google/protobuf/ByteStringTest.java66
-rw-r--r--java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java23
-rw-r--r--java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java50
-rw-r--r--java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java10
-rw-r--r--java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java50
-rw-r--r--java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java4
-rw-r--r--java/core/src/test/java/com/google/protobuf/IntArrayListTest.java8
-rw-r--r--java/core/src/test/java/com/google/protobuf/LiteTest.java61
-rw-r--r--java/core/src/test/java/com/google/protobuf/LongArrayListTest.java8
-rw-r--r--java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java204
-rw-r--r--java/core/src/test/java/com/google/protobuf/TestUtil.java37
-rw-r--r--java/core/src/test/java/com/google/protobuf/TextFormatTest.java25
-rw-r--r--java/core/src/test/java/com/google/protobuf/WireFormatTest.java4
-rw-r--r--java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto2
-rw-r--r--java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto1
-rw-r--r--java/core/src/test/proto/com/google/protobuf/map_lite_test.proto5
-rw-r--r--java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto1
-rw-r--r--java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto1
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/Durations.java3
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java16
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java2
-rw-r--r--java/util/src/main/java/com/google/protobuf/util/JsonFormat.java2
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java150
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java13
45 files changed, 797 insertions, 412 deletions
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
index fc3c2a5d..09aaed18 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -32,7 +32,6 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
import com.google.protobuf.Descriptors.OneofDescriptor;
import com.google.protobuf.Internal.EnumLite;
import java.io.IOException;
@@ -446,10 +445,7 @@ public abstract class AbstractMessage
final CodedInputStream input,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
- boolean discardUnknown =
- getDescriptorForType().getFile().getSyntax() == Syntax.PROTO3
- ? input.shouldDiscardUnknownFieldsProto3()
- : input.shouldDiscardUnknownFields();
+ boolean discardUnknown = input.shouldDiscardUnknownFields();
final UnknownFieldSet.Builder unknownFields =
discardUnknown ? null : UnknownFieldSet.newBuilder(getUnknownFields());
while (true) {
diff --git a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
index 4d7a9727..0dedb173 100644
--- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
@@ -42,7 +42,8 @@ import java.util.RandomAccess;
*
* @author dweis@google.com (Daniel Weis)
*/
-final class BooleanArrayList extends AbstractProtobufList<Boolean>
+final class BooleanArrayList
+ extends AbstractProtobufList<Boolean>
implements BooleanList, RandomAccess, PrimitiveNonBoxingCollection {
private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList();
diff --git a/java/core/src/main/java/com/google/protobuf/ByteString.java b/java/core/src/main/java/com/google/protobuf/ByteString.java
index d67bb54a..ddda0f26 100644
--- a/java/core/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/ByteString.java
@@ -46,6 +46,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
@@ -222,6 +223,67 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
}
// =================================================================
+ // Comparison
+
+ private static final int UNSIGNED_BYTE_MASK = 0xFF;
+
+ /**
+ * Returns the value of the given byte as an integer, interpreting the byte as an unsigned value.
+ * That is, returns {@code value + 256} if {@code value} is negative; {@code value} itself
+ * otherwise.
+ *
+ * <p>Note: This code was copied from {@link com.google.common.primitives.UnsignedBytes#toInt}, as
+ * Guava libraries cannot be used in the {@code com.google.protobuf} package.
+ */
+ private static int toInt(byte value) {
+ return value & UNSIGNED_BYTE_MASK;
+ }
+
+ /**
+ * Compares two {@link ByteString}s lexicographically, treating their contents as unsigned byte
+ * values between 0 and 255 (inclusive).
+ *
+ * <p>For example, {@code (byte) -1} is considered to be greater than {@code (byte) 1} because
+ * it is interpreted as an unsigned value, {@code 255}.
+ */
+ private static final Comparator<ByteString> UNSIGNED_LEXICOGRAPHICAL_COMPARATOR =
+ new Comparator<ByteString>() {
+ @Override
+ public int compare(ByteString former, ByteString latter) {
+ ByteIterator formerBytes = former.iterator();
+ ByteIterator latterBytes = latter.iterator();
+
+ while (formerBytes.hasNext() && latterBytes.hasNext()) {
+ // Note: This code was copied from com.google.common.primitives.UnsignedBytes#compare,
+ // as Guava libraries cannot be used in the {@code com.google.protobuf} package.
+ int result =
+ Integer.compare(toInt(formerBytes.nextByte()), toInt(latterBytes.nextByte()));
+ if (result != 0) {
+ return result;
+ }
+ }
+
+ return Integer.compare(former.size(), latter.size());
+ }
+ };
+
+ /**
+ * Returns a {@link Comparator<ByteString>} which compares {@link ByteString}-s lexicographically
+ * as sequences of unsigned bytes (i.e. values between 0 and 255, inclusive).
+ *
+ * <p>For example, {@code (byte) -1} is considered to be greater than {@code (byte) 1} because
+ * it is interpreted as an unsigned value, {@code 255}:
+ *
+ * <ul>
+ * <li>{@code `-1` -> 0b11111111 (two's complement) -> 255}
+ * <li>{@code `1` -> 0b00000001 -> 1}
+ * </ul>
+ */
+ public static Comparator<ByteString> unsignedLexicographicalComparator() {
+ return UNSIGNED_LEXICOGRAPHICAL_COMPARATOR;
+ }
+
+ // =================================================================
// ByteString -> substring
/**
@@ -287,8 +349,10 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* @param offset offset in source array
* @param size number of bytes to copy
* @return new {@code ByteString}
+ * @throws IndexOutOfBoundsException if {@code offset} or {@code size} are out of bounds
*/
public static ByteString copyFrom(byte[] bytes, int offset, int size) {
+ checkRange(offset, offset + size, bytes.length);
return new LiteralByteString(byteArrayCopier.copyFrom(bytes, offset, size));
}
@@ -339,8 +403,10 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* @param bytes source buffer
* @param size number of bytes to copy
* @return new {@code ByteString}
+ * @throws IndexOutOfBoundsException if {@code size > bytes.remaining()}
*/
public static ByteString copyFrom(ByteBuffer bytes, int size) {
+ checkRange(0, size, bytes.remaining());
byte[] copy = new byte[size];
bytes.get(copy);
return new LiteralByteString(copy);
@@ -578,6 +644,9 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
/**
* Copies bytes into a buffer at the given offset.
*
+ * <p>To copy a subset of bytes, you call this method on the return value of {@link
+ * #substring(int, int)}. Example: {@code byteString.substring(start, end).copyTo(target, offset)}
+ *
* @param target buffer to copy into
* @param offset in the target buffer
* @throws IndexOutOfBoundsException if the offset is negative or too large
@@ -589,15 +658,16 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
/**
* Copies bytes into a buffer.
*
- * @param target buffer to copy into
+ * @param target buffer to copy into
* @param sourceOffset offset within these bytes
* @param targetOffset offset within the target buffer
* @param numberToCopy number of bytes to copy
- * @throws IndexOutOfBoundsException if an offset or size is negative or too
- * large
+ * @throws IndexOutOfBoundsException if an offset or size is negative or too large
+ * @deprecation Instead, call {@code byteString.substring(sourceOffset, sourceOffset +
+ * numberToCopy).copyTo(target, targetOffset)}
*/
- public final void copyTo(byte[] target, int sourceOffset, int targetOffset,
- int numberToCopy) {
+ @Deprecated
+ public final void copyTo(byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
checkRange(sourceOffset, sourceOffset + numberToCopy, size());
checkRange(targetOffset, targetOffset + numberToCopy, target.length);
if (numberToCopy > 0) {
@@ -617,10 +687,13 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
/**
* Copies bytes into a ByteBuffer.
*
+ * <p>To copy a subset of bytes, you call this method on the return value of {@link
+ * #substring(int, int)}. Example: {@code byteString.substring(start, end).copyTo(target)}
+ *
* @param target ByteBuffer to copy into.
* @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only
- * @throws java.nio.BufferOverflowException if the {@code target}'s
- * remaining() space is not large enough to hold the data.
+ * @throws java.nio.BufferOverflowException if the {@code target}'s remaining() space is not large
+ * enough to hold the data.
*/
public abstract void copyTo(ByteBuffer target);
@@ -1258,6 +1331,9 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* @param bytes array to wrap
*/
LiteralByteString(byte[] bytes) {
+ if (bytes == null) {
+ throw new NullPointerException();
+ }
this.bytes = bytes;
}
diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
index 1297462e..4545d0ae 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -64,12 +64,6 @@ public abstract class CodedInputStream {
// Integer.MAX_VALUE == 0x7FFFFFF == INT_MAX from limits.h
private static final int DEFAULT_SIZE_LIMIT = Integer.MAX_VALUE;
- /**
- * Whether to enable our custom UTF-8 decode codepath which does not use {@link StringCoding}.
- * Currently disabled.
- */
- private static final boolean ENABLE_CUSTOM_UTF8_DECODE = false;
-
/** Visible for subclasses. See setRecursionLimit() */
int recursionDepth;
@@ -417,21 +411,7 @@ public abstract class CodedInputStream {
}
- private boolean explicitDiscardUnknownFields = false;
-
- private static volatile boolean proto3DiscardUnknownFieldsDefault = false;
-
- static void setProto3DiscardUnknownsByDefaultForTest() {
- proto3DiscardUnknownFieldsDefault = true;
- }
-
- static void setProto3KeepUnknownsByDefaultForTest() {
- proto3DiscardUnknownFieldsDefault = false;
- }
-
- static boolean getProto3DiscardUnknownFieldsDefault() {
- return proto3DiscardUnknownFieldsDefault;
- }
+ private boolean shouldDiscardUnknownFields = false;
/**
* Sets this {@code CodedInputStream} to discard unknown fields. Only applies to full runtime
@@ -442,7 +422,7 @@ public abstract class CodedInputStream {
* runtime.
*/
final void discardUnknownFields() {
- explicitDiscardUnknownFields = true;
+ shouldDiscardUnknownFields = true;
}
/**
@@ -450,7 +430,7 @@ public abstract class CodedInputStream {
* default.
*/
final void unsetDiscardUnknownFields() {
- explicitDiscardUnknownFields = false;
+ shouldDiscardUnknownFields = false;
}
/**
@@ -458,19 +438,7 @@ public abstract class CodedInputStream {
* runtime messages.
*/
final boolean shouldDiscardUnknownFields() {
- return explicitDiscardUnknownFields;
- }
-
- /**
- * Whether unknown fields in this input stream should be discarded during parsing for proto3 full
- * runtime messages.
- *
- * <p>This function was temporarily introduced before proto3 unknown fields behavior is changed.
- * TODO(liujisi): remove this and related code in GeneratedMessage after proto3 unknown
- * fields migration is done.
- */
- final boolean shouldDiscardUnknownFieldsProto3() {
- return explicitDiscardUnknownFields ? true : proto3DiscardUnknownFieldsDefault;
+ return shouldDiscardUnknownFields;
}
/**
@@ -831,19 +799,9 @@ public abstract class CodedInputStream {
public String readStringRequireUtf8() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= (limit - pos)) {
- if (ENABLE_CUSTOM_UTF8_DECODE) {
- String result = Utf8.decodeUtf8(buffer, pos, size);
- pos += size;
- return result;
- } else {
- // TODO(martinrb): We could save a pass by validating while decoding.
- if (!Utf8.isValidUtf8(buffer, pos, pos + size)) {
- throw InvalidProtocolBufferException.invalidUtf8();
- }
- final int tempPos = pos;
- pos += size;
- return new String(buffer, tempPos, size, UTF_8);
- }
+ String result = Utf8.decodeUtf8(buffer, pos, size);
+ pos += size;
+ return result;
}
if (size == 0) {
@@ -1559,25 +1517,10 @@ public abstract class CodedInputStream {
public String readStringRequireUtf8() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= remaining()) {
- if (ENABLE_CUSTOM_UTF8_DECODE) {
- final int bufferPos = bufferPos(pos);
- String result = Utf8.decodeUtf8(buffer, bufferPos, size);
- pos += size;
- return result;
- } else {
- // TODO(nathanmittler): Is there a way to avoid this copy?
- // The same as readBytes' logic
- byte[] bytes = new byte[size];
- UnsafeUtil.copyMemory(pos, bytes, 0, size);
- // TODO(martinrb): We could save a pass by validating while decoding.
- if (!Utf8.isValidUtf8(bytes)) {
- throw InvalidProtocolBufferException.invalidUtf8();
- }
-
- String result = new String(bytes, UTF_8);
- pos += size;
- return result;
- }
+ final int bufferPos = bufferPos(pos);
+ String result = Utf8.decodeUtf8(buffer, bufferPos, size);
+ pos += size;
+ return result;
}
if (size == 0) {
@@ -2345,15 +2288,7 @@ public abstract class CodedInputStream {
bytes = readRawBytesSlowPath(size);
tempPos = 0;
}
- if (ENABLE_CUSTOM_UTF8_DECODE) {
- return Utf8.decodeUtf8(bytes, tempPos, size);
- } else {
- // TODO(martinrb): We could save a pass by validating while decoding.
- if (!Utf8.isValidUtf8(bytes, tempPos, tempPos + size)) {
- throw InvalidProtocolBufferException.invalidUtf8();
- }
- return new String(bytes, tempPos, size, UTF_8);
- }
+ return Utf8.decodeUtf8(bytes, tempPos, size);
}
@Override
@@ -3373,34 +3308,15 @@ public abstract class CodedInputStream {
public String readStringRequireUtf8() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) {
- if (ENABLE_CUSTOM_UTF8_DECODE) {
- final int bufferPos = (int) (currentByteBufferPos - currentByteBufferStartPos);
- String result = Utf8.decodeUtf8(currentByteBuffer, bufferPos, size);
- currentByteBufferPos += size;
- return result;
- } else {
- byte[] bytes = new byte[size];
- UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size);
- if (!Utf8.isValidUtf8(bytes)) {
- throw InvalidProtocolBufferException.invalidUtf8();
- }
- String result = new String(bytes, UTF_8);
- currentByteBufferPos += size;
- return result;
- }
+ final int bufferPos = (int) (currentByteBufferPos - currentByteBufferStartPos);
+ String result = Utf8.decodeUtf8(currentByteBuffer, bufferPos, size);
+ currentByteBufferPos += size;
+ return result;
}
if (size >= 0 && size <= remaining()) {
byte[] bytes = new byte[size];
readRawBytesTo(bytes, 0, size);
- if (ENABLE_CUSTOM_UTF8_DECODE) {
- return Utf8.decodeUtf8(bytes, 0, size);
- } else {
- if (!Utf8.isValidUtf8(bytes)) {
- throw InvalidProtocolBufferException.invalidUtf8();
- }
- String result = new String(bytes, UTF_8);
- return result;
- }
+ return Utf8.decodeUtf8(bytes, 0, size);
}
if (size == 0) {
diff --git a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
index 5b28b4a8..8d987b2e 100644
--- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
@@ -42,7 +42,8 @@ import java.util.RandomAccess;
*
* @author dweis@google.com (Daniel Weis)
*/
-final class DoubleArrayList extends AbstractProtobufList<Double>
+final class DoubleArrayList
+ extends AbstractProtobufList<Double>
implements DoubleList, RandomAccess, PrimitiveNonBoxingCollection {
private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList();
diff --git a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
index a6a774b7..2c346e03 100644
--- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -608,20 +608,12 @@ public final class DynamicMessage extends AbstractMessage {
@Override
public Builder setUnknownFields(UnknownFieldSet unknownFields) {
- if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3
- && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
- return this;
- }
this.unknownFields = unknownFields;
return this;
}
@Override
public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
- if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3
- && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
- return this;
- }
this.unknownFields =
UnknownFieldSet.newBuilder(this.unknownFields)
.mergeFrom(unknownFields)
diff --git a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
index 7c080af3..41749f6d 100644
--- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
@@ -42,7 +42,8 @@ import java.util.RandomAccess;
*
* @author dweis@google.com (Daniel Weis)
*/
-final class FloatArrayList extends AbstractProtobufList<Float>
+final class FloatArrayList
+ extends AbstractProtobufList<Float>
implements FloatList, RandomAccess, PrimitiveNonBoxingCollection {
private static final FloatArrayList EMPTY_LIST = new FloatArrayList();
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index df01547e..35b31f15 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -33,7 +33,6 @@ package com.google.protobuf;
import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
import com.google.protobuf.Internal.BooleanList;
import com.google.protobuf.Internal.DoubleList;
-import com.google.protobuf.Internal.EnumLiteMap;
import com.google.protobuf.Internal.FloatList;
import com.google.protobuf.Internal.IntList;
import com.google.protobuf.Internal.LongList;
@@ -1600,7 +1599,7 @@ public abstract class GeneratedMessageLite<
protected static class DefaultInstanceBasedParser<T extends GeneratedMessageLite<T, ?>>
extends AbstractParser<T> {
- private T defaultInstance;
+ private final T defaultInstance;
public DefaultInstanceBasedParser(T defaultInstance) {
this.defaultInstance = defaultInstance;
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
index 4acd8f2f..53af544f 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -38,6 +38,11 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.Internal.BooleanList;
+import com.google.protobuf.Internal.DoubleList;
+import com.google.protobuf.Internal.FloatList;
+import com.google.protobuf.Internal.IntList;
+import com.google.protobuf.Internal.LongList;
// In opensource protobuf, we have versioned this GeneratedMessageV3 class to GeneratedMessageV3V3 and
// in the future may have GeneratedMessageV3V4 etc. This allows us to change some aspects of this
// class without breaking binary compatibility with old generated code that still subclasses
@@ -293,16 +298,17 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return unknownFields.mergeFieldFrom(tag, input);
}
+ /**
+ * Delegates to parseUnknownField. This method is obsolete, but we must retain it for
+ * compatibility with older generated code.
+ */
protected boolean parseUnknownFieldProto3(
CodedInputStream input,
UnknownFieldSet.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag)
throws IOException {
- if (input.shouldDiscardUnknownFieldsProto3()) {
- return input.skipField(tag);
- }
- return unknownFields.mergeFieldFrom(tag, input);
+ return parseUnknownField(input, unknownFields, extensionRegistry, tag);
}
protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input)
@@ -363,6 +369,76 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return UnsafeUtil.hasUnsafeArrayOperations() && UnsafeUtil.hasUnsafeByteBufferOperations();
}
+ protected static IntList emptyIntList() {
+ return IntArrayList.emptyList();
+ }
+
+ protected static IntList newIntList() {
+ return new IntArrayList();
+ }
+
+ protected static IntList mutableCopy(IntList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ protected static LongList emptyLongList() {
+ return LongArrayList.emptyList();
+ }
+
+ protected static LongList newLongList() {
+ return new LongArrayList();
+ }
+
+ protected static LongList mutableCopy(LongList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ protected static FloatList emptyFloatList() {
+ return FloatArrayList.emptyList();
+ }
+
+ protected static FloatList newFloatList() {
+ return new FloatArrayList();
+ }
+
+ protected static FloatList mutableCopy(FloatList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ protected static DoubleList emptyDoubleList() {
+ return DoubleArrayList.emptyList();
+ }
+
+ protected static DoubleList newDoubleList() {
+ return new DoubleArrayList();
+ }
+
+ protected static DoubleList mutableCopy(DoubleList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ protected static BooleanList emptyBooleanList() {
+ return BooleanArrayList.emptyList();
+ }
+
+ protected static BooleanList newBooleanList() {
+ return new BooleanArrayList();
+ }
+
+ protected static BooleanList mutableCopy(BooleanList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
@Override
public void writeTo(final CodedOutputStream output) throws IOException {
MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false);
@@ -641,13 +717,12 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return (BuilderType) this;
}
+ /**
+ * Delegates to setUnknownFields. This method is obsolete, but we must retain it for
+ * compatibility with older generated code.
+ */
protected BuilderType setUnknownFieldsProto3(final UnknownFieldSet unknownFields) {
- if (CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
- return (BuilderType) this;
- }
- this.unknownFields = unknownFields;
- onChanged();
- return (BuilderType) this;
+ return setUnknownFields(unknownFields);
}
@Override
@@ -1009,19 +1084,17 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
getDescriptorForType(), new MessageReflection.ExtensionAdapter(extensions), tag);
}
+ /**
+ * Delegates to parseUnknownField. This method is obsolete, but we must retain it for
+ * compatibility with older generated code.
+ */
@Override
protected boolean parseUnknownFieldProto3(
CodedInputStream input,
UnknownFieldSet.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
- return MessageReflection.mergeFieldFrom(
- input,
- input.shouldDiscardUnknownFieldsProto3() ? null : unknownFields,
- extensionRegistry,
- getDescriptorForType(),
- new MessageReflection.ExtensionAdapter(extensions),
- tag);
+ return parseUnknownField(input, unknownFields, extensionRegistry, tag);
}
diff --git a/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/java/core/src/main/java/com/google/protobuf/IntArrayList.java
index aacd71e1..4993eea7 100644
--- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java
@@ -42,7 +42,8 @@ import java.util.RandomAccess;
*
* @author dweis@google.com (Daniel Weis)
*/
-final class IntArrayList extends AbstractProtobufList<Integer>
+final class IntArrayList
+ extends AbstractProtobufList<Integer>
implements IntList, RandomAccess, PrimitiveNonBoxingCollection {
private static final IntArrayList EMPTY_LIST = new IntArrayList();
diff --git a/java/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java
index 848cad03..878573d5 100644
--- a/java/core/src/main/java/com/google/protobuf/Internal.java
+++ b/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -234,6 +234,11 @@ public final class Internal {
T findValueByNumber(int number);
}
+ /** Interface for an object which verifies integers are in range. */
+ public interface EnumVerifier {
+ boolean isInRange(int number);
+ }
+
/**
* Helper method for implementing {@link Message#hashCode()} for longs.
* @see Long#hashCode()
diff --git a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
index d474c51e..6cfc14a5 100644
--- a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -69,7 +69,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
static {
EMPTY_LIST.makeImmutable();
}
-
+
static LazyStringArrayList emptyList() {
return EMPTY_LIST;
}
@@ -83,8 +83,8 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
this(DEFAULT_CAPACITY);
}
- public LazyStringArrayList(int intialCapacity) {
- this(new ArrayList<Object>(intialCapacity));
+ public LazyStringArrayList(int initialCapacity) {
+ this(new ArrayList<Object>(initialCapacity));
}
public LazyStringArrayList(LazyStringList from) {
@@ -95,7 +95,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
public LazyStringArrayList(List<String> from) {
this(new ArrayList<Object>(from));
}
-
+
private LazyStringArrayList(ArrayList<Object> list) {
this.list = list;
}
@@ -150,13 +150,13 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
list.add(index, element);
modCount++;
}
-
+
private void add(int index, ByteString element) {
ensureIsMutable();
list.add(index, element);
modCount++;
}
-
+
private void add(int index, byte[] element) {
ensureIsMutable();
list.add(index, element);
@@ -221,7 +221,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
list.add(element);
modCount++;
}
-
+
@Override
public void add(byte[] element) {
ensureIsMutable();
@@ -233,7 +233,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
public Object getRaw(int index) {
return list.get(index);
}
-
+
@Override
public ByteString getByteString(int index) {
Object o = list.get(index);
@@ -243,7 +243,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
}
return b;
}
-
+
@Override
public byte[] getByteArray(int index) {
Object o = list.get(index);
@@ -258,7 +258,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
public void set(int index, ByteString s) {
setAndReturn(index, s);
}
-
+
private Object setAndReturn(int index, ByteString s) {
ensureIsMutable();
return list.set(index, s);
@@ -268,7 +268,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
public void set(int index, byte[] s) {
setAndReturn(index, s);
}
-
+
private Object setAndReturn(int index, byte[] s) {
ensureIsMutable();
return list.set(index, s);
@@ -283,7 +283,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
return Internal.toStringUtf8((byte[]) o);
}
}
-
+
private static ByteString asByteString(Object o) {
if (o instanceof ByteString) {
return (ByteString) o;
@@ -293,7 +293,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
return ByteString.copyFrom((byte[]) o);
}
}
-
+
private static byte[] asByteArray(Object o) {
if (o instanceof byte[]) {
return (byte[]) o;
@@ -327,11 +327,11 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
private static class ByteArrayListView extends AbstractList<byte[]>
implements RandomAccess {
private final LazyStringArrayList list;
-
+
ByteArrayListView(LazyStringArrayList list) {
this.list = list;
}
-
+
@Override
public byte[] get(int index) {
return list.getByteArray(index);
@@ -362,7 +362,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
return asByteArray(o);
}
}
-
+
@Override
public List<byte[]> asByteArrayList() {
return new ByteArrayListView(this);
diff --git a/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/java/core/src/main/java/com/google/protobuf/LongArrayList.java
index 95945cb7..9a5056be 100644
--- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java
@@ -42,7 +42,8 @@ import java.util.RandomAccess;
*
* @author dweis@google.com (Daniel Weis)
*/
-final class LongArrayList extends AbstractProtobufList<Long>
+final class LongArrayList
+ extends AbstractProtobufList<Long>
implements LongList, RandomAccess, PrimitiveNonBoxingCollection {
private static final LongArrayList EMPTY_LIST = new LongArrayList();
diff --git a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
index 29f567dc..b593b566 100644
--- a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -30,6 +30,8 @@
package com.google.protobuf;
+import static com.google.protobuf.Internal.checkNotNull;
+
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
@@ -290,9 +292,7 @@ public class RepeatedFieldBuilder
*/
public RepeatedFieldBuilder<MType, BType, IType> setMessage(
int index, MType message) {
- if (message == null) {
- throw new NullPointerException();
- }
+ checkNotNull(message);
ensureMutableMessageList();
messages.set(index, message);
if (builders != null) {
@@ -315,9 +315,7 @@ public class RepeatedFieldBuilder
*/
public RepeatedFieldBuilder<MType, BType, IType> addMessage(
MType message) {
- if (message == null) {
- throw new NullPointerException();
- }
+ checkNotNull(message);
ensureMutableMessageList();
messages.add(message);
if (builders != null) {
@@ -339,9 +337,7 @@ public class RepeatedFieldBuilder
*/
public RepeatedFieldBuilder<MType, BType, IType> addMessage(
int index, MType message) {
- if (message == null) {
- throw new NullPointerException();
- }
+ checkNotNull(message);
ensureMutableMessageList();
messages.add(index, message);
if (builders != null) {
@@ -363,9 +359,7 @@ public class RepeatedFieldBuilder
public RepeatedFieldBuilder<MType, BType, IType> addAllMessages(
Iterable<? extends MType> values) {
for (final MType value : values) {
- if (value == null) {
- throw new NullPointerException();
- }
+ checkNotNull(value);
}
// If we can inspect the size, we can more efficiently add messages.
diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
index 941b5def..1f5ec8a2 100644
--- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
@@ -30,6 +30,8 @@
package com.google.protobuf;
+import static com.google.protobuf.Internal.checkNotNull;
+
/**
* {@code SingleFieldBuilder} implements a structure that a protocol
* message uses to hold a single field of another protocol message. It supports
@@ -84,10 +86,7 @@ public class SingleFieldBuilder
MType message,
GeneratedMessage.BuilderParent parent,
boolean isClean) {
- if (message == null) {
- throw new NullPointerException();
- }
- this.message = message;
+ this.message = checkNotNull(message);
this.parent = parent;
this.isClean = isClean;
}
@@ -169,10 +168,7 @@ public class SingleFieldBuilder
*/
public SingleFieldBuilder<MType, BType, IType> setMessage(
MType message) {
- if (message == null) {
- throw new NullPointerException();
- }
- this.message = message;
+ this.message = checkNotNull(message);
if (builder != null) {
builder.dispose();
builder = null;
diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java
index 25c3474f..79962e08 100644
--- a/java/core/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -1444,8 +1444,8 @@ public final class TextFormat {
logger.warning(msg.toString());
} else {
String[] lineColumn = unknownFields.get(0).split(":");
- throw new ParseException(Integer.valueOf(lineColumn[0]),
- Integer.valueOf(lineColumn[1]), msg.toString());
+ throw new ParseException(
+ Integer.parseInt(lineColumn[0]), Integer.parseInt(lineColumn[1]), msg.toString());
}
}
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 37d64633..b3fdebcb 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -786,6 +786,23 @@ public final class UnknownFieldSet implements MessageLite {
}
/**
+ * Serializes the message to a {@code ByteString} and returns it. This is just a trivial wrapper
+ * around {@link #writeTo(int, CodedOutputStream)}.
+ */
+ public ByteString toByteString(int fieldNumber) {
+ try {
+ // TODO(lukes): consider caching serialized size in a volatile long
+ final ByteString.CodedBuilder out =
+ ByteString.newCodedBuilder(getSerializedSize(fieldNumber));
+ writeTo(fieldNumber, out.getCodedOutput());
+ return out.build();
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Serializing to a ByteString should never fail with an IOException", e);
+ }
+ }
+
+ /**
* Serializes the field, including field number, and writes it to
* {@code output}.
*/
diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
index d84ef3c5..f822ce51 100644
--- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
+++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
@@ -33,6 +33,7 @@ package com.google.protobuf;
import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.logging.Level;
@@ -146,6 +147,10 @@ final class UnsafeUtil {
return MEMORY_ACCESSOR.getObject(target, offset);
}
+ static void putObject(Object target, long offset, Object value) {
+ MEMORY_ACCESSOR.putObject(target, offset, value);
+ }
+
static byte getByte(byte[] target, long index) {
return MEMORY_ACCESSOR.getByte(target, BYTE_ARRAY_BASE_OFFSET + index);
}
@@ -370,12 +375,6 @@ final class UnsafeUtil {
return field != null && field.getType() == long.class ? field : null;
}
- /** Finds the value field within a {@link String}. */
- private static Field stringValueField() {
- Field field = field(String.class, "value");
- return field != null && field.getType() == char[].class ? field : null;
- }
-
/**
* Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not
* available.
diff --git a/java/core/src/main/java/com/google/protobuf/Utf8.java b/java/core/src/main/java/com/google/protobuf/Utf8.java
index de75fe6b..b4a81ca3 100644
--- a/java/core/src/main/java/com/google/protobuf/Utf8.java
+++ b/java/core/src/main/java/com/google/protobuf/Utf8.java
@@ -42,7 +42,6 @@ import static java.lang.Character.isSurrogatePair;
import static java.lang.Character.toCodePoint;
import java.nio.ByteBuffer;
-import java.util.Arrays;
/**
* A set of low-level, high-performance static utility methods related
@@ -87,7 +86,9 @@ final class Utf8 {
* delegate for which all methods are delegated directly to.
*/
private static final Processor processor =
- UnsafeProcessor.isAvailable() ? new UnsafeProcessor() : new SafeProcessor();
+ (UnsafeProcessor.isAvailable() && !Android.isOnAndroidDevice())
+ ? new UnsafeProcessor()
+ : new SafeProcessor();
/**
* A mask used when performing unsafe reads to determine if a long value contains any non-ASCII
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
index cb2d34eb..bb11bd0f 100644
--- a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -210,8 +210,8 @@ public class AbstractMessageTest extends TestCase {
new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
TestUtil.ReflectionTester extensionsReflectionTester =
- new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
- TestUtil.getExtensionRegistry());
+ new TestUtil.ReflectionTester(
+ TestAllExtensions.getDescriptor(), TestUtil.getFullExtensionRegistry());
public void testClear() throws Exception {
AbstractMessageWrapper message =
diff --git a/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java b/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
index 4906763c..febe8537 100644
--- a/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
+++ b/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
@@ -299,20 +299,22 @@ public class BooleanArrayListTest extends TestCase {
}
public void testRemoveEndOfCapacity() {
- BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(1);
+ BooleanList toRemove =
+ BooleanArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addBoolean(true);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
- BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(1);
+ BooleanList toRemove =
+ BooleanArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addBoolean(true);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
- private void assertImmutable(BooleanArrayList list) {
+ private void assertImmutable(BooleanList list) {
try {
list.add(true);
diff --git a/java/core/src/test/java/com/google/protobuf/ByteStringTest.java b/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
index be71f1f5..fc22955d 100644
--- a/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
+++ b/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
@@ -41,6 +41,7 @@ import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
@@ -86,6 +87,40 @@ public class ByteStringTest extends TestCase {
return left.length == right.length && isArrayRange(left, right, 0, left.length);
}
+ public void testCompare_equalByteStrings_compareEqual() throws Exception {
+ byte[] referenceBytes = getTestBytes();
+ ByteString string1 = ByteString.copyFrom(referenceBytes);
+ ByteString string2 = ByteString.copyFrom(referenceBytes);
+
+ assertEquals(
+ "ByteString instances containing the same data must compare equal.",
+ 0,
+ ByteString.unsignedLexicographicalComparator().compare(string1, string2));
+ }
+
+ public void testCompare_byteStringsSortLexicographically() throws Exception {
+ ByteString app = ByteString.copyFromUtf8("app");
+ ByteString apple = ByteString.copyFromUtf8("apple");
+ ByteString banana = ByteString.copyFromUtf8("banana");
+
+ Comparator<ByteString> comparator = ByteString.unsignedLexicographicalComparator();
+
+ assertTrue("ByteString(app) < ByteString(apple)", comparator.compare(app, apple) < 0);
+ assertTrue("ByteString(app) < ByteString(banana)", comparator.compare(app, banana) < 0);
+ assertTrue("ByteString(apple) < ByteString(banana)", comparator.compare(apple, banana) < 0);
+ }
+
+ public void testCompare_interpretsByteValuesAsUnsigned() throws Exception {
+ // Two's compliment of `-1` == 0b11111111 == 255
+ ByteString twoHundredFiftyFive = ByteString.copyFrom(new byte[] {-1});
+ // 0b00000001 == 1
+ ByteString one = ByteString.copyFrom(new byte[] {1});
+
+ assertTrue(
+ "ByteString comparison treats bytes as unsigned values",
+ ByteString.unsignedLexicographicalComparator().compare(one, twoHundredFiftyFive) < 0);
+ }
+
public void testSubstring_BeginIndex() {
byte[] bytes = getTestBytes();
ByteString substring = ByteString.copyFrom(bytes).substring(500);
@@ -161,6 +196,34 @@ public class ByteStringTest extends TestCase {
byteString, byteStringAlt);
}
+ public void testCopyFrom_LengthTooBig() {
+ byte[] testBytes = getTestBytes(100);
+ try {
+ ByteString.copyFrom(testBytes, 0, 200);
+ fail("Should throw");
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ ByteString.copyFrom(testBytes, 99, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ ByteBuffer buf = ByteBuffer.wrap(testBytes);
+ try {
+ ByteString.copyFrom(buf, 101);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ ByteString.copyFrom(testBytes, -1, 10);
+ fail("Should throw");
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ }
+
public void testCopyTo_TargetOffset() {
byte[] bytes = getTestBytes();
ByteString byteString = ByteString.copyFrom(bytes);
@@ -761,6 +824,9 @@ public class ByteStringTest extends TestCase {
* Tests ByteString uses Arrays based byte copier when running under Hotstop VM.
*/
public void testByteArrayCopier() throws Exception {
+ if (Android.isOnAndroidDevice()) {
+ return;
+ }
Field field = ByteString.class.getDeclaredField("byteArrayCopier");
field.setAccessible(true);
Object byteArrayCopier = field.get(null);
diff --git a/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java b/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java
index 0f09a51b..36c4611f 100644
--- a/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java
@@ -62,22 +62,17 @@ public class DiscardUnknownFieldsTest {
}
private static void testProto2Message(Message message) throws Exception {
- assertUnknownFieldsDefaultPreserved(message);
+ assertUnknownFieldsPreserved(message);
assertUnknownFieldsExplicitlyDiscarded(message);
assertReuseCodedInputStreamPreserve(message);
assertUnknownFieldsInUnknownFieldSetArePreserve(message);
}
private static void testProto3Message(Message message) throws Exception {
- CodedInputStream.setProto3KeepUnknownsByDefaultForTest();
- assertUnknownFieldsDefaultPreserved(message);
+ assertUnknownFieldsPreserved(message);
assertUnknownFieldsExplicitlyDiscarded(message);
assertReuseCodedInputStreamPreserve(message);
assertUnknownFieldsInUnknownFieldSetArePreserve(message);
- CodedInputStream.setProto3DiscardUnknownsByDefaultForTest();
- assertUnknownFieldsDefaultDiscarded(message);
- assertUnknownFieldsExplicitlyDiscarded(message);
- assertUnknownFieldsInUnknownFieldSetAreDiscarded(message);
}
private static void assertReuseCodedInputStreamPreserve(Message message) throws Exception {
@@ -122,7 +117,7 @@ public class DiscardUnknownFieldsTest {
assertEquals(message.getClass().getName(), 0, built.getSerializedSize());
}
- private static void assertUnknownFieldsDefaultPreserved(MessageLite message) throws Exception {
+ private static void assertUnknownFieldsPreserved(MessageLite message) throws Exception {
{
MessageLite parsed = message.getParserForType().parseFrom(payload);
assertEquals(message.getClass().getName(), payload, parsed.toByteString());
@@ -134,18 +129,6 @@ public class DiscardUnknownFieldsTest {
}
}
- private static void assertUnknownFieldsDefaultDiscarded(MessageLite message) throws Exception {
- {
- MessageLite parsed = message.getParserForType().parseFrom(payload);
- assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
- }
-
- {
- MessageLite parsed = message.newBuilderForType().mergeFrom(payload).build();
- assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
- }
- }
-
private static void assertUnknownFieldsExplicitlyDiscarded(Message message) throws Exception {
Message parsed =
DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(payload);
diff --git a/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java b/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
index 923d7f43..a4c2f5aa 100644
--- a/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
@@ -78,10 +78,10 @@ public class DoubleArrayListTest extends TestCase {
list.addAll(asList(1D, 2D, 3D, 4D));
Iterator<Double> iterator = list.iterator();
assertEquals(4, list.size());
- assertEquals(1D, (double) list.get(0));
- assertEquals(1D, (double) iterator.next());
+ assertEquals(1D, (double) list.get(0), 0.0);
+ assertEquals(1D, (double) iterator.next(), 0.0);
list.set(0, 1D);
- assertEquals(2D, (double) iterator.next());
+ assertEquals(2D, (double) iterator.next(), 0.0);
list.remove(0);
try {
@@ -102,9 +102,9 @@ public class DoubleArrayListTest extends TestCase {
}
public void testGet() {
- assertEquals(1D, (double) TERTIARY_LIST.get(0));
- assertEquals(2D, (double) TERTIARY_LIST.get(1));
- assertEquals(3D, (double) TERTIARY_LIST.get(2));
+ assertEquals(1D, (double) TERTIARY_LIST.get(0), 0.0);
+ assertEquals(2D, (double) TERTIARY_LIST.get(1), 0.0);
+ assertEquals(3D, (double) TERTIARY_LIST.get(2), 0.0);
try {
TERTIARY_LIST.get(-1);
@@ -122,9 +122,9 @@ public class DoubleArrayListTest extends TestCase {
}
public void testGetDouble() {
- assertEquals(1D, TERTIARY_LIST.getDouble(0));
- assertEquals(2D, TERTIARY_LIST.getDouble(1));
- assertEquals(3D, TERTIARY_LIST.getDouble(2));
+ assertEquals(1D, TERTIARY_LIST.getDouble(0), 0.0);
+ assertEquals(2D, TERTIARY_LIST.getDouble(1), 0.0);
+ assertEquals(3D, TERTIARY_LIST.getDouble(2), 0.0);
try {
TERTIARY_LIST.get(-1);
@@ -163,11 +163,11 @@ public class DoubleArrayListTest extends TestCase {
list.addDouble(2);
list.addDouble(4);
- assertEquals(2D, (double) list.set(0, 3D));
- assertEquals(3D, list.getDouble(0));
+ assertEquals(2D, (double) list.set(0, 3D), 0.0);
+ assertEquals(3D, list.getDouble(0), 0.0);
- assertEquals(4D, (double) list.set(1, 0D));
- assertEquals(0D, list.getDouble(1));
+ assertEquals(4D, (double) list.set(1, 0D), 0.0);
+ assertEquals(0D, list.getDouble(1), 0.0);
try {
list.set(-1, 0D);
@@ -188,11 +188,11 @@ public class DoubleArrayListTest extends TestCase {
list.addDouble(1);
list.addDouble(3);
- assertEquals(1D, list.setDouble(0, 0));
- assertEquals(0D, list.getDouble(0));
+ assertEquals(1D, list.setDouble(0, 0), 0.0);
+ assertEquals(0D, list.getDouble(0), 0.0);
- assertEquals(3D, list.setDouble(1, 0));
- assertEquals(0D, list.getDouble(1));
+ assertEquals(3D, list.setDouble(1, 0), 0.0);
+ assertEquals(0D, list.getDouble(1), 0.0);
try {
list.setDouble(-1, 0);
@@ -257,8 +257,8 @@ public class DoubleArrayListTest extends TestCase {
assertTrue(list.addAll(Collections.singleton(1D)));
assertEquals(1, list.size());
- assertEquals(1D, (double) list.get(0));
- assertEquals(1D, list.getDouble(0));
+ assertEquals(1D, (double) list.get(0), 0.0);
+ assertEquals(1D, list.getDouble(0), 0.0);
assertTrue(list.addAll(asList(2D, 3D, 4D, 5D, 6D)));
assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D), list);
@@ -272,7 +272,7 @@ public class DoubleArrayListTest extends TestCase {
public void testRemove() {
list.addAll(TERTIARY_LIST);
- assertEquals(1D, (double) list.remove(0));
+ assertEquals(1D, (double) list.remove(0), 0.0);
assertEquals(asList(2D, 3D), list);
assertTrue(list.remove(Double.valueOf(3)));
@@ -281,7 +281,7 @@ public class DoubleArrayListTest extends TestCase {
assertFalse(list.remove(Double.valueOf(3)));
assertEquals(asList(2D), list);
- assertEquals(2D, (double) list.remove(0));
+ assertEquals(2D, (double) list.remove(0), 0.0);
assertEquals(asList(), list);
try {
@@ -299,20 +299,22 @@ public class DoubleArrayListTest extends TestCase {
}
public void testRemoveEndOfCapacity() {
- DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(1);
+ DoubleList toRemove =
+ DoubleArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addDouble(3);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
- DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(1);
+ DoubleList toRemove =
+ DoubleArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addDouble(3);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
- private void assertImmutable(DoubleArrayList list) {
+ private void assertImmutable(DoubleList list) {
if (list.contains(1D)) {
throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
}
diff --git a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
index 77d14f6b..346c1e6a 100644
--- a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -51,8 +51,8 @@ public class DynamicMessageTest extends TestCase {
new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
TestUtil.ReflectionTester extensionsReflectionTester =
- new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
- TestUtil.getExtensionRegistry());
+ new TestUtil.ReflectionTester(
+ TestAllExtensions.getDescriptor(), TestUtil.getFullExtensionRegistry());
TestUtil.ReflectionTester packedReflectionTester =
new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null);
@@ -194,9 +194,9 @@ public class DynamicMessageTest extends TestCase {
public void testDynamicMessageExtensionParsing() throws Exception {
ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString();
- Message message = DynamicMessage.parseFrom(
- TestAllExtensions.getDescriptor(), rawBytes,
- TestUtil.getExtensionRegistry());
+ Message message =
+ DynamicMessage.parseFrom(
+ TestAllExtensions.getDescriptor(), rawBytes, TestUtil.getFullExtensionRegistry());
extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
// Test Parser interface.
diff --git a/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java b/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
index 903a79db..38eccc93 100644
--- a/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
+++ b/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
@@ -78,10 +78,10 @@ public class FloatArrayListTest extends TestCase {
list.addAll(asList(1F, 2F, 3F, 4F));
Iterator<Float> iterator = list.iterator();
assertEquals(4, list.size());
- assertEquals(1F, (float) list.get(0));
- assertEquals(1F, (float) iterator.next());
+ assertEquals(1F, (float) list.get(0), 0.0f);
+ assertEquals(1F, (float) iterator.next(), 0.0f);
list.set(0, 1F);
- assertEquals(2F, (float) iterator.next());
+ assertEquals(2F, (float) iterator.next(), 0.0f);
list.remove(0);
try {
@@ -102,9 +102,9 @@ public class FloatArrayListTest extends TestCase {
}
public void testGet() {
- assertEquals(1F, (float) TERTIARY_LIST.get(0));
- assertEquals(2F, (float) TERTIARY_LIST.get(1));
- assertEquals(3F, (float) TERTIARY_LIST.get(2));
+ assertEquals(1F, (float) TERTIARY_LIST.get(0), 0.0f);
+ assertEquals(2F, (float) TERTIARY_LIST.get(1), 0.0f);
+ assertEquals(3F, (float) TERTIARY_LIST.get(2), 0.0f);
try {
TERTIARY_LIST.get(-1);
@@ -122,9 +122,9 @@ public class FloatArrayListTest extends TestCase {
}
public void testGetFloat() {
- assertEquals(1F, TERTIARY_LIST.getFloat(0));
- assertEquals(2F, TERTIARY_LIST.getFloat(1));
- assertEquals(3F, TERTIARY_LIST.getFloat(2));
+ assertEquals(1F, TERTIARY_LIST.getFloat(0), 0.0f);
+ assertEquals(2F, TERTIARY_LIST.getFloat(1), 0.0f);
+ assertEquals(3F, TERTIARY_LIST.getFloat(2), 0.0f);
try {
TERTIARY_LIST.get(-1);
@@ -163,11 +163,11 @@ public class FloatArrayListTest extends TestCase {
list.addFloat(2);
list.addFloat(4);
- assertEquals(2F, (float) list.set(0, 3F));
- assertEquals(3F, list.getFloat(0));
+ assertEquals(2F, (float) list.set(0, 3F), 0.0f);
+ assertEquals(3F, list.getFloat(0), 0.0f);
- assertEquals(4F, (float) list.set(1, 0F));
- assertEquals(0F, list.getFloat(1));
+ assertEquals(4F, (float) list.set(1, 0F), 0.0f);
+ assertEquals(0F, list.getFloat(1), 0.0f);
try {
list.set(-1, 0F);
@@ -188,11 +188,11 @@ public class FloatArrayListTest extends TestCase {
list.addFloat(1);
list.addFloat(3);
- assertEquals(1F, list.setFloat(0, 0));
- assertEquals(0F, list.getFloat(0));
+ assertEquals(1F, list.setFloat(0, 0), 0.0f);
+ assertEquals(0F, list.getFloat(0), 0.0f);
- assertEquals(3F, list.setFloat(1, 0));
- assertEquals(0F, list.getFloat(1));
+ assertEquals(3F, list.setFloat(1, 0), 0.0f);
+ assertEquals(0F, list.getFloat(1), 0.0f);
try {
list.setFloat(-1, 0);
@@ -257,8 +257,8 @@ public class FloatArrayListTest extends TestCase {
assertTrue(list.addAll(Collections.singleton(1F)));
assertEquals(1, list.size());
- assertEquals(1F, (float) list.get(0));
- assertEquals(1F, list.getFloat(0));
+ assertEquals(1F, (float) list.get(0), 0.0f);
+ assertEquals(1F, list.getFloat(0), 0.0f);
assertTrue(list.addAll(asList(2F, 3F, 4F, 5F, 6F)));
assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F), list);
@@ -272,7 +272,7 @@ public class FloatArrayListTest extends TestCase {
public void testRemove() {
list.addAll(TERTIARY_LIST);
- assertEquals(1F, (float) list.remove(0));
+ assertEquals(1F, (float) list.remove(0), 0.0f);
assertEquals(asList(2F, 3F), list);
assertTrue(list.remove(Float.valueOf(3)));
@@ -281,7 +281,7 @@ public class FloatArrayListTest extends TestCase {
assertFalse(list.remove(Float.valueOf(3)));
assertEquals(asList(2F), list);
- assertEquals(2F, (float) list.remove(0));
+ assertEquals(2F, (float) list.remove(0), 0.0f);
assertEquals(asList(), list);
try {
@@ -299,20 +299,22 @@ public class FloatArrayListTest extends TestCase {
}
public void testRemoveEndOfCapacity() {
- FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(1);
+ FloatList toRemove =
+ FloatArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addFloat(3);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
- FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(1);
+ FloatList toRemove =
+ FloatArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addFloat(3);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
- private void assertImmutable(FloatArrayList list) {
+ private void assertImmutable(FloatList list) {
if (list.contains(1F)) {
throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
}
diff --git a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index c9ebe7f5..a4143cd4 100644
--- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -590,8 +590,8 @@ public class GeneratedMessageTest extends TestCase {
// Extensions.
TestUtil.ReflectionTester extensionsReflectionTester =
- new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
- TestUtil.getExtensionRegistry());
+ new TestUtil.ReflectionTester(
+ TestAllExtensions.getDescriptor(), TestUtil.getFullExtensionRegistry());
public void testExtensionMessageOrBuilder() throws Exception {
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
diff --git a/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java b/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
index d8e97d4f..9edc4344 100644
--- a/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
+++ b/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
@@ -299,20 +299,22 @@ public class IntArrayListTest extends TestCase {
}
public void testRemoveEndOfCapacity() {
- IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(1);
+ IntList toRemove =
+ IntArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addInt(3);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
- IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(1);
+ IntList toRemove =
+ IntArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addInt(3);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
- private void assertImmutable(IntArrayList list) {
+ private void assertImmutable(IntList list) {
if (list.contains(1)) {
throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
}
diff --git a/java/core/src/test/java/com/google/protobuf/LiteTest.java b/java/core/src/test/java/com/google/protobuf/LiteTest.java
index 5ab80ca2..b20114e0 100644
--- a/java/core/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/core/src/test/java/com/google/protobuf/LiteTest.java
@@ -57,6 +57,8 @@ import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -2378,4 +2380,63 @@ public class LiteTest extends TestCase {
} catch (NullPointerException expected) {
}
}
+
+ public void testSerializeToOutputStreamThrowsIOException() {
+ try {
+ TestAllTypesLite.newBuilder()
+ .setOptionalBytes(ByteString.copyFromUtf8("hello"))
+ .build()
+ .writeTo(
+ new OutputStream() {
+
+ @Override
+ public void write(int b) throws IOException {
+ throw new IOException();
+ }
+ });
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ public void testUnpairedSurrogatesReplacedByQuestionMark() throws InvalidProtocolBufferException {
+ String testString = "foo \ud83d bar";
+ String expectedString = "foo ? bar";
+
+ TestAllTypesLite testMessage =
+ TestAllTypesLite.newBuilder().setOptionalString(testString).build();
+ ByteString serializedMessage = testMessage.toByteString();
+
+ // Behavior is compatible with String.getBytes("UTF-8"), which replaces
+ // unpaired surrogates with a question mark.
+ TestAllTypesLite parsedMessage = TestAllTypesLite.parseFrom(serializedMessage);
+ assertEquals(expectedString, parsedMessage.getOptionalString());
+
+ // Conversion happens during serialization.
+ ByteString expectedBytes = ByteString.copyFromUtf8(expectedString);
+ assertTrue(
+ String.format(
+ "Expected serializedMessage (%s) to contain \"%s\" (%s).",
+ encodeHex(serializedMessage), expectedString, encodeHex(expectedBytes)),
+ contains(serializedMessage, expectedBytes));
+ }
+
+ private String encodeHex(ByteString bytes) {
+ String hexDigits = "0123456789abcdef";
+ StringBuilder stringBuilder = new StringBuilder(bytes.size() * 2);
+ for (byte b : bytes) {
+ stringBuilder.append(hexDigits.charAt((b & 0xf0) >> 4));
+ stringBuilder.append(hexDigits.charAt(b & 0x0f));
+ }
+ return stringBuilder.toString();
+ }
+
+ private boolean contains(ByteString a, ByteString b) {
+ for (int i = 0; i <= a.size() - b.size(); ++i) {
+ if (a.substring(i, i + b.size()).equals(b)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java b/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
index e50c7d1e..14a8e159 100644
--- a/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
+++ b/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
@@ -299,20 +299,22 @@ public class LongArrayListTest extends TestCase {
}
public void testRemoveEndOfCapacity() {
- LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(1);
+ LongList toRemove =
+ LongArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addLong(3);
toRemove.remove(0);
assertEquals(0, toRemove.size());
}
public void testSublistRemoveEndOfCapacity() {
- LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(1);
+ LongList toRemove =
+ LongArrayList.emptyList().mutableCopyWithCapacity(1);
toRemove.addLong(3);
toRemove.subList(0, 1).clear();
assertEquals(0, toRemove.size());
}
- private void assertImmutable(LongArrayList list) {
+ private void assertImmutable(LongList list) {
if (list.contains(1L)) {
throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
}
diff --git a/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java b/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
index af717bfd..0a2c3e37 100644
--- a/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
+++ b/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
@@ -42,33 +42,33 @@ import junit.framework.TestCase;
* Tests for {@link ProtobufArrayList}.
*/
public class ProtobufArrayListTest extends TestCase {
-
+
private static final ProtobufArrayList<Integer> UNARY_LIST = newImmutableProtoArrayList(1);
private static final ProtobufArrayList<Integer> TERTIARY_LIST =
newImmutableProtoArrayList(1, 2, 3);
-
+
private ProtobufArrayList<Integer> list;
-
+
@Override
protected void setUp() throws Exception {
list = new ProtobufArrayList<Integer>();
}
-
+
public void testEmptyListReturnsSameInstance() {
assertSame(ProtobufArrayList.emptyList(), ProtobufArrayList.emptyList());
}
-
+
public void testEmptyListIsImmutable() {
assertImmutable(ProtobufArrayList.<Integer>emptyList());
}
-
+
public void testModificationWithIteration() {
list.addAll(asList(1, 2, 3, 4));
Iterator<Integer> iterator = list.iterator();
assertEquals(4, list.size());
assertEquals(1, (int) list.get(0));
assertEquals(1, (int) iterator.next());
-
+
list.remove(0);
try {
iterator.next();
@@ -76,7 +76,7 @@ public class ProtobufArrayListTest extends TestCase {
} catch (ConcurrentModificationException e) {
// expected
}
-
+
iterator = list.iterator();
list.set(0, 1);
try {
@@ -85,7 +85,7 @@ public class ProtobufArrayListTest extends TestCase {
} catch (ConcurrentModificationException e) {
// expected
}
-
+
iterator = list.iterator();
list.add(0, 0);
try {
@@ -95,7 +95,7 @@ public class ProtobufArrayListTest extends TestCase {
// expected
}
}
-
+
public void testMakeImmutable() {
list.add(2);
list.add(4);
@@ -104,107 +104,213 @@ public class ProtobufArrayListTest extends TestCase {
list.makeImmutable();
assertImmutable(list);
}
-
+
public void testRemove() {
- list.add(2);
- list.add(4);
- list.add(6);
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1, (int) list.remove(0));
+ assertEquals(asList(2, 3), list);
- list.remove(1);
- assertEquals(asList(2, 6), list);
+ assertTrue(list.remove(Integer.valueOf(3)));
+ assertEquals(asList(2), list);
- list.remove(1);
+ assertFalse(list.remove(Integer.valueOf(3)));
assertEquals(asList(2), list);
- list.remove(0);
+ assertEquals(2, (int) list.remove(0));
assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
}
-
+
public void testGet() {
- list.add(2);
- list.add(6);
-
- assertEquals(2, (int) list.get(0));
- assertEquals(6, (int) list.get(1));
+ assertEquals(1, (int) TERTIARY_LIST.get(0));
+ assertEquals(2, (int) TERTIARY_LIST.get(1));
+ assertEquals(3, (int) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
}
-
+
public void testSet() {
list.add(2);
- list.add(6);
-
- list.set(0, 1);
+ list.add(4);
+
+ assertEquals(2, (int) list.set(0, 3));
+ assertEquals(3, (int) list.get(0));
+
+ assertEquals(4, (int) list.set(1, 0));
+ assertEquals(0, (int) list.get(1));
+
+ try {
+ list.set(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2));
+ assertEquals(asList(2), list);
+
+ assertTrue(list.add(3));
+ list.add(0, 4);
+ assertEquals(asList(4, 2, 3), list);
+
+ list.add(0, 1);
+ list.add(0, 0);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Integer.valueOf(5 + i));
+ }
+ assertEquals(asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), list);
+
+ try {
+ list.add(-1, 5);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1)));
+ assertEquals(1, list.size());
assertEquals(1, (int) list.get(0));
- list.set(1, 2);
- assertEquals(2, (int) list.get(1));
+
+ assertTrue(list.addAll(asList(2, 3, 4, 5, 6)));
+ assertEquals(asList(1, 2, 3, 4, 5, 6), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1, 2, 3, 4, 5, 6, 1, 2, 3), list);
+
+ assertFalse(list.addAll(Collections.<Integer>emptyList()));
+ assertFalse(list.addAll(IntArrayList.emptyList()));
+ }
+
+ public void testSize() {
+ assertEquals(0, ProtobufArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.add(3);
+ list.add(4);
+ list.add(6);
+ list.add(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(17);
+ assertEquals(4, list.size());
}
private void assertImmutable(List<Integer> list) {
if (list.contains(1)) {
throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
}
-
+
try {
list.add(1);
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.add(0, 1);
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.addAll(Collections.<Integer>emptyList());
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.addAll(Collections.singletonList(1));
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.addAll(new ProtobufArrayList<Integer>());
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.addAll(UNARY_LIST);
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.addAll(0, Collections.singleton(1));
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.addAll(0, UNARY_LIST);
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.addAll(0, Collections.<Integer>emptyList());
fail();
} catch (UnsupportedOperationException e) {
// expected
- }
+ }
try {
list.clear();
@@ -219,56 +325,56 @@ public class ProtobufArrayListTest extends TestCase {
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.remove(new Object());
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.removeAll(Collections.emptyList());
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.removeAll(Collections.singleton(1));
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.removeAll(UNARY_LIST);
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.retainAll(Collections.emptyList());
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.retainAll(Collections.singleton(1));
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.retainAll(UNARY_LIST);
fail();
} catch (UnsupportedOperationException e) {
// expected
}
-
+
try {
list.set(0, 0);
fail();
@@ -276,7 +382,7 @@ public class ProtobufArrayListTest extends TestCase {
// expected
}
}
-
+
private static ProtobufArrayList<Integer> newImmutableProtoArrayList(int... elements) {
ProtobufArrayList<Integer> list = new ProtobufArrayList<Integer>();
for (int element : elements) {
diff --git a/java/core/src/test/java/com/google/protobuf/TestUtil.java b/java/core/src/test/java/com/google/protobuf/TestUtil.java
index b4bc3a3d..8ec22d3f 100644
--- a/java/core/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/core/src/test/java/com/google/protobuf/TestUtil.java
@@ -130,8 +130,6 @@ import static protobuf_unittest.UnittestProto.defaultFixed64Extension;
import static protobuf_unittest.UnittestProto.defaultFloatExtension;
import static protobuf_unittest.UnittestProto.defaultForeignEnumExtension;
import static protobuf_unittest.UnittestProto.defaultImportEnumExtension;
-// The static imports are to avoid 100+ char lines. The following is roughly equivalent to
-// import static protobuf_unittest.UnittestProto.*;
import static protobuf_unittest.UnittestProto.defaultInt32Extension;
import static protobuf_unittest.UnittestProto.defaultInt64Extension;
import static protobuf_unittest.UnittestProto.defaultNestedEnumExtension;
@@ -263,12 +261,14 @@ public final class TestUtil {
return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
}
+ // BEGIN FULL-RUNTIME
/**
* Dirties the message by resetting the momoized serialized size.
*/
public static void resetMemoizedSize(AbstractMessage message) {
message.memoizedSize = -1;
}
+ // END FULL-RUNTIME
/**
* Get a {@code TestAllTypes} with all fields set as they would be by
@@ -1201,17 +1201,29 @@ public final class TestUtil {
* Get an unmodifiable {@link ExtensionRegistry} containing all the
* extensions of {@code TestAllExtensions}.
*/
- public static ExtensionRegistry getExtensionRegistry() {
+ public static ExtensionRegistryLite getExtensionRegistry() {
+ ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+ registerAllExtensions(registry);
+ return registry.getUnmodifiable();
+ }
+
+ // BEGIN FULL-RUNTIME
+ /**
+ * Get an unmodifiable {@link ExtensionRegistry} containing all the
+ * extensions of {@code TestAllExtensions}.
+ */
+ public static ExtensionRegistry getFullExtensionRegistry() {
ExtensionRegistry registry = ExtensionRegistry.newInstance();
registerAllExtensions(registry);
return registry.getUnmodifiable();
}
+ // END FULL-RUNTIME
/**
* Register all of {@code TestAllExtensions}'s extensions with the
* given {@link ExtensionRegistry}.
*/
- public static void registerAllExtensions(ExtensionRegistry registry) {
+ public static void registerAllExtensions(ExtensionRegistryLite registry) {
UnittestProto.registerAllExtensions(registry);
TestUtilLite.registerAllExtensionsLite(registry);
}
@@ -2634,6 +2646,7 @@ public final class TestUtil {
}
// =================================================================
+ // BEGIN FULL-RUNTIME
/**
* Performs the same things that the methods of {@code TestUtil} do, but
@@ -3819,6 +3832,16 @@ public final class TestUtil {
"Couldn't read file: " + fullPath.getPath(), e);
}
}
+ // END FULL-RUNTIME
+
+ private static ByteString readBytesFromResource(String name) {
+ try {
+ return ByteString.copyFrom(
+ com.google.common.io.ByteStreams.toByteArray(TestUtil.class.getResourceAsStream(name)));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
/**
* Get the bytes of the "golden message". This is a serialized TestAllTypes
@@ -3829,7 +3852,7 @@ public final class TestUtil {
*/
public static ByteString getGoldenMessage() {
if (goldenMessage == null) {
- goldenMessage = readBytesFromFile("golden_message_oneof_implemented");
+ goldenMessage = readBytesFromResource("/google/protobuf/testdata/golden_message_oneof_implemented");
}
return goldenMessage;
}
@@ -3846,12 +3869,13 @@ public final class TestUtil {
public static ByteString getGoldenPackedFieldsMessage() {
if (goldenPackedFieldsMessage == null) {
goldenPackedFieldsMessage =
- readBytesFromFile("golden_packed_fields_message");
+ readBytesFromResource("/google/protobuf/testdata/golden_packed_fields_message");
}
return goldenPackedFieldsMessage;
}
private static ByteString goldenPackedFieldsMessage = null;
+ // BEGIN FULL-RUNTIME
/**
* Mock implementation of {@link GeneratedMessage.BuilderParent} for testing.
*
@@ -3871,4 +3895,5 @@ public final class TestUtil {
return invalidations;
}
}
+ // END FULL-RUNTIME
}
diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
index 720061d2..24d5589f 100644
--- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -382,17 +382,14 @@ public class TextFormatTest extends TestCase {
public void testMergeExtensions() throws Exception {
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
- TextFormat.merge(allExtensionsSetText,
- TestUtil.getExtensionRegistry(),
- builder);
+ TextFormat.merge(allExtensionsSetText, TestUtil.getFullExtensionRegistry(), builder);
TestUtil.assertAllExtensionsSet(builder.build());
}
public void testParseExtensions() throws Exception {
TestUtil.assertAllExtensionsSet(
- TextFormat.parse(allExtensionsSetText,
- TestUtil.getExtensionRegistry(),
- TestAllExtensions.class));
+ TextFormat.parse(
+ allExtensionsSetText, TestUtil.getFullExtensionRegistry(), TestAllExtensions.class));
}
public void testMergeAndParseCompatibility() throws Exception {
@@ -523,7 +520,7 @@ public class TextFormatTest extends TestCase {
// Test merge().
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
try {
- TextFormat.merge(text, TestUtil.getExtensionRegistry(), builder);
+ TextFormat.merge(text, TestUtil.getFullExtensionRegistry(), builder);
fail("Expected parse exception.");
} catch (TextFormat.ParseException e) {
assertEquals(error, e.getMessage());
@@ -531,8 +528,7 @@ public class TextFormatTest extends TestCase {
// Test parse().
try {
- TextFormat.parse(
- text, TestUtil.getExtensionRegistry(), TestAllTypes.class);
+ TextFormat.parse(text, TestUtil.getFullExtensionRegistry(), TestAllTypes.class);
fail("Expected parse exception.");
} catch (TextFormat.ParseException e) {
assertEquals(error, e.getMessage());
@@ -544,8 +540,7 @@ public class TextFormatTest extends TestCase {
String text) {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
try {
- parserWithOverwriteForbidden.merge(
- text, TestUtil.getExtensionRegistry(), builder);
+ parserWithOverwriteForbidden.merge(text, TestUtil.getFullExtensionRegistry(), builder);
fail("Expected parse exception.");
} catch (TextFormat.ParseException e) {
assertEquals(error, e.getMessage());
@@ -555,8 +550,7 @@ public class TextFormatTest extends TestCase {
private TestAllTypes assertParseSuccessWithOverwriteForbidden(
String text) throws TextFormat.ParseException {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
- parserWithOverwriteForbidden.merge(
- text, TestUtil.getExtensionRegistry(), builder);
+ parserWithOverwriteForbidden.merge(text, TestUtil.getFullExtensionRegistry(), builder);
return builder.build();
}
@@ -1118,8 +1112,7 @@ public class TextFormatTest extends TestCase {
String input = "foo_string: \"stringvalue\" foo_int: 123";
TestOneof2.Builder builder = TestOneof2.newBuilder();
try {
- parserWithOverwriteForbidden.merge(
- input, TestUtil.getExtensionRegistry(), builder);
+ parserWithOverwriteForbidden.merge(input, TestUtil.getFullExtensionRegistry(), builder);
fail("Expected parse exception.");
} catch (TextFormat.ParseException e) {
assertEquals("1:36: Field \"protobuf_unittest.TestOneof2.foo_int\""
@@ -1131,7 +1124,7 @@ public class TextFormatTest extends TestCase {
public void testOneofOverwriteAllowed() throws Exception {
String input = "foo_string: \"stringvalue\" foo_int: 123";
TestOneof2.Builder builder = TestOneof2.newBuilder();
- defaultParser.merge(input, TestUtil.getExtensionRegistry(), builder);
+ defaultParser.merge(input, TestUtil.getFullExtensionRegistry(), builder);
// Only the last value sticks.
TestOneof2 oneof = builder.build();
assertFalse(oneof.hasFooString());
diff --git a/java/core/src/test/java/com/google/protobuf/WireFormatTest.java b/java/core/src/test/java/com/google/protobuf/WireFormatTest.java
index 03c33ecf..425b56da 100644
--- a/java/core/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/core/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -132,7 +132,7 @@ public class WireFormatTest extends TestCase {
TestAllTypes message = TestUtil.getAllSet();
ByteString rawBytes = message.toByteString();
- ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+ ExtensionRegistryLite registry = TestUtil.getExtensionRegistry();
TestAllExtensions message2 =
TestAllExtensions.parseFrom(rawBytes, registry);
@@ -145,7 +145,7 @@ public class WireFormatTest extends TestCase {
TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
ByteString rawBytes = message.toByteString();
- ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+ ExtensionRegistryLite registry = TestUtil.getExtensionRegistry();
TestPackedExtensions message2 =
TestPackedExtensions.parseFrom(rawBytes, registry);
diff --git a/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto b/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto
index 5580f72d..736a344f 100644
--- a/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto
+++ b/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto
@@ -36,8 +36,6 @@ syntax = "proto2";
package protobuf_unittest;
-option optimize_for = LITE_RUNTIME;
-
message LazyMessageLite {
optional int32 num = 1;
optional int32 num_with_default = 2 [default = 421];
diff --git a/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto b/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto
index b18b0d79..20fa03b9 100644
--- a/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto
+++ b/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto
@@ -34,7 +34,6 @@ syntax = "proto2";
package protobuf_unittest.lite_equals_and_hash;
-option optimize_for = LITE_RUNTIME;
message TestOneofEquals {
oneof oneof_field {
diff --git a/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto b/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto
index c04f5d57..bc2105e5 100644
--- a/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto
+++ b/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto
@@ -30,10 +30,9 @@
syntax = "proto3";
-package map_lite_test;
+package map_test;
-option optimize_for = LITE_RUNTIME;
-option java_package = "map_lite_test";
+option java_package = "map_test";
option java_outer_classname = "MapTestProto";
message TestMap {
diff --git a/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto b/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
index a95c38b2..6793d6b7 100644
--- a/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
+++ b/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
@@ -38,7 +38,6 @@ syntax = "proto2";
package protobuf_unittest;
-option optimize_for = LITE_RUNTIME;
import "com/google/protobuf/non_nested_extension_lite.proto";
diff --git a/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto b/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto
index 37c369ed..e42faaa8 100644
--- a/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto
+++ b/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto
@@ -36,7 +36,6 @@ syntax = "proto2";
package protobuf_unittest;
-option optimize_for = LITE_RUNTIME;
message MessageLiteToBeExtended {
extensions 1 to max;
diff --git a/java/util/src/main/java/com/google/protobuf/util/Durations.java b/java/util/src/main/java/com/google/protobuf/util/Durations.java
index fb7f4343..17b41cbb 100644
--- a/java/util/src/main/java/com/google/protobuf/util/Durations.java
+++ b/java/util/src/main/java/com/google/protobuf/util/Durations.java
@@ -61,6 +61,9 @@ public final class Durations {
public static final Duration MAX_VALUE =
Duration.newBuilder().setSeconds(DURATION_SECONDS_MAX).setNanos(999999999).build();
+ /** A constant holding the duration of zero. */
+ public static final Duration ZERO = Duration.newBuilder().setSeconds(0L).setNanos(0).build();
+
private Durations() {}
private static final Comparator<Duration> COMPARATOR =
diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
index 4a13fb1d..7b4facc1 100644
--- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
@@ -249,12 +249,9 @@ final class FieldMaskTree {
continue;
}
String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey();
- merge(
- entry.getValue(),
- childPath,
- (Message) source.getField(field),
- destination.getFieldBuilder(field),
- options);
+ Message.Builder childBuilder = ((Message) destination.getField(field)).toBuilder();
+ merge(entry.getValue(), childPath, (Message) source.getField(field), childBuilder, options);
+ destination.setField(field, childBuilder.buildPartial());
continue;
}
if (field.isRepeated()) {
@@ -275,7 +272,12 @@ final class FieldMaskTree {
}
} else {
if (source.hasField(field)) {
- destination.getFieldBuilder(field).mergeFrom((Message) source.getField(field));
+ destination.setField(
+ field,
+ ((Message) destination.getField(field))
+ .toBuilder()
+ .mergeFrom((Message) source.getField(field))
+ .build());
}
}
} else {
diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
index b2f849c4..aedc5eac 100644
--- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
@@ -235,7 +235,7 @@ public class FieldMaskUtil {
/**
* Converts a FieldMask to its canonical form. In the canonical form of a
* FieldMask, all field paths are sorted alphabetically and redundant field
- * paths are moved.
+ * paths are removed.
*/
public static FieldMask normalize(FieldMask mask) {
return new FieldMaskTree(mask).toFieldMask();
diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
index 7f69ee68..973f1517 100644
--- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
+++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
@@ -610,7 +610,7 @@ public class JsonFormat {
private final CharSequence blankOrNewLine;
private static class GsonHolder {
- private static final Gson DEFAULT_GSON = new GsonBuilder().disableHtmlEscaping().create();
+ private static final Gson DEFAULT_GSON = new GsonBuilder().create();
}
PrinterImpl(
diff --git a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
index 853b6151..a0d317d4 100644
--- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
@@ -30,9 +30,14 @@
package com.google.protobuf.util;
+import com.google.protobuf.DynamicMessage;
+import com.google.protobuf.Message;
+import com.google.protobuf.UninitializedMessageException;
import protobuf_unittest.UnittestProto.NestedTestAllTypes;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestRequiredMessage;
import junit.framework.TestCase;
public class FieldMaskTreeTest extends TestCase {
@@ -90,8 +95,68 @@ public class FieldMaskTreeTest extends TestCase {
tree.intersectFieldPath("bar", result);
assertEquals("bar.baz,bar.quz,foo", result.toString());
}
-
+
public void testMerge() throws Exception {
+ testMergeImpl(true);
+ testMergeImpl(false);
+ testMergeRequire(false);
+ testMergeRequire(true);
+ }
+
+ private void merge(
+ FieldMaskTree tree,
+ Message source,
+ Message.Builder builder,
+ FieldMaskUtil.MergeOptions options,
+ boolean useDynamicMessage)
+ throws Exception {
+ if (useDynamicMessage) {
+ Message.Builder newBuilder =
+ DynamicMessage.newBuilder(source.getDescriptorForType())
+ .mergeFrom(builder.buildPartial().toByteArray());
+ tree.merge(
+ DynamicMessage.newBuilder(source.getDescriptorForType())
+ .mergeFrom(source.toByteArray())
+ .build(),
+ newBuilder,
+ options);
+ builder.clear();
+ builder.mergeFrom(newBuilder.buildPartial());
+ } else {
+ tree.merge(source, builder, options);
+ }
+ }
+
+ private void testMergeRequire(boolean useDynamicMessage) throws Exception {
+ TestRequired value = TestRequired.newBuilder().setA(4321).setB(8765).setC(233333).build();
+ TestRequiredMessage source = TestRequiredMessage.newBuilder().setRequiredMessage(value).build();
+
+ FieldMaskUtil.MergeOptions options = new FieldMaskUtil.MergeOptions();
+ TestRequiredMessage.Builder builder = TestRequiredMessage.newBuilder();
+ merge(
+ new FieldMaskTree().addFieldPath("required_message.a"),
+ source,
+ builder,
+ options,
+ useDynamicMessage);
+ assertTrue(builder.hasRequiredMessage());
+ assertTrue(builder.getRequiredMessage().hasA());
+ assertFalse(builder.getRequiredMessage().hasB());
+ assertFalse(builder.getRequiredMessage().hasC());
+ merge(
+ new FieldMaskTree().addFieldPath("required_message.b").addFieldPath("required_message.c"),
+ source,
+ builder,
+ options,
+ useDynamicMessage);
+ try {
+ assertEquals(builder.build(), source);
+ } catch (UninitializedMessageException e) {
+ throw new AssertionError("required field isn't set", e);
+ }
+ }
+
+ private void testMergeImpl(boolean useDynamicMessage) throws Exception {
TestAllTypes value =
TestAllTypes.newBuilder()
.setOptionalInt32(1234)
@@ -119,45 +184,51 @@ public class FieldMaskTreeTest extends TestCase {
// Test merging each individual field.
NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree().addFieldPath("payload.optional_int32").merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
+ source, builder, options, useDynamicMessage);
NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder();
expected.getPayloadBuilder().setOptionalInt32(1234);
assertEquals(expected.build(), builder.build());
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree()
- .addFieldPath("payload.optional_nested_message")
- .merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload.optional_nested_message"),
+ source, builder, options, useDynamicMessage);
expected = NestedTestAllTypes.newBuilder();
expected.getPayloadBuilder().setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678));
assertEquals(expected.build(), builder.build());
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload.repeated_int32"),
+ source, builder, options, useDynamicMessage);
expected = NestedTestAllTypes.newBuilder();
expected.getPayloadBuilder().addRepeatedInt32(4321);
assertEquals(expected.build(), builder.build());
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree()
- .addFieldPath("payload.repeated_nested_message")
- .merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload.repeated_nested_message"),
+ source, builder, options, useDynamicMessage);
expected = NestedTestAllTypes.newBuilder();
expected.getPayloadBuilder().addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765));
assertEquals(expected.build(), builder.build());
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree()
- .addFieldPath("child.payload.optional_int32")
- .merge(source, builder, options);
+ merge(
+ new FieldMaskTree().addFieldPath("child.payload.optional_int32"),
+ source,
+ builder,
+ options,
+ useDynamicMessage);
expected = NestedTestAllTypes.newBuilder();
expected.getChildBuilder().getPayloadBuilder().setOptionalInt32(1234);
assertEquals(expected.build(), builder.build());
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree()
- .addFieldPath("child.payload.optional_nested_message")
- .merge(source, builder, options);
+ merge(
+ new FieldMaskTree().addFieldPath("child.payload.optional_nested_message"),
+ source,
+ builder,
+ options,
+ useDynamicMessage);
expected = NestedTestAllTypes.newBuilder();
expected
.getChildBuilder()
@@ -166,17 +237,15 @@ public class FieldMaskTreeTest extends TestCase {
assertEquals(expected.build(), builder.build());
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree()
- .addFieldPath("child.payload.repeated_int32")
- .merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("child.payload.repeated_int32"),
+ source, builder, options, useDynamicMessage);
expected = NestedTestAllTypes.newBuilder();
expected.getChildBuilder().getPayloadBuilder().addRepeatedInt32(4321);
assertEquals(expected.build(), builder.build());
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree()
- .addFieldPath("child.payload.repeated_nested_message")
- .merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("child.payload.repeated_nested_message"),
+ source, builder, options, useDynamicMessage);
expected = NestedTestAllTypes.newBuilder();
expected
.getChildBuilder()
@@ -186,23 +255,23 @@ public class FieldMaskTreeTest extends TestCase {
// Test merging all fields.
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree()
- .addFieldPath("child")
- .addFieldPath("payload")
- .merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("child").addFieldPath("payload"),
+ source, builder, options, useDynamicMessage);
assertEquals(source, builder.build());
// Test repeated options.
builder = NestedTestAllTypes.newBuilder();
builder.getPayloadBuilder().addRepeatedInt32(1000);
- new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload.repeated_int32"),
+ source, builder, options, useDynamicMessage);
// Default behavior is to append repeated fields.
assertEquals(2, builder.getPayload().getRepeatedInt32Count());
assertEquals(1000, builder.getPayload().getRepeatedInt32(0));
assertEquals(4321, builder.getPayload().getRepeatedInt32(1));
// Change to replace repeated fields.
options.setReplaceRepeatedFields(true);
- new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload.repeated_int32"),
+ source, builder, options, useDynamicMessage);
assertEquals(1, builder.getPayload().getRepeatedInt32Count());
assertEquals(4321, builder.getPayload().getRepeatedInt32(0));
@@ -210,7 +279,8 @@ public class FieldMaskTreeTest extends TestCase {
builder = NestedTestAllTypes.newBuilder();
builder.getPayloadBuilder().setOptionalInt32(1000);
builder.getPayloadBuilder().setOptionalUint32(2000);
- new FieldMaskTree().addFieldPath("payload").merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload"),
+ source, builder, options, useDynamicMessage);
// Default behavior is to merge message fields.
assertEquals(1234, builder.getPayload().getOptionalInt32());
assertEquals(2000, builder.getPayload().getOptionalUint32());
@@ -218,14 +288,14 @@ public class FieldMaskTreeTest extends TestCase {
// Test merging unset message fields.
NestedTestAllTypes clearedSource = source.toBuilder().clearPayload().build();
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload"),
+ clearedSource, builder, options, useDynamicMessage);
assertEquals(false, builder.hasPayload());
// Skip a message field if they are unset in both source and target.
builder = NestedTestAllTypes.newBuilder();
- new FieldMaskTree()
- .addFieldPath("payload.optional_int32")
- .merge(clearedSource, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
+ clearedSource, builder, options, useDynamicMessage);
assertEquals(false, builder.hasPayload());
// Change to replace message fields.
@@ -233,7 +303,8 @@ public class FieldMaskTreeTest extends TestCase {
builder = NestedTestAllTypes.newBuilder();
builder.getPayloadBuilder().setOptionalInt32(1000);
builder.getPayloadBuilder().setOptionalUint32(2000);
- new FieldMaskTree().addFieldPath("payload").merge(source, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload"),
+ source, builder, options, useDynamicMessage);
assertEquals(1234, builder.getPayload().getOptionalInt32());
assertEquals(0, builder.getPayload().getOptionalUint32());
@@ -241,7 +312,8 @@ public class FieldMaskTreeTest extends TestCase {
builder = NestedTestAllTypes.newBuilder();
builder.getPayloadBuilder().setOptionalInt32(1000);
builder.getPayloadBuilder().setOptionalUint32(2000);
- new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload"),
+ clearedSource, builder, options, useDynamicMessage);
assertEquals(false, builder.hasPayload());
// Test merging unset primitive fields.
@@ -249,18 +321,16 @@ public class FieldMaskTreeTest extends TestCase {
builder.getPayloadBuilder().clearOptionalInt32();
NestedTestAllTypes sourceWithPayloadInt32Unset = builder.build();
builder = source.toBuilder();
- new FieldMaskTree()
- .addFieldPath("payload.optional_int32")
- .merge(sourceWithPayloadInt32Unset, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
+ sourceWithPayloadInt32Unset, builder, options, useDynamicMessage);
assertEquals(true, builder.getPayload().hasOptionalInt32());
assertEquals(0, builder.getPayload().getOptionalInt32());
// Change to clear unset primitive fields.
options.setReplacePrimitiveFields(true);
builder = source.toBuilder();
- new FieldMaskTree()
- .addFieldPath("payload.optional_int32")
- .merge(sourceWithPayloadInt32Unset, builder, options);
+ merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
+ sourceWithPayloadInt32Unset, builder, options, useDynamicMessage);
assertEquals(true, builder.hasPayload());
assertEquals(false, builder.getPayload().hasOptionalInt32());
}
diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
index 6ef08508..d9bbe587 100644
--- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -70,7 +70,6 @@ import java.io.StringReader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
@@ -1188,10 +1187,14 @@ public class JsonFormatTest extends TestCase {
assertRoundTripEquals(message);
}
- public void testDefaultGsonDoesNotHtmlEscape() throws Exception {
- TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("=").build();
- assertEquals(
- "{\n" + " \"optionalString\": \"=\"" + "\n}", JsonFormat.printer().print(message));
+ // Regression test for b/73832901. Make sure html tags are escaped.
+ public void testHtmlEscape() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("</script>").build();
+ assertEquals("{\n \"optionalString\": \"\\u003c/script\\u003e\"\n}", toJsonString(message));
+
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ JsonFormat.parser().merge(toJsonString(message), builder);
+ assertEquals(message.getOptionalString(), builder.getOptionalString());
}
public void testIncludingDefaultValueFields() throws Exception {