Pārlūkot izejas kodu

Integrated internal changes from Google

Adam Cozzette 6 gadi atpakaļ
vecāks
revīzija
0894e07536
100 mainītis faili ar 2965 papildinājumiem un 1611 dzēšanām
  1. 0 1
      cmake/libprotoc.cmake
  2. 2 3
      java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
  3. 39 17
      java/core/src/main/java/com/google/protobuf/ByteString.java
  4. 39 12
      java/core/src/main/java/com/google/protobuf/CodedInputStream.java
  5. 3 4
      java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
  6. 3 4
      java/core/src/main/java/com/google/protobuf/FloatArrayList.java
  7. 50 24
      java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
  8. 2 3
      java/core/src/main/java/com/google/protobuf/IntArrayList.java
  9. 2 3
      java/core/src/main/java/com/google/protobuf/LongArrayList.java
  10. 6 2
      java/core/src/main/java/com/google/protobuf/Message.java
  11. 36 2
      java/core/src/main/java/com/google/protobuf/MessageReflection.java
  12. 7 0
      java/core/src/main/java/com/google/protobuf/NioByteString.java
  13. 41 7
      java/core/src/main/java/com/google/protobuf/RopeByteString.java
  14. 169 52
      java/core/src/main/java/com/google/protobuf/TextFormat.java
  15. 9 0
      java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
  16. 2 2
      java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
  17. 10 21
      java/core/src/test/java/com/google/protobuf/AnyTest.java
  18. 38 22
      java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
  19. 100 47
      java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
  20. 284 321
      java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
  21. 19 1
      java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
  22. 1 1
      java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
  23. 19 1
      java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
  24. 17 1
      java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
  25. 1 1
      java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java
  26. 3 3
      java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
  27. 11 12
      java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
  28. 39 39
      java/core/src/test/java/com/google/protobuf/LiteTest.java
  29. 4 4
      java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
  30. 17 1
      java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
  31. 9 6
      java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
  32. 85 102
      java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
  33. 18 19
      java/core/src/test/java/com/google/protobuf/MapTest.java
  34. 2 2
      java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
  35. 64 77
      java/core/src/test/java/com/google/protobuf/ParserTest.java
  36. 72 71
      java/core/src/test/java/com/google/protobuf/ServiceTest.java
  37. 32 4
      java/core/src/test/java/com/google/protobuf/TestUtil.java
  38. 75 7
      java/core/src/test/java/com/google/protobuf/TextFormatTest.java
  39. 2 2
      java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
  40. 6 6
      java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
  41. 2 2
      java/core/src/test/proto/com/google/protobuf/field_presence_test.proto
  42. 1 2
      java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto
  43. 28 19
      java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto
  44. 28 19
      java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto
  45. 1 2
      java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto
  46. 31 22
      java/core/src/test/proto/com/google/protobuf/map_lite_test.proto
  47. 29 19
      java/core/src/test/proto/com/google/protobuf/map_test.proto
  48. 0 1
      java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto
  49. 1 3
      java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto
  50. 1 3
      java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto
  51. 1 2
      java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto
  52. 1 2
      java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto
  53. 1 3
      java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto
  54. 6 0
      java/pom.xml
  55. 5 0
      java/util/pom.xml
  56. 143 18
      java/util/src/main/java/com/google/protobuf/util/Durations.java
  57. 73 11
      java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
  58. 1 0
      java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
  59. 9 0
      java/util/src/main/java/com/google/protobuf/util/Timestamps.java
  60. 49 0
      java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
  61. 1 0
      js/binary/proto_test.js
  62. 11 0
      js/debug.js
  63. 72 0
      js/debug_test.js
  64. 21 3
      js/maps_test.js
  65. 19 7
      js/message.js
  66. 201 270
      js/message_test.js
  67. 6 4
      js/proto3_test.js
  68. 11 0
      js/test.proto
  69. 52 0
      js/test11.proto
  70. 119 0
      js/test12.proto
  71. 70 0
      js/test13.proto
  72. 43 0
      js/test14.proto
  73. 39 0
      js/test15.proto
  74. 4 4
      python/google/protobuf/internal/containers.py
  75. 0 4
      python/google/protobuf/internal/descriptor_pool_test.py
  76. 8 0
      python/google/protobuf/internal/descriptor_test.py
  77. 2 2
      python/google/protobuf/internal/enum_type_wrapper.py
  78. 2 1
      python/google/protobuf/internal/json_format_test.py
  79. 14 12
      python/google/protobuf/internal/message_test.py
  80. 20 19
      python/google/protobuf/internal/python_message.py
  81. 88 2
      python/google/protobuf/internal/text_format_test.py
  82. 1 5
      python/google/protobuf/internal/well_known_types.py
  83. 25 1
      python/google/protobuf/internal/well_known_types_test.py
  84. 27 9
      python/google/protobuf/pyext/descriptor.cc
  85. 10 10
      python/google/protobuf/pyext/map_container.cc
  86. 10 13
      python/google/protobuf/pyext/message.cc
  87. 6 4
      python/google/protobuf/text_format.py
  88. 0 2
      src/Makefile.am
  89. 30 21
      src/google/protobuf/any.pb.cc
  90. 1 1
      src/google/protobuf/any.pb.h
  91. 94 71
      src/google/protobuf/api.pb.cc
  92. 3 3
      src/google/protobuf/api.pb.h
  93. 14 15
      src/google/protobuf/arena.cc
  94. 4 2
      src/google/protobuf/arena_impl.h
  95. 1 1
      src/google/protobuf/arena_unittest.cc
  96. 88 47
      src/google/protobuf/compiler/command_line_interface.cc
  97. 11 5
      src/google/protobuf/compiler/command_line_interface.h
  98. 40 10
      src/google/protobuf/compiler/command_line_interface_unittest.cc
  99. 4 0
      src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
  100. 44 28
      src/google/protobuf/compiler/cpp/cpp_file.cc

+ 0 - 1
cmake/libprotoc.cmake

@@ -78,7 +78,6 @@ set(libprotoc_files
   ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/python/python_generator.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator.cc
-  ${protobuf_source_dir}/src/google/protobuf/compiler/scc.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/subprocess.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.cc
 )

+ 2 - 3
java/core/src/main/java/com/google/protobuf/BooleanArrayList.java

@@ -46,7 +46,6 @@ final class BooleanArrayList extends AbstractProtobufList<Boolean>
     implements BooleanList, RandomAccess, PrimitiveNonBoxingCollection {
 
   private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList();
-
   static {
     EMPTY_LIST.makeImmutable();
   }
@@ -237,7 +236,7 @@ final class BooleanArrayList extends AbstractProtobufList<Boolean>
     ensureIsMutable();
     for (int i = 0; i < size; i++) {
       if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i);
+        System.arraycopy(array, i + 1, array, i, size - i - 1);
         size--;
         modCount++;
         return true;
@@ -252,7 +251,7 @@ final class BooleanArrayList extends AbstractProtobufList<Boolean>
     ensureIndexInRange(index);
     boolean value = array[index];
     if (index < size - 1) {
-      System.arraycopy(array, index + 1, array, index, size - index);
+      System.arraycopy(array, index + 1, array, index, size - index - 1);
     }
     size--;
     modCount++;

+ 39 - 17
java/core/src/main/java/com/google/protobuf/ByteString.java

@@ -146,6 +146,15 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
    */
   public abstract byte byteAt(int index);
 
+  /**
+   * Gets the byte at the given index, assumes bounds checking has already been performed.
+   *
+   * @param index index of byte
+   * @return the value
+   * @throws IndexOutOfBoundsException {@code index < 0 or index >= size}
+   */
+  abstract byte internalByteAt(int index);
+
   /**
    * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString. To avoid
    * auto-boxing, you may get the iterator manually and call {@link ByteIterator#nextByte()}.
@@ -153,8 +162,8 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
    * @return the iterator
    */
   @Override
-  public final ByteIterator iterator() {
-    return new ByteIterator() {
+  public ByteIterator iterator() {
+    return new AbstractByteIterator() {
       private int position = 0;
       private final int limit = size();
 
@@ -163,24 +172,14 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
         return position < limit;
       }
 
-      @Override
-      public Byte next() {
-        // Boxing calls Byte.valueOf(byte), which does not instantiate.
-        return nextByte();
-      }
-
       @Override
       public byte nextByte() {
-        try {
-          return byteAt(position++);
-        } catch (IndexOutOfBoundsException e) {
-          throw new NoSuchElementException(e.getMessage());
+        int currentPos = position;
+        if (currentPos >= limit) {
+          throw new NoSuchElementException();
         }
-      }
-
-      @Override
-      public void remove() {
-        throw new UnsupportedOperationException();
+        position = currentPos + 1;
+        return internalByteAt(currentPos);
       }
     };
   }
@@ -198,6 +197,19 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
     byte nextByte();
   }
 
+  abstract static class AbstractByteIterator implements ByteIterator {
+    @Override
+    public final Byte next() {
+      // Boxing calls Byte.valueOf(byte), which does not instantiate.
+      return nextByte();
+    }
+
+    @Override
+    public final void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
   /**
    * Gets the number of bytes.
    *
@@ -1280,6 +1292,11 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
       return bytes[index];
     }
 
+    @Override
+    byte internalByteAt(int index) {
+      return bytes[index];
+    }
+
     @Override
     public int size() {
       return bytes.length;
@@ -1521,6 +1538,11 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
       return bytes[bytesOffset + index];
     }
 
+    @Override
+    byte internalByteAt(int index) {
+      return bytes[bytesOffset + index];
+    }
+
     @Override
     public int size() {
       return bytesLength;

+ 39 - 12
java/core/src/main/java/com/google/protobuf/CodedInputStream.java

@@ -2783,7 +2783,8 @@ public abstract class CodedInputStream {
                   sizeLimit - totalBytesRetired - bufferSize));
       if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
         throw new IllegalStateException(
-            "InputStream#read(byte[]) returned invalid result: "
+            input.getClass()
+                + "#read(byte[]) returned invalid result: "
                 + bytesRead
                 + "\nThe InputStream implementation is buggy.");
       }
@@ -3005,20 +3006,46 @@ public abstract class CodedInputStream {
         throw InvalidProtocolBufferException.truncatedMessage();
       }
 
-      // Skipping more bytes than are in the buffer.  First skip what we have.
-      int tempPos = bufferSize - pos;
-      pos = bufferSize;
-
-      // Keep refilling the buffer until we get to the point we wanted to skip to.
-      // This has the side effect of ensuring the limits are updated correctly.
-      refillBuffer(1);
-      while (size - tempPos > bufferSize) {
-        tempPos += bufferSize;
+      if (refillCallback != null) {
+        // Skipping more bytes than are in the buffer.  First skip what we have.
+        int tempPos = bufferSize - pos;
         pos = bufferSize;
+
+        // Keep refilling the buffer until we get to the point we wanted to skip to.
+        // This has the side effect of ensuring the limits are updated correctly.
         refillBuffer(1);
-      }
+        while (size - tempPos > bufferSize) {
+          tempPos += bufferSize;
+          pos = bufferSize;
+          refillBuffer(1);
+        }
 
-      pos = size - tempPos;
+        pos = size - tempPos;
+      } else {
+        // Skipping more bytes than are in the buffer.  First skip what we have.
+        totalBytesRetired += pos;
+        int totalSkipped = bufferSize - pos;
+        bufferSize = 0;
+        pos = 0;
+
+        try {
+          while (totalSkipped < size) {
+            int toSkip = size - totalSkipped;
+            long skipped = input.skip(toSkip);
+            if (skipped < 0 || skipped > toSkip) {
+              throw new IllegalStateException(
+                  input.getClass()
+                      + "#skip returned invalid result: "
+                      + skipped
+                      + "\nThe InputStream implementation is buggy.");
+            }
+            totalSkipped += (int) skipped;
+          }
+        } finally {
+          totalBytesRetired += totalSkipped;
+          recomputeBufferSizeAfterLimit();
+        }
+      }
     }
   }
 

+ 3 - 4
java/core/src/main/java/com/google/protobuf/DoubleArrayList.java

@@ -46,7 +46,6 @@ final class DoubleArrayList extends AbstractProtobufList<Double>
     implements DoubleList, RandomAccess, PrimitiveNonBoxingCollection {
 
   private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList();
-
   static {
     EMPTY_LIST.makeImmutable();
   }
@@ -104,7 +103,7 @@ final class DoubleArrayList extends AbstractProtobufList<Double>
 
     final double[] arr = other.array;
     for (int i = 0; i < size; i++) {
-      if (array[i] != arr[i]) {
+      if (Double.doubleToLongBits(array[i]) != Double.doubleToLongBits(arr[i])) {
         return false;
       }
     }
@@ -237,7 +236,7 @@ final class DoubleArrayList extends AbstractProtobufList<Double>
     ensureIsMutable();
     for (int i = 0; i < size; i++) {
       if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i);
+        System.arraycopy(array, i + 1, array, i, size - i - 1);
         size--;
         modCount++;
         return true;
@@ -252,7 +251,7 @@ final class DoubleArrayList extends AbstractProtobufList<Double>
     ensureIndexInRange(index);
     double value = array[index];
     if (index < size - 1) {
-      System.arraycopy(array, index + 1, array, index, size - index);
+      System.arraycopy(array, index + 1, array, index, size - index - 1);
     }
     size--;
     modCount++;

+ 3 - 4
java/core/src/main/java/com/google/protobuf/FloatArrayList.java

@@ -46,7 +46,6 @@ final class FloatArrayList extends AbstractProtobufList<Float>
     implements FloatList, RandomAccess, PrimitiveNonBoxingCollection {
 
   private static final FloatArrayList EMPTY_LIST = new FloatArrayList();
-
   static {
     EMPTY_LIST.makeImmutable();
   }
@@ -104,7 +103,7 @@ final class FloatArrayList extends AbstractProtobufList<Float>
 
     final float[] arr = other.array;
     for (int i = 0; i < size; i++) {
-      if (array[i] != arr[i]) {
+      if (Float.floatToIntBits(array[i]) != Float.floatToIntBits(arr[i])) {
         return false;
       }
     }
@@ -236,7 +235,7 @@ final class FloatArrayList extends AbstractProtobufList<Float>
     ensureIsMutable();
     for (int i = 0; i < size; i++) {
       if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i);
+        System.arraycopy(array, i + 1, array, i, size - i - 1);
         size--;
         modCount++;
         return true;
@@ -251,7 +250,7 @@ final class FloatArrayList extends AbstractProtobufList<Float>
     ensureIndexInRange(index);
     float value = array[index];
     if (index < size - 1) {
-      System.arraycopy(array, index + 1, array, index, size - index);
+      System.arraycopy(array, index + 1, array, index, size - index - 1);
     }
     size--;
     modCount++;

+ 50 - 24
java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java

@@ -451,16 +451,18 @@ public abstract class GeneratedMessageLite<
     }
 
     @Override
-    public BuilderType mergeFrom(byte[] input, int offset, int length)
+    public BuilderType mergeFrom(
+        byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException {
       // BEGIN REGULAR
-      return super.mergeFrom(input, offset, length);
+      return super.mergeFrom(input, offset, length, extensionRegistry);
       // END REGULAR
       // BEGIN EXPERIMENTAL
       // copyOnWrite();
       // try {
       //   Protobuf.getInstance().schemaFor(instance).mergeFrom(
-      //       instance, input, offset, offset + length, new ArrayDecoders.Registers());
+      //       instance, input, offset, offset + length,
+      //       new ArrayDecoders.Registers(extensionRegistry));
       // } catch (InvalidProtocolBufferException e) {
       //   throw e;
       // } catch (IndexOutOfBoundsException e) {
@@ -472,6 +474,18 @@ public abstract class GeneratedMessageLite<
       // END EXPERIMENTAL
     }
 
+    @Override
+    public BuilderType mergeFrom(
+        byte[] input, int offset, int length)
+        throws InvalidProtocolBufferException {
+      // BEGIN REGULAR
+      return super.mergeFrom(input, offset, length);
+      // END REGULAR
+      // BEGIN EXPERIMENTAL
+      // return mergeFrom(input, offset, length, ExtensionRegistryLite.getEmptyRegistry());
+      // END EXPERIMENTAL
+    }
+
     @Override
     public BuilderType mergeFrom(
         com.google.protobuf.CodedInputStream input,
@@ -483,6 +497,8 @@ public abstract class GeneratedMessageLite<
         instance.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
         // END REGULAR
         // BEGIN EXPERIMENTAL
+        // // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use
+        // // fast path.
         // Protobuf.getInstance().schemaFor(instance).mergeFrom(
         //     instance, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
         // END EXPERIMENTAL
@@ -814,7 +830,7 @@ public abstract class GeneratedMessageLite<
           .setField(extension.descriptor, extension.singularToFieldSetType(value));
     }
 
-    private FieldSet<ExtensionDescriptor> ensureExtensionsAreMutable() {
+    FieldSet<ExtensionDescriptor> ensureExtensionsAreMutable() {
       if (extensions.isImmutable()) {
         extensions = extensions.clone();
       }
@@ -1558,8 +1574,11 @@ public abstract class GeneratedMessageLite<
     }
 
     @Override
-    public T parsePartialFrom(byte[] input) throws InvalidProtocolBufferException {
-      return GeneratedMessageLite.parsePartialFrom(defaultInstance, input);
+    public T parsePartialFrom(
+        byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry)
+        throws InvalidProtocolBufferException {
+      return GeneratedMessageLite.parsePartialFrom(
+          defaultInstance, input, offset, length, extensionRegistry);
     }
   }
 
@@ -1578,6 +1597,8 @@ public abstract class GeneratedMessageLite<
       result.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
       // END REGULAR
       // BEGIN EXPERIMENTAL
+      // // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use
+      // // fast path.
       // Protobuf.getInstance().schemaFor(result).mergeFrom(
       //     result, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
       // END EXPERIMENTAL
@@ -1599,17 +1620,31 @@ public abstract class GeneratedMessageLite<
   }
 
   /** A static helper method for parsing a partial from byte array. */
-  static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(T instance, byte[] input)
+  static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+      T instance, byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
     // BEGIN REGULAR
-    return parsePartialFrom(instance, input, ExtensionRegistryLite.getEmptyRegistry());
+    T message;
+    try {
+      CodedInputStream cis = CodedInputStream.newInstance(input, offset, length);
+      message = parsePartialFrom(instance, cis, extensionRegistry);
+      try {
+        cis.checkLastTagWas(0);
+      } catch (InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(message);
+      }
+      return message;
+    } catch (InvalidProtocolBufferException e) {
+      throw e;
+    }
     // END REGULAR
     // BEGIN EXPERIMENTAL
     // @SuppressWarnings("unchecked") // Guaranteed by protoc
     // T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
     // try {
     //   Protobuf.getInstance().schemaFor(result).mergeFrom(
-    //       result, input, 0, input.length, new ArrayDecoders.Registers());
+    //       result, input, offset, offset + length,
+    //       new ArrayDecoders.Registers(extensionRegistry));
     //   result.makeImmutable();
     //   if (result.memoizedHashCode != 0) {
     //     throw new RuntimeException();
@@ -1701,32 +1736,23 @@ public abstract class GeneratedMessageLite<
   private static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
       T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
-    T message;
-    try {
-      CodedInputStream input = CodedInputStream.newInstance(data);
-      message = parsePartialFrom(defaultInstance, input, extensionRegistry);
-      try {
-        input.checkLastTagWas(0);
-      } catch (InvalidProtocolBufferException e) {
-        throw e.setUnfinishedMessage(message);
-      }
-      return message;
-    } catch (InvalidProtocolBufferException e) {
-      throw e;
-    }
+    return checkMessageInitialized(
+        parsePartialFrom(defaultInstance, data, 0, data.length, extensionRegistry));
   }
 
   // Validates last tag.
   protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
       T defaultInstance, byte[] data) throws InvalidProtocolBufferException {
-    return checkMessageInitialized(parsePartialFrom(defaultInstance, data));
+    return checkMessageInitialized(parsePartialFrom(
+        defaultInstance, data, 0, data.length, ExtensionRegistryLite.getEmptyRegistry()));
   }
 
   // Validates last tag.
   protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
       T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
-    return checkMessageInitialized(parsePartialFrom(defaultInstance, data, extensionRegistry));
+    return checkMessageInitialized(
+        parsePartialFrom(defaultInstance, data, 0, data.length, extensionRegistry));
   }
 
   // Does not validate last tag.

+ 2 - 3
java/core/src/main/java/com/google/protobuf/IntArrayList.java

@@ -46,7 +46,6 @@ final class IntArrayList extends AbstractProtobufList<Integer>
     implements IntList, RandomAccess, PrimitiveNonBoxingCollection {
 
   private static final IntArrayList EMPTY_LIST = new IntArrayList();
-
   static {
     EMPTY_LIST.makeImmutable();
   }
@@ -236,7 +235,7 @@ final class IntArrayList extends AbstractProtobufList<Integer>
     ensureIsMutable();
     for (int i = 0; i < size; i++) {
       if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i);
+        System.arraycopy(array, i + 1, array, i, size - i - 1);
         size--;
         modCount++;
         return true;
@@ -251,7 +250,7 @@ final class IntArrayList extends AbstractProtobufList<Integer>
     ensureIndexInRange(index);
     int value = array[index];
     if (index < size - 1) {
-      System.arraycopy(array, index + 1, array, index, size - index);
+      System.arraycopy(array, index + 1, array, index, size - index - 1);
     }
     size--;
     modCount++;

+ 2 - 3
java/core/src/main/java/com/google/protobuf/LongArrayList.java

@@ -46,7 +46,6 @@ final class LongArrayList extends AbstractProtobufList<Long>
     implements LongList, RandomAccess, PrimitiveNonBoxingCollection {
 
   private static final LongArrayList EMPTY_LIST = new LongArrayList();
-
   static {
     EMPTY_LIST.makeImmutable();
   }
@@ -236,7 +235,7 @@ final class LongArrayList extends AbstractProtobufList<Long>
     ensureIsMutable();
     for (int i = 0; i < size; i++) {
       if (o.equals(array[i])) {
-        System.arraycopy(array, i + 1, array, i, size - i);
+        System.arraycopy(array, i + 1, array, i, size - i - 1);
         size--;
         modCount++;
         return true;
@@ -251,7 +250,7 @@ final class LongArrayList extends AbstractProtobufList<Long>
     ensureIndexInRange(index);
     long value = array[index];
     if (index < size - 1) {
-      System.arraycopy(array, index + 1, array, index, size - index);
+      System.arraycopy(array, index + 1, array, index, size - index - 1);
     }
     size--;
     modCount++;

+ 6 - 2
java/core/src/main/java/com/google/protobuf/Message.java

@@ -149,8 +149,12 @@ public interface Message extends MessageLite, MessageOrBuilder {
     Descriptors.Descriptor getDescriptorForType();
 
     /**
-     * Create a Builder for messages of the appropriate type for the given field. Messages built
-     * with this can then be passed to setField(), setRepeatedField(), or addRepeatedField().
+     * Create a builder for messages of the appropriate type for the given field. The
+     * builder is NOT nested in the current builder. However, messages built with the
+     * builder can then be passed to the {@link #setField()}, {@link #setRepeatedField()}, or {@link
+     * #addRepeatedField()} method of the current builder.
+     *
+     * <p>To obtain a builder nested in the current builder, use {@link #getFieldBuilder()} instead.
      */
     Builder newBuilderForField(Descriptors.FieldDescriptor field);
 

+ 36 - 2
java/core/src/main/java/com/google/protobuf/MessageReflection.java

@@ -334,6 +334,14 @@ class MessageReflection {
     MergeTarget newMergeTargetForField(
         Descriptors.FieldDescriptor descriptor, Message defaultInstance);
 
+    /**
+     * Returns an empty merge target for a sub-field. When defaultInstance is provided, it indicates
+     * the descriptor is for an extension type, and implementations should create a new instance
+     * from the defaultInstance prototype directly.
+     */
+    MergeTarget newEmptyTargetForField(
+        Descriptors.FieldDescriptor descriptor, Message defaultInstance);
+
     /** Finishes the merge and returns the underlying object. */
     Object finish();
   }
@@ -494,11 +502,31 @@ class MessageReflection {
     @Override
     public MergeTarget newMergeTargetForField(
         Descriptors.FieldDescriptor field, Message defaultInstance) {
+      Message.Builder subBuilder;
       if (defaultInstance != null) {
-        return new BuilderAdapter(defaultInstance.newBuilderForType());
+        subBuilder = defaultInstance.newBuilderForType();
       } else {
-        return new BuilderAdapter(builder.newBuilderForField(field));
+        subBuilder = builder.newBuilderForField(field);
+      }
+      if (!field.isRepeated()) {
+        Message originalMessage = (Message) getField(field);
+        if (originalMessage != null) {
+          subBuilder.mergeFrom(originalMessage);
+        }
       }
+      return new BuilderAdapter(subBuilder);
+    }
+
+    @Override
+    public MergeTarget newEmptyTargetForField(
+        Descriptors.FieldDescriptor field, Message defaultInstance) {
+      Message.Builder subBuilder;
+      if (defaultInstance != null) {
+        subBuilder = defaultInstance.newBuilderForType();
+      } else {
+        subBuilder = builder.newBuilderForField(field);
+      }
+      return new BuilderAdapter(subBuilder);
     }
 
     @Override
@@ -661,6 +689,12 @@ class MessageReflection {
       throw new UnsupportedOperationException("newMergeTargetForField() called on FieldSet object");
     }
 
+    @Override
+    public MergeTarget newEmptyTargetForField(
+        Descriptors.FieldDescriptor descriptor, Message defaultInstance) {
+      throw new UnsupportedOperationException("newEmptyTargetForField() called on FieldSet object");
+    }
+
     @Override
     public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
       if (descriptor.needsUtf8Check()) {

+ 7 - 0
java/core/src/main/java/com/google/protobuf/NioByteString.java

@@ -81,6 +81,13 @@ final class NioByteString extends ByteString.LeafByteString {
     }
   }
 
+  @Override
+  public byte internalByteAt(int index) {
+    // it isn't possible to avoid the bounds checking inside of ByteBuffer, so just use the default
+    // implementation.
+    return byteAt(index);
+  }
+
   @Override
   public int size() {
     return buffer.remaining();

+ 41 - 7
java/core/src/main/java/com/google/protobuf/RopeByteString.java

@@ -38,12 +38,12 @@ import java.io.ObjectInputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
-import java.util.Stack;
 
 /**
  * Class to represent {@code ByteStrings} formed by concatenation of other ByteStrings, without
@@ -240,13 +240,17 @@ final class RopeByteString extends ByteString {
   @Override
   public byte byteAt(int index) {
     checkIndex(index, totalLength);
+    return internalByteAt(index);
+  }
 
+  @Override
+  byte internalByteAt(int index) {
     // Find the relevant piece by recursive descent
     if (index < leftLength) {
-      return left.byteAt(index);
+      return left.internalByteAt(index);
     }
 
-    return right.byteAt(index - leftLength);
+    return right.internalByteAt(index - leftLength);
   }
 
   @Override
@@ -254,6 +258,37 @@ final class RopeByteString extends ByteString {
     return totalLength;
   }
 
+  @Override
+  public ByteIterator iterator() {
+    return new AbstractByteIterator() {
+      final PieceIterator pieces = new PieceIterator(RopeByteString.this);
+      ByteIterator current = nextPiece();
+
+      private ByteIterator nextPiece() {
+        // NOTE: PieceIterator is guaranteed to return non-empty pieces, so this method will always
+        // return non-empty iterators (or null)
+        return pieces.hasNext() ? pieces.next().iterator() : null;
+      }
+
+      @Override
+      public boolean hasNext() {
+        return current != null;
+      }
+
+      @Override
+      public byte nextByte() {
+        if (current == null) {
+          throw new NoSuchElementException();
+        }
+        byte b = current.nextByte();
+        if (!current.hasNext()) {
+          current = nextPiece();
+        }
+        return b;
+      }
+    };
+  }
+
   // =================================================================
   // Pieces
 
@@ -546,7 +581,7 @@ final class RopeByteString extends ByteString {
     // Stack containing the part of the string, starting from the left, that
     // we've already traversed.  The final string should be the equivalent of
     // concatenating the strings on the stack from bottom to top.
-    private final Stack<ByteString> prefixesStack = new Stack<ByteString>();
+    private final ArrayDeque<ByteString> prefixesStack = new ArrayDeque<>();
 
     private ByteString balance(ByteString left, ByteString right) {
       doBalance(left);
@@ -650,9 +685,8 @@ final class RopeByteString extends ByteString {
    *
    * <p>This iterator is used to implement {@link RopeByteString#equalsFragments(ByteString)}.
    */
-  private static class PieceIterator implements Iterator<LeafByteString> {
-
-    private final Stack<RopeByteString> breadCrumbs = new Stack<RopeByteString>();
+  private static final class PieceIterator implements Iterator<LeafByteString> {
+    private final ArrayDeque<RopeByteString> breadCrumbs = new ArrayDeque<>();
     private LeafByteString next;
 
     private PieceIterator(ByteString root) {

+ 169 - 52
java/core/src/main/java/com/google/protobuf/TextFormat.java

@@ -1127,6 +1127,7 @@ public final class TextFormat {
     PARSER.merge(input, builder);
   }
 
+
   /**
    * Parse a text-format message from {@code input}.
    *
@@ -1166,6 +1167,7 @@ public final class TextFormat {
     PARSER.merge(input, extensionRegistry, builder);
   }
 
+
   /**
    * Parse a text-format message from {@code input}. Extensions will be recognized if they are
    * registered in {@code extensionRegistry}.
@@ -1185,6 +1187,7 @@ public final class TextFormat {
   }
 
 
+
   /**
    * Parser for text-format proto2 instances. This class is thread-safe. The implementation largely
    * follows google/protobuf/text_format.cc.
@@ -1205,24 +1208,60 @@ public final class TextFormat {
      * </ul>
      */
     public enum SingularOverwritePolicy {
-      /** The last value is retained. */
+      /**
+       * Later values are merged with earlier values. For primitive fields or conflicting oneofs,
+       * the last value is retained.
+       */
       ALLOW_SINGULAR_OVERWRITES,
       /** An error is issued. */
       FORBID_SINGULAR_OVERWRITES
     }
 
+    /**
+     * Determines how to deal with repeated values for singular Message fields. For example,
+     * given a field "foo" containing subfields "baz" and "qux":
+     *
+     * <ul>
+     *   <li>"foo { baz: 1 } foo { baz: 2 }", or
+     *   <li>"foo { baz: 1 } foo { qux: 2 }"
+     * </ul>
+     */
+    public enum MergingStyle {
+      /**
+       * Merge the values in standard protobuf fashion:
+       *
+       * <ul>
+       *   <li>"foo { baz: 2 }" and
+       *   <li>"foo { baz: 1, qux: 2 }", respectively.
+       * </ul>
+       */
+      RECURSIVE,
+      /**
+       * Later values overwrite ("clobber") previous values:
+       *
+       * <ul>
+       *   <li>"foo { baz: 2 }" and
+       *   <li>"foo { qux: 2 }", respectively.
+       * </ul>
+       */
+      NON_RECURSIVE
+    }
+
     private final boolean allowUnknownFields;
     private final boolean allowUnknownEnumValues;
+    private final boolean allowUnknownExtensions;
     private final SingularOverwritePolicy singularOverwritePolicy;
     private TextFormatParseInfoTree.Builder parseInfoTreeBuilder;
 
     private Parser(
         boolean allowUnknownFields,
         boolean allowUnknownEnumValues,
+        boolean allowUnknownExtensions,
         SingularOverwritePolicy singularOverwritePolicy,
         TextFormatParseInfoTree.Builder parseInfoTreeBuilder) {
       this.allowUnknownFields = allowUnknownFields;
       this.allowUnknownEnumValues = allowUnknownEnumValues;
+      this.allowUnknownExtensions = allowUnknownExtensions;
       this.singularOverwritePolicy = singularOverwritePolicy;
       this.parseInfoTreeBuilder = parseInfoTreeBuilder;
     }
@@ -1236,11 +1275,23 @@ public final class TextFormat {
     public static class Builder {
       private boolean allowUnknownFields = false;
       private boolean allowUnknownEnumValues = false;
+      private boolean allowUnknownExtensions = false;
       private SingularOverwritePolicy singularOverwritePolicy =
           SingularOverwritePolicy.ALLOW_SINGULAR_OVERWRITES;
       private TextFormatParseInfoTree.Builder parseInfoTreeBuilder = null;
 
 
+      /**
+       * Set whether this parser will allow unknown extensions. By default, an
+       * exception is thrown if unknown extension is encountered. If this is set true,
+       * the parser will only log a warning. Allow unknown extensions does not mean
+       * allow normal unknown fields.
+       */
+      public Builder setAllowUnknownExtensions(boolean allowUnknownExtensions) {
+        this.allowUnknownExtensions = allowUnknownExtensions;
+        return this;
+      }
+
       /** Sets parser behavior when a non-repeated field appears more than once. */
       public Builder setSingularOverwritePolicy(SingularOverwritePolicy p) {
         this.singularOverwritePolicy = p;
@@ -1256,6 +1307,7 @@ public final class TextFormat {
         return new Parser(
             allowUnknownFields,
             allowUnknownEnumValues,
+            allowUnknownExtensions,
             singularOverwritePolicy,
             parseInfoTreeBuilder);
       }
@@ -1297,6 +1349,7 @@ public final class TextFormat {
     }
 
 
+
     private static final int BUFFER_SIZE = 4096;
 
     // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
@@ -1315,25 +1368,56 @@ public final class TextFormat {
       return text;
     }
 
+    static final class UnknownField {
+      static enum Type {
+        FIELD, EXTENSION;
+      }
+
+      final String message;
+      final Type type;
+
+      UnknownField(String message, Type type) {
+        this.message = message;
+        this.type = type;
+      }
+    }
+
     // Check both unknown fields and unknown extensions and log warning messages
     // or throw exceptions according to the flag.
-    private void checkUnknownFields(final List<String> unknownFields) throws ParseException {
+    private void checkUnknownFields(final List<UnknownField> unknownFields) throws ParseException {
       if (unknownFields.isEmpty()) {
         return;
       }
 
       StringBuilder msg = new StringBuilder("Input contains unknown fields and/or extensions:");
-      for (String field : unknownFields) {
-        msg.append('\n').append(field);
+      for (UnknownField field : unknownFields) {
+        msg.append('\n').append(field.message);
       }
 
       if (allowUnknownFields) {
         logger.warning(msg.toString());
-      } else {
-        String[] lineColumn = unknownFields.get(0).split(":");
-        throw new ParseException(
-            Integer.parseInt(lineColumn[0]), Integer.parseInt(lineColumn[1]), msg.toString());
+        return;
+      }
+
+      int firstErrorIndex = 0;
+      if (allowUnknownExtensions) {
+        boolean allUnknownExtensions = true;
+        for (UnknownField field : unknownFields) {
+          if (field.type == UnknownField.Type.FIELD) {
+            allUnknownExtensions = false;
+            break;
+          }
+          ++firstErrorIndex;
+        }
+        if (allUnknownExtensions) {
+          logger.warning(msg.toString());
+          return;
+        }
       }
+
+      String[] lineColumn = unknownFields.get(firstErrorIndex).message.split(":");
+      throw new ParseException(
+          Integer.parseInt(lineColumn[0]), Integer.parseInt(lineColumn[1]), msg.toString());
     }
 
     /**
@@ -1348,24 +1432,32 @@ public final class TextFormat {
       final Tokenizer tokenizer = new Tokenizer(input);
       MessageReflection.BuilderAdapter target = new MessageReflection.BuilderAdapter(builder);
 
-      List<String> unknownFields = new ArrayList<String>();
+      List<UnknownField> unknownFields = new ArrayList<UnknownField>();
 
       while (!tokenizer.atEnd()) {
-        mergeField(tokenizer, extensionRegistry, target, unknownFields);
+        mergeField(tokenizer, extensionRegistry, target, MergingStyle.RECURSIVE, unknownFields);
       }
 
       checkUnknownFields(unknownFields);
     }
 
 
+
     /** Parse a single field from {@code tokenizer} and merge it into {@code builder}. */
     private void mergeField(
         final Tokenizer tokenizer,
         final ExtensionRegistry extensionRegistry,
         final MessageReflection.MergeTarget target,
-        List<String> unknownFields)
+        final MergingStyle mergingStyle,
+        List<UnknownField> unknownFields)
         throws ParseException {
-      mergeField(tokenizer, extensionRegistry, target, parseInfoTreeBuilder, unknownFields);
+      mergeField(
+          tokenizer,
+          extensionRegistry,
+          target,
+          parseInfoTreeBuilder,
+          mergingStyle,
+          unknownFields);
     }
 
     /** Parse a single field from {@code tokenizer} and merge it into {@code target}. */
@@ -1374,7 +1466,8 @@ public final class TextFormat {
         final ExtensionRegistry extensionRegistry,
         final MessageReflection.MergeTarget target,
         TextFormatParseInfoTree.Builder parseTreeBuilder,
-        List<String> unknownFields)
+        final MergingStyle mergingStyle,
+        List<UnknownField> unknownFields)
         throws ParseException {
       FieldDescriptor field = null;
       int startLine = tokenizer.getLine();
@@ -1393,15 +1486,15 @@ public final class TextFormat {
         extension = target.findExtensionByName(extensionRegistry, name.toString());
 
         if (extension == null) {
-          unknownFields.add(
-              (tokenizer.getPreviousLine() + 1)
-                  + ":"
-                  + (tokenizer.getPreviousColumn() + 1)
-                  + ":\t"
-                  + type.getFullName()
-                  + ".["
-                  + name
-                  + "]");
+          String message = (tokenizer.getPreviousLine() + 1)
+                           + ":"
+                           + (tokenizer.getPreviousColumn() + 1)
+                           + ":\t"
+                           + type.getFullName()
+                           + ".["
+                           + name
+                           + "]";
+          unknownFields.add(new UnknownField(message, UnknownField.Type.EXTENSION));
         } else {
           if (extension.descriptor.getContainingType() != type) {
             throw tokenizer.parseExceptionPreviousToken(
@@ -1440,14 +1533,14 @@ public final class TextFormat {
         }
 
         if (field == null) {
-          unknownFields.add(
-              (tokenizer.getPreviousLine() + 1)
-                  + ":"
-                  + (tokenizer.getPreviousColumn() + 1)
-                  + ":\t"
-                  + type.getFullName()
-                  + "."
-                  + name);
+          String message = (tokenizer.getPreviousLine() + 1)
+                           + ":"
+                           + (tokenizer.getPreviousColumn() + 1)
+                           + ":\t"
+                           + type.getFullName()
+                           + "."
+                           + name;
+          unknownFields.add(new UnknownField(message, UnknownField.Type.FIELD));
         }
       }
 
@@ -1480,6 +1573,7 @@ public final class TextFormat {
               field,
               extension,
               childParseTreeBuilder,
+              mergingStyle,
               unknownFields);
         } else {
           consumeFieldValues(
@@ -1489,6 +1583,7 @@ public final class TextFormat {
               field,
               extension,
               parseTreeBuilder,
+              mergingStyle,
               unknownFields);
         }
       } else {
@@ -1500,6 +1595,7 @@ public final class TextFormat {
             field,
             extension,
             parseTreeBuilder,
+            mergingStyle,
             unknownFields);
       }
 
@@ -1524,7 +1620,8 @@ public final class TextFormat {
         final FieldDescriptor field,
         final ExtensionRegistry.ExtensionInfo extension,
         final TextFormatParseInfoTree.Builder parseTreeBuilder,
-        List<String> unknownFields)
+        final MergingStyle mergingStyle,
+        List<UnknownField> unknownFields)
         throws ParseException {
       // Support specifying repeated field values as a comma-separated list.
       // Ex."foo: [1, 2, 3]"
@@ -1538,6 +1635,7 @@ public final class TextFormat {
                 field,
                 extension,
                 parseTreeBuilder,
+                mergingStyle,
                 unknownFields);
             if (tokenizer.tryConsume("]")) {
               // End of list.
@@ -1554,6 +1652,7 @@ public final class TextFormat {
             field,
             extension,
             parseTreeBuilder,
+            mergingStyle,
             unknownFields);
       }
     }
@@ -1566,8 +1665,28 @@ public final class TextFormat {
         final FieldDescriptor field,
         final ExtensionRegistry.ExtensionInfo extension,
         final TextFormatParseInfoTree.Builder parseTreeBuilder,
-        List<String> unknownFields)
+        final MergingStyle mergingStyle,
+        List<UnknownField> unknownFields)
         throws ParseException {
+      if (singularOverwritePolicy == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES
+          && !field.isRepeated()) {
+        if (target.hasField(field)) {
+          throw tokenizer.parseExceptionPreviousToken(
+              "Non-repeated field \"" + field.getFullName() + "\" cannot be overwritten.");
+        } else if (field.getContainingOneof() != null
+            && target.hasOneof(field.getContainingOneof())) {
+          Descriptors.OneofDescriptor oneof = field.getContainingOneof();
+          throw tokenizer.parseExceptionPreviousToken(
+              "Field \""
+                  + field.getFullName()
+                  + "\" is specified along with field \""
+                  + target.getOneofFieldDescriptor(oneof).getFullName()
+                  + "\", another member of oneof \""
+                  + oneof.getName()
+                  + "\".");
+        }
+      }
+
       Object value = null;
 
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
@@ -1580,15 +1699,29 @@ public final class TextFormat {
         }
 
         final MessageReflection.MergeTarget subField;
-        subField =
-            target.newMergeTargetForField(
-                field, (extension == null) ? null : extension.defaultInstance);
+        Message defaultInstance = (extension == null) ? null : extension.defaultInstance;
+        switch (mergingStyle) {
+          case RECURSIVE:
+            subField = target.newMergeTargetForField(field, defaultInstance);
+            break;
+          case NON_RECURSIVE:
+            subField = target.newEmptyTargetForField(field, defaultInstance);
+            break;
+          default:
+            throw new AssertionError();
+        }
 
         while (!tokenizer.tryConsume(endToken)) {
           if (tokenizer.atEnd()) {
             throw tokenizer.parseException("Expected \"" + endToken + "\".");
           }
-          mergeField(tokenizer, extensionRegistry, subField, parseTreeBuilder, unknownFields);
+          mergeField(
+              tokenizer,
+              extensionRegistry,
+              subField,
+              parseTreeBuilder,
+              mergingStyle,
+              unknownFields);
         }
 
         value = subField.finish();
@@ -1693,22 +1826,6 @@ public final class TextFormat {
         // TODO(b/29122459): If field.isMapField() and FORBID_SINGULAR_OVERWRITES mode,
         //     check for duplicate map keys here.
         target.addRepeatedField(field, value);
-      } else if ((singularOverwritePolicy == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES)
-          && target.hasField(field)) {
-        throw tokenizer.parseExceptionPreviousToken(
-            "Non-repeated field \"" + field.getFullName() + "\" cannot be overwritten.");
-      } else if ((singularOverwritePolicy == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES)
-          && field.getContainingOneof() != null
-          && target.hasOneof(field.getContainingOneof())) {
-        Descriptors.OneofDescriptor oneof = field.getContainingOneof();
-        throw tokenizer.parseExceptionPreviousToken(
-            "Field \""
-                + field.getFullName()
-                + "\" is specified along with field \""
-                + target.getOneofFieldDescriptor(oneof).getFullName()
-                + "\", another member of oneof \""
-                + oneof.getName()
-                + "\".");
       } else {
         target.setField(field, value);
       }

+ 9 - 0
java/core/src/main/java/com/google/protobuf/UnsafeUtil.java

@@ -83,6 +83,15 @@ final class UnsafeUtil {
   }
 
 
+  @SuppressWarnings("unchecked") // safe by method contract
+  static <T> T allocateInstance(Class<T> clazz) {
+    try {
+      return (T) UNSAFE.allocateInstance(clazz);
+    } catch (InstantiationException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
   static long objectFieldOffset(Field field) {
     return MEMORY_ACCESSOR.objectFieldOffset(field);
   }

+ 2 - 2
java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java

@@ -522,8 +522,8 @@ public class AbstractMessageTest extends TestCase {
   /**
    * Asserts that the given protos are not equal and have different hash codes.
    *
-   * @warning It's valid for non-equal objects to have the same hash code, so this test is stricter
-   *     than it needs to be. However, this should happen relatively rarely.
+   * <p><b>Note:</b> It's valid for non-equal objects to have the same hash code, so this test is
+   * stricter than it needs to be. However, this should happen relatively rarely.
    */
   private void checkNotEqual(Message m1, Message m2) {
     String equalsError = String.format("%s should not be equal to %s", m1, m2);

+ 10 - 21
java/core/src/test/java/com/google/protobuf/AnyTest.java

@@ -35,17 +35,14 @@ import protobuf_unittest.UnittestProto.TestAllTypes;
 import java.util.Objects;
 import junit.framework.TestCase;
 
-/**
- * Unit tests for Any message.
- */
+/** Unit tests for Any message. */
 public class AnyTest extends TestCase {
   public void testAnyGeneratedApi() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TestUtil.setAllFields(builder);
     TestAllTypes message = builder.build();
 
-    TestAny container = TestAny.newBuilder()
-        .setValue(Any.pack(message)).build();
+    TestAny container = TestAny.newBuilder().setValue(Any.pack(message)).build();
 
     assertTrue(container.getValue().is(TestAllTypes.class));
     assertFalse(container.getValue().is(TestAny.class));
@@ -64,8 +61,7 @@ public class AnyTest extends TestCase {
 
     // Test that unpacking throws an exception if parsing fails.
     TestAny.Builder containerBuilder = container.toBuilder();
-    containerBuilder.getValueBuilder().setValue(
-        ByteString.copyFrom(new byte[]{0x11}));
+    containerBuilder.getValueBuilder().setValue(ByteString.copyFrom(new byte[] {0x11}));
     container = containerBuilder.build();
     try {
       container.getValue().unpack(TestAllTypes.class);
@@ -80,12 +76,10 @@ public class AnyTest extends TestCase {
     TestUtil.setAllFields(builder);
     TestAllTypes message = builder.build();
 
-    TestAny container = TestAny.newBuilder()
-        .setValue(Any.pack(message, "xxx.com")).build();
+    TestAny container = TestAny.newBuilder().setValue(Any.pack(message, "xxx.com")).build();
 
     assertEquals(
-        "xxx.com/" + TestAllTypes.getDescriptor().getFullName(),
-        container.getValue().getTypeUrl());
+        "xxx.com/" + TestAllTypes.getDescriptor().getFullName(), container.getValue().getTypeUrl());
 
     assertTrue(container.getValue().is(TestAllTypes.class));
     assertFalse(container.getValue().is(TestAny.class));
@@ -93,12 +87,10 @@ public class AnyTest extends TestCase {
     TestAllTypes result = container.getValue().unpack(TestAllTypes.class);
     TestUtil.assertAllFieldsSet(result);
 
-    container = TestAny.newBuilder()
-        .setValue(Any.pack(message, "yyy.com/")).build();
+    container = TestAny.newBuilder().setValue(Any.pack(message, "yyy.com/")).build();
 
     assertEquals(
-        "yyy.com/" + TestAllTypes.getDescriptor().getFullName(),
-        container.getValue().getTypeUrl());
+        "yyy.com/" + TestAllTypes.getDescriptor().getFullName(), container.getValue().getTypeUrl());
 
     assertTrue(container.getValue().is(TestAllTypes.class));
     assertFalse(container.getValue().is(TestAny.class));
@@ -106,12 +98,10 @@ public class AnyTest extends TestCase {
     result = container.getValue().unpack(TestAllTypes.class);
     TestUtil.assertAllFieldsSet(result);
 
-    container = TestAny.newBuilder()
-        .setValue(Any.pack(message, "")).build();
+    container = TestAny.newBuilder().setValue(Any.pack(message, "")).build();
 
     assertEquals(
-        "/" + TestAllTypes.getDescriptor().getFullName(),
-        container.getValue().getTypeUrl());
+        "/" + TestAllTypes.getDescriptor().getFullName(), container.getValue().getTypeUrl());
 
     assertTrue(container.getValue().is(TestAllTypes.class));
     assertFalse(container.getValue().is(TestAny.class));
@@ -125,8 +115,7 @@ public class AnyTest extends TestCase {
     TestUtil.setAllFields(builder);
     TestAllTypes message = builder.build();
 
-    TestAny container = TestAny.newBuilder()
-        .setValue(Any.pack(message)).build();
+    TestAny container = TestAny.newBuilder().setValue(Any.pack(message)).build();
 
     assertTrue(container.getValue().is(TestAllTypes.class));
 

+ 38 - 22
java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java

@@ -77,10 +77,10 @@ public class BooleanArrayListTest extends TestCase {
     list.addAll(asList(true, false, true, false));
     Iterator<Boolean> iterator = list.iterator();
     assertEquals(4, list.size());
-    assertTrue(list.get(0));
-    assertTrue(iterator.next());
+    assertEquals(true, (boolean) list.get(0));
+    assertEquals(true, (boolean) iterator.next());
     list.set(0, true);
-    assertFalse(iterator.next());
+    assertEquals(false, (boolean) iterator.next());
 
     list.remove(0);
     try {
@@ -101,9 +101,9 @@ public class BooleanArrayListTest extends TestCase {
   }
 
   public void testGet() {
-    assertTrue(TERTIARY_LIST.get(0));
-    assertFalse(TERTIARY_LIST.get(1));
-    assertTrue(TERTIARY_LIST.get(2));
+    assertEquals(true, (boolean) TERTIARY_LIST.get(0));
+    assertEquals(false, (boolean) TERTIARY_LIST.get(1));
+    assertEquals(true, (boolean) TERTIARY_LIST.get(2));
 
     try {
       TERTIARY_LIST.get(-1);
@@ -121,9 +121,9 @@ public class BooleanArrayListTest extends TestCase {
   }
 
   public void testGetBoolean() {
-    assertTrue(TERTIARY_LIST.getBoolean(0));
-    assertFalse(TERTIARY_LIST.getBoolean(1));
-    assertTrue(TERTIARY_LIST.getBoolean(2));
+    assertEquals(true, TERTIARY_LIST.getBoolean(0));
+    assertEquals(false, TERTIARY_LIST.getBoolean(1));
+    assertEquals(true, TERTIARY_LIST.getBoolean(2));
 
     try {
       TERTIARY_LIST.get(-1);
@@ -162,11 +162,11 @@ public class BooleanArrayListTest extends TestCase {
     list.addBoolean(false);
     list.addBoolean(false);
 
-    assertFalse(list.set(0, true));
-    assertTrue(list.getBoolean(0));
+    assertEquals(false, (boolean) list.set(0, true));
+    assertEquals(true, list.getBoolean(0));
 
-    assertFalse(list.set(1, false));
-    assertFalse(list.getBoolean(1));
+    assertEquals(false, (boolean) list.set(1, false));
+    assertEquals(false, list.getBoolean(1));
 
     try {
       list.set(-1, false);
@@ -187,11 +187,11 @@ public class BooleanArrayListTest extends TestCase {
     list.addBoolean(true);
     list.addBoolean(true);
 
-    assertTrue(list.setBoolean(0, false));
-    assertFalse(list.getBoolean(0));
+    assertEquals(true, list.setBoolean(0, false));
+    assertEquals(false, list.getBoolean(0));
 
-    assertTrue(list.setBoolean(1, false));
-    assertFalse(list.getBoolean(1));
+    assertEquals(true, list.setBoolean(1, false));
+    assertEquals(false, list.getBoolean(1));
 
     try {
       list.setBoolean(-1, false);
@@ -255,8 +255,8 @@ public class BooleanArrayListTest extends TestCase {
 
     assertTrue(list.addAll(Collections.singleton(true)));
     assertEquals(1, list.size());
-    assertTrue(list.get(0));
-    assertTrue(list.getBoolean(0));
+    assertEquals(true, (boolean) list.get(0));
+    assertEquals(true, list.getBoolean(0));
 
     assertTrue(list.addAll(asList(false, true, false, true, false)));
     assertEquals(asList(true, false, true, false, true, false), list);
@@ -268,9 +268,16 @@ public class BooleanArrayListTest extends TestCase {
     assertFalse(list.addAll(BooleanArrayList.emptyList()));
   }
 
+  public void testEquals() {
+    BooleanArrayList list1 = new BooleanArrayList();
+    BooleanArrayList list2 = new BooleanArrayList();
+
+    assertEquals(list1, list2);
+  }
+
   public void testRemove() {
     list.addAll(TERTIARY_LIST);
-    assertTrue(list.remove(0));
+    assertEquals(true, (boolean) list.remove(0));
     assertEquals(asList(false, true), list);
 
     assertTrue(list.remove(Boolean.TRUE));
@@ -279,7 +286,7 @@ public class BooleanArrayListTest extends TestCase {
     assertFalse(list.remove(Boolean.TRUE));
     assertEquals(asList(false), list);
 
-    assertFalse(list.remove(0));
+    assertEquals(false, (boolean) list.remove(0));
     assertEquals(asList(), list);
 
     try {
@@ -296,13 +303,22 @@ public class BooleanArrayListTest extends TestCase {
     }
   }
 
-  public void testRemoveEndOfCapacity() {
+  public void testRemoveEnd_listAtCapacity() {
     BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addBoolean(true);
     toRemove.remove(0);
     assertEquals(0, toRemove.size());
   }
 
+  public void testRemove_listAtCapacity() {
+    BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(2);
+    toRemove.addBoolean(true);
+    toRemove.addBoolean(false);
+    toRemove.remove(0);
+    assertEquals(1, toRemove.size());
+    assertEquals(false, (boolean) toRemove.get(0));
+  }
+
   public void testSublistRemoveEndOfCapacity() {
     BooleanList toRemove = BooleanArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addBoolean(true);

+ 100 - 47
java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java

@@ -30,6 +30,7 @@
 
 package com.google.protobuf;
 
+import static org.junit.Assert.assertArrayEquals;
 import protobuf_unittest.UnittestProto.BoolMessage;
 import protobuf_unittest.UnittestProto.Int32Message;
 import protobuf_unittest.UnittestProto.Int64Message;
@@ -51,9 +52,9 @@ import junit.framework.TestCase;
  * @author kenton@google.com Kenton Varda
  */
 public class CodedInputStreamTest extends TestCase {
-  
-  private static final int DEFAULT_BLOCK_SIZE = 4096; 
-  
+
+  private static final int DEFAULT_BLOCK_SIZE = 4096;
+
   private enum InputType {
     ARRAY {
       @Override
@@ -88,10 +89,10 @@ public class CodedInputStreamTest extends TestCase {
         if (blockSize > DEFAULT_BLOCK_SIZE) {
           blockSize = DEFAULT_BLOCK_SIZE;
         }
-        ArrayList <ByteBuffer> input = new ArrayList <ByteBuffer>();
+        ArrayList<ByteBuffer> input = new ArrayList<ByteBuffer>();
         for (int i = 0; i < data.length; i += blockSize) {
-          int rl = Math.min(blockSize, data.length - i); 
-          ByteBuffer rb = ByteBuffer.allocateDirect(rl); 
+          int rl = Math.min(blockSize, data.length - i);
+          ByteBuffer rb = ByteBuffer.allocateDirect(rl);
           rb.put(data, i, rl);
           rb.flip();
           input.add(rb);
@@ -105,10 +106,10 @@ public class CodedInputStreamTest extends TestCase {
         if (blockSize > DEFAULT_BLOCK_SIZE) {
           blockSize = DEFAULT_BLOCK_SIZE;
         }
-        ArrayList <ByteBuffer> input = new ArrayList <ByteBuffer>();
+        ArrayList<ByteBuffer> input = new ArrayList<ByteBuffer>();
         for (int i = 0; i < data.length; i += blockSize) {
-          int rl = Math.min(blockSize, data.length - i); 
-          ByteBuffer rb = ByteBuffer.allocateDirect(rl); 
+          int rl = Math.min(blockSize, data.length - i);
+          ByteBuffer rb = ByteBuffer.allocateDirect(rl);
           rb.put(data, i, rl);
           rb.flip();
           input.add(rb);
@@ -116,8 +117,6 @@ public class CodedInputStreamTest extends TestCase {
         return CodedInputStream.newInstance(new IterableByteBufferInputStream(input));
       }
     };
-    
-    
 
     CodedInputStream newDecoder(byte[] data) {
       return newDecoder(data, data.length);
@@ -144,21 +143,37 @@ public class CodedInputStreamTest extends TestCase {
    */
   private static final class SmallBlockInputStream extends FilterInputStream {
     private final int blockSize;
+    private int skipCalls;
+    private int readCalls;
 
     public SmallBlockInputStream(byte[] data, int blockSize) {
       super(new ByteArrayInputStream(data));
       this.blockSize = blockSize;
     }
 
+    @Override
+    public int read() throws IOException {
+      readCalls++;
+      return super.read();
+    }
+
     @Override
     public int read(byte[] b) throws IOException {
+      readCalls++;
       return super.read(b, 0, Math.min(b.length, blockSize));
     }
 
     @Override
     public int read(byte[] b, int off, int len) throws IOException {
+      readCalls++;
       return super.read(b, off, Math.min(len, blockSize));
     }
+
+    @Override
+    public long skip(long len) throws IOException {
+      skipCalls++;
+      return super.skip(Math.min(len, blockSize));
+    }
   }
 
   private void assertDataConsumed(String msg, byte[] data, CodedInputStream input)
@@ -430,6 +445,41 @@ public class CodedInputStreamTest extends TestCase {
     }
   }
 
+  /**
+   * Test that calling skipRawBytes (when not merging a message) actually skips from the underlying
+   * inputstream, regardless of the buffer size used.
+   */
+  public void testSkipRawBytesActuallySkips() throws Exception {
+    SmallBlockInputStream bytes = new SmallBlockInputStream(new byte[] {1, 2, 3, 4, 5}, 3);
+    CodedInputStream input = CodedInputStream.newInstance(bytes, 1); // Tiny buffer
+    input.skipRawBytes(3);
+    input.skipRawBytes(2);
+    assertEquals(2, bytes.skipCalls);
+    assertEquals(0, bytes.readCalls);
+  }
+
+  public void testSkipHugeBlob() throws Exception {
+    // Allocate and initialize a 1MB blob.
+    int blobSize = 1 << 20;
+    byte[] blob = new byte[blobSize];
+    for (int i = 0; i < blob.length; i++) {
+      blob[i] = (byte) i;
+    }
+
+    for (InputType inputType : InputType.values()) {
+      CodedInputStream decoder = inputType.newDecoder(blob);
+      decoder.skipRawBytes(blobSize - 10);
+      byte[] remaining = decoder.readRawBytes(10);
+      assertArrayEquals(Arrays.copyOfRange(blob, blobSize - 10, blobSize), remaining);
+    }
+  }
+
+  /** Skipping a huge blob should not allocate excessive memory, so there should be no limit */
+  public void testSkipMaliciouslyHugeBlob() throws Exception {
+    InputStream is = new RepeatingInputStream(new byte[]{1}, Integer.MAX_VALUE);
+    CodedInputStream.newInstance(is).skipRawBytes(Integer.MAX_VALUE);
+  }
+
   public void testReadHugeBlob() throws Exception {
     // Allocate and initialize a 1MB blob.
     byte[] blob = new byte[1 << 20];
@@ -485,8 +535,9 @@ public class CodedInputStreamTest extends TestCase {
   }
 
   /**
-   * Test we can do messages that are up to CodedInputStream#DEFAULT_SIZE_LIMIT
-   * in size (2G or Integer#MAX_SIZE).
+   * Test we can do messages that are up to CodedInputStream#DEFAULT_SIZE_LIMIT in size (2G or
+   * Integer#MAX_SIZE).
+   *
    * @throws IOException
    */
   public void testParseMessagesCloseTo2G() throws IOException {
@@ -501,8 +552,9 @@ public class CodedInputStreamTest extends TestCase {
   }
 
   /**
-   * Test there is an exception if a message exceeds
-   * CodedInputStream#DEFAULT_SIZE_LIMIT in size (2G or Integer#MAX_SIZE).
+   * Test there is an exception if a message exceeds CodedInputStream#DEFAULT_SIZE_LIMIT in size (2G
+   * or Integer#MAX_SIZE).
+   *
    * @throws IOException
    */
   public void testParseMessagesOver2G() throws IOException {
@@ -526,7 +578,7 @@ public class CodedInputStreamTest extends TestCase {
    * @return A serialized big message.
    */
   private static byte[] getBigSerializedMessage() {
-    byte[] value = new byte[16 * 1024 * 1024]; 
+    byte[] value = new byte[16 * 1024 * 1024];
     ByteString bsValue = ByteString.wrap(value);
     return TestAllTypes.newBuilder().setOptionalBytes(bsValue).build().toByteArray();
   }
@@ -654,7 +706,7 @@ public class CodedInputStreamTest extends TestCase {
       checkSizeLimitExceeded(expected);
     }
   }
-  
+
   public void testRefillBufferWithCorrectSize() throws Exception {
     // NOTE: refillBuffer only applies to the stream-backed CIS.
     byte[] bytes = "123456789".getBytes("UTF-8");
@@ -672,14 +724,15 @@ public class CodedInputStreamTest extends TestCase {
     output.flush();
 
     // Input is two string with length 9 and one raw byte.
-    byte[] rawInput = rawOutput.toByteArray(); 
-    for (int inputStreamBufferLength = 8; 
-        inputStreamBufferLength <= rawInput.length + 1; inputStreamBufferLength++) {
-      CodedInputStream input = CodedInputStream.newInstance(
-              new ByteArrayInputStream(rawInput), inputStreamBufferLength);
+    byte[] rawInput = rawOutput.toByteArray();
+    for (int inputStreamBufferLength = 8;
+        inputStreamBufferLength <= rawInput.length + 1;
+        inputStreamBufferLength++) {
+      CodedInputStream input =
+          CodedInputStream.newInstance(new ByteArrayInputStream(rawInput), inputStreamBufferLength);
       input.setSizeLimit(rawInput.length - 1);
       input.readString();
-      input.readString(); 
+      input.readString();
       try {
         input.readRawByte(); // Hits limit.
         fail("Should have thrown an exception!");
@@ -690,9 +743,8 @@ public class CodedInputStreamTest extends TestCase {
   }
 
   public void testIsAtEnd() throws Exception {
-    CodedInputStream input = CodedInputStream.newInstance(
-        new ByteArrayInputStream(new byte[5]));
-    try {   
+    CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(new byte[5]));
+    try {
       for (int i = 0; i < 5; i++) {
         assertEquals(false, input.isAtEnd());
         input.readRawByte();
@@ -715,19 +767,18 @@ public class CodedInputStreamTest extends TestCase {
     output.flush();
 
     byte[] rawInput = rawOutput.toByteArray();
-    CodedInputStream input = CodedInputStream.newInstance(
-              new ByteArrayInputStream(rawInput));
+    CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(rawInput));
     // The length of the whole rawInput
     input.setSizeLimit(11);
     // Some number that is smaller than the rawInput's length
-    // but larger than 2 
+    // but larger than 2
     input.pushLimit(5);
     try {
       input.readString();
       fail("Should have thrown an exception");
     } catch (InvalidProtocolBufferException expected) {
-      assertEquals(expected.getMessage(), 
-          InvalidProtocolBufferException.truncatedMessage().getMessage());
+      assertEquals(
+          expected.getMessage(), InvalidProtocolBufferException.truncatedMessage().getMessage());
     }
   }
 
@@ -936,13 +987,14 @@ public class CodedInputStreamTest extends TestCase {
     output.flush();
     byte[] data = rawOutput.toByteString().toByteArray();
 
-    CodedInputStream input = CodedInputStream.newInstance(
-        new ByteArrayInputStream(data) {
-          @Override
-          public synchronized int available() {
-            return 0;
-          }
-        });
+    CodedInputStream input =
+        CodedInputStream.newInstance(
+            new ByteArrayInputStream(data) {
+              @Override
+              public synchronized int available() {
+                return 0;
+              }
+            });
     ByteString result = input.readBytes();
     assertEquals(ByteString.copyFrom(bytes), result);
   }
@@ -959,13 +1011,14 @@ public class CodedInputStreamTest extends TestCase {
     output.flush();
     byte[] data = rawOutput.toByteString().toByteArray();
 
-    CodedInputStream input = CodedInputStream.newInstance(
-        new ByteArrayInputStream(data) {
-          @Override
-          public synchronized int available() {
-            return 0;
-          }
-        });
+    CodedInputStream input =
+        CodedInputStream.newInstance(
+            new ByteArrayInputStream(data) {
+              @Override
+              public synchronized int available() {
+                return 0;
+              }
+            });
     byte[] result = input.readByteArray();
     assertTrue(Arrays.equals(bytes, result));
   }
@@ -1034,8 +1087,8 @@ public class CodedInputStreamTest extends TestCase {
     byte[] data = byteArrayStream.toByteArray();
 
     for (InputType inputType : InputType.values()) {
-      if (inputType == InputType.STREAM 
-          || inputType == InputType.STREAM_ITER_DIRECT 
+      if (inputType == InputType.STREAM
+          || inputType == InputType.STREAM_ITER_DIRECT
           || inputType == InputType.ITER_DIRECT) {
         // Aliasing doesn't apply to stream-backed CIS.
         continue;

+ 284 - 321
java/core/src/test/java/com/google/protobuf/DescriptorsTest.java

@@ -79,8 +79,7 @@ public class DescriptorsTest extends TestCase {
   private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
 
   public void testFieldTypeEnumMapping() throws Exception {
-    assertEquals(FieldDescriptor.Type.values().length,
-        FieldDescriptorProto.Type.values().length);
+    assertEquals(FieldDescriptor.Type.values().length, FieldDescriptorProto.Type.values().length);
     for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
       FieldDescriptorProto.Type protoType = type.toProto();
       assertEquals("TYPE_" + type.name(), protoType.name());
@@ -95,11 +94,9 @@ public class DescriptorsTest extends TestCase {
     assertEquals("protobuf_unittest", file.getPackage());
 
     assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname());
-    assertEquals("google/protobuf/unittest.proto",
-                 file.toProto().getName());
+    assertEquals("google/protobuf/unittest.proto", file.toProto().getName());
 
-    assertEquals(Arrays.asList(UnittestImport.getDescriptor()),
-                 file.getDependencies());
+    assertEquals(Arrays.asList(UnittestImport.getDescriptor()), file.getDependencies());
 
     Descriptor messageType = TestAllTypes.getDescriptor();
     assertEquals(messageType, file.getMessageTypes().get(0));
@@ -115,9 +112,9 @@ public class DescriptorsTest extends TestCase {
     assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
     assertNull(file.findEnumTypeByName("NoSuchType"));
     assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
-    assertEquals(Arrays.asList(ImportEnum.getDescriptor(),
-                               ImportEnumForMap.getDescriptor()),
-                 UnittestImport.getDescriptor().getEnumTypes());
+    assertEquals(
+        Arrays.asList(ImportEnum.getDescriptor(), ImportEnumForMap.getDescriptor()),
+        UnittestImport.getDescriptor().getEnumTypes());
     for (int i = 0; i < file.getEnumTypes().size(); i++) {
       assertEquals(i, file.getEnumTypes().get(i).getIndex());
     }
@@ -127,22 +124,17 @@ public class DescriptorsTest extends TestCase {
     assertEquals(service, file.findServiceByName("TestService"));
     assertNull(file.findServiceByName("NoSuchType"));
     assertNull(file.findServiceByName("protobuf_unittest.TestService"));
-    assertEquals(Collections.emptyList(),
-                 UnittestImport.getDescriptor().getServices());
+    assertEquals(Collections.emptyList(), UnittestImport.getDescriptor().getServices());
     for (int i = 0; i < file.getServices().size(); i++) {
       assertEquals(i, file.getServices().get(i).getIndex());
     }
 
-    FieldDescriptor extension =
-      UnittestProto.optionalInt32Extension.getDescriptor();
+    FieldDescriptor extension = UnittestProto.optionalInt32Extension.getDescriptor();
     assertEquals(extension, file.getExtensions().get(0));
-    assertEquals(extension,
-                 file.findExtensionByName("optional_int32_extension"));
+    assertEquals(extension, file.findExtensionByName("optional_int32_extension"));
     assertNull(file.findExtensionByName("no_such_ext"));
-    assertNull(file.findExtensionByName(
-      "protobuf_unittest.optional_int32_extension"));
-    assertEquals(Collections.emptyList(),
-                 UnittestImport.getDescriptor().getExtensions());
+    assertNull(file.findExtensionByName("protobuf_unittest.optional_int32_extension"));
+    assertEquals(Collections.emptyList(), UnittestImport.getDescriptor().getExtensions());
     for (int i = 0; i < file.getExtensions().size(); i++) {
       assertEquals(i, file.getExtensions().get(i).getIndex());
     }
@@ -156,13 +148,11 @@ public class DescriptorsTest extends TestCase {
     assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName());
     assertEquals(UnittestProto.getDescriptor(), messageType.getFile());
     assertNull(messageType.getContainingType());
-    assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(),
-                 messageType.getOptions());
+    assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(), messageType.getOptions());
     assertEquals("TestAllTypes", messageType.toProto().getName());
 
     assertEquals("NestedMessage", nestedType.getName());
-    assertEquals("protobuf_unittest.TestAllTypes.NestedMessage",
-                 nestedType.getFullName());
+    assertEquals("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.getFullName());
     assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
     assertEquals(messageType, nestedType.getContainingType());
 
@@ -194,36 +184,28 @@ public class DescriptorsTest extends TestCase {
 
   public void testFieldDescriptor() throws Exception {
     Descriptor messageType = TestAllTypes.getDescriptor();
-    FieldDescriptor primitiveField =
-      messageType.findFieldByName("optional_int32");
-    FieldDescriptor enumField =
-      messageType.findFieldByName("optional_nested_enum");
-    FieldDescriptor messageField =
-      messageType.findFieldByName("optional_foreign_message");
-    FieldDescriptor cordField =
-      messageType.findFieldByName("optional_cord");
-    FieldDescriptor extension =
-      UnittestProto.optionalInt32Extension.getDescriptor();
+    FieldDescriptor primitiveField = messageType.findFieldByName("optional_int32");
+    FieldDescriptor enumField = messageType.findFieldByName("optional_nested_enum");
+    FieldDescriptor messageField = messageType.findFieldByName("optional_foreign_message");
+    FieldDescriptor cordField = messageType.findFieldByName("optional_cord");
+    FieldDescriptor extension = UnittestProto.optionalInt32Extension.getDescriptor();
     FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();
 
     assertEquals("optional_int32", primitiveField.getName());
-    assertEquals("protobuf_unittest.TestAllTypes.optional_int32",
-                 primitiveField.getFullName());
+    assertEquals("protobuf_unittest.TestAllTypes.optional_int32", primitiveField.getFullName());
     assertEquals(1, primitiveField.getNumber());
     assertEquals(messageType, primitiveField.getContainingType());
     assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
     assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
     assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
-    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
-                 primitiveField.getOptions());
+    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(), primitiveField.getOptions());
     assertFalse(primitiveField.isExtension());
     assertEquals("optional_int32", primitiveField.toProto().getName());
 
     assertEquals("optional_nested_enum", enumField.getName());
     assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
     assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
-    assertEquals(TestAllTypes.NestedEnum.getDescriptor(),
-                 enumField.getEnumType());
+    assertEquals(TestAllTypes.NestedEnum.getDescriptor(), enumField.getEnumType());
 
     assertEquals("optional_foreign_message", messageField.getName());
     assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
@@ -233,38 +215,29 @@ public class DescriptorsTest extends TestCase {
     assertEquals("optional_cord", cordField.getName());
     assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
     assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
-    assertEquals(DescriptorProtos.FieldOptions.CType.CORD,
-                 cordField.getOptions().getCtype());
+    assertEquals(DescriptorProtos.FieldOptions.CType.CORD, cordField.getOptions().getCtype());
 
     assertEquals("optional_int32_extension", extension.getName());
-    assertEquals("protobuf_unittest.optional_int32_extension",
-                 extension.getFullName());
+    assertEquals("protobuf_unittest.optional_int32_extension", extension.getFullName());
     assertEquals(1, extension.getNumber());
-    assertEquals(TestAllExtensions.getDescriptor(),
-                 extension.getContainingType());
+    assertEquals(TestAllExtensions.getDescriptor(), extension.getContainingType());
     assertEquals(UnittestProto.getDescriptor(), extension.getFile());
     assertEquals(FieldDescriptor.Type.INT32, extension.getType());
     assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
-    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
-                 extension.getOptions());
+    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(), extension.getOptions());
     assertTrue(extension.isExtension());
     assertEquals(null, extension.getExtensionScope());
     assertEquals("optional_int32_extension", extension.toProto().getName());
 
     assertEquals("single", nestedExtension.getName());
-    assertEquals("protobuf_unittest.TestRequired.single",
-                 nestedExtension.getFullName());
-    assertEquals(TestRequired.getDescriptor(),
-                 nestedExtension.getExtensionScope());
+    assertEquals("protobuf_unittest.TestRequired.single", nestedExtension.getFullName());
+    assertEquals(TestRequired.getDescriptor(), nestedExtension.getExtensionScope());
   }
 
   public void testFieldDescriptorLabel() throws Exception {
-    FieldDescriptor requiredField =
-      TestRequired.getDescriptor().findFieldByName("a");
-    FieldDescriptor optionalField =
-      TestAllTypes.getDescriptor().findFieldByName("optional_int32");
-    FieldDescriptor repeatedField =
-      TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
+    FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a");
+    FieldDescriptor optionalField = TestAllTypes.getDescriptor().findFieldByName("optional_int32");
+    FieldDescriptor repeatedField = TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
 
     assertTrue(requiredField.isRequired());
     assertFalse(requiredField.isRepeated());
@@ -273,7 +246,7 @@ public class DescriptorsTest extends TestCase {
     assertFalse(repeatedField.isRequired());
     assertTrue(repeatedField.isRepeated());
   }
-  
+
   public void testFieldDescriptorJsonName() throws Exception {
     FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a");
     FieldDescriptor optionalField = TestAllTypes.getDescriptor().findFieldByName("optional_int32");
@@ -292,9 +265,8 @@ public class DescriptorsTest extends TestCase {
 
     d = TestExtremeDefaultValues.getDescriptor();
     assertEquals(
-      ByteString.copyFrom(
-        "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes(Internal.ISO_8859_1)),
-      d.findFieldByName("escaped_bytes").getDefaultValue());
+        ByteString.copyFrom("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes(Internal.ISO_8859_1)),
+        d.findFieldByName("escaped_bytes").getDefaultValue());
     assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue());
     assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue());
   }
@@ -307,12 +279,10 @@ public class DescriptorsTest extends TestCase {
     assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName());
     assertEquals(UnittestProto.getDescriptor(), enumType.getFile());
     assertNull(enumType.getContainingType());
-    assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(),
-                 enumType.getOptions());
+    assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(), enumType.getOptions());
 
     assertEquals("NestedEnum", nestedType.getName());
-    assertEquals("protobuf_unittest.TestAllTypes.NestedEnum",
-                 nestedType.getFullName());
+    assertEquals("protobuf_unittest.TestAllTypes.NestedEnum", nestedType.getFullName());
     assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
     assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType());
 
@@ -339,18 +309,14 @@ public class DescriptorsTest extends TestCase {
 
     MethodDescriptor fooMethod = service.getMethods().get(0);
     assertEquals("Foo", fooMethod.getName());
-    assertEquals(UnittestProto.FooRequest.getDescriptor(),
-                 fooMethod.getInputType());
-    assertEquals(UnittestProto.FooResponse.getDescriptor(),
-                 fooMethod.getOutputType());
+    assertEquals(UnittestProto.FooRequest.getDescriptor(), fooMethod.getInputType());
+    assertEquals(UnittestProto.FooResponse.getDescriptor(), fooMethod.getOutputType());
     assertEquals(fooMethod, service.findMethodByName("Foo"));
 
     MethodDescriptor barMethod = service.getMethods().get(1);
     assertEquals("Bar", barMethod.getName());
-    assertEquals(UnittestProto.BarRequest.getDescriptor(),
-                 barMethod.getInputType());
-    assertEquals(UnittestProto.BarResponse.getDescriptor(),
-                 barMethod.getOutputType());
+    assertEquals(UnittestProto.BarRequest.getDescriptor(), barMethod.getInputType());
+    assertEquals(UnittestProto.BarResponse.getDescriptor(), barMethod.getOutputType());
     assertEquals(barMethod, service.findMethodByName("Bar"));
 
     assertNull(service.findMethodByName("NoSuchMethod"));
@@ -367,58 +333,53 @@ public class DescriptorsTest extends TestCase {
     // dependencies are also properly initialized.
     Descriptor descriptor =
         TestCustomOptions.TestMessageWithCustomOptionsContainer.getDescriptor()
-        .findFieldByName("field").getMessageType();
+            .findFieldByName("field")
+            .getMessageType();
 
-    assertTrue(
-      descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
-    assertEquals(Integer.valueOf(-56),
-      descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
+    assertTrue(descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
+    assertEquals(
+        Integer.valueOf(-56),
+        descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
 
     FieldDescriptor field = descriptor.findFieldByName("field1");
     assertNotNull(field);
 
-    assertTrue(
-      field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
-    assertEquals(Long.valueOf(8765432109L),
-      field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
+    assertTrue(field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
+    assertEquals(
+        Long.valueOf(8765432109L),
+        field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
 
     OneofDescriptor oneof = descriptor.getOneofs().get(0);
     assertNotNull(oneof);
 
-    assertTrue(
-      oneof.getOptions().hasExtension(UnittestCustomOptions.oneofOpt1));
-    assertEquals(Integer.valueOf(-99),
-      oneof.getOptions().getExtension(UnittestCustomOptions.oneofOpt1));
+    assertTrue(oneof.getOptions().hasExtension(UnittestCustomOptions.oneofOpt1));
+    assertEquals(
+        Integer.valueOf(-99), oneof.getOptions().getExtension(UnittestCustomOptions.oneofOpt1));
 
     EnumDescriptor enumType =
-      UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
+        UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
 
-    assertTrue(
-      enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
-    assertEquals(Integer.valueOf(-789),
-      enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
+    assertTrue(enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
+    assertEquals(
+        Integer.valueOf(-789), enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
 
-    ServiceDescriptor service =
-      UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
+    ServiceDescriptor service = UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
 
-    assertTrue(
-      service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
-    assertEquals(Long.valueOf(-9876543210L),
-      service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
+    assertTrue(service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
+    assertEquals(
+        Long.valueOf(-9876543210L),
+        service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
 
     MethodDescriptor method = service.findMethodByName("Foo");
     assertNotNull(method);
 
-    assertTrue(
-      method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
-    assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
-      method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
+    assertTrue(method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
+    assertEquals(
+        UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
+        method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
   }
 
-  /**
-   * Test that the FieldDescriptor.Type enum is the same as the
-   * WireFormat.FieldType enum.
-   */
+  /** Test that the FieldDescriptor.Type enum is the same as the WireFormat.FieldType enum. */
   public void testFieldTypeTablesMatch() throws Exception {
     FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
     WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
@@ -430,10 +391,7 @@ public class DescriptorsTest extends TestCase {
     }
   }
 
-  /**
-   * Test that the FieldDescriptor.JavaType enum is the same as the
-   * WireFormat.JavaType enum.
-   */
+  /** Test that the FieldDescriptor.JavaType enum is the same as the WireFormat.JavaType enum. */
   public void testJavaTypeTablesMatch() throws Exception {
     FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
     WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
@@ -448,31 +406,29 @@ public class DescriptorsTest extends TestCase {
   public void testEnormousDescriptor() throws Exception {
     // The descriptor for this file is larger than 64k, yet it did not cause
     // a compiler error due to an over-long string literal.
-    assertTrue(
-        UnittestEnormousDescriptor.getDescriptor()
-          .toProto().getSerializedSize() > 65536);
+    assertTrue(UnittestEnormousDescriptor.getDescriptor().toProto().getSerializedSize() > 65536);
   }
 
-  /**
-   * Tests that the DescriptorValidationException works as intended.
-   */
+  /** Tests that the DescriptorValidationException works as intended. */
   public void testDescriptorValidatorException() throws Exception {
-    FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
-      .setName("foo.proto")
-      .addMessageType(DescriptorProto.newBuilder()
-      .setName("Foo")
-        .addField(FieldDescriptorProto.newBuilder()
-          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-          .setType(FieldDescriptorProto.Type.TYPE_INT32)
-          .setName("foo")
-          .setNumber(1)
-          .setDefaultValue("invalid")
-          .build())
-        .build())
-      .build();
+    FileDescriptorProto fileDescriptorProto =
+        FileDescriptorProto.newBuilder()
+            .setName("foo.proto")
+            .addMessageType(
+                DescriptorProto.newBuilder()
+                    .setName("Foo")
+                    .addField(
+                        FieldDescriptorProto.newBuilder()
+                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                            .setType(FieldDescriptorProto.Type.TYPE_INT32)
+                            .setName("foo")
+                            .setNumber(1)
+                            .setDefaultValue("invalid")
+                            .build())
+                    .build())
+            .build();
     try {
-      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
-          new FileDescriptor[0]);
+      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]);
       fail("DescriptorValidationException expected");
     } catch (DescriptorValidationException e) {
       // Expected; check that the error message contains some useful hints
@@ -485,35 +441,39 @@ public class DescriptorsTest extends TestCase {
   }
 
   /**
-   * Tests the translate/crosslink for an example where a message field's name
-   * and type name are the same.
+   * Tests the translate/crosslink for an example where a message field's name and type name are the
+   * same.
    */
   public void testDescriptorComplexCrosslink() throws Exception {
-    FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
-      .setName("foo.proto")
-      .addMessageType(DescriptorProto.newBuilder()
-        .setName("Foo")
-        .addField(FieldDescriptorProto.newBuilder()
-          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-          .setType(FieldDescriptorProto.Type.TYPE_INT32)
-          .setName("foo")
-          .setNumber(1)
-          .build())
-        .build())
-      .addMessageType(DescriptorProto.newBuilder()
-        .setName("Bar")
-        .addField(FieldDescriptorProto.newBuilder()
-          .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-          .setTypeName("Foo")
-          .setName("Foo")
-          .setNumber(1)
-          .build())
-        .build())
-      .build();
+    FileDescriptorProto fileDescriptorProto =
+        FileDescriptorProto.newBuilder()
+            .setName("foo.proto")
+            .addMessageType(
+                DescriptorProto.newBuilder()
+                    .setName("Foo")
+                    .addField(
+                        FieldDescriptorProto.newBuilder()
+                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                            .setType(FieldDescriptorProto.Type.TYPE_INT32)
+                            .setName("foo")
+                            .setNumber(1)
+                            .build())
+                    .build())
+            .addMessageType(
+                DescriptorProto.newBuilder()
+                    .setName("Bar")
+                    .addField(
+                        FieldDescriptorProto.newBuilder()
+                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                            .setTypeName("Foo")
+                            .setName("Foo")
+                            .setNumber(1)
+                            .build())
+                    .build())
+            .build();
     // translate and crosslink
     FileDescriptor file =
-      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
-          new FileDescriptor[0]);
+        Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]);
     // verify resulting descriptors
     assertNotNull(file);
     List<Descriptor> msglist = file.getMessageTypes();
@@ -535,62 +495,57 @@ public class DescriptorsTest extends TestCase {
   }
 
   public void testDependencyOrder() throws Exception {
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto").build();
-    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
-        .setName("bar.proto")
-        .addDependency("foo.proto")
-        .build();
-    FileDescriptorProto bazProto = FileDescriptorProto.newBuilder()
-        .setName("baz.proto")
-        .addDependency("foo.proto")
-        .addDependency("bar.proto")
-        .addPublicDependency(0)
-        .addPublicDependency(1)
-        .build();
-    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
-        new FileDescriptor[0]);
-    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto,
-        new FileDescriptor[] {fooFile});
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder().setName("foo.proto").build();
+    FileDescriptorProto barProto =
+        FileDescriptorProto.newBuilder().setName("bar.proto").addDependency("foo.proto").build();
+    FileDescriptorProto bazProto =
+        FileDescriptorProto.newBuilder()
+            .setName("baz.proto")
+            .addDependency("foo.proto")
+            .addDependency("bar.proto")
+            .addPublicDependency(0)
+            .addPublicDependency(1)
+            .build();
+    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
+    FileDescriptor barFile =
+        Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile});
 
     // Items in the FileDescriptor array can be in any order.
-    Descriptors.FileDescriptor.buildFrom(bazProto,
-        new FileDescriptor[] {fooFile, barFile});
-    Descriptors.FileDescriptor.buildFrom(bazProto,
-        new FileDescriptor[] {barFile, fooFile});
+    Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {fooFile, barFile});
+    Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {barFile, fooFile});
   }
 
   public void testInvalidPublicDependency() throws Exception {
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto").build();
-    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
-        .setName("boo.proto")
-        .addDependency("foo.proto")
-        .addPublicDependency(1)  // Error, should be 0.
-        .build();
-    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
-        new FileDescriptor[0]);
+    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder().setName("foo.proto").build();
+    FileDescriptorProto barProto =
+        FileDescriptorProto.newBuilder()
+            .setName("boo.proto")
+            .addDependency("foo.proto")
+            .addPublicDependency(1) // Error, should be 0.
+            .build();
+    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
     try {
-      Descriptors.FileDescriptor.buildFrom(barProto,
-          new FileDescriptor[] {fooFile});
+      Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile});
       fail("DescriptorValidationException expected");
     } catch (DescriptorValidationException e) {
-      assertTrue(
-          e.getMessage().indexOf("Invalid public dependency index.") != -1);
+      assertTrue(e.getMessage().indexOf("Invalid public dependency index.") != -1);
     }
   }
 
   public void testUnknownFieldsDenied() throws Exception {
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto")
-        .addMessageType(DescriptorProto.newBuilder()
-            .setName("Foo")
-            .addField(FieldDescriptorProto.newBuilder()
-                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-                .setTypeName("Bar")
-                .setName("bar")
-                .setNumber(1)))
-        .build();
+    FileDescriptorProto fooProto =
+        FileDescriptorProto.newBuilder()
+            .setName("foo.proto")
+            .addMessageType(
+                DescriptorProto.newBuilder()
+                    .setName("Foo")
+                    .addField(
+                        FieldDescriptorProto.newBuilder()
+                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                            .setTypeName("Bar")
+                            .setName("bar")
+                            .setNumber(1)))
+            .build();
 
     try {
       Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
@@ -602,48 +557,54 @@ public class DescriptorsTest extends TestCase {
   }
 
   public void testUnknownFieldsAllowed() throws Exception {
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto")
-        .addDependency("bar.proto")
-        .addMessageType(DescriptorProto.newBuilder()
-            .setName("Foo")
-            .addField(FieldDescriptorProto.newBuilder()
-                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-                .setTypeName("Bar")
-                .setName("bar")
-                .setNumber(1)))
-        .build();
+    FileDescriptorProto fooProto =
+        FileDescriptorProto.newBuilder()
+            .setName("foo.proto")
+            .addDependency("bar.proto")
+            .addMessageType(
+                DescriptorProto.newBuilder()
+                    .setName("Foo")
+                    .addField(
+                        FieldDescriptorProto.newBuilder()
+                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                            .setTypeName("Bar")
+                            .setName("bar")
+                            .setNumber(1)))
+            .build();
     Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true);
   }
 
   public void testHiddenDependency() throws Exception {
-    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
-        .setName("bar.proto")
-        .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
-        .build();
-    FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
-        .setName("forward.proto")
-        .addDependency("bar.proto")
-        .build();
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto")
-        .addDependency("forward.proto")
-        .addMessageType(DescriptorProto.newBuilder()
-            .setName("Foo")
-            .addField(FieldDescriptorProto.newBuilder()
-                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-                .setTypeName("Bar")
-                .setName("bar")
-                .setNumber(1)))
-        .build();
-    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
-        barProto, new FileDescriptor[0]);
-    FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
-        forwardProto, new FileDescriptor[] {barFile});
+    FileDescriptorProto barProto =
+        FileDescriptorProto.newBuilder()
+            .setName("bar.proto")
+            .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+            .build();
+    FileDescriptorProto forwardProto =
+        FileDescriptorProto.newBuilder()
+            .setName("forward.proto")
+            .addDependency("bar.proto")
+            .build();
+    FileDescriptorProto fooProto =
+        FileDescriptorProto.newBuilder()
+            .setName("foo.proto")
+            .addDependency("forward.proto")
+            .addMessageType(
+                DescriptorProto.newBuilder()
+                    .setName("Foo")
+                    .addField(
+                        FieldDescriptorProto.newBuilder()
+                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                            .setTypeName("Bar")
+                            .setName("bar")
+                            .setNumber(1)))
+            .build();
+    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[0]);
+    FileDescriptor forwardFile =
+        Descriptors.FileDescriptor.buildFrom(forwardProto, new FileDescriptor[] {barFile});
 
     try {
-      Descriptors.FileDescriptor.buildFrom(
-          fooProto, new FileDescriptor[] {forwardFile});
+      Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile});
       fail("DescriptorValidationException expected");
     } catch (DescriptorValidationException e) {
       assertTrue(e.getMessage().indexOf("Bar") != -1);
@@ -652,65 +613,67 @@ public class DescriptorsTest extends TestCase {
   }
 
   public void testPublicDependency() throws Exception {
-    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
-        .setName("bar.proto")
-        .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
-        .build();
-    FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
-        .setName("forward.proto")
-        .addDependency("bar.proto")
-        .addPublicDependency(0)
-        .build();
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto")
-        .addDependency("forward.proto")
-        .addMessageType(DescriptorProto.newBuilder()
-            .setName("Foo")
-            .addField(FieldDescriptorProto.newBuilder()
-                .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-                .setTypeName("Bar")
-                .setName("bar")
-                .setNumber(1)))
-        .build();
-    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
-        barProto, new FileDescriptor[0]);
-    FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
-        forwardProto, new FileDescriptor[]{barFile});
-    Descriptors.FileDescriptor.buildFrom(
-        fooProto, new FileDescriptor[] {forwardFile});
+    FileDescriptorProto barProto =
+        FileDescriptorProto.newBuilder()
+            .setName("bar.proto")
+            .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+            .build();
+    FileDescriptorProto forwardProto =
+        FileDescriptorProto.newBuilder()
+            .setName("forward.proto")
+            .addDependency("bar.proto")
+            .addPublicDependency(0)
+            .build();
+    FileDescriptorProto fooProto =
+        FileDescriptorProto.newBuilder()
+            .setName("foo.proto")
+            .addDependency("forward.proto")
+            .addMessageType(
+                DescriptorProto.newBuilder()
+                    .setName("Foo")
+                    .addField(
+                        FieldDescriptorProto.newBuilder()
+                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+                            .setTypeName("Bar")
+                            .setName("bar")
+                            .setNumber(1)))
+            .build();
+    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[0]);
+    FileDescriptor forwardFile =
+        Descriptors.FileDescriptor.buildFrom(forwardProto, new FileDescriptor[] {barFile});
+    Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile});
   }
 
-  /**
-   * Tests the translate/crosslink for an example with a more complex namespace
-   * referencing.
-   */
+  /** Tests the translate/crosslink for an example with a more complex namespace referencing. */
   public void testComplexNamespacePublicDependency() throws Exception {
-    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
-        .setName("bar.proto")
-        .setPackage("a.b.c.d.bar.shared")
-        .addEnumType(EnumDescriptorProto.newBuilder()
-            .setName("MyEnum")
-            .addValue(EnumValueDescriptorProto.newBuilder()
-                .setName("BLAH")
-                .setNumber(1)))
-        .build();
-    FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto")
-        .addDependency("bar.proto")
-        .setPackage("a.b.c.d.foo.shared")
-        .addMessageType(DescriptorProto.newBuilder()
-            .setName("MyMessage")
-            .addField(FieldDescriptorProto.newBuilder()
-                .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
-                .setTypeName("bar.shared.MyEnum")
-                .setName("MyField")
-                .setNumber(1)))
-        .build();
+    FileDescriptorProto fooProto =
+        FileDescriptorProto.newBuilder()
+            .setName("bar.proto")
+            .setPackage("a.b.c.d.bar.shared")
+            .addEnumType(
+                EnumDescriptorProto.newBuilder()
+                    .setName("MyEnum")
+                    .addValue(EnumValueDescriptorProto.newBuilder().setName("BLAH").setNumber(1)))
+            .build();
+    FileDescriptorProto barProto =
+        FileDescriptorProto.newBuilder()
+            .setName("foo.proto")
+            .addDependency("bar.proto")
+            .setPackage("a.b.c.d.foo.shared")
+            .addMessageType(
+                DescriptorProto.newBuilder()
+                    .setName("MyMessage")
+                    .addField(
+                        FieldDescriptorProto.newBuilder()
+                            .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+                            .setTypeName("bar.shared.MyEnum")
+                            .setName("MyField")
+                            .setNumber(1)))
+            .build();
     // translate and crosslink
-    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(
-        fooProto, new FileDescriptor[0]);
-    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
-        barProto, new FileDescriptor[]{fooFile});
+    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
+    FileDescriptor barFile =
+        Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile});
     // verify resulting descriptors
     assertNotNull(barFile);
     List<Descriptor> msglist = barFile.getMessageTypes();
@@ -726,15 +689,13 @@ public class DescriptorsTest extends TestCase {
       assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
       assertTrue(field.getEnumType().getName().equals("MyEnum"));
       assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
-      assertTrue(field.getEnumType().getFile().getPackage().equals(
-          "a.b.c.d.bar.shared"));
+      assertTrue(field.getEnumType().getFile().getPackage().equals("a.b.c.d.bar.shared"));
     }
   }
 
   public void testOneofDescriptor() throws Exception {
     Descriptor messageType = TestAllTypes.getDescriptor();
-    FieldDescriptor field =
-        messageType.findFieldByName("oneof_nested_message");
+    FieldDescriptor field = messageType.findFieldByName("oneof_nested_message");
     OneofDescriptor oneofDescriptor = field.getContainingOneof();
     assertNotNull(oneofDescriptor);
     assertSame(oneofDescriptor, messageType.getOneofs().get(0));
@@ -774,36 +735,38 @@ public class DescriptorsTest extends TestCase {
   }
 
   public void testToString() {
-    assertEquals("protobuf_unittest.TestAllTypes.optional_uint64",
-        UnittestProto.TestAllTypes.getDescriptor().findFieldByNumber(
-            UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER).toString());
+    assertEquals(
+        "protobuf_unittest.TestAllTypes.optional_uint64",
+        UnittestProto.TestAllTypes.getDescriptor()
+            .findFieldByNumber(UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER)
+            .toString());
   }
 
   public void testPackedEnumField() throws Exception {
-    FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
-        .setName("foo.proto")
-        .addEnumType(EnumDescriptorProto.newBuilder()
-          .setName("Enum")
-          .addValue(EnumValueDescriptorProto.newBuilder()
-            .setName("FOO")
-            .setNumber(1)
-            .build())
-          .build())
-        .addMessageType(DescriptorProto.newBuilder()
-          .setName("Message")
-          .addField(FieldDescriptorProto.newBuilder()
-            .setName("foo")
-            .setTypeName("Enum")
-            .setNumber(1)
-            .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
-            .setOptions(DescriptorProtos.FieldOptions.newBuilder()
-              .setPacked(true)
-              .build())
-            .build())
-          .build())
-        .build();
-    Descriptors.FileDescriptor.buildFrom(
-        fileDescriptorProto, new FileDescriptor[0]);
+    FileDescriptorProto fileDescriptorProto =
+        FileDescriptorProto.newBuilder()
+            .setName("foo.proto")
+            .addEnumType(
+                EnumDescriptorProto.newBuilder()
+                    .setName("Enum")
+                    .addValue(
+                        EnumValueDescriptorProto.newBuilder().setName("FOO").setNumber(1).build())
+                    .build())
+            .addMessageType(
+                DescriptorProto.newBuilder()
+                    .setName("Message")
+                    .addField(
+                        FieldDescriptorProto.newBuilder()
+                            .setName("foo")
+                            .setTypeName("Enum")
+                            .setNumber(1)
+                            .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+                            .setOptions(
+                                DescriptorProtos.FieldOptions.newBuilder().setPacked(true).build())
+                            .build())
+                    .build())
+            .build();
+    Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]);
   }
 
   public void testFieldJsonName() throws Exception {

+ 19 - 1
java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java

@@ -266,6 +266,15 @@ public class DoubleArrayListTest extends TestCase {
     assertFalse(list.addAll(DoubleArrayList.emptyList()));
   }
 
+  public void testEquals() {
+    DoubleArrayList list1 = new DoubleArrayList();
+    DoubleArrayList list2 = new DoubleArrayList();
+
+    list1.addDouble(Double.longBitsToDouble(0x7ff0000000000001L));
+    list2.addDouble(Double.longBitsToDouble(0x7ff0000000000002L));
+    assertEquals(list1, list2);
+  }
+
   public void testRemove() {
     list.addAll(TERTIARY_LIST);
     assertEquals(1D, (double) list.remove(0), 0.0);
@@ -294,13 +303,22 @@ public class DoubleArrayListTest extends TestCase {
     }
   }
 
-  public void testRemoveEndOfCapacity() {
+  public void testRemoveEnd_listAtCapacity() {
     DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addDouble(3);
     toRemove.remove(0);
     assertEquals(0, toRemove.size());
   }
 
+  public void testRemove_listAtCapacity() {
+    DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(2);
+    toRemove.addDouble(3);
+    toRemove.addDouble(4);
+    toRemove.remove(0);
+    assertEquals(1, toRemove.size());
+    assertEquals(4D, (double) toRemove.get(0));
+  }
+
   public void testSublistRemoveEndOfCapacity() {
     DoubleList toRemove = DoubleArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addDouble(3);

+ 1 - 1
java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java

@@ -238,7 +238,7 @@ public class ExtensionRegistryFactoryTest extends TestCase {
     classLoader.loadClass(ExtensionRegistryFactory.class.getName());
     Class<?> test = classLoader.loadClass(testClass.getName());
     String testName = getName();
-    test.getMethod(testName).invoke(test.newInstance());
+    test.getMethod(testName).invoke(test.getDeclaredConstructor().newInstance());
   }
 
   /**

+ 19 - 1
java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java

@@ -266,6 +266,15 @@ public class FloatArrayListTest extends TestCase {
     assertFalse(list.addAll(FloatArrayList.emptyList()));
   }
 
+  public void testEquals() {
+    FloatArrayList list1 = new FloatArrayList();
+    FloatArrayList list2 = new FloatArrayList();
+
+    list1.addFloat(Float.intBitsToFloat(0xff800001));
+    list2.addFloat(Float.intBitsToFloat(0xff800002));
+    assertEquals(list1, list2);
+  }
+
   public void testRemove() {
     list.addAll(TERTIARY_LIST);
     assertEquals(1F, (float) list.remove(0), 0.0f);
@@ -294,13 +303,22 @@ public class FloatArrayListTest extends TestCase {
     }
   }
 
-  public void testRemoveEndOfCapacity() {
+  public void testRemoveEnd_listAtCapacity() {
     FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addFloat(3);
     toRemove.remove(0);
     assertEquals(0, toRemove.size());
   }
 
+  public void testRemove_listAtCapacity() {
+    FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(2);
+    toRemove.addFloat(3);
+    toRemove.addFloat(4);
+    toRemove.remove(0);
+    assertEquals(1, toRemove.size());
+    assertEquals(4F, (float) toRemove.get(0));
+  }
+
   public void testSublistRemoveEndOfCapacity() {
     FloatList toRemove = FloatArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addFloat(3);

+ 17 - 1
java/core/src/test/java/com/google/protobuf/IntArrayListTest.java

@@ -266,6 +266,13 @@ public class IntArrayListTest extends TestCase {
     assertFalse(list.addAll(IntArrayList.emptyList()));
   }
 
+  public void testEquals() {
+    IntArrayList list1 = new IntArrayList();
+    IntArrayList list2 = new IntArrayList();
+
+    assertEquals(list1, list2);
+  }
+
   public void testRemove() {
     list.addAll(TERTIARY_LIST);
     assertEquals(1, (int) list.remove(0));
@@ -294,13 +301,22 @@ public class IntArrayListTest extends TestCase {
     }
   }
 
-  public void testRemoveEndOfCapacity() {
+  public void testRemoveEnd_listAtCapacity() {
     IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addInt(3);
     toRemove.remove(0);
     assertEquals(0, toRemove.size());
   }
 
+  public void testRemove_listAtCapacity() {
+    IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(2);
+    toRemove.addInt(3);
+    toRemove.addInt(4);
+    toRemove.remove(0);
+    assertEquals(1, toRemove.size());
+    assertEquals(4, (int) toRemove.get(0));
+  }
+
   public void testSublistRemoveEndOfCapacity() {
     IntList toRemove = IntArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addInt(3);

+ 1 - 1
java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java

@@ -168,7 +168,7 @@ public class IsValidUtf8Test extends TestCase {
     // A sanity check.
     int actual = 0;
     for (Shard shard : IsValidUtf8TestUtil.FOUR_BYTE_SHARDS) {
-      actual += shard.expected;
+      actual = (int) (actual + shard.expected);
     }
     assertEquals(IsValidUtf8TestUtil.EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, actual);
   }

+ 3 - 3
java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java

@@ -218,9 +218,9 @@ final class IsValidUtf8TestUtil {
   private static List<Shard> generateFourByteShards(int numShards, long[] expected) {
     assertEquals(numShards, expected.length);
     List<Shard> shards = new ArrayList<Shard>(numShards);
-    long LIM = 1L << 32;
-    long increment = LIM / numShards;
-    assertTrue(LIM % numShards == 0);
+    long lim = 1L << 32;
+    long increment = lim / numShards;
+    assertTrue(lim % numShards == 0);
     for (int i = 0; i < numShards; i++) {
       shards.add(new Shard(i, increment * i, increment * (i + 1), expected[i]));
     }

+ 11 - 12
java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java

@@ -117,8 +117,8 @@ public class LazyFieldLiteTest extends TestCase {
     LazyFieldLite original = createLazyFieldLiteFromMessage(message);
     LazyFieldLite merged = new LazyFieldLite();
     merged.merge(original);
-    TestAllExtensions value = (TestAllExtensions) merged.getValue(
-        TestAllExtensions.getDefaultInstance());
+    TestAllExtensions value =
+        (TestAllExtensions) merged.getValue(TestAllExtensions.getDefaultInstance());
     assertEquals(message, value);
   }
 
@@ -130,8 +130,8 @@ public class LazyFieldLiteTest extends TestCase {
 
   public void testInvalidProto() throws Exception {
     // Silently fails and uses the default instance.
-    LazyFieldLite field = new LazyFieldLite(
-        TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+    LazyFieldLite field =
+        new LazyFieldLite(TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
     assertEquals(
         TestAllTypes.getDefaultInstance(), field.getValue(TestAllTypes.getDefaultInstance()));
     assertEquals(0, field.getSerializedSize());
@@ -158,7 +158,7 @@ public class LazyFieldLiteTest extends TestCase {
         TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
 
     LazyFieldLite field1 = LazyFieldLite.fromValue(message1);
-    field1.getValue(TestAllTypes.getDefaultInstance());  // Force parsing.
+    field1.getValue(TestAllTypes.getDefaultInstance()); // Force parsing.
     LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
     field1.merge(field2);
     assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
@@ -166,7 +166,7 @@ public class LazyFieldLiteTest extends TestCase {
     // Now reverse which one is parsed first.
     field1 = LazyFieldLite.fromValue(message1);
     field2 = createLazyFieldLiteFromMessage(message2);
-    field2.getValue(TestAllTypes.getDefaultInstance());  // Force parsing.
+    field2.getValue(TestAllTypes.getDefaultInstance()); // Force parsing.
     field1.merge(field2);
     assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
   }
@@ -175,8 +175,8 @@ public class LazyFieldLiteTest extends TestCase {
     // Test a few different paths that involve one message that was not parsed.
     TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(1).build();
     LazyFieldLite valid = LazyFieldLite.fromValue(message);
-    LazyFieldLite invalid = new LazyFieldLite(
-        TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+    LazyFieldLite invalid =
+        new LazyFieldLite(TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
     invalid.merge(valid);
 
     // We swallow the exception and just use the set field.
@@ -206,13 +206,13 @@ public class LazyFieldLiteTest extends TestCase {
     // Now try parsing the empty field first.
     field = LazyFieldLite.fromValue(messageWithExtensions);
     LazyFieldLite other = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
-    other.getValue(TestAllExtensions.getDefaultInstance());  // Force parsing.
+    other.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing.
     field.merge(other);
     assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
 
     // And again reverse.
     field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
-    field.getValue(TestAllExtensions.getDefaultInstance());  // Force parsing.
+    field.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing.
     other = LazyFieldLite.fromValue(messageWithExtensions);
     field.merge(other);
     assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
@@ -239,8 +239,7 @@ public class LazyFieldLiteTest extends TestCase {
   }
 
   private void assertNotEqual(Object unexpected, Object actual) {
-    assertFalse(unexpected == actual
-        || (unexpected != null && unexpected.equals(actual)));
+    assertFalse(unexpected == actual || (unexpected != null && unexpected.equals(actual)));
   }
 
 }

+ 39 - 39
java/core/src/test/java/com/google/protobuf/LiteTest.java

@@ -81,7 +81,7 @@ public class LiteTest extends TestCase {
     //
     // We put this in setUp() rather than in its own test method because we
     // need to make sure it runs before any actual tests.
-    assertTrue(TestNestedExtensionLite.nestedExtension != null);
+    assertNotNull(TestNestedExtensionLite.nestedExtension);
   }
 
   public void testLite() throws Exception {
@@ -320,16 +320,16 @@ public class LiteTest extends TestCase {
     assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage());
 
     message = builder.build();
-    ForeignMessageLite.Builder foreignMessageBuilder = ForeignMessageLite.newBuilder().setC(3);
-    builder.setOptionalForeignMessage(foreignMessageBuilder);
+    ForeignMessageLite foreignMessageC3 = ForeignMessageLite.newBuilder().setC(3).build();
+    builder.setOptionalForeignMessage(foreignMessageC3);
     assertEquals(ForeignMessageLite.getDefaultInstance(), message.getOptionalForeignMessage());
-    assertEquals(foreignMessageBuilder.build(), builder.getOptionalForeignMessage());
+    assertEquals(foreignMessageC3, builder.getOptionalForeignMessage());
     messageAfterBuild = builder.build();
-    assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage());
+    assertEquals(foreignMessageC3, messageAfterBuild.getOptionalForeignMessage());
     assertEquals(ForeignMessageLite.getDefaultInstance(), message.getOptionalForeignMessage());
     builder.clearOptionalForeignMessage();
     assertEquals(ForeignMessageLite.getDefaultInstance(), builder.getOptionalForeignMessage());
-    assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage());
+    assertEquals(foreignMessageC3, messageAfterBuild.getOptionalForeignMessage());
 
     message = builder.build();
     OptionalGroup optionalGroup = OptionalGroup.newBuilder().setA(1).build();
@@ -1033,11 +1033,11 @@ public class LiteTest extends TestCase {
     builder.clearRepeatedForeignMessage();
 
     message = builder.build();
-    builder.addRepeatedForeignMessage(foreignMessageBuilder);
+    builder.addRepeatedForeignMessage(foreignMessageC3);
     messageAfterBuild = builder.build();
     assertEquals(0, message.getRepeatedForeignMessageCount());
     builder.setRepeatedForeignMessage(0, ForeignMessageLite.getDefaultInstance());
-    assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getRepeatedForeignMessage(0));
+    assertEquals(foreignMessageC3, messageAfterBuild.getRepeatedForeignMessage(0));
     assertEquals(ForeignMessageLite.getDefaultInstance(), builder.getRepeatedForeignMessage(0));
     builder.clearRepeatedForeignMessage();
 
@@ -1045,9 +1045,9 @@ public class LiteTest extends TestCase {
     builder.addRepeatedForeignMessage(0, foreignMessage);
     messageAfterBuild = builder.build();
     assertEquals(0, message.getRepeatedForeignMessageCount());
-    builder.setRepeatedForeignMessage(0, foreignMessageBuilder);
+    builder.setRepeatedForeignMessage(0, foreignMessageC3);
     assertEquals(foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
-    assertEquals(foreignMessageBuilder.build(), builder.getRepeatedForeignMessage(0));
+    assertEquals(foreignMessageC3, builder.getRepeatedForeignMessage(0));
     builder.clearRepeatedForeignMessage();
 
     message = builder.build();
@@ -1533,7 +1533,7 @@ public class LiteTest extends TestCase {
   private static void assertToStringEquals(String expected, MessageLite message) {
     String toString = message.toString();
     assertEquals('#', toString.charAt(0));
-    if (toString.indexOf("\n") >= 0) {
+    if (toString.contains("\n")) {
       toString = toString.substring(toString.indexOf("\n") + 1);
     } else {
       toString = "";
@@ -2210,29 +2210,29 @@ public class LiteTest extends TestCase {
 
   public void testAddAllIteratesOnce() {
     TestAllTypesLite.newBuilder()
-        .addAllRepeatedBool(new OneTimeIterableList(false))
-        .addAllRepeatedInt32(new OneTimeIterableList(0))
-        .addAllRepeatedInt64(new OneTimeIterableList(0L))
-        .addAllRepeatedFloat(new OneTimeIterableList(0f))
-        .addAllRepeatedDouble(new OneTimeIterableList(0d))
-        .addAllRepeatedBytes(new OneTimeIterableList(ByteString.EMPTY))
-        .addAllRepeatedString(new OneTimeIterableList(""))
-        .addAllRepeatedNestedMessage(new OneTimeIterableList(NestedMessage.getDefaultInstance()))
-        .addAllRepeatedBool(new OneTimeIterable(false))
-        .addAllRepeatedInt32(new OneTimeIterable(0))
-        .addAllRepeatedInt64(new OneTimeIterable(0L))
-        .addAllRepeatedFloat(new OneTimeIterable(0f))
-        .addAllRepeatedDouble(new OneTimeIterable(0d))
-        .addAllRepeatedBytes(new OneTimeIterable(ByteString.EMPTY))
-        .addAllRepeatedString(new OneTimeIterable(""))
-        .addAllRepeatedNestedMessage(new OneTimeIterable(NestedMessage.getDefaultInstance()))
+        .addAllRepeatedBool(new OneTimeIterableList<>(false))
+        .addAllRepeatedInt32(new OneTimeIterableList<>(0))
+        .addAllRepeatedInt64(new OneTimeIterableList<>(0L))
+        .addAllRepeatedFloat(new OneTimeIterableList<>(0f))
+        .addAllRepeatedDouble(new OneTimeIterableList<>(0d))
+        .addAllRepeatedBytes(new OneTimeIterableList<>(ByteString.EMPTY))
+        .addAllRepeatedString(new OneTimeIterableList<>(""))
+        .addAllRepeatedNestedMessage(new OneTimeIterableList<>(NestedMessage.getDefaultInstance()))
+        .addAllRepeatedBool(new OneTimeIterable<>(false))
+        .addAllRepeatedInt32(new OneTimeIterable<>(0))
+        .addAllRepeatedInt64(new OneTimeIterable<>(0L))
+        .addAllRepeatedFloat(new OneTimeIterable<>(0f))
+        .addAllRepeatedDouble(new OneTimeIterable<>(0d))
+        .addAllRepeatedBytes(new OneTimeIterable<>(ByteString.EMPTY))
+        .addAllRepeatedString(new OneTimeIterable<>(""))
+        .addAllRepeatedNestedMessage(new OneTimeIterable<>(NestedMessage.getDefaultInstance()))
         .build();
   }
 
   public void testAddAllIteratesOnce_throwsOnNull() {
     TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
     try {
-      builder.addAllRepeatedBool(new OneTimeIterableList(true, false, (Boolean) null));
+      builder.addAllRepeatedBool(new OneTimeIterableList<>(true, false, null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 2 is null.", expected.getMessage());
@@ -2240,7 +2240,7 @@ public class LiteTest extends TestCase {
     }
 
     try {
-      builder.addAllRepeatedBool(new OneTimeIterable(true, false, (Boolean) null));
+      builder.addAllRepeatedBool(new OneTimeIterable<>(true, false, null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 2 is null.", expected.getMessage());
@@ -2249,7 +2249,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedBool(new OneTimeIterableList((Boolean) null));
+      builder.addAllRepeatedBool(new OneTimeIterableList<>((Boolean) null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 0 is null.", expected.getMessage());
@@ -2258,7 +2258,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedInt32(new OneTimeIterableList((Integer) null));
+      builder.addAllRepeatedInt32(new OneTimeIterableList<>((Integer) null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 0 is null.", expected.getMessage());
@@ -2267,7 +2267,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedInt64(new OneTimeIterableList((Long) null));
+      builder.addAllRepeatedInt64(new OneTimeIterableList<>((Long) null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 0 is null.", expected.getMessage());
@@ -2276,7 +2276,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedFloat(new OneTimeIterableList((Float) null));
+      builder.addAllRepeatedFloat(new OneTimeIterableList<>((Float) null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 0 is null.", expected.getMessage());
@@ -2285,7 +2285,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedDouble(new OneTimeIterableList((Double) null));
+      builder.addAllRepeatedDouble(new OneTimeIterableList<>((Double) null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 0 is null.", expected.getMessage());
@@ -2294,7 +2294,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedBytes(new OneTimeIterableList((ByteString) null));
+      builder.addAllRepeatedBytes(new OneTimeIterableList<>((ByteString) null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 0 is null.", expected.getMessage());
@@ -2303,7 +2303,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedString(new OneTimeIterableList("", "", (String) null, ""));
+      builder.addAllRepeatedString(new OneTimeIterableList<>("", "", null, ""));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 2 is null.", expected.getMessage());
@@ -2312,7 +2312,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedString(new OneTimeIterable("", "", (String) null, ""));
+      builder.addAllRepeatedString(new OneTimeIterable<>("", "", null, ""));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 2 is null.", expected.getMessage());
@@ -2321,7 +2321,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedString(new OneTimeIterableList((String) null));
+      builder.addAllRepeatedString(new OneTimeIterableList<>((String) null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 0 is null.", expected.getMessage());
@@ -2330,7 +2330,7 @@ public class LiteTest extends TestCase {
 
     try {
       builder = TestAllTypesLite.newBuilder();
-      builder.addAllRepeatedNestedMessage(new OneTimeIterableList((NestedMessage) null));
+      builder.addAllRepeatedNestedMessage(new OneTimeIterableList<>((NestedMessage) null));
       fail();
     } catch (NullPointerException expected) {
       assertEquals("Element at index 0 is null.", expected.getMessage());

+ 4 - 4
java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java

@@ -369,13 +369,13 @@ public class LiteralByteStringTest extends TestCase {
           }
 
           @Override
-          public void writeLazy(byte[] value, int offset, int length) throws IOException {
-            Arrays.fill(value, offset, offset + length, (byte) 0);
+          public void write(ByteBuffer value) throws IOException {
+            throw new UnsupportedOperationException();
           }
 
           @Override
-          public void write(ByteBuffer value) throws IOException {
-            throw new UnsupportedOperationException();
+          public void writeLazy(byte[] value, int offset, int length) throws IOException {
+            Arrays.fill(value, offset, offset + length, (byte) 0);
           }
 
           @Override

+ 17 - 1
java/core/src/test/java/com/google/protobuf/LongArrayListTest.java

@@ -266,6 +266,13 @@ public class LongArrayListTest extends TestCase {
     assertFalse(list.addAll(LongArrayList.emptyList()));
   }
 
+  public void testEquals() {
+    LongArrayList list1 = new LongArrayList();
+    LongArrayList list2 = new LongArrayList();
+
+    assertEquals(list1, list2);
+  }
+
   public void testRemove() {
     list.addAll(TERTIARY_LIST);
     assertEquals(1L, (long) list.remove(0));
@@ -294,13 +301,22 @@ public class LongArrayListTest extends TestCase {
     }
   }
 
-  public void testRemoveEndOfCapacity() {
+  public void testRemoveEnd_listAtCapacity() {
     LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addLong(3);
     toRemove.remove(0);
     assertEquals(0, toRemove.size());
   }
 
+  public void testRemove_listAtCapacity() {
+    LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(2);
+    toRemove.addLong(3);
+    toRemove.addLong(4);
+    toRemove.remove(0);
+    assertEquals(1, toRemove.size());
+    assertEquals(4L, (long) toRemove.get(0));
+  }
+
   public void testSublistRemoveEndOfCapacity() {
     LongList toRemove = LongArrayList.emptyList().mutableCopyWithCapacity(1);
     toRemove.addLong(3);

+ 9 - 6
java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java

@@ -440,12 +440,12 @@ public final class MapForProto2LiteTest extends TestCase {
 
     // We can't control the order of elements in a HashMap. The best we can do
     // here is to add elements in different order.
-    TestMap.Builder b1 =
+    TestMap m1 =
         TestMap.newBuilder()
             .putInt32ToInt32Field(1, 2)
             .putInt32ToInt32Field(3, 4)
-            .putInt32ToInt32Field(5, 6);
-    TestMap m1 = b1.build();
+            .putInt32ToInt32Field(5, 6)
+            .build();
 
     TestMap.Builder b2 =
         TestMap.newBuilder()
@@ -466,9 +466,12 @@ public final class MapForProto2LiteTest extends TestCase {
   }
 
   public void testUnknownEnumValues() throws Exception {
-    TestUnknownEnumValue.Builder builder =
-        TestUnknownEnumValue.newBuilder().putInt32ToInt32Field(1, 1).putInt32ToInt32Field(2, 54321);
-    ByteString data = builder.build().toByteString();
+    ByteString data =
+        TestUnknownEnumValue.newBuilder()
+            .putInt32ToInt32Field(1, 1)
+            .putInt32ToInt32Field(2, 54321)
+            .build()
+            .toByteString();
 
     TestMap message = TestMap.parseFrom(data);
     // Entries with unknown enum values will be stored into UnknownFieldSet so

+ 85 - 102
java/core/src/test/java/com/google/protobuf/MapForProto2Test.java

@@ -49,9 +49,7 @@ import java.util.List;
 import java.util.Map;
 import junit.framework.TestCase;
 
-/**
- * Unit tests for map fields in proto2 protos.
- */
+/** Unit tests for map fields in proto2 protos. */
 public class MapForProto2Test extends TestCase {
 
   private void setMapValuesUsingMutableMap(TestMap.Builder builder) {
@@ -88,23 +86,18 @@ public class MapForProto2Test extends TestCase {
         .putInt32ToInt32Field(1, 11)
         .putInt32ToInt32Field(2, 22)
         .putInt32ToInt32Field(3, 33)
-
         .putInt32ToStringField(1, "11")
         .putInt32ToStringField(2, "22")
         .putInt32ToStringField(3, "33")
-
         .putInt32ToBytesField(1, TestUtil.toBytes("11"))
         .putInt32ToBytesField(2, TestUtil.toBytes("22"))
         .putInt32ToBytesField(3, TestUtil.toBytes("33"))
-
         .putInt32ToEnumField(1, TestMap.EnumValue.FOO)
         .putInt32ToEnumField(2, TestMap.EnumValue.BAR)
         .putInt32ToEnumField(3, TestMap.EnumValue.BAZ)
-
         .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build())
         .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build())
         .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build())
-
         .putStringToInt32Field("1", 11)
         .putStringToInt32Field("2", 22)
         .putStringToInt32Field("3", 33);
@@ -199,23 +192,18 @@ public class MapForProto2Test extends TestCase {
         .putInt32ToInt32Field(1, 111)
         .removeInt32ToInt32Field(2)
         .putInt32ToInt32Field(4, 44)
-
         .putInt32ToStringField(1, "111")
         .removeInt32ToStringField(2)
         .putInt32ToStringField(4, "44")
-
         .putInt32ToBytesField(1, TestUtil.toBytes("111"))
         .removeInt32ToBytesField(2)
         .putInt32ToBytesField(4, TestUtil.toBytes("44"))
-
         .putInt32ToEnumField(1, TestMap.EnumValue.BAR)
         .removeInt32ToEnumField(2)
         .putInt32ToEnumField(4, TestMap.EnumValue.QUX)
-
         .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build())
         .removeInt32ToMessageField(2)
         .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build())
-
         .putStringToInt32Field("1", 111)
         .removeStringToInt32Field("2")
         .putStringToInt32Field("4", 44);
@@ -337,7 +325,7 @@ public class MapForProto2Test extends TestCase {
     assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
     builder.getMutableInt32ToInt32Field().put(2, 3);
     assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
- //
+  //
     Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
     enumMap.put(1, TestMap.EnumValue.BAR);
     assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
@@ -432,7 +420,19 @@ public class MapForProto2Test extends TestCase {
     assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
     assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
   }
-
+  //
+  private static <K, V> Map<K, V> newMap(K key1, V value1) {
+    Map<K, V> map = new HashMap<K, V>();
+    map.put(key1, value1);
+    return map;
+  }
+  //
+  private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+    Map<K, V> map = new HashMap<K, V>();
+    map.put(key1, value1);
+    map.put(key2, value2);
+    return map;
+  }
 
   public void testGettersAndSetters() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
@@ -543,30 +543,22 @@ public class MapForProto2Test extends TestCase {
     ByteString bytes = TestUtil.toBytes("SOME BYTES");
     String stringKey = "a string key";
 
-    TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
-        .putInt32ToInt32Field(5, bytes)
-        .build());
+    TestMap map =
+        tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToInt32Field(5, bytes).build());
     assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
 
-    map = tryParseTestMap(BizarroTestMap.newBuilder()
-        .putInt32ToStringField(stringKey, 5)
-        .build());
+    map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToStringField(stringKey, 5).build());
     assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
 
-    map = tryParseTestMap(BizarroTestMap.newBuilder()
-        .putInt32ToBytesField(stringKey, 5)
-        .build());
+    map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToBytesField(stringKey, 5).build());
     assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY);
 
-    map = tryParseTestMap(BizarroTestMap.newBuilder()
-        .putInt32ToEnumField(stringKey, bytes)
-        .build());
+    map =
+        tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToEnumField(stringKey, bytes).build());
     assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
 
     try {
-      tryParseTestMap(BizarroTestMap.newBuilder()
-          .putInt32ToMessageField(stringKey, bytes)
-          .build());
+      tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToMessageField(stringKey, bytes).build());
       fail();
     } catch (InvalidProtocolBufferException expected) {
       assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
@@ -574,9 +566,9 @@ public class MapForProto2Test extends TestCase {
       assertTrue(map.getInt32ToMessageField().isEmpty());
     }
 
-    map = tryParseTestMap(BizarroTestMap.newBuilder()
-        .putStringToInt32Field(stringKey, bytes)
-        .build());
+    map =
+        tryParseTestMap(
+            BizarroTestMap.newBuilder().putStringToInt32Field(stringKey, bytes).build());
     assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
   }
 
@@ -657,8 +649,7 @@ public class MapForProto2Test extends TestCase {
     }
   }
 
-  private static <KeyType, ValueType>
-  Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
+  private static <K, V> Message newMapEntry(Message.Builder builder, String name, K key, V value) {
     FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
     Message.Builder entryBuilder = builder.newBuilderForField(field);
     FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
@@ -677,9 +668,8 @@ public class MapForProto2Test extends TestCase {
     builder.setField(field, entryList);
   }
 
-  private static <KeyType, ValueType> Map<KeyType, ValueType> mapForValues(
-      KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
-    Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
+  private static <K, V> Map<K, V> mapForValues(K key1, V value1, K key2, V value2) {
+    Map<K, V> map = new HashMap<K, V>();
     map.put(key1, value1);
     map.put(key2, value2);
     return map;
@@ -687,17 +677,19 @@ public class MapForProto2Test extends TestCase {
 
   public void testReflectionApi() throws Exception {
     // In reflection API, map fields are just repeated message fields.
-    TestMap.Builder builder = TestMap.newBuilder()
-        .putInt32ToInt32Field(1, 2)
-        .putInt32ToInt32Field(3, 4)
-        .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build())
-        .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build());
+    TestMap.Builder builder =
+        TestMap.newBuilder()
+            .putInt32ToInt32Field(1, 2)
+            .putInt32ToInt32Field(3, 4)
+            .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build())
+            .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build());
     TestMap message = builder.build();
 
     // Test getField(), getRepeatedFieldCount(), getRepeatedField().
-    assertHasMapValues(message, "int32_to_int32_field",
-        mapForValues(1, 2, 3, 4));
-    assertHasMapValues(message, "int32_to_message_field",
+    assertHasMapValues(message, "int32_to_int32_field", mapForValues(1, 2, 3, 4));
+    assertHasMapValues(
+        message,
+        "int32_to_message_field",
         mapForValues(
             11, MessageValue.newBuilder().setValue(22).build(),
             33, MessageValue.newBuilder().setValue(44).build()));
@@ -710,9 +702,10 @@ public class MapForProto2Test extends TestCase {
     assertEquals(0, message.getInt32ToMessageField().size());
 
     // Test setField()
-    setMapValues(builder, "int32_to_int32_field",
-        mapForValues(11, 22, 33, 44));
-    setMapValues(builder, "int32_to_message_field",
+    setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44));
+    setMapValues(
+        builder,
+        "int32_to_message_field",
         mapForValues(
             111, MessageValue.newBuilder().setValue(222).build(),
             333, MessageValue.newBuilder().setValue(444).build()));
@@ -723,20 +716,28 @@ public class MapForProto2Test extends TestCase {
     assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
 
     // Test addRepeatedField
-    builder.addRepeatedField(f("int32_to_int32_field"),
-        newMapEntry(builder, "int32_to_int32_field", 55, 66));
-    builder.addRepeatedField(f("int32_to_message_field"),
-        newMapEntry(builder, "int32_to_message_field", 555,
+    builder.addRepeatedField(
+        f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 66));
+    builder.addRepeatedField(
+        f("int32_to_message_field"),
+        newMapEntry(
+            builder,
+            "int32_to_message_field",
+            555,
             MessageValue.newBuilder().setValue(666).build()));
     message = builder.build();
     assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
     assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
 
     // Test addRepeatedField (overriding existing values)
-    builder.addRepeatedField(f("int32_to_int32_field"),
-        newMapEntry(builder, "int32_to_int32_field", 55, 55));
-    builder.addRepeatedField(f("int32_to_message_field"),
-        newMapEntry(builder, "int32_to_message_field", 555,
+    builder.addRepeatedField(
+        f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 55));
+    builder.addRepeatedField(
+        f("int32_to_message_field"),
+        newMapEntry(
+            builder,
+            "int32_to_message_field",
+            555,
             MessageValue.newBuilder().setValue(555).build()));
     message = builder.build();
     assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
@@ -779,10 +780,9 @@ public class MapForProto2Test extends TestCase {
     setMapValuesUsingAccessors(builder);
     TestMap message = builder.build();
 
-    Message dynamicDefaultInstance =
-        DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
-    Message dynamicMessage = dynamicDefaultInstance
-        .newBuilderForType().mergeFrom(message.toByteString()).build();
+    Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+    Message dynamicMessage =
+        dynamicDefaultInstance.newBuilderForType().mergeFrom(message.toByteString()).build();
 
     assertEquals(message, dynamicMessage);
     assertEquals(message.hashCode(), dynamicMessage.hashCode());
@@ -793,8 +793,7 @@ public class MapForProto2Test extends TestCase {
   public void testDynamicMessageUnsetKeyAndValue() throws Exception {
     FieldDescriptor field = f("int32_to_int32_field");
 
-    Message dynamicDefaultInstance =
-        DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+    Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
     Message.Builder builder = dynamicDefaultInstance.newBuilderForType();
     // Add an entry without key and value.
     builder.addRepeatedField(field, builder.newBuilderForField(field).build());
@@ -811,8 +810,7 @@ public class MapForProto2Test extends TestCase {
     // of map entries when comparing/hashing map fields.
 
     // We use DynamicMessage to test reflection based equals()/hashCode().
-    Message dynamicDefaultInstance =
-        DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+    Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
     FieldDescriptor field = f("int32_to_int32_field");
 
     Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
@@ -839,9 +837,8 @@ public class MapForProto2Test extends TestCase {
   }
 
   public void testUnknownEnumValues() throws Exception {
-    TestUnknownEnumValue.Builder builder = TestUnknownEnumValue.newBuilder()
-        .putInt32ToInt32Field(1, 1)
-        .putInt32ToInt32Field(2, 54321);
+    TestUnknownEnumValue.Builder builder =
+        TestUnknownEnumValue.newBuilder().putInt32ToInt32Field(1, 1).putInt32ToInt32Field(2, 54321);
     ByteString data = builder.build().toByteString();
 
     TestMap message = TestMap.parseFrom(data);
@@ -853,8 +850,7 @@ public class MapForProto2Test extends TestCase {
     assertFalse(message.getUnknownFields().asMap().isEmpty());
     // Serializing and parsing should preserve the unknown entry.
     data = message.toByteString();
-    TestUnknownEnumValue messageWithUnknownEnums =
-        TestUnknownEnumValue.parseFrom(data);
+    TestUnknownEnumValue messageWithUnknownEnums = TestUnknownEnumValue.parseFrom(data);
     assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
     assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
     assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
@@ -887,7 +883,8 @@ public class MapForProto2Test extends TestCase {
     setMapValuesUsingAccessors(builder);
     TestMap message = builder.build();
 
-    assertEquals(Arrays.asList("1", "2", "3"),
+    assertEquals(
+        Arrays.asList("1", "2", "3"),
         new ArrayList<String>(message.getStringToInt32Field().keySet()));
   }
 
@@ -979,7 +976,8 @@ public class MapForProto2Test extends TestCase {
     assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null));
     assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null));
 
-    assertEquals(MessageValue.newBuilder().setValue(11).build(),
+    assertEquals(
+        MessageValue.newBuilder().setValue(11).build(),
         testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null));
     assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null));
 
@@ -1037,7 +1035,8 @@ public class MapForProto2Test extends TestCase {
       // expected
     }
 
-    assertEquals(MessageValue.newBuilder().setValue(11).build(),
+    assertEquals(
+        MessageValue.newBuilder().setValue(11).build(),
         testMapOrBuilder.getInt32ToMessageFieldOrThrow(1));
     try {
       testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1);
@@ -1146,15 +1145,20 @@ public class MapForProto2Test extends TestCase {
 
   // Regression test for b/20494788
   public void testMapInitializationOrder() throws Exception {
-    assertEquals("RedactAllTypes", map_test.RedactAllTypes
-        .getDefaultInstance().getDescriptorForType().getName());
+    assertEquals(
+        "RedactAllTypes",
+        map_test.RedactAllTypes.getDefaultInstance()
+            .getDescriptorForType()
+            .getName());
 
     map_test.Message1.Builder builder =
         map_test.Message1.newBuilder();
     builder.putMapField("key", true);
     map_test.Message1 message = builder.build();
-    Message mapEntry = (Message) message.getRepeatedField(
-        message.getDescriptorForType().findFieldByName("map_field"), 0);
+    Message mapEntry =
+        (Message)
+            message.getRepeatedField(
+                message.getDescriptorForType().findFieldByName("map_field"), 0);
     assertEquals(2, mapEntry.getAllFields().size());
   }
 
@@ -1163,35 +1167,14 @@ public class MapForProto2Test extends TestCase {
     ReservedAsMapFieldWithEnumValue.newBuilder().build();
   }
 
-  private static <K, V> Map<K, V> newMap(K key1, V value1) {
-    Map<K, V> map = new HashMap<K, V>();
-    map.put(key1, value1);
-    return map;
-  }
-
-  private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
-    Map<K, V> map = new HashMap<K, V>();
-    map.put(key1, value1);
-    map.put(key2, value2);
-    return map;
-  }
-
   public void testGetMap() {
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValuesUsingAccessors(builder);
     assertMapValuesSet(builder);
     TestMap message = builder.build();
-    assertEquals(
-        message.getStringToInt32Field(),
-        message.getStringToInt32FieldMap());
-    assertEquals(
-        message.getInt32ToBytesField(),
-        message.getInt32ToBytesFieldMap());
-    assertEquals(
-        message.getInt32ToEnumField(),
-        message.getInt32ToEnumFieldMap());
-    assertEquals(
-        message.getInt32ToMessageField(),
-        message.getInt32ToMessageFieldMap());
+    assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap());
+    assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap());
+    assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap());
+    assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap());
   }
 }

+ 18 - 19
java/core/src/test/java/com/google/protobuf/MapTest.java

@@ -477,12 +477,12 @@ public class MapTest extends TestCase {
   }
 
   public void testPutForUnknownEnumValues() throws Exception {
-    TestMap.Builder builder =
+    TestMap message =
         TestMap.newBuilder()
             .putInt32ToEnumFieldValue(0, 0)
             .putInt32ToEnumFieldValue(1, 1)
-            .putInt32ToEnumFieldValue(2, 1000); // unknown value.
-    TestMap message = builder.build();
+            .putInt32ToEnumFieldValue(2, 1000) // unknown value.
+            .build();
     assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0));
     assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1));
     assertEquals(1000, message.getInt32ToEnumFieldValueOrThrow(2));
@@ -608,12 +608,12 @@ public class MapTest extends TestCase {
 
     // We can't control the order of elements in a HashMap. The best we can do
     // here is to add elements in different order.
-    TestMap.Builder b1 =
+    TestMap m1 =
         TestMap.newBuilder()
             .putInt32ToInt32Field(1, 2)
             .putInt32ToInt32Field(3, 4)
-            .putInt32ToInt32Field(5, 6);
-    TestMap m1 = b1.build();
+            .putInt32ToInt32Field(5, 6)
+            .build();
 
     TestMap.Builder b2 =
         TestMap.newBuilder()
@@ -654,8 +654,8 @@ public class MapTest extends TestCase {
     assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
 
     // Make another change using mergeFrom()
-    TestMap.Builder other = TestMap.newBuilder().putInt32ToInt32Field(1, 4);
-    parent.getOptionalMessageBuilder().mergeFrom(other.build());
+    TestMap other = TestMap.newBuilder().putInt32ToInt32Field(1, 4).build();
+    parent.getOptionalMessageBuilder().mergeFrom(other);
 
     // Should be able to observe the change.
     message = parent.build();
@@ -751,7 +751,7 @@ public class MapTest extends TestCase {
   }
 
   private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
-    List<Message> entryList = new ArrayList<Message>();
+    List<Message> entryList = new ArrayList<>();
     for (Map.Entry<?, ?> entry : values.entrySet()) {
       entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
     }
@@ -760,7 +760,7 @@ public class MapTest extends TestCase {
   }
 
   private static <K, V> Map<K, V> mapForValues(K key1, V value1, K key2, V value2) {
-    Map<K, V> map = new HashMap<K, V>();
+    Map<K, V> map = new HashMap<>();
     map.put(key1, value1);
     map.put(key2, value2);
     return map;
@@ -1002,8 +1002,7 @@ public class MapTest extends TestCase {
     TestMap message = builder.build();
 
     assertEquals(
-        Arrays.asList("1", "2", "3"),
-        new ArrayList<String>(message.getStringToInt32Field().keySet()));
+        Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32Field().keySet()));
   }
 
   public void testGetMap() {
@@ -1336,10 +1335,10 @@ public class MapTest extends TestCase {
     output.flush();
 
     CodedInputStream input = CodedInputStream.newInstance(serialized);
-    List<Integer> int32Keys = new ArrayList<Integer>();
-    List<Integer> uint32Keys = new ArrayList<Integer>();
-    List<Long> int64Keys = new ArrayList<Long>();
-    List<String> stringKeys = new ArrayList<String>();
+    List<Integer> int32Keys = new ArrayList<>();
+    List<Integer> uint32Keys = new ArrayList<>();
+    List<Long> int64Keys = new ArrayList<>();
+    List<String> stringKeys = new ArrayList<>();
     int tag;
     while (true) {
       tag = input.readTag();
@@ -1450,20 +1449,20 @@ public class MapTest extends TestCase {
   }
 
   private static <K, V> Map<K, V> newMap(K key1, V value1) {
-    Map<K, V> map = new HashMap<K, V>();
+    Map<K, V> map = new HashMap<>();
     map.put(key1, value1);
     return map;
   }
 
   private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
-    Map<K, V> map = new HashMap<K, V>();
+    Map<K, V> map = new HashMap<>();
     map.put(key1, value1);
     map.put(key2, value2);
     return map;
   }
 
   private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2, K key3, V value3) {
-    Map<K, V> map = new HashMap<K, V>();
+    Map<K, V> map = new HashMap<>();
     map.put(key1, value1);
     map.put(key2, value2);
     map.put(key3, value3);

+ 2 - 2
java/core/src/test/java/com/google/protobuf/NioByteStringTest.java

@@ -385,12 +385,12 @@ public class NioByteStringTest extends TestCase {
           }
 
           @Override
-          public void writeLazy(byte[] value, int offset, int length) throws IOException {
+          public void write(ByteBuffer value) throws IOException {
             throw new UnsupportedOperationException();
           }
 
           @Override
-          public void write(ByteBuffer value) throws IOException {
+          public void writeLazy(byte[] value, int offset, int length) throws IOException {
             throw new UnsupportedOperationException();
           }
 

+ 64 - 77
java/core/src/test/java/com/google/protobuf/ParserTest.java

@@ -58,8 +58,7 @@ public class ParserTest extends TestCase {
     }
   }
 
-  private void assertRoundTripEquals(MessageLite message,
-                                     ExtensionRegistryLite registry)
+  private void assertRoundTripEquals(MessageLite message, ExtensionRegistryLite registry)
       throws Exception {
     final byte[] data = message.toByteArray();
     final int offset = 20;
@@ -67,15 +66,12 @@ public class ParserTest extends TestCase {
     final int padding = 30;
     Parser<? extends MessageLite> parser = message.getParserForType();
     assertMessageEquals(message, parser.parseFrom(data, registry));
-    assertMessageEquals(message, parser.parseFrom(
-        generatePaddingArray(data, offset, padding),
-        offset, length, registry));
-    assertMessageEquals(message, parser.parseFrom(
-        message.toByteString(), registry));
-    assertMessageEquals(message, parser.parseFrom(
-        new ByteArrayInputStream(data), registry));
-    assertMessageEquals(message, parser.parseFrom(
-        CodedInputStream.newInstance(data), registry));
+    assertMessageEquals(
+        message,
+        parser.parseFrom(generatePaddingArray(data, offset, padding), offset, length, registry));
+    assertMessageEquals(message, parser.parseFrom(message.toByteString(), registry));
+    assertMessageEquals(message, parser.parseFrom(new ByteArrayInputStream(data), registry));
+    assertMessageEquals(message, parser.parseFrom(CodedInputStream.newInstance(data), registry));
     assertMessageEquals(
         message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer(), registry));
   }
@@ -87,23 +83,17 @@ public class ParserTest extends TestCase {
     final int length = data.length;
     final int padding = 30;
 
-    Parser<MessageLite> parser =
-        (Parser<MessageLite>) message.getParserForType();
+    Parser<MessageLite> parser = (Parser<MessageLite>) message.getParserForType();
     assertMessageEquals(message, parser.parseFrom(data));
-    assertMessageEquals(message, parser.parseFrom(
-        generatePaddingArray(data, offset, padding),
-        offset, length));
+    assertMessageEquals(
+        message, parser.parseFrom(generatePaddingArray(data, offset, padding), offset, length));
     assertMessageEquals(message, parser.parseFrom(message.toByteString()));
-    assertMessageEquals(message, parser.parseFrom(
-        new ByteArrayInputStream(data)));
-    assertMessageEquals(message, parser.parseFrom(
-        CodedInputStream.newInstance(data)));
+    assertMessageEquals(message, parser.parseFrom(new ByteArrayInputStream(data)));
+    assertMessageEquals(message, parser.parseFrom(CodedInputStream.newInstance(data)));
     assertMessageEquals(message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer()));
   }
 
-  private void assertMessageEquals(
-      MessageLite expected, MessageLite actual)
-      throws Exception {
+  private void assertMessageEquals(MessageLite expected, MessageLite actual) throws Exception {
     if (expected instanceof Message) {
       assertEquals(expected, actual);
     } else {
@@ -126,20 +116,16 @@ public class ParserTest extends TestCase {
     assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
   }
 
-  private <T extends MessageLite> void assertParsePartial(
-      Parser<T> parser, T partialMessage) throws Exception {
-    final String errorString =
-        "Should throw exceptions when the parsed message isn't initialized.";
+  private <T extends MessageLite> void assertParsePartial(Parser<T> parser, T partialMessage)
+      throws Exception {
+    final String errorString = "Should throw exceptions when the parsed message isn't initialized.";
 
     // parsePartialFrom should pass.
     byte[] data = partialMessage.toByteArray();
     assertEquals(partialMessage, parser.parsePartialFrom(data));
-    assertEquals(partialMessage, parser.parsePartialFrom(
-        partialMessage.toByteString()));
-    assertEquals(partialMessage, parser.parsePartialFrom(
-        new ByteArrayInputStream(data)));
-    assertEquals(partialMessage, parser.parsePartialFrom(
-        CodedInputStream.newInstance(data)));
+    assertEquals(partialMessage, parser.parsePartialFrom(partialMessage.toByteString()));
+    assertEquals(partialMessage, parser.parsePartialFrom(new ByteArrayInputStream(data)));
+    assertEquals(partialMessage, parser.parsePartialFrom(CodedInputStream.newInstance(data)));
 
     // parseFrom(ByteArray)
     try {
@@ -167,8 +153,7 @@ public class ParserTest extends TestCase {
 
     // parseFrom(CodedInputStream)
     try {
-      parser.parseFrom(CodedInputStream.newInstance(
-          partialMessage.toByteArray()));
+      parser.parseFrom(CodedInputStream.newInstance(partialMessage.toByteArray()));
       fail(errorString);
     } catch (IOException e) {
       // pass.
@@ -176,14 +161,12 @@ public class ParserTest extends TestCase {
   }
 
   public void testParseExtensions() throws Exception {
-    assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
-                          TestUtil.getExtensionRegistry());
+    assertRoundTripEquals(TestUtil.getAllExtensionsSet(), TestUtil.getExtensionRegistry());
   }
 
   public void testParsePacked() throws Exception {
     assertRoundTripEquals(TestUtil.getPackedSet());
-    assertRoundTripEquals(TestUtil.getPackedExtensionsSet(),
-                          TestUtil.getExtensionRegistry());
+    assertRoundTripEquals(TestUtil.getPackedExtensionsSet(), TestUtil.getExtensionRegistry());
   }
 
   public void testParseDelimitedTo() throws Exception {
@@ -202,9 +185,7 @@ public class ParserTest extends TestCase {
     // All fields will be treated as unknown fields in emptyMessage.
     TestEmptyMessage emptyMessage =
         TestEmptyMessage.parser().parseFrom(TestUtil.getAllSet().toByteString());
-    assertEquals(
-        TestUtil.getAllSet().toByteString(),
-        emptyMessage.toByteString());
+    assertEquals(TestUtil.getAllSet().toByteString(), emptyMessage.toByteString());
   }
 
 
@@ -212,7 +193,8 @@ public class ParserTest extends TestCase {
     TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
     builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
     builder.setExtension(TestOptimizedForSize.testExtension, 56);
-    builder.setExtension(TestOptimizedForSize.testExtension2,
+    builder.setExtension(
+        TestOptimizedForSize.testExtension2,
         TestRequiredOptimizedForSize.newBuilder().setX(78).build());
 
     TestOptimizedForSize message = builder.build();
@@ -222,9 +204,8 @@ public class ParserTest extends TestCase {
     assertRoundTripEquals(message, registry);
   }
 
-  /** Helper method for {@link #testParsingMerge()}.*/
-  private void assertMessageMerged(TestAllTypes allTypes)
-      throws Exception {
+  /** Helper method for {@link #testParsingMerge()}. */
+  private void assertMessageMerged(TestAllTypes allTypes) throws Exception {
     assertEquals(3, allTypes.getOptionalInt32());
     assertEquals(2, allTypes.getOptionalInt64());
     assertEquals("hello", allTypes.getOptionalString());
@@ -237,39 +218,48 @@ public class ParserTest extends TestCase {
     builder.clear();
     TestAllTypes msg2 = builder.setOptionalInt64(2).build();
     builder.clear();
-    TestAllTypes msg3 = builder.setOptionalInt32(3)
-        .setOptionalString("hello").build();
+    TestAllTypes msg3 = builder.setOptionalInt32(3).setOptionalString("hello").build();
 
     // Build groups.
     TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
-        .setField1(msg1).build();
+        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder().setField1(msg1).build();
     TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
-        .setField1(msg2).build();
+        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder().setField1(msg2).build();
     TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
-        .setField1(msg3).build();
+        TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder().setField1(msg3).build();
     TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
-        .setField1(msg1).build();
+        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder().setField1(msg1).build();
     TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
-        .setField1(msg2).build();
+        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder().setField1(msg2).build();
     TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
-        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
-        .setField1(msg3).build();
+        TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder().setField1(msg3).build();
 
     // Assign and serialize RepeatedFieldsGenerator.
-    ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
-        .addField1(msg1).addField1(msg2).addField1(msg3)
-        .addField2(msg1).addField2(msg2).addField2(msg3)
-        .addField3(msg1).addField3(msg2).addField3(msg3)
-        .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
-        .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
-        .addExt1(msg1).addExt1(msg2).addExt1(msg3)
-        .addExt2(msg1).addExt2(msg2).addExt2(msg3)
-        .build().toByteString();
+    ByteString data =
+        TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
+            .addField1(msg1)
+            .addField1(msg2)
+            .addField1(msg3)
+            .addField2(msg1)
+            .addField2(msg2)
+            .addField2(msg3)
+            .addField3(msg1)
+            .addField3(msg2)
+            .addField3(msg3)
+            .addGroup1(optionalG1)
+            .addGroup1(optionalG2)
+            .addGroup1(optionalG3)
+            .addGroup2(repeatedG1)
+            .addGroup2(repeatedG2)
+            .addGroup2(repeatedG3)
+            .addExt1(msg1)
+            .addExt1(msg2)
+            .addExt1(msg3)
+            .addExt2(msg1)
+            .addExt2(msg2)
+            .addExt2(msg3)
+            .build()
+            .toByteString();
 
     // Parse TestParsingMerge.
     ExtensionRegistry registry = ExtensionRegistry.newInstance();
@@ -279,21 +269,18 @@ public class ParserTest extends TestCase {
     // Required and optional fields should be merged.
     assertMessageMerged(parsingMerge.getRequiredAllTypes());
     assertMessageMerged(parsingMerge.getOptionalAllTypes());
-    assertMessageMerged(
-        parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
-    assertMessageMerged(parsingMerge.getExtension(
-        TestParsingMerge.optionalExt));
+    assertMessageMerged(parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+    assertMessageMerged(parsingMerge.getExtension(TestParsingMerge.optionalExt));
 
     // Repeated fields should not be merged.
     assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
     assertEquals(3, parsingMerge.getRepeatedGroupCount());
-    assertEquals(3, parsingMerge.getExtensionCount(
-        TestParsingMerge.repeatedExt));
+    assertEquals(3, parsingMerge.getExtensionCount(TestParsingMerge.repeatedExt));
   }
 
   public void testParseDelimitedFrom_firstByteInterrupted_preservesCause() {
     try {
-      TestUtil.getAllSet().parseDelimitedFrom(
+      TestAllTypes.parseDelimitedFrom(
           new InputStream() {
             @Override
             public int read() throws IOException {
@@ -308,7 +295,7 @@ public class ParserTest extends TestCase {
 
   public void testParseDelimitedFrom_secondByteInterrupted_preservesCause() {
     try {
-      TestUtil.getAllSet().parseDelimitedFrom(
+      TestAllTypes.parseDelimitedFrom(
           new InputStream() {
             private int i;
 

+ 72 - 71
java/core/src/test/java/com/google/protobuf/ServiceTest.java

@@ -58,9 +58,9 @@ public class ServiceTest extends TestCase {
   private RpcController mockController;
 
   private final Descriptors.MethodDescriptor fooDescriptor =
-    TestService.getDescriptor().getMethods().get(0);
+      TestService.getDescriptor().getMethods().get(0);
   private final Descriptors.MethodDescriptor barDescriptor =
-    TestService.getDescriptor().getMethods().get(1);
+      TestService.getDescriptor().getMethods().get(1);
 
   @Override
   protected void setUp() throws Exception {
@@ -79,16 +79,22 @@ public class ServiceTest extends TestCase {
     MockCallback<Message> barCallback = new MockCallback<Message>();
     TestService mockService = control.createMock(TestService.class);
 
-    mockService.foo(EasyMock.same(mockController), EasyMock.same(fooRequest),
-                    this.<FooResponse>wrapsCallback(fooCallback));
-    mockService.bar(EasyMock.same(mockController), EasyMock.same(barRequest),
-                    this.<BarResponse>wrapsCallback(barCallback));
+    mockService.foo(
+        EasyMock.same(mockController),
+        EasyMock.same(fooRequest),
+        this.<FooResponse>wrapsCallback(fooCallback));
+    mockService.bar(
+        EasyMock.same(mockController),
+        EasyMock.same(barRequest),
+        this.<BarResponse>wrapsCallback(barCallback));
     control.replay();
 
-    mockService.callMethod(fooDescriptor, mockController,
-                           fooRequest, fooCallback);
-    mockService.callMethod(barDescriptor, mockController,
-                           barRequest, barCallback);
+    mockService.callMethod(
+        fooDescriptor, mockController,
+        fooRequest, fooCallback);
+    mockService.callMethod(
+        barDescriptor, mockController,
+        barRequest, barCallback);
     control.verify();
   }
 
@@ -96,14 +102,10 @@ public class ServiceTest extends TestCase {
   public void testGetPrototype() throws Exception {
     TestService mockService = control.createMock(TestService.class);
 
-    assertSame(mockService.getRequestPrototype(fooDescriptor),
-               FooRequest.getDefaultInstance());
-    assertSame(mockService.getResponsePrototype(fooDescriptor),
-               FooResponse.getDefaultInstance());
-    assertSame(mockService.getRequestPrototype(barDescriptor),
-               BarRequest.getDefaultInstance());
-    assertSame(mockService.getResponsePrototype(barDescriptor),
-               BarResponse.getDefaultInstance());
+    assertSame(mockService.getRequestPrototype(fooDescriptor), FooRequest.getDefaultInstance());
+    assertSame(mockService.getResponsePrototype(fooDescriptor), FooResponse.getDefaultInstance());
+    assertSame(mockService.getRequestPrototype(barDescriptor), BarRequest.getDefaultInstance());
+    assertSame(mockService.getResponsePrototype(barDescriptor), BarResponse.getDefaultInstance());
   }
 
   /** Tests generated stubs. */
@@ -116,17 +118,17 @@ public class ServiceTest extends TestCase {
     TestService stub = TestService.newStub(mockChannel);
 
     mockChannel.callMethod(
-      EasyMock.same(fooDescriptor),
-      EasyMock.same(mockController),
-      EasyMock.same(fooRequest),
-      EasyMock.same(FooResponse.getDefaultInstance()),
-      this.<Message>wrapsCallback(fooCallback));
+        EasyMock.same(fooDescriptor),
+        EasyMock.same(mockController),
+        EasyMock.same(fooRequest),
+        EasyMock.same(FooResponse.getDefaultInstance()),
+        this.<Message>wrapsCallback(fooCallback));
     mockChannel.callMethod(
-      EasyMock.same(barDescriptor),
-      EasyMock.same(mockController),
-      EasyMock.same(barRequest),
-      EasyMock.same(BarResponse.getDefaultInstance()),
-      this.<Message>wrapsCallback(barCallback));
+        EasyMock.same(barDescriptor),
+        EasyMock.same(mockController),
+        EasyMock.same(barRequest),
+        EasyMock.same(BarResponse.getDefaultInstance()),
+        this.<Message>wrapsCallback(barCallback));
     control.replay();
 
     stub.foo(mockController, fooRequest, fooCallback);
@@ -138,24 +140,26 @@ public class ServiceTest extends TestCase {
   public void testBlockingStub() throws Exception {
     FooRequest fooRequest = FooRequest.newBuilder().build();
     BarRequest barRequest = BarRequest.newBuilder().build();
-    BlockingRpcChannel mockChannel =
-        control.createMock(BlockingRpcChannel.class);
-    TestService.BlockingInterface stub =
-        TestService.newBlockingStub(mockChannel);
+    BlockingRpcChannel mockChannel = control.createMock(BlockingRpcChannel.class);
+    TestService.BlockingInterface stub = TestService.newBlockingStub(mockChannel);
 
     FooResponse fooResponse = FooResponse.newBuilder().build();
     BarResponse barResponse = BarResponse.newBuilder().build();
 
-    EasyMock.expect(mockChannel.callBlockingMethod(
-      EasyMock.same(fooDescriptor),
-      EasyMock.same(mockController),
-      EasyMock.same(fooRequest),
-      EasyMock.same(FooResponse.getDefaultInstance()))).andReturn(fooResponse);
-    EasyMock.expect(mockChannel.callBlockingMethod(
-      EasyMock.same(barDescriptor),
-      EasyMock.same(mockController),
-      EasyMock.same(barRequest),
-      EasyMock.same(BarResponse.getDefaultInstance()))).andReturn(barResponse);
+    EasyMock.expect(
+            mockChannel.callBlockingMethod(
+                EasyMock.same(fooDescriptor),
+                EasyMock.same(mockController),
+                EasyMock.same(fooRequest),
+                EasyMock.same(FooResponse.getDefaultInstance())))
+        .andReturn(fooResponse);
+    EasyMock.expect(
+            mockChannel.callBlockingMethod(
+                EasyMock.same(barDescriptor),
+                EasyMock.same(mockController),
+                EasyMock.same(barRequest),
+                EasyMock.same(BarResponse.getDefaultInstance())))
+        .andReturn(barResponse);
     control.replay();
 
     assertSame(fooResponse, stub.foo(mockController, fooRequest));
@@ -164,13 +168,11 @@ public class ServiceTest extends TestCase {
   }
 
   public void testNewReflectiveService() {
-    ServiceWithNoOuter.Interface impl =
-        control.createMock(ServiceWithNoOuter.Interface.class);
+    ServiceWithNoOuter.Interface impl = control.createMock(ServiceWithNoOuter.Interface.class);
     RpcController controller = control.createMock(RpcController.class);
     Service service = ServiceWithNoOuter.newReflectiveService(impl);
 
-    MethodDescriptor fooMethod =
-        ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+    MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
     MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
     RpcCallback<Message> callback =
         new RpcCallback<Message>() {
@@ -180,11 +182,9 @@ public class ServiceTest extends TestCase {
             fail();
           }
         };
-    RpcCallback<TestAllTypes> specializedCallback =
-        RpcUtil.specializeCallback(callback);
+    RpcCallback<TestAllTypes> specializedCallback = RpcUtil.specializeCallback(callback);
 
-    impl.foo(EasyMock.same(controller), EasyMock.same(request),
-        EasyMock.same(specializedCallback));
+    impl.foo(EasyMock.same(controller), EasyMock.same(request), EasyMock.same(specializedCallback));
     EasyMock.expectLastCall();
 
     control.replay();
@@ -198,11 +198,9 @@ public class ServiceTest extends TestCase {
     ServiceWithNoOuter.BlockingInterface impl =
         control.createMock(ServiceWithNoOuter.BlockingInterface.class);
     RpcController controller = control.createMock(RpcController.class);
-    BlockingService service =
-        ServiceWithNoOuter.newReflectiveBlockingService(impl);
+    BlockingService service = ServiceWithNoOuter.newReflectiveBlockingService(impl);
 
-    MethodDescriptor fooMethod =
-        ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+    MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
     MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
 
     TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance();
@@ -211,8 +209,7 @@ public class ServiceTest extends TestCase {
 
     control.replay();
 
-    Message response =
-        service.callBlockingMethod(fooMethod, controller, request);
+    Message response = service.callBlockingMethod(fooMethod, controller, request);
     assertEquals(expectedResponse, response);
 
     control.verify();
@@ -221,16 +218,16 @@ public class ServiceTest extends TestCase {
   public void testNoGenericServices() throws Exception {
     // Non-services should be usable.
     UnittestNoGenericServices.TestMessage message =
-      UnittestNoGenericServices.TestMessage.newBuilder()
-        .setA(123)
-        .setExtension(UnittestNoGenericServices.testExtension, 456)
-        .build();
+        UnittestNoGenericServices.TestMessage.newBuilder()
+            .setA(123)
+            .setExtension(UnittestNoGenericServices.testExtension, 456)
+            .build();
     assertEquals(123, message.getA());
     assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber());
 
     // Build a list of the class names nested in UnittestNoGenericServices.
-    String outerName = "google.protobuf.no_generic_services_test." +
-                       "UnittestNoGenericServices";
+    String outerName =
+        "google.protobuf.no_generic_services_test.UnittestNoGenericServices";
     Class<?> outerClass = Class.forName(outerName);
 
     Set<String> innerClassNames = new HashSet<String>();
@@ -244,9 +241,9 @@ public class ServiceTest extends TestCase {
       //   separator.
       assertTrue(fullName.startsWith(outerName));
 
-      if (!Service.class.isAssignableFrom(innerClass) &&
-          !Message.class.isAssignableFrom(innerClass) &&
-          !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) {
+      if (!Service.class.isAssignableFrom(innerClass)
+          && !Message.class.isAssignableFrom(innerClass)
+          && !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) {
         // Ignore any classes not generated by the base code generator.
         continue;
       }
@@ -264,8 +261,7 @@ public class ServiceTest extends TestCase {
     assertEquals(1, file.getServices().size());
     assertEquals("TestService", file.getServices().get(0).getName());
     assertEquals(1, file.getServices().get(0).getMethods().size());
-    assertEquals("Foo",
-        file.getServices().get(0).getMethods().get(0).getName());
+    assertEquals("Foo", file.getServices().get(0).getMethods().get(0).getName());
   }
 
 
@@ -284,13 +280,18 @@ public class ServiceTest extends TestCase {
   private static class MockCallback<T extends Message> implements RpcCallback<T> {
     private boolean called = false;
 
-    public boolean isCalled() { return called; }
+    public boolean isCalled() {
+      return called;
+    }
 
-    public void reset() { called = false; }
+    public void reset() {
+      called = false;
+    }
 
     @Override
     public void run(T message) {
-      called = true; }
+      called = true;
+    }
   }
 
   /** Implementation of the wrapsCallback() argument matcher. */
@@ -307,7 +308,7 @@ public class ServiceTest extends TestCase {
       if (!(actual instanceof RpcCallback)) {
         return false;
       }
-      RpcCallback actualCallback = (RpcCallback)actual;
+      RpcCallback actualCallback = (RpcCallback) actual;
 
       callback.reset();
       actualCallback.run(null);

+ 32 - 4
java/core/src/test/java/com/google/protobuf/TestUtil.java

@@ -119,8 +119,6 @@ import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite;
 import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite;
 import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite;
 import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite;
-import static protobuf_unittest.UnittestProto.OptionalGroup_extension;
-import static protobuf_unittest.UnittestProto.RepeatedGroup_extension;
 import static protobuf_unittest.UnittestProto.defaultBoolExtension;
 import static protobuf_unittest.UnittestProto.defaultBytesExtension;
 import static protobuf_unittest.UnittestProto.defaultCordExtension;
@@ -222,6 +220,8 @@ import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage;
 import protobuf_unittest.UnittestProto;
 import protobuf_unittest.UnittestProto.ForeignEnum;
 import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.OptionalGroup_extension;
+import protobuf_unittest.UnittestProto.RepeatedGroup_extension;
 import protobuf_unittest.UnittestProto.TestAllExtensions;
 import protobuf_unittest.UnittestProto.TestAllExtensionsOrBuilder;
 import protobuf_unittest.UnittestProto.TestAllTypes;
@@ -234,6 +234,11 @@ import protobuf_unittest.UnittestProto.TestUnpackedTypes;
 import java.io.File;
 import java.io.IOException;
 import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
 import junit.framework.Assert;
 
 /**
@@ -2634,7 +2639,6 @@ public final class TestUtil {
         break;
       case FOO_NOT_SET:
         break;
-      default:
         // TODO(b/18683919): go/enum-switch-lsc
     }
   }
@@ -2702,7 +2706,7 @@ public final class TestUtil {
       this.publicImportFile = importFile.getDependencies().get(0);
 
       Descriptors.Descriptor testAllTypes;
-      if (baseDescriptor.getName() == "TestAllTypes") {
+      if ("TestAllTypes".equals(baseDescriptor.getName())) {
         testAllTypes = baseDescriptor;
       } else {
         testAllTypes = file.findMessageTypeByName("TestAllTypes");
@@ -3857,4 +3861,28 @@ public final class TestUtil {
     }
   }
   // END FULL-RUNTIME
+
+  /** Helper class to test logged messages */
+  public static class TestLogHandler extends Handler {
+    /** We will keep a private list of all logged records */
+    private final List<LogRecord> list = new ArrayList<>();
+
+    /** Adds the most recently logged record to our list. */
+    @Override
+    public synchronized void publish(LogRecord record) {
+      list.add(record);
+    }
+
+    @Override
+    public void flush() {}
+
+    @Override
+    public void close() {}
+
+    /** Returns a snapshot of the logged records. */
+    public synchronized List<LogRecord> getStoredLogRecords() {
+      List<LogRecord> result = new ArrayList<>(list);
+      return Collections.unmodifiableList(result);
+    }
+  }
 }

+ 75 - 7
java/core/src/test/java/com/google/protobuf/TextFormatTest.java

@@ -49,6 +49,7 @@ import protobuf_unittest.UnittestProto.TestRequired;
 import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
 import java.io.StringReader;
 import java.util.List;
+import java.util.logging.Logger;
 import junit.framework.TestCase;
 
 /**
@@ -131,6 +132,8 @@ public class TextFormatTest extends TestCase {
           + "  i: 456\n"
           + "}\n";
 
+  private final TextFormat.Parser parserAllowingUnknownExtensions =
+      TextFormat.Parser.newBuilder().setAllowUnknownExtensions(true).build();
 
   private final TextFormat.Parser parserWithOverwriteForbidden =
       TextFormat.Parser.newBuilder()
@@ -467,7 +470,7 @@ public class TextFormatTest extends TestCase {
       fail("expected parse exception");
     } catch (TextFormat.ParseException e) {
       assertEquals(
-          "6:1: Non-repeated field "
+          "4:44: Non-repeated field "
               + "\"protobuf_unittest.TestMessageSetExtension1.message_set_extension\""
               + " cannot be overwritten.",
           e.getMessage());
@@ -519,6 +522,23 @@ public class TextFormatTest extends TestCase {
   }
 
 
+  private void assertParseErrorWithUnknownExtensions(String error, String text) {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    try {
+      parserAllowingUnknownExtensions.merge(text, builder);
+      fail("Expected parse exception.");
+    } catch (TextFormat.ParseException e) {
+      assertEquals(error, e.getMessage());
+    }
+  }
+
+  private TestAllTypes assertParseSuccessWithUnknownExtensions(String text)
+      throws TextFormat.ParseException {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    parserAllowingUnknownExtensions.merge(text, builder);
+    return builder.build();
+  }
+
   private void assertParseErrorWithOverwriteForbidden(String error, String text) {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     try {
@@ -954,6 +974,54 @@ public class TextFormatTest extends TestCase {
   }
 
 
+  public void testParseUnknownExtensions() throws Exception {
+    TestUtil.TestLogHandler logHandler = new TestUtil.TestLogHandler();
+    Logger logger = Logger.getLogger(TextFormat.class.getName());
+    logger.addHandler(logHandler);
+    // Test unknown extension can pass.
+    assertParseSuccessWithUnknownExtensions("[unknown_extension]: 123");
+    assertParseSuccessWithUnknownExtensions("[unknown_extension]: 123\n"
+        + "[unknown_ext]: inf\n"
+        + "[unknown]: 1.234");
+    // Test warning messages.
+    assertEquals("Input contains unknown fields and/or extensions:\n"
+        + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]",
+        logHandler.getStoredLogRecords().get(0).getMessage());
+    assertEquals("Input contains unknown fields and/or extensions:\n"
+        + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]\n"
+        + "2:2:\tprotobuf_unittest.TestAllTypes.[unknown_ext]\n"
+        + "3:2:\tprotobuf_unittest.TestAllTypes.[unknown]",
+        logHandler.getStoredLogRecords().get(1).getMessage());
+
+    // Test unknown field can not pass.
+    assertParseErrorWithUnknownExtensions(
+        "2:1: Input contains unknown fields and/or extensions:\n"
+        + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]\n"
+        + "2:1:\tprotobuf_unittest.TestAllTypes.unknown_field",
+        "[unknown_extension]: 1\n"
+        + "unknown_field: 12345");
+    assertParseErrorWithUnknownExtensions(
+        "3:1: Input contains unknown fields and/or extensions:\n"
+        + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension1]\n"
+        + "2:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension2]\n"
+        + "3:1:\tprotobuf_unittest.TestAllTypes.unknown_field\n"
+        + "4:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension3]",
+        "[unknown_extension1]: 1\n"
+        + "[unknown_extension2]: 2\n"
+        + "unknown_field: 12345\n"
+        + "[unknown_extension3]: 3\n");
+    assertParseErrorWithUnknownExtensions(
+        "1:1: Input contains unknown fields and/or extensions:\n"
+        + "1:1:\tprotobuf_unittest.TestAllTypes.unknown_field1\n"
+        + "2:1:\tprotobuf_unittest.TestAllTypes.unknown_field2\n"
+        + "3:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]\n"
+        + "4:1:\tprotobuf_unittest.TestAllTypes.unknown_field3",
+        "unknown_field1: 1\n"
+        + "unknown_field2: 2\n"
+        + "[unknown_extension]: 12345\n"
+        + "unknown_field3: 3\n");
+  }
+
   // See additional coverage in testOneofOverwriteForbidden and testMapOverwriteForbidden.
   public void testParseNonRepeatedFields() throws Exception {
     assertParseSuccessWithOverwriteForbidden("repeated_int32: 1\nrepeated_int32: 2\n");
@@ -962,29 +1030,29 @@ public class TextFormatTest extends TestCase {
         "repeated_nested_message { bb: 1 }\nrepeated_nested_message { bb: 2 }\n");
 
     assertParseErrorWithOverwriteForbidden(
-        "3:17: Non-repeated field "
+        "3:15: Non-repeated field "
             + "\"protobuf_unittest.TestAllTypes.optional_int32\" "
             + "cannot be overwritten.",
         "optional_int32: 1\noptional_bool: true\noptional_int32: 1\n");
     assertParseErrorWithOverwriteForbidden(
-        "2:17: Non-repeated field "
+        "2:1: Non-repeated field "
             + "\"protobuf_unittest.TestAllTypes.optionalgroup\" "
             + "cannot be overwritten.",
         "OptionalGroup { a: 1 }\nOptionalGroup { }\n");
     assertParseErrorWithOverwriteForbidden(
-        "2:33: Non-repeated field "
+        "2:1: Non-repeated field "
             + "\"protobuf_unittest.TestAllTypes.optional_nested_message\" "
             + "cannot be overwritten.",
         "optional_nested_message { }\noptional_nested_message { bb: 3 }\n");
     assertParseErrorWithOverwriteForbidden(
-        "2:16: Non-repeated field "
+        "2:14: Non-repeated field "
             + "\"protobuf_unittest.TestAllTypes.default_int32\" "
             + "cannot be overwritten.",
         "default_int32: 41\n"
             + // the default value
             "default_int32: 41\n");
     assertParseErrorWithOverwriteForbidden(
-        "2:17: Non-repeated field "
+        "2:15: Non-repeated field "
             + "\"protobuf_unittest.TestAllTypes.default_string\" "
             + "cannot be overwritten.",
         "default_string: \"zxcv\"\ndefault_string: \"asdf\"\n");
@@ -1044,7 +1112,7 @@ public class TextFormatTest extends TestCase {
       fail("Expected parse exception.");
     } catch (TextFormat.ParseException e) {
       assertEquals(
-          "1:36: Field \"protobuf_unittest.TestOneof2.foo_int\""
+          "1:34: Field \"protobuf_unittest.TestOneof2.foo_int\""
               + " is specified along with field \"protobuf_unittest.TestOneof2.foo_string\","
               + " another member of oneof \"foo\".",
           e.getMessage());

+ 2 - 2
java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java

@@ -353,8 +353,8 @@ public class UnknownFieldSetTest extends TestCase {
   /**
    * Asserts that the given field sets are not equal and have different hash codes.
    *
-   * @warning It's valid for non-equal objects to have the same hash code, so this test is stricter
-   *     than it needs to be. However, this should happen relatively rarely.
+   * <p><b>Note:</b> It's valid for non-equal objects to have the same hash code, so this test is
+   * stricter than it needs to be. However, this should happen relatively rarely.
    */
   private void checkNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) {
     String equalsError = String.format("%s should not be equal to %s", s1, s2);

+ 6 - 6
java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java

@@ -42,13 +42,13 @@ import junit.framework.TestCase;
  */
 public class UnmodifiableLazyStringListTest extends TestCase {
 
-  private static String STRING_A = "A";
-  private static String STRING_B = "B";
-  private static String STRING_C = "C";
+  private static final String STRING_A = "A";
+  private static final String STRING_B = "B";
+  private static final String STRING_C = "C";
 
-  private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
-  private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
-  private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+  private static final ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+  private static final ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+  private static final ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
 
   public void testReadOnlyMethods() {
     LazyStringArrayList rawList = createSampleList();

+ 2 - 2
java/core/src/test/proto/com/google/protobuf/field_presence_test.proto

@@ -53,7 +53,7 @@ message TestAllTypes {
   NestedEnum optional_nested_enum = 4;
   NestedMessage optional_nested_message = 5;
   protobuf_unittest.TestRequired optional_proto2_message = 6;
-  NestedMessage optional_lazy_message = 7 [lazy=true];
+  NestedMessage optional_lazy_message = 7 [lazy = true];
 
   oneof oneof_field {
     int32 oneof_int32 = 11;
@@ -81,7 +81,7 @@ message TestOptionalFieldsOnly {
   TestAllTypes.NestedEnum optional_nested_enum = 4;
   TestAllTypes.NestedMessage optional_nested_message = 5;
   protobuf_unittest.TestRequired optional_proto2_message = 6;
-  TestAllTypes.NestedMessage optional_lazy_message = 7 [lazy=true];
+  TestAllTypes.NestedMessage optional_lazy_message = 7 [lazy = true];
 }
 
 message TestRepeatedFieldsOnly {

+ 1 - 2
java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto

@@ -69,8 +69,7 @@ message BarPrime {
   optional string name = 1;
 }
 
-message Empty {
-}
+message Empty {}
 
 extend Foo {
   optional int32 varint = 101;

+ 28 - 19
java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto

@@ -44,12 +44,12 @@ message TestMap {
     QUX = 3;
   }
 
-  map<int32, int32>         int32_to_int32_field = 1;
-  map<int32, string>        int32_to_string_field = 2;
-  map<int32, bytes>         int32_to_bytes_field = 3;
-  map<int32, EnumValue>     int32_to_enum_field = 4;
-  map<int32, MessageValue>  int32_to_message_field = 5;
-  map<string, int32>        string_to_int32_field = 6;
+  map<int32, int32> int32_to_int32_field = 1;
+  map<int32, string> int32_to_string_field = 2;
+  map<int32, bytes> int32_to_bytes_field = 3;
+  map<int32, EnumValue> int32_to_enum_field = 4;
+  map<int32, MessageValue> int32_to_message_field = 5;
+  map<string, int32> string_to_int32_field = 6;
 
   message MessageWithRequiredFields {
     required int32 value = 1;
@@ -70,15 +70,20 @@ message TestRecursiveMap {
   map<int32, TestRecursiveMap> recursive_map_field = 2;
 }
 
-
 // a decoy of TestMap for testing parsing errors
 message BizarroTestMap {
-  map<int32, bytes> int32_to_int32_field = 1; // same key type, different value
-  map<string, int32> int32_to_string_field = 2; // different key and value types
-  map<string, int32> int32_to_bytes_field = 3; // different key types, same value
-  map<string, bytes> int32_to_enum_field = 4; // different key and value types
-  map<string, bytes> int32_to_message_field = 5; // different key and value types
-  map<string, bytes> string_to_int32_field = 6;  // same key type, different value
+  // same key type, different value
+  map<int32, bytes> int32_to_int32_field = 1;
+  // different key and value types
+  map<string, int32> int32_to_string_field = 2;
+  // different key types, same value
+  map<string, int32> int32_to_bytes_field = 3;
+  // different key and value types
+  map<string, bytes> int32_to_enum_field = 4;
+  // different key and value types
+  map<string, bytes> int32_to_message_field = 5;
+  // same key type, different value
+  map<string, bytes> string_to_int32_field = 6;
 }
 
 // Used to test that java reserved words can be used as protobuf field names
@@ -92,11 +97,13 @@ message ReservedAsMapField {
   map<string, uint32> class = 4;
   map<string, uint32> int = 5;
   map<string, uint32> void = 6;
-  map<string, uint32> string = 7; // These are also proto keywords
+  // These are also proto keywords
+  map<string, uint32> string = 7;
   map<string, uint32> package = 8;
-  map<string, uint32> enum = 9; // Most recent Java reserved word
-  map<string, uint32> null = 10;
+  // Most recent Java reserved word
+  map<string, uint32> enum = 9;
   // null is not a 'reserved word' per se but as a literal needs similar care
+  map<string, uint32> null = 10;
 }
 
 message ReservedAsMapFieldWithEnumValue {
@@ -110,11 +117,13 @@ message ReservedAsMapFieldWithEnumValue {
   map<string, SampleEnum> class = 4;
   map<string, SampleEnum> int = 5;
   map<string, SampleEnum> void = 6;
-  map<string, SampleEnum> string = 7; // These are also proto keywords
+  // These are also proto keywords
+  map<string, SampleEnum> string = 7;
   map<string, SampleEnum> package = 8;
-  map<string, SampleEnum> enum = 9; // Most recent Java reserved word
-  map<string, SampleEnum> null = 10;
+  // Most recent Java reserved word
+  map<string, SampleEnum> enum = 9;
   // null is not a 'reserved word' per se but as a literal needs similar care
+  map<string, SampleEnum> null = 10;
 }
 package map_for_proto2_lite_test;
 option java_package = "map_lite_test";

+ 28 - 19
java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto

@@ -46,12 +46,12 @@ message TestMap {
     QUX = 3;
   }
 
-  map<int32, int32>         int32_to_int32_field = 1;
-  map<int32, string>        int32_to_string_field = 2;
-  map<int32, bytes>         int32_to_bytes_field = 3;
-  map<int32, EnumValue>     int32_to_enum_field = 4;
-  map<int32, MessageValue>  int32_to_message_field = 5;
-  map<string, int32>        string_to_int32_field = 6;
+  map<int32, int32> int32_to_int32_field = 1;
+  map<int32, string> int32_to_string_field = 2;
+  map<int32, bytes> int32_to_bytes_field = 3;
+  map<int32, EnumValue> int32_to_enum_field = 4;
+  map<int32, MessageValue> int32_to_message_field = 5;
+  map<string, int32> string_to_int32_field = 6;
 
   message MessageWithRequiredFields {
     required int32 value = 1;
@@ -72,15 +72,20 @@ message TestRecursiveMap {
   map<int32, TestRecursiveMap> recursive_map_field = 2;
 }
 
-
 // a decoy of TestMap for testing parsing errors
 message BizarroTestMap {
-  map<int32, bytes> int32_to_int32_field = 1; // same key type, different value
-  map<string, int32> int32_to_string_field = 2; // different key and value types
-  map<string, int32> int32_to_bytes_field = 3; // different key types, same value
-  map<string, bytes> int32_to_enum_field = 4; // different key and value types
-  map<string, bytes> int32_to_message_field = 5; // different key and value types
-  map<string, bytes> string_to_int32_field = 6;  // same key type, different value
+  // same key type, different value
+  map<int32, bytes> int32_to_int32_field = 1;
+  // different key and value types
+  map<string, int32> int32_to_string_field = 2;
+  // different key types, same value
+  map<string, int32> int32_to_bytes_field = 3;
+  // different key and value types
+  map<string, bytes> int32_to_enum_field = 4;
+  // different key and value types
+  map<string, bytes> int32_to_message_field = 5;
+  // same key type, different value
+  map<string, bytes> string_to_int32_field = 6;
 }
 
 // Used to test that java reserved words can be used as protobuf field names
@@ -94,11 +99,13 @@ message ReservedAsMapField {
   map<string, uint32> class = 4;
   map<string, uint32> int = 5;
   map<string, uint32> void = 6;
-  map<string, uint32> string = 7; // These are also proto keywords
+  // These are also proto keywords
+  map<string, uint32> string = 7;
   map<string, uint32> package = 8;
-  map<string, uint32> enum = 9; // Most recent Java reserved word
-  map<string, uint32> null = 10;
+  // Most recent Java reserved word
+  map<string, uint32> enum = 9;
   // null is not a 'reserved word' per se but as a literal needs similar care
+  map<string, uint32> null = 10;
 }
 
 message ReservedAsMapFieldWithEnumValue {
@@ -112,9 +119,11 @@ message ReservedAsMapFieldWithEnumValue {
   map<string, SampleEnum> class = 4;
   map<string, SampleEnum> int = 5;
   map<string, SampleEnum> void = 6;
-  map<string, SampleEnum> string = 7; // These are also proto keywords
+  // These are also proto keywords
+  map<string, SampleEnum> string = 7;
   map<string, SampleEnum> package = 8;
-  map<string, SampleEnum> enum = 9; // Most recent Java reserved word
-  map<string, SampleEnum> null = 10;
+  // Most recent Java reserved word
+  map<string, SampleEnum> enum = 9;
   // null is not a 'reserved word' per se but as a literal needs similar care
+  map<string, SampleEnum> null = 10;
 }

+ 1 - 2
java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto

@@ -57,5 +57,4 @@ extend Message1 {
   optional Message1 recursive_extension = 1001;
 }
 
-message RedactAllTypes {
-}
+message RedactAllTypes {}

+ 31 - 22
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 {
@@ -47,14 +46,14 @@ message TestMap {
     QUX = 3;
   }
 
-  map<int32, int32>        int32_to_int32_field = 1;
-  map<int32, string>       int32_to_string_field = 2;
-  map<int32, bytes>        int32_to_bytes_field = 3;
-  map<int32, EnumValue>    int32_to_enum_field = 4;
+  map<int32, int32> int32_to_int32_field = 1;
+  map<int32, string> int32_to_string_field = 2;
+  map<int32, bytes> int32_to_bytes_field = 3;
+  map<int32, EnumValue> int32_to_enum_field = 4;
   map<int32, MessageValue> int32_to_message_field = 5;
-  map<string, int32>       string_to_int32_field = 6;
-  map<uint32, int32>       uint32_to_int32_field = 7;
-  map<int64, int32>        int64_to_int32_field = 8;
+  map<string, int32> string_to_int32_field = 6;
+  map<uint32, int32> uint32_to_int32_field = 7;
+  map<int64, int32> int64_to_int32_field = 8;
 }
 
 // Used to test that a nested builder containing map fields will properly
@@ -66,12 +65,18 @@ message TestOnChangeEventPropagation {
 
 // a decoy of TestMap for testing parsing errors
 message BizarroTestMap {
-  map<int32, bytes> int32_to_int32_field = 1; // same key type, different value
-  map<string, int32> int32_to_string_field = 2; // different key and value types
-  map<string, int32> int32_to_bytes_field = 3; // different key types, same value
-  map<string, bytes> int32_to_enum_field = 4; // different key and value types
-  map<string, bytes> int32_to_message_field = 5; // different key and value types
-  map<string, bytes> string_to_int32_field = 6;  // same key type, different value
+  // same key type, different value
+  map<int32, bytes> int32_to_int32_field = 1;
+  // different key and value types
+  map<string, int32> int32_to_string_field = 2;
+  // different key types, same value
+  map<string, int32> int32_to_bytes_field = 3;
+  // different key and value types
+  map<string, bytes> int32_to_enum_field = 4;
+  // different key and value types
+  map<string, bytes> int32_to_message_field = 5;
+  // same key type, different value
+  map<string, bytes> string_to_int32_field = 6;
 }
 
 // Used to test that java reserved words can be used as protobuf field names
@@ -85,11 +90,13 @@ message ReservedAsMapField {
   map<string, uint32> class = 4;
   map<string, uint32> int = 5;
   map<string, uint32> void = 6;
-  map<string, uint32> string = 7; // These are also proto keywords
+  // These are also proto keywords
+  map<string, uint32> string = 7;
   map<string, uint32> package = 8;
-  map<string, uint32> enum = 9; // Most recent Java reserved word
-  map<string, uint32> null = 10;
+  // Most recent Java reserved word
+  map<string, uint32> enum = 9;
   // null is not a 'reserved word' per se but as a literal needs similar care
+  map<string, uint32> null = 10;
 }
 
 message ReservedAsMapFieldWithEnumValue {
@@ -103,9 +110,11 @@ message ReservedAsMapFieldWithEnumValue {
   map<string, SampleEnum> class = 4;
   map<string, SampleEnum> int = 5;
   map<string, SampleEnum> void = 6;
-  map<string, SampleEnum> string = 7; // These are also proto keywords
+  // These are also proto keywords
+  map<string, SampleEnum> string = 7;
   map<string, SampleEnum> package = 8;
-  map<string, SampleEnum> enum = 9; // Most recent Java reserved word
-  map<string, SampleEnum> null = 10;
+  // Most recent Java reserved word
+  map<string, SampleEnum> enum = 9;
   // null is not a 'reserved word' per se but as a literal needs similar care
+  map<string, SampleEnum> null = 10;
 }

+ 29 - 19
java/core/src/test/proto/com/google/protobuf/map_test.proto

@@ -46,14 +46,14 @@ message TestMap {
     QUX = 3;
   }
 
-  map<int32, int32>        int32_to_int32_field = 1;
-  map<int32, string>       int32_to_string_field = 2;
-  map<int32, bytes>        int32_to_bytes_field = 3;
-  map<int32, EnumValue>    int32_to_enum_field = 4;
+  map<int32, int32> int32_to_int32_field = 1;
+  map<int32, string> int32_to_string_field = 2;
+  map<int32, bytes> int32_to_bytes_field = 3;
+  map<int32, EnumValue> int32_to_enum_field = 4;
   map<int32, MessageValue> int32_to_message_field = 5;
-  map<string, int32>       string_to_int32_field = 6;
-  map<uint32, int32>       uint32_to_int32_field = 7;
-  map<int64, int32>        int64_to_int32_field = 8;
+  map<string, int32> string_to_int32_field = 6;
+  map<uint32, int32> uint32_to_int32_field = 7;
+  map<int64, int32> int64_to_int32_field = 8;
 }
 
 // Used to test that a nested builder containing map fields will properly
@@ -65,12 +65,18 @@ message TestOnChangeEventPropagation {
 
 // a decoy of TestMap for testing parsing errors
 message BizarroTestMap {
-  map<int32, bytes> int32_to_int32_field = 1; // same key type, different value
-  map<string, int32> int32_to_string_field = 2; // different key and value types
-  map<string, int32> int32_to_bytes_field = 3; // different key types, same value
-  map<string, bytes> int32_to_enum_field = 4; // different key and value types
-  map<string, bytes> int32_to_message_field = 5; // different key and value types
-  map<string, bytes> string_to_int32_field = 6;  // same key type, different value
+  // same key type, different value
+  map<int32, bytes> int32_to_int32_field = 1;
+  // different key and value types
+  map<string, int32> int32_to_string_field = 2;
+  // different key types, same value
+  map<string, int32> int32_to_bytes_field = 3;
+  // different key and value types
+  map<string, bytes> int32_to_enum_field = 4;
+  // different key and value types
+  map<string, bytes> int32_to_message_field = 5;
+  // same key type, different value
+  map<string, bytes> string_to_int32_field = 6;
 }
 
 // Used to test that java reserved words can be used as protobuf field names
@@ -84,11 +90,13 @@ message ReservedAsMapField {
   map<string, uint32> class = 4;
   map<string, uint32> int = 5;
   map<string, uint32> void = 6;
-  map<string, uint32> string = 7; // These are also proto keywords
+  // These are also proto keywords
+  map<string, uint32> string = 7;
   map<string, uint32> package = 8;
-  map<string, uint32> enum = 9; // Most recent Java reserved word
-  map<string, uint32> null = 10;
+  // Most recent Java reserved word
+  map<string, uint32> enum = 9;
   // null is not a 'reserved word' per se but as a literal needs similar care
+  map<string, uint32> null = 10;
 }
 
 message ReservedAsMapFieldWithEnumValue {
@@ -102,9 +110,11 @@ message ReservedAsMapFieldWithEnumValue {
   map<string, SampleEnum> class = 4;
   map<string, SampleEnum> int = 5;
   map<string, SampleEnum> void = 6;
-  map<string, SampleEnum> string = 7; // These are also proto keywords
+  // These are also proto keywords
+  map<string, SampleEnum> string = 7;
   map<string, SampleEnum> package = 8;
-  map<string, SampleEnum> enum = 9; // Most recent Java reserved word
-  map<string, SampleEnum> null = 10;
+  // Most recent Java reserved word
+  map<string, SampleEnum> enum = 9;
   // null is not a 'reserved word' per se but as a literal needs similar care
+  map<string, SampleEnum> null = 10;
 }

+ 0 - 1
java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto

@@ -37,7 +37,6 @@ package protobuf_unittest;
 option java_multiple_files = true;
 option java_outer_classname = "NestedBuilders";
 
-
 message Vehicle {
   optional Engine engine = 1;
   repeated Wheel wheel = 2;

+ 1 - 3
java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto

@@ -41,10 +41,8 @@ message MessageToBeExtended {
   extensions 1 to max;
 }
 
-message MyNonNestedExtension {
-}
+message MyNonNestedExtension {}
 
 extend MessageToBeExtended {
   optional MyNonNestedExtension nonNestedExtension = 1;
 }
-

+ 1 - 3
java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto

@@ -42,10 +42,8 @@ message MessageLiteToBeExtended {
   extensions 1 to max;
 }
 
-message MyNonNestedExtensionLite {
-}
+message MyNonNestedExtensionLite {}
 
 extend MessageLiteToBeExtended {
   optional MyNonNestedExtensionLite nonNestedExtensionLite = 1;
 }
-

+ 1 - 2
java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto

@@ -36,5 +36,4 @@ package protobuf_unittest;
 // This message's name is the same with the default outer class name of this
 // proto file. It's used to test if the compiler can avoid this conflict
 // correctly.
-message OuterClassNameTest {
-}
+message OuterClassNameTest {}

+ 1 - 2
java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto

@@ -38,7 +38,6 @@ message TestMessage2 {
     // This message's name is the same with the default outer class name of this
     // proto file. It's used to test if the compiler can avoid this conflict
     // correctly.
-    message OuterClassNameTest2 {
-    }
+    message OuterClassNameTest2 {}
   }
 }

+ 1 - 3
java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto

@@ -38,8 +38,6 @@ message TestMessage3 {
     // This enum's name is the same with the default outer class name of this
     // proto file. It's used to test if the compiler can avoid this conflict
     // correctly.
-    enum OuterClassNameTest3 {
-      DUMMY_VALUE = 1;
-    }
+    enum OuterClassNameTest3 { DUMMY_VALUE = 1; }
   }
 }

+ 6 - 0
java/pom.xml

@@ -79,6 +79,12 @@
         <artifactId>guava</artifactId>
         <version>20.0</version>
       </dependency>
+      <dependency>
+        <groupId>com.google.guava</groupId>
+        <artifactId>guava-testlib</artifactId>
+        <version>26.0</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 

+ 5 - 0
java/util/pom.xml

@@ -25,6 +25,11 @@
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
     </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava-testlib</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>com.google.code.gson</groupId>
       <artifactId>gson</artifactId>

+ 143 - 18
java/util/src/main/java/com/google/protobuf/util/Durations.java

@@ -30,6 +30,7 @@
 
 package com.google.protobuf.util;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.math.IntMath.checkedAdd;
 import static com.google.common.math.IntMath.checkedSubtract;
 import static com.google.common.math.LongMath.checkedAdd;
@@ -53,6 +54,10 @@ public final class Durations {
   static final long DURATION_SECONDS_MIN = -315576000000L;
   static final long DURATION_SECONDS_MAX = 315576000000L;
 
+  private static final long SECONDS_PER_MINUTE = 60L;
+  private static final long SECONDS_PER_HOUR = SECONDS_PER_MINUTE * 60;
+  private static final long SECONDS_PER_DAY = SECONDS_PER_HOUR * 24;
+
   /** A constant holding the minimum valid {@link Duration}, approximately {@code -10,000} years. */
   public static final Duration MIN_VALUE =
       Duration.newBuilder().setSeconds(DURATION_SECONDS_MIN).setNanos(-999999999).build();
@@ -118,6 +123,7 @@ public final class Durations {
    * and a positive or negative {@code nanos} field. For durations of one second or more, a non-zero
    * value for the {@code nanos} field must be of the same sign as the {@code seconds} field.
    */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static boolean isValid(long seconds, int nanos) {
     if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
       return false;
@@ -133,6 +139,39 @@ public final class Durations {
     return true;
   }
 
+  /** Returns whether the given {@link Duration} is negative or not. */
+  public static boolean isNegative(Duration duration) {
+    checkValid(duration);
+    return (duration.getSeconds() == 0) ? duration.getNanos() < 0 : duration.getSeconds() < 0;
+  }
+
+  /**
+   * Ensures that the given {@link Duration} is not negative.
+   *
+   * @throws IllegalArgumentException if {@code duration} is negative or invalid
+   * @throws NullPointerException if {@code duration} is {@code null}
+   */
+  public static Duration checkNotNegative(Duration duration) {
+    checkValid(duration);
+    checkArgument(!isNegative(duration), "duration (%s) must not be negative", toString(duration));
+    return duration;
+  }
+
+  /**
+   * Ensures that the given {@link Duration} is positive.
+   *
+   * @throws IllegalArgumentException if {@code duration} is negative, {@code ZERO}, or invalid
+   * @throws NullPointerException if {@code duration} is {@code null}
+   */
+  public static Duration checkPositive(Duration duration) {
+    checkValid(duration);
+    checkArgument(
+        !isNegative(duration) && !duration.equals(ZERO),
+        "duration (%s) must be positive",
+        toString(duration));
+    return duration;
+  }
+
   /** Throws an {@link IllegalArgumentException} if the given {@link Duration} is not valid. */
   public static Duration checkValid(Duration duration) {
     long seconds = duration.getSeconds();
@@ -216,30 +255,125 @@ public final class Durations {
     }
   }
 
+  // Static factories
+
+  /** Create a Duration from the number of days. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
+  public static Duration fromDays(long days) {
+    return Duration.newBuilder()
+        .setSeconds(checkedMultiply(days, SECONDS_PER_DAY))
+        .setNanos(0)
+        .build();
+  }
+
+  /** Create a Duration from the number of hours. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
+  public static Duration fromHours(long hours) {
+    return Duration.newBuilder()
+        .setSeconds(checkedMultiply(hours, SECONDS_PER_HOUR))
+        .setNanos(0)
+        .build();
+  }
+
+  /** Create a Duration from the number of minutes. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
+  public static Duration fromMinutes(long minutes) {
+    return Duration.newBuilder()
+        .setSeconds(checkedMultiply(minutes, SECONDS_PER_MINUTE))
+        .setNanos(0)
+        .build();
+  }
+
   /** Create a Duration from the number of seconds. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static Duration fromSeconds(long seconds) {
     return normalizedDuration(seconds, 0);
   }
 
+  /** Create a Duration from the number of milliseconds. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
+  public static Duration fromMillis(long milliseconds) {
+    return normalizedDuration(
+        milliseconds / MILLIS_PER_SECOND,
+        (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
+  }
+
+  /** Create a Duration from the number of microseconds. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
+  public static Duration fromMicros(long microseconds) {
+    return normalizedDuration(
+        microseconds / MICROS_PER_SECOND,
+        (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
+  }
+
+  /** Create a Duration from the number of nanoseconds. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
+  public static Duration fromNanos(long nanoseconds) {
+    return normalizedDuration(
+        nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND));
+  }
+
+  // Conversion APIs
+
+  /**
+   * Convert a Duration to the number of days. The result will be rounded towards 0 to the nearest
+   * day.
+   */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
+  public static long toDays(Duration duration) {
+    return checkValid(duration).getSeconds() / SECONDS_PER_DAY;
+  }
+
+  /**
+   * Convert a Duration to the number of hours. The result will be rounded towards 0 to the nearest
+   * hour.
+   */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
+  public static long toHours(Duration duration) {
+    return checkValid(duration).getSeconds() / SECONDS_PER_HOUR;
+  }
+
+  /**
+   * Convert a Duration to the number of minutes. The result will be rounded towards 0 to the
+   * nearest minute.
+   */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
+  public static long toMinutes(Duration duration) {
+    return checkValid(duration).getSeconds() / SECONDS_PER_MINUTE;
+  }
+
   /**
    * Convert a Duration to the number of seconds. The result will be rounded towards 0 to the
    * nearest second. E.g., if the duration represents -1 nanosecond, it will be rounded to 0.
    */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static long toSeconds(Duration duration) {
     return checkValid(duration).getSeconds();
   }
 
-  /** Create a Duration from the number of milliseconds. */
-  public static Duration fromMillis(long milliseconds) {
-    return normalizedDuration(
-        milliseconds / MILLIS_PER_SECOND,
-        (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
+  /**
+   * Returns the number of seconds of the given duration as a {@code double}. This method should be
+   * used to accommodate APIs that <b>only</b> accept durations as {@code double} values.
+   *
+   * <p>This conversion may lose precision.
+   *
+   * <p>If you need the number of seconds in this duration as a {@code long} (not a {@code double}),
+   * simply use {@code duration.getSeconds()} or {@link #toSeconds} (which includes validation).
+   */
+  @SuppressWarnings({
+    "DurationSecondsToDouble", // that's the whole point of this method
+    "GoodTime" // this is a legacy conversion API
+  })
+  public static double toSecondsAsDouble(Duration duration) {
+    checkValid(duration);
+    return duration.getSeconds() + duration.getNanos() / 1e9;
   }
 
   /**
    * Convert a Duration to the number of milliseconds. The result will be rounded towards 0 to the
    * nearest millisecond. E.g., if the duration represents -1 nanosecond, it will be rounded to 0.
    */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static long toMillis(Duration duration) {
     checkValid(duration);
     return checkedAdd(
@@ -247,17 +381,11 @@ public final class Durations {
         duration.getNanos() / NANOS_PER_MILLISECOND);
   }
 
-  /** Create a Duration from the number of microseconds. */
-  public static Duration fromMicros(long microseconds) {
-    return normalizedDuration(
-        microseconds / MICROS_PER_SECOND,
-        (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
-  }
-
   /**
    * Convert a Duration to the number of microseconds. The result will be rounded towards 0 to the
    * nearest microseconds. E.g., if the duration represents -1 nanosecond, it will be rounded to 0.
    */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static long toMicros(Duration duration) {
     checkValid(duration);
     return checkedAdd(
@@ -265,19 +393,16 @@ public final class Durations {
         duration.getNanos() / NANOS_PER_MICROSECOND);
   }
 
-  /** Create a Duration from the number of nanoseconds. */
-  public static Duration fromNanos(long nanoseconds) {
-    return normalizedDuration(
-        nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND));
-  }
-
   /** Convert a Duration to the number of nanoseconds. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static long toNanos(Duration duration) {
     checkValid(duration);
     return checkedAdd(
         checkedMultiply(duration.getSeconds(), NANOS_PER_SECOND), duration.getNanos());
   }
 
+  // Math operations
+
   /** Add two durations. */
   public static Duration add(Duration d1, Duration d2) {
     checkValid(d1);

+ 73 - 11
java/util/src/main/java/com/google/protobuf/util/JsonFormat.java

@@ -77,7 +77,9 @@ import java.io.StringReader;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.text.ParseException;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -106,7 +108,7 @@ public class JsonFormat {
   public static Printer printer() {
     return new Printer(
         TypeRegistry.getEmptyTypeRegistry(), false, Collections.<FieldDescriptor>emptySet(),
-        false, false, false);
+        false, false, false, false);
   }
 
   /**
@@ -127,6 +129,7 @@ public class JsonFormat {
     private final boolean preservingProtoFieldNames;
     private final boolean omittingInsignificantWhitespace;
     private final boolean printingEnumsAsInts;
+    private final boolean sortingMapKeys;
 
     private Printer(
         TypeRegistry registry,
@@ -134,13 +137,15 @@ public class JsonFormat {
         Set<FieldDescriptor> includingDefaultValueFields,
         boolean preservingProtoFieldNames,
         boolean omittingInsignificantWhitespace,
-        boolean printingEnumsAsInts) {
+        boolean printingEnumsAsInts,
+        boolean sortingMapKeys) {
       this.registry = registry;
       this.alwaysOutputDefaultValueFields = alwaysOutputDefaultValueFields;
       this.includingDefaultValueFields = includingDefaultValueFields;
       this.preservingProtoFieldNames = preservingProtoFieldNames;
       this.omittingInsignificantWhitespace = omittingInsignificantWhitespace;
       this.printingEnumsAsInts = printingEnumsAsInts;
+      this.sortingMapKeys = sortingMapKeys;
     }
 
     /**
@@ -159,7 +164,8 @@ public class JsonFormat {
           includingDefaultValueFields,
           preservingProtoFieldNames,
           omittingInsignificantWhitespace,
-          printingEnumsAsInts);
+          printingEnumsAsInts,
+          sortingMapKeys);
     }
 
     /**
@@ -176,7 +182,8 @@ public class JsonFormat {
           Collections.<FieldDescriptor>emptySet(),
           preservingProtoFieldNames,
           omittingInsignificantWhitespace,
-          printingEnumsAsInts);
+          printingEnumsAsInts,
+          sortingMapKeys);
     }
 
     /**
@@ -193,7 +200,8 @@ public class JsonFormat {
           Collections.<FieldDescriptor>emptySet(),
           preservingProtoFieldNames,
           omittingInsignificantWhitespace,
-          true);
+          true,
+          sortingMapKeys);
     }
 
     private void checkUnsetPrintingEnumsAsInts() {
@@ -221,7 +229,8 @@ public class JsonFormat {
           fieldsToAlwaysOutput,
           preservingProtoFieldNames,
           omittingInsignificantWhitespace,
-          printingEnumsAsInts);
+          printingEnumsAsInts,
+          sortingMapKeys);
     }
 
     private void checkUnsetIncludingDefaultValueFields() {
@@ -244,7 +253,8 @@ public class JsonFormat {
           includingDefaultValueFields,
           true,
           omittingInsignificantWhitespace,
-          printingEnumsAsInts);
+          printingEnumsAsInts,
+          sortingMapKeys);
     }
 
 
@@ -272,7 +282,31 @@ public class JsonFormat {
           includingDefaultValueFields,
           preservingProtoFieldNames,
           true,
-          printingEnumsAsInts);
+          printingEnumsAsInts,
+          sortingMapKeys);
+    }
+
+    /**
+     * Create a new {@link Printer} that will sort the map keys in the JSON output.
+     *
+     * Use of this modifier is discouraged, the generated JSON messages are equivalent
+     * with and without this option set, but there are some corner caseuse cases that
+     * demand a stable output, while order of map keys is otherwise arbitrary.
+     *
+     * The generated order is not well-defined and should not be depended on, but
+     * it's stable.
+     *
+     * This new Printer clones all other configurations from the current {@link Printer}.
+     */
+    public Printer sortingMapKeys() {
+      return new Printer(
+          registry,
+          alwaysOutputDefaultValueFields,
+          includingDefaultValueFields,
+          preservingProtoFieldNames,
+          omittingInsignificantWhitespace,
+          printingEnumsAsInts,
+          true);
     }
 
     /**
@@ -292,7 +326,8 @@ public class JsonFormat {
               preservingProtoFieldNames,
               output,
               omittingInsignificantWhitespace,
-              printingEnumsAsInts)
+              printingEnumsAsInts,
+              sortingMapKeys)
           .print(message);
     }
 
@@ -604,6 +639,7 @@ public class JsonFormat {
     private final Set<FieldDescriptor> includingDefaultValueFields;
     private final boolean preservingProtoFieldNames;
     private final boolean printingEnumsAsInts;
+    private final boolean sortingMapKeys;
     private final TextGenerator generator;
     // We use Gson to help handle string escapes.
     private final Gson gson;
@@ -621,12 +657,14 @@ public class JsonFormat {
         boolean preservingProtoFieldNames,
         Appendable jsonOutput,
         boolean omittingInsignificantWhitespace,
-        boolean printingEnumsAsInts) {
+        boolean printingEnumsAsInts,
+        boolean sortingMapKeys) {
       this.registry = registry;
       this.alwaysOutputDefaultValueFields = alwaysOutputDefaultValueFields;
       this.includingDefaultValueFields = includingDefaultValueFields;
       this.preservingProtoFieldNames = preservingProtoFieldNames;
       this.printingEnumsAsInts = printingEnumsAsInts;
+      this.sortingMapKeys = sortingMapKeys;
       this.gson = GsonHolder.DEFAULT_GSON;
       // json format related properties, determined by printerType
       if (omittingInsignificantWhitespace) {
@@ -957,8 +995,32 @@ public class JsonFormat {
       }
       generator.print("{" + blankOrNewLine);
       generator.indent();
+
+      @SuppressWarnings("unchecked") // Object guaranteed to be a List for a map field.
+      Collection<Object> elements = (List<Object>) value;
+      if (sortingMapKeys && !elements.isEmpty()) {
+        Comparator<Object> cmp = null;
+        if (keyField.getType() == FieldDescriptor.Type.STRING) {
+          cmp = new Comparator<Object>() {
+            @Override
+            public int compare(final Object o1, final Object o2) {
+              ByteString s1 = ByteString.copyFromUtf8((String) o1);
+              ByteString s2 = ByteString.copyFromUtf8((String) o2);
+              return ByteString.unsignedLexicographicalComparator().compare(s1, s2);
+            }
+          };
+        }
+        TreeMap<Object, Object> tm = new TreeMap<Object, Object>(cmp);
+        for (Object element : elements) {
+          Message entry = (Message) element;
+          Object entryKey = entry.getField(keyField);
+          tm.put(entryKey, element);
+        }
+        elements = tm.values();
+      }
+
       boolean printedElement = false;
-      for (Object element : (List) value) {
+      for (Object element : elements) {
         Message entry = (Message) element;
         Object entryKey = entry.getField(keyField);
         Object entryValue = entry.getField(valueField);

+ 1 - 0
java/util/src/main/java/com/google/protobuf/util/TimeUtil.java

@@ -325,6 +325,7 @@ public final class TimeUtil {
   // Multiplications and divisions.
 
   // TODO(kak): Delete this.
+  @SuppressWarnings("DurationSecondsToDouble")
   public static Duration multiply(Duration duration, double times) {
     double result = duration.getSeconds() * times + duration.getNanos() * times / 1000000000.0;
     if (result < Long.MIN_VALUE || result > Long.MAX_VALUE) {

+ 9 - 0
java/util/src/main/java/com/google/protobuf/util/Timestamps.java

@@ -150,6 +150,7 @@ public final class Timestamps {
    * <p><b>Note:</b> Negative second values with fractional seconds must still have non-negative
    * nanos values that count forward in time.
    */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static boolean isValid(long seconds, int nanos) {
     if (seconds < TIMESTAMP_SECONDS_MIN || seconds > TIMESTAMP_SECONDS_MAX) {
       return false;
@@ -266,6 +267,7 @@ public final class Timestamps {
   }
 
   /** Create a Timestamp from the number of seconds elapsed from the epoch. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static Timestamp fromSeconds(long seconds) {
     return normalizedTimestamp(seconds, 0);
   }
@@ -276,11 +278,13 @@ public final class Timestamps {
    * <p>The result will be rounded down to the nearest second. E.g., if the timestamp represents
    * "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 second.
    */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static long toSeconds(Timestamp timestamp) {
     return checkValid(timestamp).getSeconds();
   }
 
   /** Create a Timestamp from the number of milliseconds elapsed from the epoch. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static Timestamp fromMillis(long milliseconds) {
     return normalizedTimestamp(
         milliseconds / MILLIS_PER_SECOND,
@@ -293,6 +297,7 @@ public final class Timestamps {
    * <p>The result will be rounded down to the nearest millisecond. E.g., if the timestamp
    * represents "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 millisecond.
    */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static long toMillis(Timestamp timestamp) {
     checkValid(timestamp);
     return checkedAdd(
@@ -301,6 +306,7 @@ public final class Timestamps {
   }
 
   /** Create a Timestamp from the number of microseconds elapsed from the epoch. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static Timestamp fromMicros(long microseconds) {
     return normalizedTimestamp(
         microseconds / MICROS_PER_SECOND,
@@ -313,6 +319,7 @@ public final class Timestamps {
    * <p>The result will be rounded down to the nearest microsecond. E.g., if the timestamp
    * represents "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 microsecond.
    */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static long toMicros(Timestamp timestamp) {
     checkValid(timestamp);
     return checkedAdd(
@@ -321,12 +328,14 @@ public final class Timestamps {
   }
 
   /** Create a Timestamp from the number of nanoseconds elapsed from the epoch. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static Timestamp fromNanos(long nanoseconds) {
     return normalizedTimestamp(
         nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND));
   }
 
   /** Convert a Timestamp to the number of nanoseconds elapsed from the epoch. */
+  @SuppressWarnings("GoodTime") // this is a legacy conversion API
   public static long toNanos(Timestamp timestamp) {
     checkValid(timestamp);
     return checkedAdd(

+ 49 - 0
java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java

@@ -156,6 +156,9 @@ public class JsonFormatTest extends TestCase {
   private String toCompactJsonString(Message message) throws IOException {
     return JsonFormat.printer().omittingInsignificantWhitespace().print(message);
   }
+  private String toSortedJsonString(Message message) throws IOException {
+    return JsonFormat.printer().sortingMapKeys().print(message);
+  }
 
   private void mergeFromJson(String json, Message.Builder builder) throws IOException {
     JsonFormat.parser().merge(json, builder);
@@ -1635,4 +1638,50 @@ public class JsonFormatTest extends TestCase {
       // Expected.
     }
   }
+
+  public void testSortedMapKeys() throws Exception {
+    TestMap.Builder mapBuilder = TestMap.newBuilder();
+    mapBuilder.putStringToInt32Map("\ud834\udd20", 3); // utf-8 F0 9D 84 A0
+    mapBuilder.putStringToInt32Map("foo", 99);
+    mapBuilder.putStringToInt32Map("xxx", 123);
+    mapBuilder.putStringToInt32Map("\u20ac", 1);  // utf-8 E2 82 AC
+    mapBuilder.putStringToInt32Map("abc", 20);
+    mapBuilder.putStringToInt32Map("19", 19);
+    mapBuilder.putStringToInt32Map("8", 8);
+    mapBuilder.putStringToInt32Map("\ufb00", 2);  // utf-8 EF AC 80
+    mapBuilder.putInt32ToInt32Map(3, 3);
+    mapBuilder.putInt32ToInt32Map(10, 10);
+    mapBuilder.putInt32ToInt32Map(5, 5);
+    mapBuilder.putInt32ToInt32Map(4, 4);
+    mapBuilder.putInt32ToInt32Map(1, 1);
+    mapBuilder.putInt32ToInt32Map(2, 2);
+    mapBuilder.putInt32ToInt32Map(-3, -3);
+    TestMap mapMessage = mapBuilder.build();
+    assertEquals(
+        "{\n"
+            + "  \"int32ToInt32Map\": {\n"
+            + "    \"-3\": -3,\n"
+            + "    \"1\": 1,\n"
+            + "    \"2\": 2,\n"
+            + "    \"3\": 3,\n"
+            + "    \"4\": 4,\n"
+            + "    \"5\": 5,\n"
+            + "    \"10\": 10\n"
+            + "  },\n"
+            + "  \"stringToInt32Map\": {\n"
+            + "    \"19\": 19,\n"
+            + "    \"8\": 8,\n"
+            + "    \"abc\": 20,\n"
+            + "    \"foo\": 99,\n"
+            + "    \"xxx\": 123,\n"
+            + "    \"\u20ac\": 1,\n"
+            + "    \"\ufb00\": 2,\n"
+            + "    \"\ud834\udd20\": 3\n"
+            + "  }\n"
+            + "}",
+        toSortedJsonString(mapMessage));
+
+    TestMap emptyMap = TestMap.getDefaultInstance();
+    assertEquals("{\n}", toSortedJsonString(emptyMap));
+  }
 }

+ 1 - 0
js/binary/proto_test.js

@@ -659,5 +659,6 @@ describe('protoBinaryTest', function() {
         'jspb.test.TestAllTypes');
 
     checkAllFields(msg, msg2);
+
   });
 });

+ 11 - 0
js/debug.js

@@ -37,6 +37,7 @@ goog.provide('jspb.debug');
 goog.require('goog.array');
 goog.require('goog.asserts');
 goog.require('goog.object');
+goog.require('jspb.Map');
 goog.require('jspb.Message');
 
 
@@ -90,6 +91,16 @@ jspb.debug.dump_ = function(thing) {
     goog.asserts.assertArray(thing);
     return goog.array.map(thing, jspb.debug.dump_);
   }
+
+  if (message instanceof jspb.Map) {
+    var mapObject = {};
+    var entries = message.entries();
+    for (var entry = entries.next(); !entry.done; entry = entries.next()) {
+      mapObject[entry.value[0]] = jspb.debug.dump_(entry.value[1]);
+    }
+    return mapObject;
+  }
+
   goog.asserts.assert(message instanceof jspb.Message,
       'Only messages expected: ' + thing);
   var ctor = message.constructor;

+ 72 - 0
js/debug_test.js

@@ -38,7 +38,9 @@ goog.require('jspb.debug');
 // CommonJS-LoadFromFile: test_pb
 goog.require('proto.jspb.test.HasExtensions');
 goog.require('proto.jspb.test.IsExtension');
+goog.require('proto.jspb.test.MapValueMessageNoBinary');
 goog.require('proto.jspb.test.Simple1');
+goog.require('proto.jspb.test.TestMapFieldsNoBinary');
 
 
 // CommonJS-LoadFromFile: testbinary_pb
@@ -113,4 +115,74 @@ describe('debugTest', function() {
     }, jspb.debug.dump(extendable));
   });
 
+  it('testMapsBasicTypes', function() {
+    if (COMPILED) {
+      return;
+    }
+
+    var message = new proto.jspb.test.TestMapFieldsNoBinary();
+    message.getMapBoolStringMap().set(true, 'bool_string_value1');
+    message.getMapBoolStringMap().set(false, 'bool_string_value2');
+    message.getMapStringInt32Map().set('key', 111);
+
+    assertObjectEquals({
+      '$name': 'proto.jspb.test.TestMapFieldsNoBinary',
+      'mapBoolStringMap': {
+        true: 'bool_string_value1',
+        false: 'bool_string_value2'
+      },
+      'mapInt32StringMap': {},
+      'mapInt64StringMap': {},
+      'mapStringBoolMap': {},
+      'mapStringDoubleMap': {},
+      'mapStringEnumMap': {},
+      'mapStringInt32Map': {
+        'key': 111
+      },
+      'mapStringInt64Map': {},
+      'mapStringMsgMap': {},
+      'mapStringStringMap': {},
+      'mapStringTestmapfieldsMap': {}
+    }, jspb.debug.dump(message));
+  });
+
+  it('testMapsMessageValues', function() {
+    if (COMPILED) {
+      return;
+    }
+
+    var value1 = new proto.jspb.test.MapValueMessageNoBinary();
+    value1.setFoo(1111);
+    var value2 = new proto.jspb.test.MapValueMessageNoBinary();
+    value2.setFoo(2222);
+
+    var message = new proto.jspb.test.TestMapFieldsNoBinary();
+    message.getMapStringMsgMap().set('key1', value1);
+    message.getMapStringMsgMap().set('key2', value2);
+
+    assertObjectEquals({
+      '$name': 'proto.jspb.test.TestMapFieldsNoBinary',
+      'mapBoolStringMap': {},
+      'mapInt32StringMap': {},
+      'mapInt64StringMap': {},
+      'mapStringBoolMap': {},
+      'mapStringDoubleMap': {},
+      'mapStringEnumMap': {},
+      'mapStringInt32Map': {},
+      'mapStringInt64Map': {},
+      'mapStringMsgMap': {
+        'key1': {
+          '$name': 'proto.jspb.test.MapValueMessageNoBinary',
+          'foo': 1111
+        },
+        'key2': {
+          '$name': 'proto.jspb.test.MapValueMessageNoBinary',
+          'foo': 2222
+        }
+      },
+      'mapStringStringMap': {},
+      'mapStringTestmapfieldsMap': {}
+    }, jspb.debug.dump(message));
+  });
+
 });

+ 21 - 3
js/maps_test.js

@@ -340,11 +340,17 @@ function makeTests(msgInfo, submessageCtor, suffix) {
     assertElementsEquals(entryIterator.next().value, ['key2', 'value2']);
     assertEquals(entryIterator.next().done, true);
 
-    if (typeof(Symbol) != 'undefined') {
+    try {
       var entryIterable = m.entries()[Symbol.iterator]();
       assertElementsEquals(entryIterable.next().value, ['key1', 'value1']);
       assertElementsEquals(entryIterable.next().value, ['key2', 'value2']);
       assertEquals(entryIterable.next().done, true);
+    } catch (err) {
+      // jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] may be
+      // undefined in some environment.
+      if (err.name != 'TypeError' && err.name != 'ReferenceError') {
+        throw err;
+      }
     }
 
     var keyIterator = m.keys();
@@ -352,22 +358,34 @@ function makeTests(msgInfo, submessageCtor, suffix) {
     assertEquals(keyIterator.next().value, 'key2');
     assertEquals(keyIterator.next().done, true);
 
-    if (typeof(Symbol) != 'undefined') {
+    try {
       var keyIterable = m.keys()[Symbol.iterator]();
       assertEquals(keyIterable.next().value, 'key1');
       assertEquals(keyIterable.next().value, 'key2');
       assertEquals(keyIterable.next().done, true);
+    } catch (err) {
+      // jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] may be
+      // undefined in some environment.
+      if (err.name != 'TypeError' && err.name != 'ReferenceError') {
+        throw err;
+      }
     }
     var valueIterator = m.values();
     assertEquals(valueIterator.next().value, 'value1');
     assertEquals(valueIterator.next().value, 'value2');
     assertEquals(valueIterator.next().done, true);
 
-    if (typeof(Symbol) != 'undefined') {
+    try {
       var valueIterable = m.values()[Symbol.iterator]();
       assertEquals(valueIterable.next().value, 'value1');
       assertEquals(valueIterable.next().value, 'value2');
       assertEquals(valueIterable.next().done, true);
+    } catch (err) {
+      // jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] may be
+      // undefined in some environment.
+      if (err.name != 'TypeError' && err.name != 'ReferenceError') {
+        throw err;
+      }
     }
   });
 }

+ 19 - 7
js/message.js

@@ -427,6 +427,24 @@ jspb.Message.isArray_ = function(o) {
                                             goog.isArray(o);
 };
 
+/**
+ * Returns true if the provided argument is an extension object.
+ * @param {*} o The object to classify as array or not.
+ * @return {boolean} True if the provided object is an extension object.
+ * @private
+ */
+jspb.Message.isExtensionObject_ = function(o) {
+  // Normal fields are never objects, so we can be sure that if we find an
+  // object here, then it's the extension object. However, we must ensure that
+  // the object is not an array, since arrays are valid field values (bytes
+  // fields can also be array).
+  // NOTE(lukestebbing): We avoid looking at .length to avoid a JIT bug
+  // in Safari on iOS 8. See the description of CL/86511464 for details.
+  return (o !== null && typeof o == 'object' &&
+      !jspb.Message.isArray_(o) &&
+      !(jspb.Message.SUPPORTS_UINT8ARRAY_ && o instanceof Uint8Array));
+};
+
 
 /**
  * If the array contains an extension object in its last position, then the
@@ -452,13 +470,7 @@ jspb.Message.initPivotAndExtensionObject_ = function(msg, suggestedPivot) {
   if (msgLength) {
     lastIndex = msgLength - 1;
     var obj = msg.array[lastIndex];
-    // Normal fields are never objects, so we can be sure that if we find an
-    // object here, then it's the extension object. However, we must ensure that
-    // the object is not an array, since arrays are valid field values.
-    // NOTE(lukestebbing): We avoid looking at .length to avoid a JIT bug
-    // in Safari on iOS 8. See the description of CL/86511464 for details.
-    if (obj && typeof obj == 'object' && !jspb.Message.isArray_(obj) &&
-        !(jspb.Message.SUPPORTS_UINT8ARRAY_ && obj instanceof Uint8Array)) {
+    if (jspb.Message.isExtensionObject_(obj)) {
       msg.pivot_ = jspb.Message.getFieldNumber_(msg, lastIndex);
       msg.extensionObject_ = obj;
       return;

+ 201 - 270
js/message_test.js

@@ -33,7 +33,6 @@
 goog.setTestOnly();
 
 goog.require('goog.json');
-goog.require('goog.string');
 goog.require('goog.testing.PropertyReplacer');
 goog.require('goog.testing.asserts');
 goog.require('goog.userAgent');
@@ -41,6 +40,38 @@ goog.require('goog.userAgent');
 // CommonJS-LoadFromFile: google-protobuf jspb
 goog.require('jspb.Message');
 
+// CommonJS-LoadFromFile: test15_pb proto.jspb.filenametest.package1
+goog.require('proto.jspb.filenametest.package1.b');
+
+// CommonJS-LoadFromFile: test14_pb proto.jspb.filenametest.package2
+goog.require('proto.jspb.filenametest.package2.TestMessage');
+
+// CommonJS-LoadFromFile: test13_pb proto.jspb.filenametest.package1
+goog.require('proto.jspb.filenametest.package1.a');
+goog.require('proto.jspb.filenametest.package1.TestMessage');
+
+// CommonJS-LoadFromFile: test12_pb proto.jspb.circulartest
+goog.require('proto.jspb.circulartest.ExtensionContainingType1');
+goog.require('proto.jspb.circulartest.ExtensionContainingType2');
+goog.require('proto.jspb.circulartest.ExtensionField1');
+goog.require('proto.jspb.circulartest.ExtensionField2');
+goog.require('proto.jspb.circulartest.ExtensionField3');
+goog.require('proto.jspb.circulartest.MapField1');
+goog.require('proto.jspb.circulartest.MapField2');
+goog.require('proto.jspb.circulartest.MessageField1');
+goog.require('proto.jspb.circulartest.MessageField2');
+goog.require('proto.jspb.circulartest.NestedEnum1');
+goog.require('proto.jspb.circulartest.NestedEnum2');
+goog.require('proto.jspb.circulartest.NestedMessage1');
+goog.require('proto.jspb.circulartest.NestedMessage2');
+goog.require('proto.jspb.circulartest.RepeatedMessageField1');
+goog.require('proto.jspb.circulartest.RepeatedMessageField2');
+
+// CommonJS-LoadFromFile: test11_pb proto.jspb.exttest.reverse
+goog.require('proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1');
+goog.require('proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage2');
+goog.require('proto.jspb.exttest.reverse.c');
+
 // CommonJS-LoadFromFile: test8_pb proto.jspb.exttest.nested
 goog.require('proto.jspb.exttest.nested.TestNestedExtensionsMessage');
 goog.require('proto.jspb.exttest.nested.TestOuterMessage');
@@ -77,6 +108,7 @@ goog.require('proto.jspb.test.TestCloneExtension');
 goog.require('proto.jspb.test.TestEndsWithBytes');
 goog.require('proto.jspb.test.TestGroup');
 goog.require('proto.jspb.test.TestGroup1');
+goog.require('proto.jspb.test.TestLastFieldBeforePivot');
 goog.require('proto.jspb.test.TestMessageWithOneof');
 goog.require('proto.jspb.test.TestReservedNames');
 goog.require('proto.jspb.test.TestReservedNamesExtension');
@@ -284,42 +316,6 @@ describe('Message test suite', function() {
     assertFalse(response.hasEnumField());
   });
 
-  it('testClearFields', function() {
-    var data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
-    var foo = new proto.jspb.test.OptionalFields(data);
-    foo.clearAString();
-    foo.clearABool();
-    foo.clearANestedMessage();
-    foo.clearARepeatedMessageList();
-    foo.clearARepeatedStringList();
-    assertEquals('', foo.getAString());
-    assertEquals(false, foo.getABool());
-    assertUndefined(foo.getANestedMessage());
-    assertFalse(foo.hasAString());
-    assertFalse(foo.hasABool());
-    assertObjectEquals([], foo.getARepeatedMessageList());
-    assertObjectEquals([], foo.getARepeatedStringList());
-    // NOTE: We want the missing fields in 'expected' to be undefined,
-    // but we actually get a sparse array instead. We could use something
-    // like [1,undefined,2] to avoid this, except that this is still
-    // sparse on IE. No comment...
-    var expected = [,,, [], []];
-    expected[0] = expected[1] = expected[2] = undefined;
-    assertObjectEquals(expected, foo.toArray());
-  });
-
-  it('testDifferenceRawObject', /** @suppress {visibility} */ function() {
-    var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]);
-    var p2 = new proto.jspb.test.HasExtensions(['hi', 'what',
-                                               {1000: 'unique'}]);
-    var diff = /** @type {proto.jspb.test.HasExtensions} */
-        (jspb.Message.difference(p1, p2));
-    assertEquals('', diff.getStr1());
-    assertEquals('what', diff.getStr2());
-    assertEquals('', diff.getStr3());
-    assertEquals('unique', diff.extensionObject_[1000]);
-  });
-
   it('testEqualsSimple', function() {
     var s1 = new proto.jspb.test.Simple1(['hi']);
     assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi'])));
@@ -419,6 +415,12 @@ describe('Message test suite', function() {
         ['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
   });
 
+  it('testInitializeMessageWithLastFieldNull', function() {
+    // This tests for regression to bug http://b/117298778
+    var msg = new proto.jspb.test.TestLastFieldBeforePivot([null]);
+    assertNotUndefined(msg.getLastFieldBeforePivot());
+  });
+
   it('testEqualsNonFinite', function() {
     assertTrue(jspb.Message.compareFields(NaN, NaN));
     assertTrue(jspb.Message.compareFields(NaN, 'NaN'));
@@ -787,71 +789,6 @@ describe('Message test suite', function() {
         message.getRecursiveOneofCase());
   });
 
-  it('testInitializeMessageWithSingleValueSetInOneof', function() {
-    var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']);
-
-    assertEquals('x', message.getPone());
-    assertEquals('', message.getPthree());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
-        message.getPartialOneofCase());
-  });
-
-  it('testKeepsLastWireValueSetInUnion_multipleValues', function() {
-    var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']);
-
-    assertEquals('', message.getPone());
-    assertEquals('y', message.getPthree());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
-        message.getPartialOneofCase());
-  });
-
-  it('testSettingOneofFieldClearsOthers', function() {
-    var message = new proto.jspb.test.TestMessageWithOneof;
-    assertEquals('', message.getPone());
-    assertEquals('', message.getPthree());
-    assertFalse(message.hasPone());
-    assertFalse(message.hasPthree());
-
-    message.setPone('hi');
-    assertEquals('hi', message.getPone());
-    assertEquals('', message.getPthree());
-    assertTrue(message.hasPone());
-    assertFalse(message.hasPthree());
-
-    message.setPthree('bye');
-    assertEquals('', message.getPone());
-    assertEquals('bye', message.getPthree());
-    assertFalse(message.hasPone());
-    assertTrue(message.hasPthree());
-  });
-
-  it('testSettingOneofFieldDoesNotClearFieldsFromOtherUnions', function() {
-    var other = new proto.jspb.test.TestMessageWithOneof;
-    var message = new proto.jspb.test.TestMessageWithOneof;
-    assertEquals('', message.getPone());
-    assertEquals('', message.getPthree());
-    assertUndefined(message.getRone());
-    assertFalse(message.hasPone());
-    assertFalse(message.hasPthree());
-
-    message.setPone('hi');
-    message.setRone(other);
-    assertEquals('hi', message.getPone());
-    assertEquals('', message.getPthree());
-    assertEquals(other, message.getRone());
-    assertTrue(message.hasPone());
-    assertFalse(message.hasPthree());
-
-    message.setPthree('bye');
-    assertEquals('', message.getPone());
-    assertEquals('bye', message.getPthree());
-    assertEquals(other, message.getRone());
-    assertFalse(message.hasPone());
-    assertTrue(message.hasPthree());
-  });
-
   it('testUnsetsOneofCaseWhenFieldIsCleared', function() {
     var message = new proto.jspb.test.TestMessageWithOneof;
     assertEquals(
@@ -871,198 +808,192 @@ describe('Message test suite', function() {
         message.getPartialOneofCase());
   });
 
-  it('testMessageWithDefaultOneofValues', function() {
-    var message = new proto.jspb.test.TestMessageWithOneof;
-    assertEquals(1234, message.getAone());
-    assertEquals(0, message.getAtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
-            .DEFAULT_ONEOF_A_NOT_SET,
-        message.getDefaultOneofACase());
+  it('testFloatingPointFieldsSupportNan', function() {
+    var assertNan = function(x) {
+      assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
+          goog.isNumber(x) && isNaN(x));
+    };
 
-    message.setAone(567);
-    assertEquals(567, message.getAone());
-    assertEquals(0, message.getAtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
-        message.getDefaultOneofACase());
+    var message = new proto.jspb.test.FloatingPointFields([
+      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN',
+      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
+    ]);
+    assertNan(message.getOptionalFloatField());
+    assertNan(message.getRequiredFloatField());
+    assertNan(message.getRepeatedFloatFieldList()[0]);
+    assertNan(message.getRepeatedFloatFieldList()[1]);
+    assertNan(message.getDefaultFloatField());
+    assertNan(message.getOptionalDoubleField());
+    assertNan(message.getRequiredDoubleField());
+    assertNan(message.getRepeatedDoubleFieldList()[0]);
+    assertNan(message.getRepeatedDoubleFieldList()[1]);
+    assertNan(message.getDefaultDoubleField());
+  });
 
-    message.setAtwo(890);
-    assertEquals(1234, message.getAone());
-    assertEquals(890, message.getAtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
-        message.getDefaultOneofACase());
+  it('testExtensionReverseOrder', function() {
+    var message2 =
+        new proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage2;
 
-    message.clearAtwo();
-    assertEquals(1234, message.getAone());
-    assertEquals(0, message.getAtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
-            .DEFAULT_ONEOF_A_NOT_SET,
-        message.getDefaultOneofACase());
-  });
+    message2.setExtension(
+        proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1.a, 233);
+    message2.setExtension(
+        proto
+            .jspb
+            .exttest
+            .reverse
+            .TestExtensionReverseOrderMessage1
+            .TestExtensionReverseOrderNestedMessage1.b, 2333);
+    message2.setExtension(proto.jspb.exttest.reverse.c, 23333);
 
-  it('testMessageWithDefaultOneofValues_defaultNotOnFirstField', function() {
-    var message = new proto.jspb.test.TestMessageWithOneof;
-    assertEquals(0, message.getBone());
-    assertEquals(1234, message.getBtwo());
-    assertFalse(message.hasBone());
-    assertFalse(message.hasBtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
-            .DEFAULT_ONEOF_B_NOT_SET,
-        message.getDefaultOneofBCase());
-
-    message.setBone(2);
-    assertEquals(2, message.getBone());
-    assertEquals(1234, message.getBtwo());
-    assertTrue(message.hasBone());
-    assertFalse(message.hasBtwo());
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
-        message.getDefaultOneofBCase());
-
-    message.setBtwo(3);
-    assertEquals(0, message.getBone());
-    assertFalse(message.hasBone());
-    assertTrue(message.hasBtwo());
-    assertEquals(3, message.getBtwo());
+        233,
+        message2.getExtension(
+            proto.jspb.exttest.reverse.TestExtensionReverseOrderMessage1.a));
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
-        message.getDefaultOneofBCase());
-
-    message.clearBtwo();
-    assertEquals(0, message.getBone());
-    assertFalse(message.hasBone());
-    assertFalse(message.hasBtwo());
-    assertEquals(1234, message.getBtwo());
+        2333,
+        message2.getExtension(
+            proto
+                .jspb
+                .exttest
+                .reverse
+                .TestExtensionReverseOrderMessage1
+                .TestExtensionReverseOrderNestedMessage1.b));
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
-            .DEFAULT_ONEOF_B_NOT_SET,
-        message.getDefaultOneofBCase());
+        23333,
+        message2.getExtension(proto.jspb.exttest.reverse.c));
   });
 
-  it('testInitializeMessageWithOneofDefaults', function() {
-    var message =
-        new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567));
-    assertEquals(567, message.getAone());
-    assertEquals(0, message.getAtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
-        message.getDefaultOneofACase());
+  it('testCircularDepsBaseOnMessageField', function() {
+    var nestMessage1 = new proto.jspb.circulartest.MessageField1;
+    var nestMessage2 = new proto.jspb.circulartest.MessageField2;
+    var message1 = new proto.jspb.circulartest.MessageField1;
+    var message2 = new proto.jspb.circulartest.MessageField2;
 
-    message =
-        new proto.jspb.test.TestMessageWithOneof(new Array(10).concat(890));
-    assertEquals(1234, message.getAone());
-    assertEquals(890, message.getAtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
-        message.getDefaultOneofACase());
+    nestMessage1.setA(1);
+    nestMessage2.setA(2);
+    message1.setB(nestMessage2);
+    message2.setB(nestMessage1);
 
-    message =
-        new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567, 890));
-    assertEquals(1234, message.getAone());
-    assertEquals(890, message.getAtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
-        message.getDefaultOneofACase());
+
+    assertEquals(2, message1.getB().getA());
+    assertEquals(1, message2.getB().getA());
   });
 
-  it('testInitializeMessageWithOneofDefaults_defaultNotSetOnFirstField',
-      function() {
-        var message;
-
-        message =
-            new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567));
-        assertEquals(567, message.getBone());
-        assertEquals(1234, message.getBtwo());
-        assertEquals(
-            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
-            message.getDefaultOneofBCase());
-
-        message =
-            new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890));
-        assertEquals(0, message.getBone());
-        assertEquals(890, message.getBtwo());
-        assertEquals(
-            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
-            message.getDefaultOneofBCase());
-
-        message = new proto.jspb.test.TestMessageWithOneof(
-            new Array(11).concat(567, 890));
-        assertEquals(0, message.getBone());
-        assertEquals(890, message.getBtwo());
-        assertEquals(
-            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
-            message.getDefaultOneofBCase());
-      });
-
-  it('testOneofContainingAnotherMessage', function() {
-    var message = new proto.jspb.test.TestMessageWithOneof;
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
-            RECURSIVE_ONEOF_NOT_SET,
-        message.getRecursiveOneofCase());
 
-    var other = new proto.jspb.test.TestMessageWithOneof;
-    message.setRone(other);
-    assertEquals(other, message.getRone());
-    assertEquals('', message.getRtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RONE,
-        message.getRecursiveOneofCase());
+  it('testCircularDepsBaseOnRepeatedMessageField', function() {
+    var nestMessage1 = new proto.jspb.circulartest.RepeatedMessageField1;
+    var nestMessage2 = new proto.jspb.circulartest.RepeatedMessageField2;
+    var message1 = new proto.jspb.circulartest.RepeatedMessageField1;
+    var message2 = new proto.jspb.circulartest.RepeatedMessageField2;
 
-    message.setRtwo('hi');
-    assertUndefined(message.getRone());
-    assertEquals('hi', message.getRtwo());
-    assertEquals(
-        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RTWO,
-        message.getRecursiveOneofCase());
+    nestMessage1.setA(1);
+    nestMessage2.setA(2);
+    message1.setB(nestMessage2);
+    message2.addB(nestMessage1);
+
+
+    assertEquals(2, message1.getB().getA());
+    assertEquals(1, message2.getBList()[0].getA());
   });
 
-  it('testQueryingOneofCaseEnsuresOnlyOneFieldIsSetInUnderlyingArray',
-     function() {
-    var message = new proto.jspb.test.TestMessageWithOneof;
-    message.setPone('x');
-    assertEquals('x', message.getPone());
-    assertEquals('', message.getPthree());
+  it('testCircularDepsBaseOnMapField', function() {
+    var nestMessage1 = new proto.jspb.circulartest.MapField1;
+    var nestMessage2 = new proto.jspb.circulartest.MapField2;
+    var message1 = new proto.jspb.circulartest.MapField1;
+    var message2 = new proto.jspb.circulartest.MapField2;
+
+    nestMessage1.setA(1);
+    nestMessage2.setA(2);
+    message1.setB(nestMessage2);
+    message2.getBMap().set(1, nestMessage1);
+
+
+    assertEquals(2, message1.getB().getA());
+    assertEquals(1, message2.getBMap().get(1).getA());
+  });
+
+  it('testCircularDepsBaseOnNestedMessage', function() {
+    var nestMessage1 =
+        new proto.jspb.circulartest.NestedMessage1.NestedNestedMessage;
+    var nestMessage2 = new proto.jspb.circulartest.NestedMessage2;
+    var message1 = new proto.jspb.circulartest.NestedMessage1;
+    var message2 = new proto.jspb.circulartest.NestedMessage2;
+
+    nestMessage1.setA(1);
+    nestMessage2.setA(2);
+    message1.setB(nestMessage2);
+    message2.setB(nestMessage1);
+
+
+    assertEquals(2, message1.getB().getA());
+    assertEquals(1, message2.getB().getA());
+  });
+
+  it('testCircularDepsBaseOnNestedEnum', function() {
+    var nestMessage2 = new proto.jspb.circulartest.NestedEnum2;
+    var message1 = new proto.jspb.circulartest.NestedEnum1;
+    var message2 = new proto.jspb.circulartest.NestedEnum2;
+
+    nestMessage2.setA(2);
+    message1.setB(nestMessage2);
+    message2.setB(proto.jspb.circulartest.NestedEnum1.NestedNestedEnum.VALUE_1);
+
+
+    assertEquals(2, message1.getB().getA());
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
-        message.getPartialOneofCase());
+        proto.jspb.circulartest.NestedEnum1.NestedNestedEnum.VALUE_1,
+        message2.getB());
+  });
+
+  it('testCircularDepsBaseOnExtensionContainingType', function() {
+    var nestMessage2 = new proto.jspb.circulartest.ExtensionContainingType2;
+    var message1 = new proto.jspb.circulartest.ExtensionContainingType1;
 
-    var array = message.toArray();
-    assertEquals('x', array[2]);
-    assertUndefined(array[4]);
-    array[4] = 'y';
+    nestMessage2.setA(2);
+    message1.setB(nestMessage2);
+    message1.setExtension(
+        proto.jspb.circulartest.ExtensionContainingType2.c, 1);
 
+
+    assertEquals(2, message1.getB().getA());
     assertEquals(
-        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
-        message.getPartialOneofCase());
-    assertUndefined(array[2]);
-    assertEquals('y', array[4]);
+        1,
+        message1.getExtension(
+            proto.jspb.circulartest.ExtensionContainingType2.c));
   });
 
-  it('testFloatingPointFieldsSupportNan', function() {
-    var assertNan = function(x) {
-      assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
-          goog.isNumber(x) && isNaN(x));
-    };
+  it('testCircularDepsBaseOnExtensionField', function() {
+    var nestMessage2 = new proto.jspb.circulartest.ExtensionField2;
+    var message1 = new proto.jspb.circulartest.ExtensionField1;
+    var message3 = new proto.jspb.circulartest.ExtensionField3;
 
-    var message = new proto.jspb.test.FloatingPointFields([
-      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN',
-      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
-    ]);
-    assertNan(message.getOptionalFloatField());
-    assertNan(message.getRequiredFloatField());
-    assertNan(message.getRepeatedFloatFieldList()[0]);
-    assertNan(message.getRepeatedFloatFieldList()[1]);
-    assertNan(message.getDefaultFloatField());
-    assertNan(message.getOptionalDoubleField());
-    assertNan(message.getRequiredDoubleField());
-    assertNan(message.getRepeatedDoubleFieldList()[0]);
-    assertNan(message.getRepeatedDoubleFieldList()[1]);
-    assertNan(message.getDefaultDoubleField());
+    nestMessage2.setA(2);
+    message1.setB(nestMessage2);
+    message3.setExtension(proto.jspb.circulartest.ExtensionField2.c, message1);
+
+
+    assertEquals(
+        2,
+        message3.getExtension(proto.jspb.circulartest.ExtensionField2.c)
+            .getB()
+            .getA());
+  });
+
+  it('testSameMessageNameOuputs', function() {
+    var package1Message = new proto.jspb.filenametest.package1.TestMessage;
+    var package2Message = new proto.jspb.filenametest.package2.TestMessage;
+
+    package1Message.setExtension(
+        proto.jspb.filenametest.package1.a, 10);
+    package1Message.setExtension(
+        proto.jspb.filenametest.package1.b, 11);
+    package2Message.setA(12);
+
+    assertEquals(10,
+        package1Message.getExtension(proto.jspb.filenametest.package1.a));
+    assertEquals(11,
+        package1Message.getExtension(proto.jspb.filenametest.package1.b));
+    assertEquals(12, package2Message.getA());
   });
 
 });

+ 6 - 4
js/proto3_test.js

@@ -30,17 +30,15 @@
 
 goog.require('goog.crypt.base64');
 goog.require('goog.testing.asserts');
-
 // CommonJS-LoadFromFile: testbinary_pb proto.jspb.test
 goog.require('proto.jspb.test.ForeignMessage');
-
 // CommonJS-LoadFromFile: proto3_test_pb proto.jspb.test
 goog.require('proto.jspb.test.Proto3Enum');
 goog.require('proto.jspb.test.TestProto3');
-
+// CommonJS-LoadFromFile: google/protobuf/any_pb proto.google.protobuf
+goog.require('proto.google.protobuf.Any');
 // CommonJS-LoadFromFile: google/protobuf/timestamp_pb proto.google.protobuf
 goog.require('proto.google.protobuf.Timestamp');
-
 // CommonJS-LoadFromFile: google/protobuf/struct_pb proto.google.protobuf
 goog.require('proto.google.protobuf.Struct');
 
@@ -377,6 +375,7 @@ describe('proto3Test', function() {
 
   });
 
+
   it('testTimestampWellKnownType', function() {
     var msg = new proto.google.protobuf.Timestamp();
     msg.fromDate(new Date(123456789));
@@ -384,6 +383,9 @@ describe('proto3Test', function() {
     assertEquals(789000000, msg.getNanos());
     var date = msg.toDate();
     assertEquals(123456789, date.getTime());
+    var anotherMsg = proto.google.protobuf.Timestamp.fromDate(date);
+    assertEquals(msg.getSeconds(), anotherMsg.getSeconds());
+    assertEquals(msg.getNanos(), anotherMsg.getNanos());
   });
 
   it('testStructWellKnownType', function() {

+ 11 - 0
js/test.proto

@@ -241,6 +241,17 @@ message TestEndsWithBytes {
   optional bytes data = 2;
 }
 
+// This message is for testing extension handling doesn't affect fields before
+// pivot. Don't add new field to this message. See b/117298778 for more detail.
+message TestLastFieldBeforePivot {
+  optional int32 last_field_before_pivot = 1;
+  extensions 100 to max;
+}
+
+extend TestLastFieldBeforePivot {
+  optional int32 extend_test_last_field_before_pivot_field = 101;
+}
+
 
 message Int64Types {
   optional int64 int64_normal = 1 [jstype=JS_NORMAL];

+ 52 - 0
js/test11.proto

@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package jspb.exttest.reverse;
+
+message TestExtensionReverseOrderMessage1 {
+  extend TestExtensionReverseOrderMessage2 {
+    optional int32 a = 1;
+  }
+  message TestExtensionReverseOrderNestedMessage1 {
+    extend TestExtensionReverseOrderMessage2 {
+      optional int32 b = 2;
+    }
+  }
+}
+
+extend TestExtensionReverseOrderMessage2 {
+  optional int32 c = 3;
+}
+
+message TestExtensionReverseOrderMessage2 {
+  extensions 1 to 100;
+}

+ 119 - 0
js/test12.proto

@@ -0,0 +1,119 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+
+package jspb.circulartest;
+
+message MessageField1 {
+  optional int32 a = 1;
+  optional MessageField2 b = 2;
+}
+
+message MessageField2 {
+  optional int32 a = 1;
+  optional MessageField1 b = 2;
+}
+
+
+message RepeatedMessageField1 {
+  optional int32 a = 1;
+  optional RepeatedMessageField2 b = 2;
+}
+
+message RepeatedMessageField2 {
+  optional int32 a = 1;
+  repeated RepeatedMessageField1 b = 2;
+}
+
+message MapField1 {
+  optional int32 a = 1;
+  optional MapField2 b = 2;
+}
+
+message MapField2 {
+  optional int32 a = 1;
+  map<int32, MapField1> b = 2;
+}
+
+message NestedMessage1 {
+  optional NestedMessage2 b = 2;
+  message NestedNestedMessage {
+    optional int32 a = 1;
+  }
+}
+
+message NestedMessage2 {
+  optional int32 a = 1;
+  optional NestedMessage1.NestedNestedMessage b = 2;
+}
+
+message NestedEnum1 {
+  optional NestedEnum2 b = 2;
+  enum NestedNestedEnum {
+    UNDEFINED = 0;
+    VALUE_1 = 1;
+  }
+}
+
+message NestedEnum2 {
+  optional int32 a = 1;
+  optional NestedEnum1.NestedNestedEnum b = 2;
+}
+
+message ExtensionContainingType1 {
+  optional int32 a = 1;
+  optional ExtensionContainingType2 b = 2;
+  extensions 99 to 100;
+}
+
+message ExtensionContainingType2 {
+  optional int32 a = 1;
+  extend ExtensionContainingType1 {
+    optional int32 c = 99;
+  }
+}
+
+message ExtensionField1 {
+  optional int32 a = 1;
+  optional ExtensionField2 b = 2;
+}
+
+message ExtensionField2 {
+  optional int32 a = 1;
+  extend ExtensionField3 {
+    optional ExtensionField1 c = 99;
+  }
+}
+
+message ExtensionField3 {
+  extensions 99 to 100;
+}

+ 70 - 0
js/test13.proto

@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package jspb.filenametest.package1;
+
+message TestMessage {
+  extensions 1 to 100;
+}
+
+extend TestMessage {
+  optional int32 a = 1;
+}
+
+enum TestEnum {
+  VALUE_0 = 0;
+  VALUE_1 = 1;
+}
+
+message TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName1 {
+  optional TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName2
+    a = 1;
+  optional int32 b = 2;
+}
+
+message TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName2 {
+  optional TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName3
+    a = 1;
+  optional int32 b = 2;
+}
+
+message TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName3 {
+  optional TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName4
+    a = 1;
+  optional int32 b = 2;
+}
+
+message TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName4 {
+  optional TestLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName1
+    a = 1;
+  optional int32 b = 2;
+}

+ 43 - 0
js/test14.proto

@@ -0,0 +1,43 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package jspb.filenametest.package2;
+
+message TestMessage {
+  optional int32 a = 1;
+}
+
+enum TestEnum {
+  VALUE_0 = 0;
+  VALUE_1 = 1;
+  VALUE_2 = 2;
+}

+ 39 - 0
js/test15.proto

@@ -0,0 +1,39 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+import "test13.proto";
+
+package jspb.filenametest.package1;
+
+extend TestMessage {
+  optional int32 b = 2;
+}

+ 4 - 4
python/google/protobuf/internal/containers.py

@@ -41,12 +41,12 @@ are:
 
 __author__ = 'petar@google.com (Petar Petrov)'
 
+import sys
 try:
-    # This fallback applies for all versions of Python before 3.3
-    import collections.abc as collections_abc
+  # This fallback applies for all versions of Python before 3.3
+  import collections.abc as collections_abc
 except ImportError:
-    import collections as collections_abc
-import sys
+  import collections as collections_abc
 
 if sys.version_info[0] < 3:
   # We would use collections_abc.MutableMapping all the time, but in Python 2

+ 0 - 4
python/google/protobuf/internal/descriptor_pool_test.py

@@ -529,10 +529,6 @@ class DescriptorPoolTestBase(object):
     conflict_fd = copy.deepcopy(unittest_fd)
     conflict_fd.name = 'other_file'
     if api_implementation.Type() == 'cpp':
-      try:
-        self.pool.Add(unittest_fd)
-        self.pool.Add(conflict_fd)
-      except TypeError:
         pass
     else:
       with warnings.catch_warnings(record=True) as w:

+ 8 - 0
python/google/protobuf/internal/descriptor_test.py

@@ -192,6 +192,14 @@ class DescriptorTest(unittest.TestCase):
     self.assertTrue(enum_value_descriptor.has_options)
     self.assertFalse(other_enum_value_descriptor.has_options)
 
+  def testCustomOptionsCopyTo(self):
+    message_descriptor = (unittest_custom_options_pb2.
+                          TestMessageWithCustomOptions.DESCRIPTOR)
+    message_proto = descriptor_pb2.DescriptorProto()
+    message_descriptor.CopyToProto(message_proto)
+    self.assertEqual(len(message_proto.options.ListFields()),
+                     2)
+
   def testDifferentCustomOptionTypes(self):
     kint32min = -2**31
     kint64min = -2**63

+ 2 - 2
python/google/protobuf/internal/enum_type_wrapper.py

@@ -46,7 +46,7 @@ class EnumTypeWrapper(object):
   def __init__(self, enum_type):
     """Inits EnumTypeWrapper with an EnumDescriptor."""
     self._enum_type = enum_type
-    self.DESCRIPTOR = enum_type;
+    self.DESCRIPTOR = enum_type
 
   def Name(self, number):
     """Returns a string containing the name of an enum value."""
@@ -56,7 +56,7 @@ class EnumTypeWrapper(object):
         self._enum_type.name, number))
 
   def Value(self, name):
-    """Returns the value coresponding to the given enum name."""
+    """Returns the value corresponding to the given enum name."""
     if name in self._enum_type.values_by_name:
       return self._enum_type.values_by_name[name].number
     raise ValueError('Enum %s has no value defined for name %s' % (

+ 2 - 1
python/google/protobuf/internal/json_format_test.py

@@ -523,7 +523,8 @@ class JsonFormatTest(JsonFormatBase):
             '}'))
     parsed_message = json_format_proto3_pb2.TestStruct()
     self.CheckParseBack(message, parsed_message)
-    parsed_message.value['empty_struct']  # check for regression; this used to raise
+    # check for regression; this used to raise
+    parsed_message.value['empty_struct']
     parsed_message.value['empty_list']
 
   def testValueMessage(self):

+ 14 - 12
python/google/protobuf/internal/message_test.py

@@ -159,15 +159,6 @@ class MessageTest(BaseTestCase):
       with self.assertRaises(message.DecodeError) as context:
         msg.FromString(end_tag)
       self.assertEqual('Unexpected end-group tag.', str(context.exception))
-    else:
-      with warnings.catch_warnings(record=True) as w:
-        # Cause all warnings to always be triggered.
-        warnings.simplefilter('always')
-        msg.FromString(end_tag)
-        assert len(w) == 1
-        assert issubclass(w[-1].category, RuntimeWarning)
-        self.assertEqual('Unexpected end-group tag: Not all data was converted',
-                         str(w[-1].message))
 
   def testDeterminismParameters(self, message_module):
     # This message is always deterministically serialized, even if determinism
@@ -1791,6 +1782,13 @@ class Proto3Test(BaseTestCase):
     old_map_value = msg2.map_int32_foreign_message[222]
 
     msg2.MergeFrom(msg)
+    # Compare with expected message instead of call
+    # msg2.map_int32_foreign_message[222] to make sure MergeFrom does not
+    # sync with repeated field and there is no duplicated keys.
+    expected_msg = map_unittest_pb2.TestMap()
+    expected_msg.CopyFrom(msg)
+    expected_msg.map_int64_int64[88] = 99
+    self.assertEqual(msg2, expected_msg)
 
     self.assertEqual(34, msg2.map_int32_int32[12])
     self.assertEqual(78, msg2.map_int32_int32[56])
@@ -1854,9 +1852,13 @@ class Proto3Test(BaseTestCase):
     self.assertEqual(99, msg2.map_int64_int64[88])
 
     msg2.map_int32_foreign_message.MergeFrom(msg.map_int32_foreign_message)
-    self.assertEqual(5, msg2.map_int32_foreign_message[111].c)
-    self.assertEqual(10, msg2.map_int32_foreign_message[222].c)
-    self.assertFalse(msg2.map_int32_foreign_message[222].HasField('d'))
+    # Compare with expected message instead of call
+    # msg.map_int32_foreign_message[222] to make sure MergeFrom does not
+    # sync with repeated field and no duplicated keys.
+    expected_msg = map_unittest_pb2.TestMap()
+    expected_msg.CopyFrom(msg)
+    expected_msg.map_int64_int64[88] = 99
+    self.assertEqual(msg2, expected_msg)
 
     # Test when cpp extension cache a map.
     m1 = map_unittest_pb2.TestMap()

+ 20 - 19
python/google/protobuf/internal/python_message.py

@@ -294,7 +294,7 @@ def _IsMapField(field):
 
 
 def _IsMessageMapField(field):
-  value_type = field.message_type.fields_by_name["value"]
+  value_type = field.message_type.fields_by_name['value']
   return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE
 
 
@@ -311,12 +311,12 @@ def _AttachFieldHelpers(cls, field_descriptor):
                  wire_format.IsTypePackable(field_descriptor.type))
   if not is_packable:
     is_packed = False
-  elif field_descriptor.containing_type.syntax == "proto2":
+  elif field_descriptor.containing_type.syntax == 'proto2':
     is_packed = (field_descriptor.has_options and
                 field_descriptor.GetOptions().packed)
   else:
     has_packed_false = (field_descriptor.has_options and
-                        field_descriptor.GetOptions().HasField("packed") and
+                        field_descriptor.GetOptions().HasField('packed') and
                         field_descriptor.GetOptions().packed == False)
     is_packed = not has_packed_false
   is_map_entry = _IsMapField(field_descriptor)
@@ -529,7 +529,7 @@ def _AddInitMethod(message_descriptor, cls):
     for field_name, field_value in kwargs.items():
       field = _GetFieldByName(message_descriptor, field_name)
       if field is None:
-        raise TypeError("%s() got an unexpected keyword argument '%s'" %
+        raise TypeError('%s() got an unexpected keyword argument "%s"' %
                         (message_descriptor.name, field_name))
       if field_value is None:
         # field=None is the same as no field at all.
@@ -619,7 +619,7 @@ def _AddPropertiesForField(field, cls):
   # handle specially here.
   assert _FieldDescriptor.MAX_CPPTYPE == 10
 
-  constant_name = field.name.upper() + "_FIELD_NUMBER"
+  constant_name = field.name.upper() + '_FIELD_NUMBER'
   setattr(cls, constant_name, field.number)
 
   if field.label == _FieldDescriptor.LABEL_REPEATED:
@@ -698,7 +698,7 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls):
   type_checker = type_checkers.GetTypeChecker(field)
   default_value = field.default_value
   valid_values = set()
-  is_proto3 = field.containing_type.syntax == "proto3"
+  is_proto3 = field.containing_type.syntax == 'proto3'
 
   def getter(self):
     # TODO(protobuf-team): This may be broken since there may not be
@@ -786,7 +786,7 @@ def _AddPropertiesForExtensions(descriptor, cls):
   """Adds properties for all fields in this protocol message type."""
   extension_dict = descriptor.extensions_by_name
   for extension_name, extension_field in extension_dict.items():
-    constant_name = extension_name.upper() + "_FIELD_NUMBER"
+    constant_name = extension_name.upper() + '_FIELD_NUMBER'
     setattr(cls, constant_name, extension_field.number)
 
   # TODO(amauryfa): Migrate all users of these attributes to functions like
@@ -835,14 +835,15 @@ def _AddListFieldsMethod(message_descriptor, cls):
 
   cls.ListFields = ListFields
 
-_Proto3HasError = 'Protocol message has no non-repeated submessage field "%s"'
-_Proto2HasError = 'Protocol message has no non-repeated field "%s"'
+_PROTO3_ERROR_TEMPLATE = \
+  'Protocol message %s has no non-repeated submessage field "%s"'
+_PROTO2_ERROR_TEMPLATE = 'Protocol message %s has no non-repeated field "%s"'
 
 def _AddHasFieldMethod(message_descriptor, cls):
   """Helper for _AddMessageMethods()."""
 
   is_proto3 = (message_descriptor.syntax == "proto3")
-  error_msg = _Proto3HasError if is_proto3 else _Proto2HasError
+  error_msg = _PROTO3_ERROR_TEMPLATE if is_proto3 else _PROTO2_ERROR_TEMPLATE
 
   hassable_fields = {}
   for field in message_descriptor.fields:
@@ -863,7 +864,7 @@ def _AddHasFieldMethod(message_descriptor, cls):
     try:
       field = hassable_fields[field_name]
     except KeyError:
-      raise ValueError(error_msg % field_name)
+      raise ValueError(error_msg % (message_descriptor.full_name, field_name))
 
     if isinstance(field, descriptor_mod.OneofDescriptor):
       try:
@@ -893,7 +894,7 @@ def _AddClearFieldMethod(message_descriptor, cls):
         else:
           return
       except KeyError:
-        raise ValueError('Protocol message %s() has no "%s" field.' %
+        raise ValueError('Protocol message %s has no "%s" field.' %
                          (message_descriptor.name, field_name))
 
     if field in self._fields:
@@ -1278,7 +1279,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
     for field, value in self.ListFields():
       if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
         if field.is_extension:
-          name = "(%s)" % field.full_name
+          name = '(%s)' % field.full_name
         else:
           name = field.name
 
@@ -1286,7 +1287,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
           if _IsMessageMapField(field):
             for key in value:
               element = value[key]
-              prefix = "%s[%s]." % (name, key)
+              prefix = '%s[%s].' % (name, key)
               sub_errors = element.FindInitializationErrors()
               errors += [prefix + error for error in sub_errors]
           else:
@@ -1295,11 +1296,11 @@ def _AddIsInitializedMethod(message_descriptor, cls):
         elif field.label == _FieldDescriptor.LABEL_REPEATED:
           for i in range(len(value)):
             element = value[i]
-            prefix = "%s[%d]." % (name, i)
+            prefix = '%s[%d].' % (name, i)
             sub_errors = element.FindInitializationErrors()
             errors += [prefix + error for error in sub_errors]
         else:
-          prefix = name + "."
+          prefix = name + '.'
           sub_errors = value.FindInitializationErrors()
           errors += [prefix + error for error in sub_errors]
 
@@ -1315,7 +1316,7 @@ def _AddMergeFromMethod(cls):
   def MergeFrom(self, msg):
     if not isinstance(msg, cls):
       raise TypeError(
-          "Parameter to MergeFrom() must be instance of same class: "
+          'Parameter to MergeFrom() must be instance of same class: '
           'expected %s got %s.' % (cls.__name__, msg.__class__.__name__))
 
     assert msg is not self
@@ -1611,8 +1612,8 @@ class _ExtensionDict(object):
     other_fields = other._extended_message.ListFields()
 
     # Get rid of non-extension fields.
-    my_fields    = [ field for field in my_fields    if field.is_extension ]
-    other_fields = [ field for field in other_fields if field.is_extension ]
+    my_fields = [field for field in my_fields if field.is_extension]
+    other_fields = [field for field in other_fields if field.is_extension]
 
     return my_fields == other_fields
 

+ 88 - 2
python/google/protobuf/internal/text_format_test.py

@@ -50,9 +50,11 @@ except ImportError:
 from google.protobuf import any_pb2
 from google.protobuf import any_test_pb2
 from google.protobuf import map_unittest_pb2
+from google.protobuf import unittest_custom_options_pb2
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_proto3_arena_pb2
+from google.protobuf import descriptor_pb2
 from google.protobuf.internal import any_test_pb2 as test_extend_any
 from google.protobuf.internal import message_set_extensions_pb2
 from google.protobuf.internal import test_util
@@ -175,7 +177,10 @@ class TextFormatMessageToStringTests(TextFormatBase):
         'repeated_nested_message {\n  bb: 32\n}\n'
         'repeated_foreign_enum: [FOREIGN_FOO, FOREIGN_BAR, FOREIGN_BAZ]\n')
     if as_one_line:
-      expected_ascii = expected_ascii.replace('\n ', '').replace('\n', '')
+      expected_ascii = expected_ascii.replace('\n', ' ')
+      expected_ascii = re.sub(r'\s+', ' ', expected_ascii)
+      expected_ascii = re.sub(r'\s$', '', expected_ascii)
+
     actual_ascii = text_format.MessageToString(
         message, use_short_repeated_primitives=True,
         as_one_line=as_one_line)
@@ -184,7 +189,7 @@ class TextFormatMessageToStringTests(TextFormatBase):
     text_format.Parse(actual_ascii, parsed_message)
     self.assertEqual(parsed_message, message)
 
-  def tesPrintShortFormatRepeatedFields(self, message_module, as_one_line):
+  def testPrintShortFormatRepeatedFields(self, message_module):
     self.VerifyPrintShortFormatRepeatedFields(message_module, False)
     self.VerifyPrintShortFormatRepeatedFields(message_module, True)
 
@@ -358,6 +363,63 @@ class TextFormatMessageToStringTests(TextFormatBase):
     self.assertEqual('0.0', out.getvalue())
     out.close()
 
+  def testCustomOptions(self, message_module):
+    message_descriptor = (unittest_custom_options_pb2.
+                          TestMessageWithCustomOptions.DESCRIPTOR)
+    message_proto = descriptor_pb2.DescriptorProto()
+    message_descriptor.CopyToProto(message_proto)
+    expected_text = (
+        'name: "TestMessageWithCustomOptions"\n'
+        'field {\n'
+        '  name: "field1"\n'
+        '  number: 1\n'
+        '  label: LABEL_OPTIONAL\n'
+        '  type: TYPE_STRING\n'
+        '  options {\n'
+        '    ctype: CORD\n'
+        '    [protobuf_unittest.field_opt1]: 8765432109\n'
+        '  }\n'
+        '}\n'
+        'field {\n'
+        '  name: "oneof_field"\n'
+        '  number: 2\n'
+        '  label: LABEL_OPTIONAL\n'
+        '  type: TYPE_INT32\n'
+        '  oneof_index: 0\n'
+        '}\n'
+        'enum_type {\n'
+        '  name: "AnEnum"\n'
+        '  value {\n'
+        '    name: "ANENUM_VAL1"\n'
+        '    number: 1\n'
+        '  }\n'
+        '  value {\n'
+        '    name: "ANENUM_VAL2"\n'
+        '    number: 2\n'
+        '    options {\n'
+        '      [protobuf_unittest.enum_value_opt1]: 123\n'
+        '    }\n'
+        '  }\n'
+        '  options {\n'
+        '    [protobuf_unittest.enum_opt1]: -789\n'
+        '  }\n'
+        '}\n'
+        'options {\n'
+        '  message_set_wire_format: false\n'
+        '  [protobuf_unittest.message_opt1]: -56\n'
+        '}\n'
+        'oneof_decl {\n'
+        '  name: "AnOneof"\n'
+        '  options {\n'
+        '    [protobuf_unittest.oneof_opt1]: -99\n'
+        '  }\n'
+        '}\n')
+    self.assertEqual(expected_text,
+                     text_format.MessageToString(message_proto))
+    parsed_proto = descriptor_pb2.DescriptorProto()
+    text_format.Parse(expected_text, parsed_proto)
+    self.assertEqual(message_proto, parsed_proto)
+
 
 @_parameterized.parameters(unittest_pb2, unittest_proto3_arena_pb2)
 class TextFormatMessageToTextBytesTests(TextFormatBase):
@@ -1907,6 +1969,30 @@ class PrettyPrinterTest(TextFormatBase):
          'repeated_nested_message { My lucky number is 42 } '
          'repeated_nested_message { My lucky number is 99 }'))
 
+    out = text_format.TextWriter(False)
+    text_format.PrintField(
+        message_module.TestAllTypes.DESCRIPTOR.fields_by_name[
+            'optional_nested_message'],
+        message.optional_nested_message,
+        out,
+        message_formatter=printer)
+    self.assertEqual(
+        'optional_nested_message {\n  My lucky number is 1\n}\n',
+        out.getvalue())
+    out.close()
+
+    out = text_format.TextWriter(False)
+    text_format.PrintFieldValue(
+        message_module.TestAllTypes.DESCRIPTOR.fields_by_name[
+            'optional_nested_message'],
+        message.optional_nested_message,
+        out,
+        message_formatter=printer)
+    self.assertEqual(
+        '{\n  My lucky number is 1\n}',
+        out.getvalue())
+    out.close()
+
 
 class WhitespaceTest(TextFormatBase):
 

+ 1 - 5
python/google/protobuf/internal/well_known_types.py

@@ -669,11 +669,7 @@ def _MergeMessage(
         destination.ClearField(_StrConvert(name))
       repeated_source = getattr(source, name)
       repeated_destination = getattr(destination, name)
-      if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
-        for item in repeated_source:
-          repeated_destination.add().MergeFrom(item)
-      else:
-        repeated_destination.extend(repeated_source)
+      repeated_destination.MergeFrom(repeated_source)
     else:
       if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
         if replace_message:

+ 25 - 1
python/google/protobuf/internal/well_known_types_test.py

@@ -47,6 +47,7 @@ from google.protobuf import duration_pb2
 from google.protobuf import field_mask_pb2
 from google.protobuf import struct_pb2
 from google.protobuf import timestamp_pb2
+from google.protobuf import map_unittest_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf.internal import any_test_pb2
 from google.protobuf.internal import test_util
@@ -526,7 +527,7 @@ class FieldMaskTest(unittest.TestCase):
     out_mask.Intersect(mask1, mask2)
     self.assertEqual('foo.bar.baz', out_mask.ToJsonString())
 
-  def testMergeMessage(self):
+  def testMergeMessageWithoutMapFields(self):
     # Test merge one field.
     src = unittest_pb2.TestAllTypes()
     test_util.SetAllFields(src)
@@ -635,6 +636,29 @@ class FieldMaskTest(unittest.TestCase):
     self.assertTrue(dst.HasField('foo_message'))
     self.assertFalse(dst.HasField('foo_lazy_message'))
 
+  def testMergeMessageWithMapField(self):
+    empty_map = map_unittest_pb2.TestRecursiveMapMessage()
+    src_level_2 = map_unittest_pb2.TestRecursiveMapMessage()
+    src_level_2.a['src level 2'].CopyFrom(empty_map)
+    src = map_unittest_pb2.TestRecursiveMapMessage()
+    src.a['common key'].CopyFrom(src_level_2)
+    src.a['src level 1'].CopyFrom(src_level_2)
+
+    dst_level_2 = map_unittest_pb2.TestRecursiveMapMessage()
+    dst_level_2.a['dst level 2'].CopyFrom(empty_map)
+    dst = map_unittest_pb2.TestRecursiveMapMessage()
+    dst.a['common key'].CopyFrom(dst_level_2)
+    dst.a['dst level 1'].CopyFrom(empty_map)
+
+    mask = field_mask_pb2.FieldMask()
+    mask.FromJsonString('a')
+    mask.MergeMessage(src, dst)
+
+    # map from dst is replaced with map from src.
+    self.assertEqual(dst.a['common key'], src_level_2)
+    self.assertEqual(dst.a['src level 1'], src_level_2)
+    self.assertEqual(dst.a['dst level 1'], empty_map)
+
   def testMergeErrors(self):
     src = unittest_pb2.TestAllTypes()
     dst = unittest_pb2.TestAllTypes()

+ 27 - 9
python/google/protobuf/pyext/descriptor.cc

@@ -189,6 +189,21 @@ const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) {
   return descriptor->service()->file();
 }
 
+bool Reparse(
+    PyMessageFactory* message_factory, const Message& from, Message* to) {
+  // Reparse message.
+  string serialized;
+  from.SerializeToString(&serialized);
+  io::CodedInputStream input(
+      reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
+  input.SetExtensionRegistry(message_factory->pool->pool,
+                             message_factory->message_factory);
+  bool success = to->ParseFromCodedStream(&input);
+  if (!success) {
+    return false;
+  }
+  return true;
+}
 // Converts options into a Python protobuf, and cache the result.
 //
 // This is a bit tricky because options can contain extension fields defined in
@@ -251,15 +266,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
     cmsg->message->CopyFrom(options);
   } else {
     // Reparse options string!  XXX call cmessage::MergeFromString
-    string serialized;
-    options.SerializeToString(&serialized);
-    io::CodedInputStream input(
-        reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
-    input.SetExtensionRegistry(message_factory->pool->pool,
-                               message_factory->message_factory);
-    bool success = cmsg->message->MergePartialFromCodedStream(&input);
-    if (!success) {
-      PyErr_Format(PyExc_ValueError, "Error parsing Options message");
+    if (!Reparse(message_factory, options, cmsg->message)) {
+      PyErr_Format(PyExc_ValueError, "Error reparsing Options message");
       return NULL;
     }
   }
@@ -290,6 +298,16 @@ static PyObject* CopyToPythonProto(const DescriptorClass *descriptor,
   DescriptorProtoClass* descriptor_message =
       static_cast<DescriptorProtoClass*>(message->message);
   descriptor->CopyTo(descriptor_message);
+  // Custom options might in unknown extensions. Reparse
+  // the descriptor_message. Can't skip reparse when options unknown
+  // fields is empty, because they might in sub descriptors' options.
+  PyMessageFactory* message_factory =
+      GetDefaultDescriptorPool()->py_message_factory;
+  if (!Reparse(message_factory, *descriptor_message, descriptor_message)) {
+    PyErr_Format(PyExc_ValueError, "Error reparsing descriptor message");
+    return nullptr;
+  }
+
   Py_RETURN_NONE;
 }
 

+ 10 - 10
python/google/protobuf/pyext/map_container.cc

@@ -62,6 +62,7 @@ class MapReflectionFriend {
   static Py_ssize_t Length(PyObject* _self);
   static PyObject* GetIterator(PyObject *_self);
   static PyObject* IterNext(PyObject* _self);
+  static PyObject* MergeFrom(PyObject* _self, PyObject* arg);
 
   // Methods that differ between the map types.
   static PyObject* ScalarMapGetItem(PyObject* _self, PyObject* key);
@@ -338,20 +339,19 @@ PyObject* GetEntryClass(PyObject* _self) {
   return reinterpret_cast<PyObject*>(message_class);
 }
 
-PyObject* MergeFrom(PyObject* _self, PyObject* arg) {
+PyObject* MapReflectionFriend::MergeFrom(PyObject* _self, PyObject* arg) {
   MapContainer* self = GetMap(_self);
   MapContainer* other_map = GetMap(arg);
   Message* message = self->GetMutableMessage();
   const Message* other_message = other_map->message;
   const Reflection* reflection = message->GetReflection();
   const Reflection* other_reflection = other_message->GetReflection();
-  int count = other_reflection->FieldSize(
-      *other_message, other_map->parent_field_descriptor);
-  for (int i = 0 ; i < count; i ++) {
-    reflection->AddMessage(message, self->parent_field_descriptor)->MergeFrom(
-        other_reflection->GetRepeatedMessage(
-            *other_message, other_map->parent_field_descriptor, i));
-  }
+  internal::MapFieldBase* field = reflection->MapData(
+      message, self->parent_field_descriptor);
+  internal::MapFieldBase* other_field =
+      other_reflection->MapData(const_cast<Message*>(other_message),
+                                self->parent_field_descriptor);
+  field->MergeFrom(*other_field);
   self->version++;
   Py_RETURN_NONE;
 }
@@ -589,7 +589,7 @@ static PyMethodDef ScalarMapMethods[] = {
     "Gets the value for the given key if present, or otherwise a default" },
   { "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
     "Return the class used to build Entries of (key, value) pairs." },
-  { "MergeFrom", (PyCFunction)MergeFrom, METH_O,
+  { "MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
     "Merges a map into the current map." },
   /*
   { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
@@ -908,7 +908,7 @@ static PyMethodDef MessageMapMethods[] = {
     "Alias for getitem, useful to make explicit that the map is mutated." },
   { "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS,
     "Return the class used to build Entries of (key, value) pairs." },
-  { "MergeFrom", (PyCFunction)MergeFrom, METH_O,
+  { "MergeFrom", (PyCFunction)MapReflectionFriend::MergeFrom, METH_O,
     "Merges a map into the current map." },
   /*
   { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,

+ 10 - 13
python/google/protobuf/pyext/message.cc

@@ -585,10 +585,6 @@ static int VisitCompositeField(const FieldDescriptor* descriptor,
 // Returns -1 on error and 0 on success.
 template<class Visitor>
 int ForEachCompositeField(CMessage* self, Visitor visitor) {
-  Py_ssize_t pos = 0;
-  PyObject* key;
-  PyObject* field;
-
   // Visit normal fields.
   if (self->composite_fields) {
     for (CMessage::CompositeFieldsMap::iterator it =
@@ -1554,10 +1550,11 @@ const FieldDescriptor* FindFieldWithOneofs(
 }
 
 bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) {
+  auto message_name = field_descriptor->containing_type()->name();
   if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
     PyErr_Format(PyExc_ValueError,
-                 "Protocol message has no singular \"%s\" field.",
-                 field_descriptor->name().c_str());
+                 "Protocol message %s has no singular \"%s\" field.",
+                 message_name.c_str(), field_descriptor->name().c_str());
     return false;
   }
 
@@ -1565,8 +1562,8 @@ bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) {
     // HasField() for a oneof *itself* isn't supported.
     if (in_oneof) {
       PyErr_Format(PyExc_ValueError,
-                   "Can't test oneof field \"%s\" for presence in proto3, use "
-                   "WhichOneof instead.",
+                   "Can't test oneof field \"%s.%s\" for presence in proto3, "
+                   "use WhichOneof instead.", message_name.c_str(),
                    field_descriptor->containing_oneof()->name().c_str());
       return false;
     }
@@ -1579,8 +1576,8 @@ bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) {
     if (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
       PyErr_Format(
           PyExc_ValueError,
-          "Can't test non-submessage field \"%s\" for presence in proto3.",
-          field_descriptor->name().c_str());
+          "Can't test non-submessage field \"%s.%s\" for presence in proto3.",
+          message_name.c_str(), field_descriptor->name().c_str());
       return false;
     }
   }
@@ -1608,7 +1605,8 @@ PyObject* HasField(CMessage* self, PyObject* arg) {
       FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof);
   if (field_descriptor == NULL) {
     if (!is_in_oneof) {
-      PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name);
+      PyErr_Format(PyExc_ValueError, "Protocol message %s has no field %s.",
+                   message->GetDescriptor()->name().c_str(), field_name);
       return NULL;
     } else {
       Py_RETURN_FALSE;
@@ -2140,6 +2138,7 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
       reinterpret_cast<const uint8*>(data), data_length);
   if (allow_oversize_protos) {
     input.SetTotalBytesLimit(INT_MAX, INT_MAX);
+    input.SetRecursionLimit(INT_MAX);
   }
   PyMessageFactory* factory = GetFactoryForMessage(self);
   input.SetExtensionRegistry(factory->pool->pool, factory->message_factory);
@@ -2822,8 +2821,6 @@ PyObject* GetFieldValue(CMessage* self,
     }
   }
 
-  const Descriptor* message_descriptor =
-      (reinterpret_cast<CMessageClass*>(Py_TYPE(self)))->message_descriptor;
   if (self->message->GetDescriptor() != field_descriptor->containing_type()) {
     PyErr_Format(PyExc_TypeError,
                  "descriptor to field '%s' doesn't apply to '%s' object",

+ 6 - 4
python/google/protobuf/text_format.py

@@ -225,7 +225,8 @@ def PrintField(field,
   """Print a single field name/value pair."""
   printer = _Printer(out, indent, as_utf8, as_one_line,
                      use_short_repeated_primitives, pointy_brackets,
-                     use_index_order, float_format, message_formatter)
+                     use_index_order, float_format,
+                     message_formatter=message_formatter)
   printer.PrintField(field, value)
 
 
@@ -243,7 +244,8 @@ def PrintFieldValue(field,
   """Print a single field value (not including name)."""
   printer = _Printer(out, indent, as_utf8, as_one_line,
                      use_short_repeated_primitives, pointy_brackets,
-                     use_index_order, float_format, message_formatter)
+                     use_index_order, float_format,
+                     message_formatter=message_formatter)
   printer.PrintFieldValue(field, value)
 
 
@@ -427,8 +429,8 @@ class _Printer(object):
   def _PrintShortRepeatedPrimitivesValue(self, field, value):
     # Note: this is called only when value has at least one element.
     self._PrintFieldName(field)
-    self.out.write('[')
-    for i in xrange(len(value) - 1):
+    self.out.write(' [')
+    for i in six.moves.range(len(value) - 1):
       self.PrintFieldValue(field, value[i])
       self.out.write(', ')
     self.PrintFieldValue(field, value[-1])

+ 0 - 2
src/Makefile.am

@@ -74,7 +74,6 @@ nobase_include_HEADERS =                                         \
   google/protobuf/stubs/once.h                                   \
   google/protobuf/stubs/platform_macros.h                        \
   google/protobuf/stubs/port.h                                   \
-  google/protobuf/stubs/singleton.h                              \
   google/protobuf/stubs/status.h                                 \
   google/protobuf/stubs/stl_util.h                               \
   google/protobuf/stubs/stringpiece.h                            \
@@ -314,7 +313,6 @@ libprotoc_la_SOURCES =                                         \
   google/protobuf/compiler/command_line_interface.cc           \
   google/protobuf/compiler/plugin.cc                           \
   google/protobuf/compiler/plugin.pb.cc                        \
-  google/protobuf/compiler/scc.cc                              \
   google/protobuf/compiler/scc.h                               \
   google/protobuf/compiler/subprocess.cc                       \
   google/protobuf/compiler/subprocess.h                        \

+ 30 - 21
src/google/protobuf/any.pb.cc

@@ -69,15 +69,17 @@ static ::google::protobuf::Message const * const file_default_instances[] = {
   file_level_metadata_google_2fprotobuf_2fany_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
 };
 
-::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = {
-  false, InitDefaults_google_2fprotobuf_2fany_2eproto, 
+const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] =
   "\n\031google/protobuf/any.proto\022\017google.prot"
   "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
   " \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z"
   "%github.com/golang/protobuf/ptypes/any\242\002"
   "\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006p"
   "roto3"
-,
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = {
+  false, InitDefaults_google_2fprotobuf_2fany_2eproto, 
+  descriptor_table_protodef_google_2fprotobuf_2fany_2eproto,
   "google/protobuf/any.proto", &assign_descriptors_table_google_2fprotobuf_2fany_2eproto, 205,
 };
 
@@ -195,10 +197,10 @@ const char* Any::_InternalParse(const char* begin, const char* end, void* object
   auto msg = static_cast<Any*>(object);
   ::google::protobuf::uint32 size; (void)size;
   int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ::google::protobuf::uint32 tag;
     ptr = Varint::Parse32Inline(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
@@ -208,14 +210,17 @@ const char* Any::_InternalParse(const char* begin, const char* end, void* object
         ptr = Varint::Parse32Inline(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Any.type_url");
-        parser_till_end = ::google::protobuf::internal::StringParserUTF8;
-        ::std::string* str = msg->mutable_type_url();
-        str->clear();
-        object = str;
-        if (size > end - ptr) goto len_delim_till_end;
-        auto newend = ptr + size;
-        if (size) ptr = parser_till_end(ptr, newend, object, ctx);
-        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+        auto str = msg->mutable_type_url();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          object = str;
+          str->clear();
+          str->reserve(size);
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto len_delim_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx);
+        ptr += size;
         break;
       }
       // bytes value = 2;
@@ -223,25 +228,29 @@ const char* Any::_InternalParse(const char* begin, const char* end, void* object
         if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
         ptr = Varint::Parse32Inline(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
-        parser_till_end = ::google::protobuf::internal::StringParser;
-        ::std::string* str = msg->mutable_value();
-        str->clear();
-        object = str;
-        if (size > end - ptr) goto len_delim_till_end;
-        str->append(ptr, size);
+        auto str = msg->mutable_value();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          object = str;
+          str->clear();
+          str->reserve(size);
+          parser_till_end = ::google::protobuf::internal::GreedyStringParser;
+          goto len_delim_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheck(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx);
         ptr += size;
         break;
       }
       default: {
       handle_unusual: (void)&&handle_unusual;
         if ((tag & 7) == 4 || tag == 0) {
-          bool ok = ctx->ValidEndGroup(tag);
-          GOOGLE_PROTOBUF_PARSER_ASSERT(ok);
+          ctx->EndGroup(tag);
           return ptr;
         }
         auto res = UnknownFieldParse(tag, {_InternalParse, msg},
           ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
         ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
         if (res.second) return ptr;
       }
     }  // switch
@@ -252,7 +261,7 @@ len_delim_till_end: (void)&&len_delim_till_end;
                                  {parser_till_end, object}, size);
 group_continues: (void)&&group_continues;
   GOOGLE_DCHECK(ptr >= end);
-  ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth);
+  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
   return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

+ 1 - 1
src/google/protobuf/any.pb.h

@@ -134,7 +134,7 @@ class PROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_inser
   void MergeFrom(const ::google::protobuf::Message& from) final;
   void CopyFrom(const Any& from);
   void MergeFrom(const Any& from);
-  void Clear() final;
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;

+ 94 - 71
src/google/protobuf/api.pb.cc

@@ -144,8 +144,7 @@ static ::google::protobuf::Message const * const file_default_instances[] = {
   file_level_metadata_google_2fprotobuf_2fapi_2eproto, 3, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto,
 };
 
-::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto = {
-  false, InitDefaults_google_2fprotobuf_2fapi_2eproto, 
+const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] =
   "\n\031google/protobuf/api.proto\022\017google.prot"
   "obuf\032$google/protobuf/source_context.pro"
   "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014"
@@ -165,7 +164,10 @@ static ::google::protobuf::Message const * const file_default_instances[] = {
   "otobufB\010ApiProtoP\001Z+google.golang.org/ge"
   "nproto/protobuf/api;api\242\002\003GPB\252\002\036Google.P"
   "rotobuf.WellKnownTypesb\006proto3"
-,
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto = {
+  false, InitDefaults_google_2fprotobuf_2fapi_2eproto, 
+  descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto,
   "google/protobuf/api.proto", &assign_descriptors_table_google_2fprotobuf_2fapi_2eproto, 750,
 };
 
@@ -301,10 +303,10 @@ const char* Api::_InternalParse(const char* begin, const char* end, void* object
   auto msg = static_cast<Api*>(object);
   ::google::protobuf::uint32 size; (void)size;
   int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ::google::protobuf::uint32 tag;
     ptr = Varint::Parse32Inline(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
@@ -314,14 +316,17 @@ const char* Api::_InternalParse(const char* begin, const char* end, void* object
         ptr = Varint::Parse32Inline(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Api.name");
-        parser_till_end = ::google::protobuf::internal::StringParserUTF8;
-        ::std::string* str = msg->mutable_name();
-        str->clear();
-        object = str;
-        if (size > end - ptr) goto len_delim_till_end;
-        auto newend = ptr + size;
-        if (size) ptr = parser_till_end(ptr, newend, object, ctx);
-        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+        auto str = msg->mutable_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          object = str;
+          str->clear();
+          str->reserve(size);
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto len_delim_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx);
+        ptr += size;
         break;
       }
       // repeated .google.protobuf.Method methods = 2;
@@ -366,14 +371,17 @@ const char* Api::_InternalParse(const char* begin, const char* end, void* object
         ptr = Varint::Parse32Inline(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Api.version");
-        parser_till_end = ::google::protobuf::internal::StringParserUTF8;
-        ::std::string* str = msg->mutable_version();
-        str->clear();
-        object = str;
-        if (size > end - ptr) goto len_delim_till_end;
-        auto newend = ptr + size;
-        if (size) ptr = parser_till_end(ptr, newend, object, ctx);
-        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+        auto str = msg->mutable_version();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          object = str;
+          str->clear();
+          str->reserve(size);
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto len_delim_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx);
+        ptr += size;
         break;
       }
       // .google.protobuf.SourceContext source_context = 5;
@@ -422,13 +430,13 @@ const char* Api::_InternalParse(const char* begin, const char* end, void* object
       default: {
       handle_unusual: (void)&&handle_unusual;
         if ((tag & 7) == 4 || tag == 0) {
-          bool ok = ctx->ValidEndGroup(tag);
-          GOOGLE_PROTOBUF_PARSER_ASSERT(ok);
+          ctx->EndGroup(tag);
           return ptr;
         }
         auto res = UnknownFieldParse(tag, {_InternalParse, msg},
           ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
         ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
         if (res.second) return ptr;
       }
     }  // switch
@@ -439,7 +447,7 @@ len_delim_till_end: (void)&&len_delim_till_end;
                                  {parser_till_end, object}, size);
 group_continues: (void)&&group_continues;
   GOOGLE_DCHECK(ptr >= end);
-  ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth);
+  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
   return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
@@ -971,10 +979,10 @@ const char* Method::_InternalParse(const char* begin, const char* end, void* obj
   auto msg = static_cast<Method*>(object);
   ::google::protobuf::uint32 size; (void)size;
   int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ::google::protobuf::uint32 tag;
     ptr = Varint::Parse32Inline(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
@@ -984,14 +992,17 @@ const char* Method::_InternalParse(const char* begin, const char* end, void* obj
         ptr = Varint::Parse32Inline(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Method.name");
-        parser_till_end = ::google::protobuf::internal::StringParserUTF8;
-        ::std::string* str = msg->mutable_name();
-        str->clear();
-        object = str;
-        if (size > end - ptr) goto len_delim_till_end;
-        auto newend = ptr + size;
-        if (size) ptr = parser_till_end(ptr, newend, object, ctx);
-        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+        auto str = msg->mutable_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          object = str;
+          str->clear();
+          str->reserve(size);
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto len_delim_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx);
+        ptr += size;
         break;
       }
       // string request_type_url = 2;
@@ -1000,14 +1011,17 @@ const char* Method::_InternalParse(const char* begin, const char* end, void* obj
         ptr = Varint::Parse32Inline(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Method.request_type_url");
-        parser_till_end = ::google::protobuf::internal::StringParserUTF8;
-        ::std::string* str = msg->mutable_request_type_url();
-        str->clear();
-        object = str;
-        if (size > end - ptr) goto len_delim_till_end;
-        auto newend = ptr + size;
-        if (size) ptr = parser_till_end(ptr, newend, object, ctx);
-        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+        auto str = msg->mutable_request_type_url();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          object = str;
+          str->clear();
+          str->reserve(size);
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto len_delim_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx);
+        ptr += size;
         break;
       }
       // bool request_streaming = 3;
@@ -1026,14 +1040,17 @@ const char* Method::_InternalParse(const char* begin, const char* end, void* obj
         ptr = Varint::Parse32Inline(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Method.response_type_url");
-        parser_till_end = ::google::protobuf::internal::StringParserUTF8;
-        ::std::string* str = msg->mutable_response_type_url();
-        str->clear();
-        object = str;
-        if (size > end - ptr) goto len_delim_till_end;
-        auto newend = ptr + size;
-        if (size) ptr = parser_till_end(ptr, newend, object, ctx);
-        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+        auto str = msg->mutable_response_type_url();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          object = str;
+          str->clear();
+          str->reserve(size);
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto len_delim_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx);
+        ptr += size;
         break;
       }
       // bool response_streaming = 5;
@@ -1077,13 +1094,13 @@ const char* Method::_InternalParse(const char* begin, const char* end, void* obj
       default: {
       handle_unusual: (void)&&handle_unusual;
         if ((tag & 7) == 4 || tag == 0) {
-          bool ok = ctx->ValidEndGroup(tag);
-          GOOGLE_PROTOBUF_PARSER_ASSERT(ok);
+          ctx->EndGroup(tag);
           return ptr;
         }
         auto res = UnknownFieldParse(tag, {_InternalParse, msg},
           ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
         ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
         if (res.second) return ptr;
       }
     }  // switch
@@ -1094,7 +1111,7 @@ len_delim_till_end: (void)&&len_delim_till_end;
                                  {parser_till_end, object}, size);
 group_continues: (void)&&group_continues;
   GOOGLE_DCHECK(ptr >= end);
-  ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth);
+  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
   return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
@@ -1596,10 +1613,10 @@ const char* Mixin::_InternalParse(const char* begin, const char* end, void* obje
   auto msg = static_cast<Mixin*>(object);
   ::google::protobuf::uint32 size; (void)size;
   int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
   ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
   auto ptr = begin;
   while (ptr < end) {
-    ::google::protobuf::uint32 tag;
     ptr = Varint::Parse32Inline(ptr, &tag);
     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
     switch (tag >> 3) {
@@ -1609,14 +1626,17 @@ const char* Mixin::_InternalParse(const char* begin, const char* end, void* obje
         ptr = Varint::Parse32Inline(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Mixin.name");
-        parser_till_end = ::google::protobuf::internal::StringParserUTF8;
-        ::std::string* str = msg->mutable_name();
-        str->clear();
-        object = str;
-        if (size > end - ptr) goto len_delim_till_end;
-        auto newend = ptr + size;
-        if (size) ptr = parser_till_end(ptr, newend, object, ctx);
-        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+        auto str = msg->mutable_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          object = str;
+          str->clear();
+          str->reserve(size);
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto len_delim_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx);
+        ptr += size;
         break;
       }
       // string root = 2;
@@ -1625,26 +1645,29 @@ const char* Mixin::_InternalParse(const char* begin, const char* end, void* obje
         ptr = Varint::Parse32Inline(ptr, &size);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
         ctx->extra_parse_data().SetFieldName("google.protobuf.Mixin.root");
-        parser_till_end = ::google::protobuf::internal::StringParserUTF8;
-        ::std::string* str = msg->mutable_root();
-        str->clear();
-        object = str;
-        if (size > end - ptr) goto len_delim_till_end;
-        auto newend = ptr + size;
-        if (size) ptr = parser_till_end(ptr, newend, object, ctx);
-        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+        auto str = msg->mutable_root();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          object = str;
+          str->clear();
+          str->reserve(size);
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto len_delim_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx);
+        ptr += size;
         break;
       }
       default: {
       handle_unusual: (void)&&handle_unusual;
         if ((tag & 7) == 4 || tag == 0) {
-          bool ok = ctx->ValidEndGroup(tag);
-          GOOGLE_PROTOBUF_PARSER_ASSERT(ok);
+          ctx->EndGroup(tag);
           return ptr;
         }
         auto res = UnknownFieldParse(tag, {_InternalParse, msg},
           ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
         ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
         if (res.second) return ptr;
       }
     }  // switch
@@ -1655,7 +1678,7 @@ len_delim_till_end: (void)&&len_delim_till_end;
                                  {parser_till_end, object}, size);
 group_continues: (void)&&group_continues;
   GOOGLE_DCHECK(ptr >= end);
-  ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth);
+  GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth, tag));
   return ptr;
 }
 #else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

+ 3 - 3
src/google/protobuf/api.pb.h

@@ -128,7 +128,7 @@ class PROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_inser
   void MergeFrom(const ::google::protobuf::Message& from) final;
   void CopyFrom(const Api& from);
   void MergeFrom(const Api& from);
-  void Clear() final;
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
@@ -318,7 +318,7 @@ class PROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc_in
   void MergeFrom(const ::google::protobuf::Message& from) final;
   void CopyFrom(const Method& from);
   void MergeFrom(const Method& from);
-  void Clear() final;
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;
@@ -501,7 +501,7 @@ class PROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_ins
   void MergeFrom(const ::google::protobuf::Message& from) final;
   void CopyFrom(const Mixin& from);
   void MergeFrom(const Mixin& from);
-  void Clear() final;
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
   size_t ByteSizeLong() const final;

+ 14 - 15
src/google/protobuf/arena.cc

@@ -33,6 +33,7 @@
 #include <algorithm>
 #include <limits>
 
+#include <google/protobuf/stubs/mutex.h>
 
 #ifdef ADDRESS_SANITIZER
 #include <sanitizer/asan_interface.h>
@@ -323,24 +324,22 @@ void ArenaImpl::SerialArena::CleanupList() {
 }
 
 void ArenaImpl::SerialArena::CleanupListFallback() {
-  // Cleanup newest chunk: ptrs give us length.
+  // The first chunk might be only partially full, so calculate its size
+  // from cleanup_ptr_. Subsequent chunks are always full, so use list->size.
   size_t n = cleanup_ptr_ - &cleanup_->nodes[0];
-  CleanupNode* node = cleanup_ptr_;
-  for (size_t i = 0; i < n; i++) {
-    --node;
-    node->cleanup(node->elem);
-  }
-
-  // Cleanup older chunks, which are known to be full.
-  CleanupChunk* list = cleanup_->next;
-  while (list) {
-    size_t n = list->size;
-    CleanupNode* node = &list->nodes[list->size];
-    for (size_t i = 0; i < n; i++) {
-      --node;
-      node->cleanup(node->elem);
+  CleanupChunk* list = cleanup_;
+  while (true) {
+    CleanupNode* node = &list->nodes[0];
+    // Cleanup newest elements first (allocated last).
+    for (size_t i = n; i > 0; i--) {
+      node[i - 1].cleanup(node[i - 1].elem);
     }
     list = list->next;
+    if (list == nullptr) {
+      break;
+    }
+    // All but the first chunk are always full.
+    n = list->size;
   }
 }
 

+ 4 - 2
src/google/protobuf/arena_impl.h

@@ -306,8 +306,10 @@ class PROTOBUF_EXPORT ArenaImpl {
  public:
   // kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8
   // to protect the invariant that pos is always at a multiple of 8.
-  static const size_t kBlockHeaderSize = (sizeof(Block) + 7) & static_cast<size_t>(-8);
-  static const size_t kSerialArenaSize = (sizeof(SerialArena) + 7) & static_cast<size_t>(-8);
+  static const size_t kBlockHeaderSize =
+      (sizeof(Block) + 7) & static_cast<size_t>(-8);
+  static const size_t kSerialArenaSize =
+      (sizeof(SerialArena) + 7) & static_cast<size_t>(-8);
   static_assert(kBlockHeaderSize % 8 == 0,
                 "kBlockHeaderSize must be a multiple of 8.");
   static_assert(kSerialArenaSize % 8 == 0,

+ 1 - 1
src/google/protobuf/arena_unittest.cc

@@ -55,7 +55,7 @@
 #include <google/protobuf/unknown_field_set.h>
 #include <google/protobuf/wire_format_lite.h>
 #include <gtest/gtest.h>
-
+#include <google/protobuf/stubs/strutil.h>
 
 
 using proto2_arena_unittest::ArenaMessage;

+ 88 - 47
src/google/protobuf/compiler/command_line_interface.cc

@@ -834,35 +834,51 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
   }
 
   std::vector<const FileDescriptor*> parsed_files;
-  // null unless descriptor_set_in_names_.empty()
   std::unique_ptr<DiskSourceTree> disk_source_tree;
   std::unique_ptr<ErrorPrinter> error_collector;
   std::unique_ptr<DescriptorPool> descriptor_pool;
-  std::unique_ptr<DescriptorDatabase> descriptor_database;
-  if (descriptor_set_in_names_.empty()) {
+  std::unique_ptr<SimpleDescriptorDatabase> descriptor_set_in_database;
+  std::unique_ptr<SourceTreeDescriptorDatabase> source_tree_database;
+
+  // Any --descriptor_set_in FileDescriptorSet objects will be used as a
+  // fallback to input_files on command line, so create that db first.
+  if (!descriptor_set_in_names_.empty()) {
+    descriptor_set_in_database.reset(new SimpleDescriptorDatabase());
+    if (!PopulateSimpleDescriptorDatabase(descriptor_set_in_database.get())) {
+      return 1;
+    }
+  }
+
+  if (proto_path_.empty()) {
+    // If there are no --proto_path flags, then just look in the specified
+    // --descriptor_set_in files.  But first, verify that the input files are
+    // there.
+    if (!VerifyInputFilesInDescriptors(descriptor_set_in_database.get())) {
+      return 1;
+    }
+
+    error_collector.reset(new ErrorPrinter(error_format_));
+    descriptor_pool.reset(new DescriptorPool(descriptor_set_in_database.get(),
+                                             error_collector.get()));
+  } else {
     disk_source_tree.reset(new DiskSourceTree());
-    if (!InitializeDiskSourceTree(disk_source_tree.get())) {
+    if (!InitializeDiskSourceTree(disk_source_tree.get(),
+                                  descriptor_set_in_database.get())) {
       return 1;
     }
+
     error_collector.reset(
         new ErrorPrinter(error_format_, disk_source_tree.get()));
 
-    SourceTreeDescriptorDatabase* database =
-        new SourceTreeDescriptorDatabase(disk_source_tree.get());
-    database->RecordErrorsTo(error_collector.get());
-    descriptor_database.reset(database);
-    descriptor_pool.reset(new DescriptorPool(
-        descriptor_database.get(), database->GetValidationErrorCollector()));
-  } else {
-    error_collector.reset(new ErrorPrinter(error_format_));
+    source_tree_database.reset(new SourceTreeDescriptorDatabase(
+        disk_source_tree.get(), descriptor_set_in_database.get()));
+    source_tree_database->RecordErrorsTo(error_collector.get());
 
-    SimpleDescriptorDatabase* database = new SimpleDescriptorDatabase();
-    descriptor_database.reset(database);
-    if (!PopulateSimpleDescriptorDatabase(database)) {
-      return 1;
-    }
-    descriptor_pool.reset(new DescriptorPool(database, error_collector.get()));
+    descriptor_pool.reset(new DescriptorPool(
+        source_tree_database.get(),
+        source_tree_database->GetValidationErrorCollector()));
   }
+
   descriptor_pool->EnforceWeakDependencies(true);
   if (!ParseInputFiles(descriptor_pool.get(), &parsed_files)) {
     return 1;
@@ -980,7 +996,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
 }
 
 bool CommandLineInterface::InitializeDiskSourceTree(
-    DiskSourceTree* source_tree) {
+    DiskSourceTree* source_tree, DescriptorDatabase* fallback_database) {
   AddDefaultProtoPaths(&proto_path_);
 
   // Set up the source tree.
@@ -989,7 +1005,7 @@ bool CommandLineInterface::InitializeDiskSourceTree(
   }
 
   // Map input files to virtual paths if possible.
-  if (!MakeInputsBeProtoPathRelative(source_tree)) {
+  if (!MakeInputsBeProtoPathRelative(source_tree, fallback_database)) {
     return false;
   }
 
@@ -1039,6 +1055,27 @@ bool CommandLineInterface::PopulateSimpleDescriptorDatabase(
   return true;
 }
 
+bool CommandLineInterface::VerifyInputFilesInDescriptors(
+    DescriptorDatabase* database) {
+  for (const auto& input_file : input_files_) {
+    FileDescriptorProto file_descriptor;
+    if (!database->FindFileByName(input_file, &file_descriptor)) {
+      std::cerr << input_file << ": " << strerror(ENOENT) << std::endl;
+      return false;
+    }
+
+    // Enforce --disallow_services.
+    if (disallow_services_ && file_descriptor.service_size() > 0) {
+      std::cerr << file_descriptor.name()
+                << ": This file contains services, but "
+                   "--disallow_services was used."
+                << std::endl;
+      return false;
+    }
+  }
+  return true;
+}
+
 bool CommandLineInterface::ParseInputFiles(
     DescriptorPool* descriptor_pool,
     std::vector<const FileDescriptor*>* parsed_files) {
@@ -1051,9 +1088,6 @@ bool CommandLineInterface::ParseInputFiles(
         descriptor_pool->FindFileByName(input_file);
     descriptor_pool->ClearUnusedImportTrackFiles();
     if (parsed_file == NULL) {
-      if (!descriptor_set_in_names_.empty()) {
-        std::cerr << input_file << ": " << strerror(ENOENT) << std::endl;
-      }
       return false;
     }
     parsed_files->push_back(parsed_file);
@@ -1111,18 +1145,27 @@ void CommandLineInterface::Clear() {
 }
 
 bool CommandLineInterface::MakeProtoProtoPathRelative(
-    DiskSourceTree* source_tree, string* proto) {
+    DiskSourceTree* source_tree, string* proto,
+    DescriptorDatabase* fallback_database) {
+  // If it's in the fallback db, don't report non-existent file errors.
+  FileDescriptorProto fallback_file;
+  bool in_fallback_database =
+      fallback_database != nullptr &&
+      fallback_database->FindFileByName(*proto, &fallback_file);
+
   // If the input file path is not a physical file path, it must be a virtual
   // path.
   if (access(proto->c_str(), F_OK) < 0) {
     string disk_file;
-    if (source_tree->VirtualFileToDiskFile(*proto, &disk_file)) {
+    if (source_tree->VirtualFileToDiskFile(*proto, &disk_file) ||
+        in_fallback_database) {
       return true;
     } else {
       std::cerr << *proto << ": " << strerror(ENOENT) << std::endl;
       return false;
     }
   }
+
   string virtual_file, shadowing_disk_file;
   switch (source_tree->DiskFileToVirtualFile(
       *proto, &virtual_file, &shadowing_disk_file)) {
@@ -1138,13 +1181,17 @@ bool CommandLineInterface::MakeProtoProtoPathRelative(
                    "comes first." << std::endl;
       return false;
     case DiskSourceTree::CANNOT_OPEN:
+      if (in_fallback_database) {
+        return true;
+      }
       std::cerr << *proto << ": " << strerror(errno) << std::endl;
       return false;
     case DiskSourceTree::NO_MAPPING: {
       // Try to interpret the path as a virtual path.
       string disk_file;
-      if (source_tree->VirtualFileToDiskFile(*proto, &disk_file)) {
-       return true;
+      if (source_tree->VirtualFileToDiskFile(*proto, &disk_file) ||
+          in_fallback_database) {
+        return true;
       } else {
         // The input file path can't be mapped to any --proto_path and it also
         // can't be interpreted as a virtual path.
@@ -1166,9 +1213,10 @@ bool CommandLineInterface::MakeProtoProtoPathRelative(
 }
 
 bool CommandLineInterface::MakeInputsBeProtoPathRelative(
-    DiskSourceTree* source_tree) {
+    DiskSourceTree* source_tree, DescriptorDatabase* fallback_database) {
   for (auto& input_file : input_files_) {
-    if (!MakeProtoProtoPathRelative(source_tree, &input_file)) {
+    if (!MakeProtoProtoPathRelative(source_tree, &input_file,
+                                    fallback_database)) {
       return false;
     }
   }
@@ -1270,15 +1318,16 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
     return PARSE_ARGUMENT_FAIL;
   }
 
-  // If no --proto_path was given, use the current working directory.
-  if (proto_path_.empty()) {
+  // The --proto_path & --descriptor_set_in flags both specify places to look
+  // for proto files. If neither were given, use the current working directory.
+  if (proto_path_.empty() && descriptor_set_in_names_.empty()) {
     // Don't use make_pair as the old/default standard library on Solaris
     // doesn't support it without explicit template parameters, which are
     // incompatible with C++0x's make_pair.
     proto_path_.push_back(std::pair<string, string>("", "."));
   }
 
-  // Check some errror cases.
+  // Check some error cases.
   bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
   if (decoding_raw && !input_files_.empty()) {
     std::cerr << "When using --decode_raw, no input files should be given."
@@ -1395,13 +1444,6 @@ CommandLineInterface::InterpretArgument(const string& name,
     input_files_.push_back(value);
 
   } else if (name == "-I" || name == "--proto_path") {
-    if (!descriptor_set_in_names_.empty()) {
-      std::cerr << "Only one of " << name
-                << " and --descriptor_set_in can be specified."
-                << std::endl;
-      return PARSE_ARGUMENT_FAIL;
-    }
-
     // Java's -classpath (and some other languages) delimits path components
     // with colons.  Let's accept that syntax too just to make things more
     // intuitive.
@@ -1477,12 +1519,6 @@ CommandLineInterface::InterpretArgument(const string& name,
       std::cerr << name << " requires a non-empty value." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
-    if (!proto_path_.empty()) {
-      std::cerr << "Only one of " << name
-                << " and --proto_path can be specified."
-                << std::endl;
-      return PARSE_ARGUMENT_FAIL;
-    }
     if (!dependency_out_name_.empty()) {
       std::cerr << name << " cannot be used with --dependency_out."
                 << std::endl;
@@ -1698,13 +1734,18 @@ CommandLineInterface::InterpretArgument(const string& name,
 
 void CommandLineInterface::PrintHelpText() {
   // Sorry for indentation here; line wrapping would be uglier.
-  std::cout <<
-"Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n"
+  std::cout
+      <<
+      "Usage: " << executable_name_
+      << " [OPTION] PROTO_FILES\n"
 "Parse PROTO_FILES and generate output based on the options given:\n"
 "  -IPATH, --proto_path=PATH   Specify the directory in which to search for\n"
 "                              imports.  May be specified multiple times;\n"
 "                              directories will be searched in order.  If not\n"
 "                              given, the current working directory is used.\n"
+"                              If not found in any of the these directories,\n"
+"                              the --descriptor_set_in descriptors will be\n"
+"                              checked for required proto file.\n"
 "  --version                   Show version info and exit.\n"
 "  -h, --help                  Show this text and exit.\n"
 "  --encode=MESSAGE_TYPE       Read a text-format message of the given type\n"

+ 11 - 5
src/google/protobuf/compiler/command_line_interface.h

@@ -53,6 +53,7 @@ namespace google {
 namespace protobuf {
 
 class Descriptor;            // descriptor.h
+class DescriptorDatabase;    // descriptor_database.h
 class DescriptorPool;        // descriptor.h
 class FileDescriptor;        // descriptor.h
 class FileDescriptorSet;     // descriptor.h
@@ -214,14 +215,15 @@ class PROTOC_EXPORT CommandLineInterface {
   // Clear state from previous Run().
   void Clear();
 
-  // Remaps the proto file so that it is relative to one of the ddirectories
+  // Remaps the proto file so that it is relative to one of the directories
   // in proto_path_.  Returns false if an error occurred.
-  bool MakeProtoProtoPathRelative(DiskSourceTree* source_tree, std::string* proto);
+  bool MakeProtoProtoPathRelative(DiskSourceTree* source_tree, std::string* proto,
+                                  DescriptorDatabase* fallback_database);
 
   // Remaps each file in input_files_ so that it is relative to one of the
   // directories in proto_path_.  Returns false if an error occurred.
-  bool MakeInputsBeProtoPathRelative(
-    DiskSourceTree* source_tree);
+  bool MakeInputsBeProtoPathRelative(DiskSourceTree* source_tree,
+                                     DescriptorDatabase* fallback_database);
 
 
   // Return status for ParseArguments() and InterpretArgument().
@@ -259,7 +261,11 @@ class PROTOC_EXPORT CommandLineInterface {
   void PrintHelpText();
 
   // Loads proto_path_ into the provided source_tree.
-  bool InitializeDiskSourceTree(DiskSourceTree* source_tree);
+  bool InitializeDiskSourceTree(DiskSourceTree* source_tree,
+                                DescriptorDatabase* fallback_database);
+
+  // Verify that all the input files exist in the given database.
+  bool VerifyInputFilesInDescriptors(DescriptorDatabase* fallback_database);
 
   // Loads descriptor_set_in into the provided database
   bool PopulateSimpleDescriptorDatabase(SimpleDescriptorDatabase* database);

+ 40 - 10
src/google/protobuf/compiler/command_line_interface_unittest.cc

@@ -299,7 +299,6 @@ void CommandLineInterfaceTest::Run(const string& command) {
 void CommandLineInterfaceTest::RunWithArgs(std::vector<string> args) {
   if (!disallow_plugins_) {
     cli_.AllowPlugins("prefix-");
-#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
     string plugin_path;
 #ifdef GOOGLE_PROTOBUF_TEST_PLUGIN_PATH
     plugin_path = GOOGLE_PROTOBUF_TEST_PLUGIN_PATH;
@@ -330,11 +329,6 @@ void CommandLineInterfaceTest::RunWithArgs(std::vector<string> args) {
 #endif
 
     if (plugin_path.empty()) {
-#else
-    string plugin_path = "third_party/protobuf/test_plugin";
-
-    if (access(plugin_path.c_str(), F_OK) != 0) {
-#endif  // GOOGLE_THIRD_PARTY_PROTOBUF
       GOOGLE_LOG(ERROR)
           << "Plugin executable not found.  Plugin tests are likely to fail.";
     } else {
@@ -1761,13 +1755,49 @@ TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) {
 TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn) {
   Run("protocol_compiler --test_out=$tmpdir "
       "--proto_path=$tmpdir --descriptor_set_in=$tmpdir/foo.bin foo.proto");
-  ExpectErrorText(
-      "Only one of --descriptor_set_in and --proto_path can be specified.\n");
+  ExpectErrorText("$tmpdir/foo.bin: No such file or directory\n");
 
   Run("protocol_compiler --test_out=$tmpdir "
       "--descriptor_set_in=$tmpdir/foo.bin --proto_path=$tmpdir foo.proto");
-  ExpectErrorText(
-      "Only one of --proto_path and --descriptor_set_in can be specified.\n");
+  ExpectErrorText("$tmpdir/foo.bin: No such file or directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn_CompileFiles) {
+  // Test what happens if a proto is in a --descriptor_set_in and also exists
+  // on disk.
+  FileDescriptorSet file_descriptor_set;
+
+  // NOTE: This file desc SHOULD be different from the one created as a temp
+  //       to make it easier to test that the file was output instead of the
+  //       contents of the --descriptor_set_in file.
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "message FooBar { required string foo_message = 1; }\n");
+
+  Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+      "--descriptor_set_in=$tmpdir/foo.bin "
+      "--include_source_info "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+
+  FileDescriptorSet descriptor_set;
+  ReadDescriptorSet("descriptor_set", &descriptor_set);
+
+  EXPECT_EQ(1, descriptor_set.file_size());
+  EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+  // Descriptor set SHOULD have source code info.
+  EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
+
+  EXPECT_EQ("FooBar", descriptor_set.file(0).message_type(0).name());
+  EXPECT_EQ("foo_message",
+            descriptor_set.file(0).message_type(0).field(0).name());
 }
 
 TEST_F(CommandLineInterfaceTest, ProtoPathAndDependencyOut) {

+ 4 - 0
src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc

@@ -161,6 +161,10 @@ TEST(BootstrapTest, GeneratedFilesMatch) {
     EXPECT_EQ("", error_collector.text_);
     CppGenerator generator;
     MockGeneratorContext context;
+#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE
+    generator.set_opensource_runtime(true);
+    generator.set_runtime_include_base(GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE);
+#endif
     string error;
     ASSERT_TRUE(generator.Generate(file, file_parameter[1], &context, &error));
 

+ 44 - 28
src/google/protobuf/compiler/cpp/cpp_file.cc

@@ -256,8 +256,6 @@ void FileGenerator::GenerateProtoHeader(io::Printer* printer,
 
   GenerateHeader(printer);
 
-  IncludeFile("net/proto2/public/port_undef.inc", printer);
-
   GenerateBottomHeaderGuard(printer, filename_identifier);
 }
 
@@ -320,13 +318,11 @@ void FileGenerator::DoIncludeFile(const string& google3_name, bool do_export,
     path = StringReplace(path, "internal/", "", false);
     path = StringReplace(path, "proto/", "", false);
     path = StringReplace(path, "public/", "", false);
-    if (options_.opensource_include_paths) {
+    if (options_.runtime_include_base.empty()) {
       format("#include <google/protobuf/$1$>", path);
     } else {
-      format(
-          "#include "
-          "\"third_party/protobuf/testing/extracted/src/google/protobuf/$1$\"",
-          path);
+      format("#include \"$1$google/protobuf/$2$\"",
+             options_.runtime_include_base, path);
     }
   } else {
     format("#include \"$1$\"", google3_name);
@@ -346,10 +342,10 @@ string FileGenerator::CreateHeaderInclude(const string& basename,
 
   if (options_.opensource_runtime) {
     if (IsWellKnownMessage(file)) {
-      if (options_.opensource_include_paths) {
+      if (options_.runtime_include_base.empty()) {
         use_system_include = true;
       } else {
-        name = "third_party/protobuf/testing/extracted/src/" + basename;
+        name = options_.runtime_include_base + basename;
       }
     }
   }
@@ -809,36 +805,56 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
       "\n",
       message_generators_.size());
 
-  // Now generate the AddDescriptors() function.
-  format(
-      "::$proto_ns$::internal::DescriptorTable $1$ = {\n"
-      "  false, $init_defaults$, \n",
-      UniqueName("descriptor_table", file_, options_));
-  format.Indent();
-
   // Embed the descriptor.  We simply serialize the entire
-  // FileDescriptorProto
-  // and embed it as a string literal, which is parsed and built into real
-  // descriptors at initialization time.
+  // FileDescriptorProto/ and embed it as a string literal, which is parsed and
+  // built into real descriptors at initialization time.
+  const string protodef_name =
+      UniqueName("descriptor_table_protodef", file_, options_);
+  format( "const char $1$[] =\n", protodef_name);
+  format.Indent();
   FileDescriptorProto file_proto;
   file_->CopyTo(&file_proto);
   string file_data;
   file_proto.SerializeToString(&file_data);
 
   {
-    // Only write 40 bytes per line.
-    static const int kBytesPerLine = 40;
-    for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
-      format(
-          "\"$1$\"\n",
-          EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
+    if (file_data.size() > 65535) {
+      // Workaround for MSVC: "Error C1091: compiler limit: string exceeds
+      // 65535 bytes in length". Declare a static array of chars rather than
+      // use a string literal. Only write 25 bytes per line.
+      static const int kBytesPerLine = 25;
+      format("{ ");
+      for (int i = 0; i < file_data.size();) {
+        for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
+          format("'$1$', ", CEscape(file_data.substr(i, 1)));
+        }
+        format("\n");
+      }
+      format("'\\0' }");  // null-terminate
+    } else {
+      // Only write 40 bytes per line.
+      static const int kBytesPerLine = 40;
+      for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
+        format(
+            "\"$1$\"\n",
+            EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
+      }
     }
+    format(";\n");
   }
-
   format.Outdent();
+
+  // Now generate the AddDescriptors() function.
+  format(
+      "::$proto_ns$::internal::DescriptorTable $1$ = {\n"
+      "  false, $init_defaults$, \n"
+      "  $2$,\n",
+      UniqueName("descriptor_table", file_, options_),
+      protodef_name);
+
   const int num_deps = file_->dependency_count();
   format(
-      ",\n  \"$filename$\", &$assign_desc_table$, $1$,\n"
+      "  \"$filename$\", &$assign_desc_table$, $1$,\n"
       "};\n\n"
       "void $add_descriptors$() {\n"
       "  static constexpr ::$proto_ns$::internal::InitFunc deps[$2$] =\n"
@@ -1277,7 +1293,7 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
     IncludeFile("net/proto2/public/unknown_field_set.h", printer);
   }
 
-  if (IsAnyMessage(file_)) {
+  if (IsAnyMessage(file_, options_)) {
     IncludeFile("net/proto2/internal/any.h", printer);
   }
 }

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels