Merge from Google internal for 3.4 release

pull/3393/head
Jisi Liu 7 years ago
parent 9053033a50
commit 09354db143
  1. 2
      Makefile.am
  2. 3
      cmake/extract_includes.bat.in
  3. 1
      cmake/libprotoc.cmake
  4. 1
      cmake/tests.cmake
  5. 7
      conformance/conformance_test.cc
  6. 2
      conformance/failure_list_cpp.txt
  7. 601
      conformance/failure_list_python.txt
  8. 589
      conformance/failure_list_python_cpp.txt
  9. 35
      generate_descriptor_proto.sh
  10. 3
      java/core/generate-test-sources-build.xml
  11. 27
      java/core/src/main/java/com/google/protobuf/AbstractMessage.java
  12. 84
      java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
  13. 299
      java/core/src/main/java/com/google/protobuf/CodedInputStream.java
  14. 82
      java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
  15. 71
      java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java
  16. 10
      java/core/src/main/java/com/google/protobuf/DynamicMessage.java
  17. 7
      java/core/src/main/java/com/google/protobuf/Extension.java
  18. 5
      java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
  19. 78
      java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
  20. 93
      java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
  21. 5
      java/core/src/main/java/com/google/protobuf/Internal.java
  22. 4
      java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
  23. 24
      java/core/src/main/java/com/google/protobuf/MessageReflection.java
  24. 211
      java/core/src/main/java/com/google/protobuf/TextFormat.java
  25. 2
      java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
  26. 173
      java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
  27. 33
      java/core/src/main/java/com/google/protobuf/Utf8.java
  28. 6
      java/core/src/main/java/com/google/protobuf/WireFormat.java
  29. 123
      java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
  30. 157
      java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java
  31. 12
      java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
  32. 78
      java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
  33. 214
      java/core/src/test/java/com/google/protobuf/LiteTest.java
  34. 8
      java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
  35. 8
      java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
  36. 8
      java/core/src/test/java/com/google/protobuf/MapTest.java
  37. 12
      java/core/src/test/java/com/google/protobuf/MessageTest.java
  38. 26
      java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
  39. 83
      java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java
  40. 28
      java/core/src/test/java/com/google/protobuf/TextFormatTest.java
  41. 14
      java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
  42. 17
      java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto
  43. 11
      java/util/src/main/java/com/google/protobuf/util/Durations.java
  44. 9
      java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
  45. 6
      java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
  46. 11
      java/util/src/main/java/com/google/protobuf/util/Timestamps.java
  47. 4
      java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
  48. 8
      js/binary/encoder.js
  49. 4
      js/binary/utils.js
  50. 10
      js/binary/writer.js
  51. 355
      js/compatibility_tests/v3.1.0/binary/arith_test.js
  52. 334
      js/compatibility_tests/v3.1.0/binary/decoder_test.js
  53. 628
      js/compatibility_tests/v3.1.0/binary/proto_test.js
  54. 922
      js/compatibility_tests/v3.1.0/binary/reader_test.js
  55. 668
      js/compatibility_tests/v3.1.0/binary/utils_test.js
  56. 122
      js/compatibility_tests/v3.1.0/binary/writer_test.js
  57. 40
      js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto
  58. 42
      js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto
  59. 51
      js/compatibility_tests/v3.1.0/data.proto
  60. 105
      js/compatibility_tests/v3.1.0/debug_test.js
  61. 301
      js/compatibility_tests/v3.1.0/maps_test.js
  62. 1037
      js/compatibility_tests/v3.1.0/message_test.js
  63. 329
      js/compatibility_tests/v3.1.0/proto3_test.js
  64. 89
      js/compatibility_tests/v3.1.0/proto3_test.proto
  65. 262
      js/compatibility_tests/v3.1.0/test.proto
  66. 54
      js/compatibility_tests/v3.1.0/test2.proto
  67. 53
      js/compatibility_tests/v3.1.0/test3.proto
  68. 42
      js/compatibility_tests/v3.1.0/test4.proto
  69. 44
      js/compatibility_tests/v3.1.0/test5.proto
  70. 212
      js/compatibility_tests/v3.1.0/testbinary.proto
  71. 34
      js/compatibility_tests/v3.1.0/testempty.proto
  72. 86
      js/message.js
  73. 18
      js/message_test.js
  74. 1
      js/proto3_test.proto
  75. 8
      js/test.proto
  76. 3
      python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py
  77. 9
      python/google/protobuf/descriptor.py
  78. 3
      python/google/protobuf/descriptor_database.py
  79. 21
      python/google/protobuf/descriptor_pool.py
  80. 26
      python/google/protobuf/internal/api_implementation.py
  81. 46
      python/google/protobuf/internal/descriptor_pool_test.py
  82. 6
      python/google/protobuf/internal/descriptor_test.py
  83. 107
      python/google/protobuf/internal/encoder.py
  84. 5
      python/google/protobuf/internal/factory_test2.proto
  85. 103
      python/google/protobuf/internal/json_format_test.py
  86. 92
      python/google/protobuf/internal/message_test.py
  87. 1
      python/google/protobuf/internal/more_extensions_dynamic.proto
  88. 18
      python/google/protobuf/internal/python_message.py
  89. 151
      python/google/protobuf/internal/text_format_test.py
  90. 4
      python/google/protobuf/internal/well_known_types.py
  91. 2
      python/google/protobuf/internal/well_known_types_test.py
  92. 54
      python/google/protobuf/json_format.py
  93. 16
      python/google/protobuf/message.py
  94. 14
      python/google/protobuf/message_factory.py
  95. 10
      python/google/protobuf/pyext/descriptor.cc
  96. 24
      python/google/protobuf/pyext/map_container.cc
  97. 62
      python/google/protobuf/pyext/message.cc
  98. 11
      python/google/protobuf/pyext/message_factory.cc
  99. 22
      python/google/protobuf/pyext/repeated_composite_container.cc
  100. 14
      python/google/protobuf/pyext/repeated_scalar_container.cc
  101. Some files were not shown because too many files have changed in this diff Show More

@ -713,7 +713,6 @@ python_EXTRA_DIST= \
python/google/protobuf/internal/packed_field_test.proto \
python/google/protobuf/internal/proto_builder_test.py \
python/google/protobuf/internal/python_message.py \
python/google/protobuf/internal/python_protobuf.cc \
python/google/protobuf/internal/reflection_test.py \
python/google/protobuf/internal/service_reflection_test.py \
python/google/protobuf/internal/symbol_database_test.py \
@ -762,7 +761,6 @@ python_EXTRA_DIST= \
python/google/protobuf/pyext/repeated_scalar_container.h \
python/google/protobuf/pyext/safe_numerics.h \
python/google/protobuf/pyext/scoped_pyobject_ptr.h \
python/google/protobuf/python_protobuf.h \
python/google/protobuf/reflection.py \
python/google/protobuf/service.py \
python/google/protobuf/service_reflection.py \

@ -36,7 +36,6 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\parser.h" in
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\php\php_generator.h" include\google\protobuf\compiler\php\php_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.h" include\google\protobuf\compiler\plugin.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.pb.h" include\google\protobuf\compiler\plugin.pb.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\profile.pb.h" include\google\protobuf\compiler\profile.pb.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\python_generator.h" include\google\protobuf\compiler\python\python_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\ruby\ruby_generator.h" include\google\protobuf\compiler\ruby\ruby_generator.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.h" include\google\protobuf\descriptor.h
@ -50,6 +49,7 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.pb.h" incl
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_reflection.h" include\google\protobuf\generated_enum_reflection.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h" include\google\protobuf\generated_enum_util.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_reflection.h" include\google\protobuf\generated_message_reflection.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_table_driven.h" include\google\protobuf\generated_message_table_driven.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h" include\google\protobuf\generated_message_util.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\has_bits.h" include\google\protobuf\has_bits.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h" include\google\protobuf\io\coded_stream.h
@ -70,6 +70,7 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_type_handler.h" i
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message.h" include\google\protobuf\message.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message_lite.h" include\google\protobuf\message_lite.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h" include\google\protobuf\metadata.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata_lite.h" include\google\protobuf\metadata_lite.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h" include\google\protobuf\reflection.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h" include\google\protobuf\reflection_ops.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h" include\google\protobuf\repeated_field.h

@ -88,7 +88,6 @@ set(libprotoc_files
${protobuf_source_dir}/src/google/protobuf/compiler/php/php_generator.cc
${protobuf_source_dir}/src/google/protobuf/compiler/plugin.cc
${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.cc
${protobuf_source_dir}/src/google/protobuf/compiler/profile.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/subprocess.cc

@ -123,6 +123,7 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/arenastring_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_unittest.cc
${protobuf_source_dir}/src/google/protobuf/compiler/cpp/metadata_test.cc

@ -1516,9 +1516,10 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
"BytesField", REQUIRED,
R"({"optionalBytes": "AQI="})",
R"(optional_bytes: "\x01\x02")");
ExpectParseFailureForJson(
"BytesFieldInvalidBase64Characters", REQUIRED,
R"({"optionalBytes": "-_=="})");
RunValidJsonTest(
"BytesFieldBase64Url", RECOMMENDED,
R"({"optionalBytes": "-_"})",
R"(optional_bytes: "\xfb")");
// Message fields.
RunValidJsonTest(

@ -12,6 +12,8 @@ Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.JsonInput.BoolFieldDoubleQuotedFalse
Recommended.JsonInput.BoolFieldDoubleQuotedTrue
Recommended.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.JsonInput.FieldMaskInvalidCharacter
Recommended.JsonInput.FieldNameDuplicate
Recommended.JsonInput.FieldNameDuplicateDifferentCasing1

@ -1,17 +1,616 @@
Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.JsonInput.BoolFieldAllCapitalFalse
Recommended.JsonInput.BoolFieldAllCapitalTrue
Recommended.JsonInput.BoolFieldCamelCaseFalse
Recommended.JsonInput.BoolFieldCamelCaseTrue
Recommended.JsonInput.BoolFieldDoubleQuotedFalse
Recommended.JsonInput.BoolFieldDoubleQuotedTrue
Recommended.JsonInput.BoolFieldIntegerOne
Recommended.JsonInput.BoolFieldIntegerZero
Recommended.JsonInput.BoolMapFieldKeyNotQuoted
Recommended.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.JsonInput.DoubleFieldInfinityNotQuoted
Recommended.JsonInput.DoubleFieldNanNotQuoted
Recommended.JsonInput.DoubleFieldNegativeInfinityNotQuoted
Recommended.JsonInput.DurationHas3FractionalDigits.Validator
Recommended.JsonInput.DurationHas6FractionalDigits.Validator
Recommended.JsonInput.DurationHas9FractionalDigits.Validator
Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator
Recommended.JsonInput.FieldMaskInvalidCharacter
Recommended.JsonInput.FieldNameDuplicate
Recommended.JsonInput.FieldNameDuplicateDifferentCasing1
Recommended.JsonInput.FieldNameDuplicateDifferentCasing2
Recommended.JsonInput.FieldNameNotQuoted
Recommended.JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.Validator
Recommended.JsonInput.FloatFieldInfinityNotQuoted
Recommended.JsonInput.FloatFieldNanNotQuoted
Recommended.JsonInput.FloatFieldNegativeInfinityNotQuoted
Required.JsonInput.BytesFieldInvalidBase64Characters
Recommended.JsonInput.Int32MapFieldKeyNotQuoted
Recommended.JsonInput.Int64FieldBeString.Validator
Recommended.JsonInput.Int64MapFieldKeyNotQuoted
Recommended.JsonInput.JsonWithComments
Recommended.JsonInput.MapFieldKeyIsNull
Recommended.JsonInput.MapFieldValueIsNull
Recommended.JsonInput.MissingCommaMultiline
Recommended.JsonInput.MissingCommaOneLine
Recommended.JsonInput.MultilineNoSpaces.JsonOutput
Recommended.JsonInput.MultilineNoSpaces.ProtobufOutput
Recommended.JsonInput.MultilineWithSpaces.JsonOutput
Recommended.JsonInput.MultilineWithSpaces.ProtobufOutput
Recommended.JsonInput.OneLineNoSpaces.JsonOutput
Recommended.JsonInput.OneLineNoSpaces.ProtobufOutput
Recommended.JsonInput.OneLineWithSpaces.JsonOutput
Recommended.JsonInput.OneLineWithSpaces.ProtobufOutput
Recommended.JsonInput.OneofZeroBool.JsonOutput
Recommended.JsonInput.OneofZeroBool.ProtobufOutput
Recommended.JsonInput.OneofZeroBytes.JsonOutput
Recommended.JsonInput.OneofZeroBytes.ProtobufOutput
Recommended.JsonInput.OneofZeroDouble.JsonOutput
Recommended.JsonInput.OneofZeroDouble.ProtobufOutput
Recommended.JsonInput.OneofZeroEnum.JsonOutput
Recommended.JsonInput.OneofZeroEnum.ProtobufOutput
Recommended.JsonInput.OneofZeroFloat.JsonOutput
Recommended.JsonInput.OneofZeroFloat.ProtobufOutput
Recommended.JsonInput.OneofZeroMessage.JsonOutput
Recommended.JsonInput.OneofZeroMessage.ProtobufOutput
Recommended.JsonInput.OneofZeroString.JsonOutput
Recommended.JsonInput.OneofZeroString.ProtobufOutput
Recommended.JsonInput.OneofZeroUint32.JsonOutput
Recommended.JsonInput.OneofZeroUint32.ProtobufOutput
Recommended.JsonInput.OneofZeroUint64.JsonOutput
Recommended.JsonInput.OneofZeroUint64.ProtobufOutput
Recommended.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.JsonInput.RepeatedFieldPrimitiveElementIsNull
Recommended.JsonInput.RepeatedFieldTrailingComma
Recommended.JsonInput.RepeatedFieldTrailingCommaWithNewlines
Recommended.JsonInput.RepeatedFieldTrailingCommaWithSpace
Recommended.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
Recommended.JsonInput.StringEndsWithEscapeChar
Recommended.JsonInput.StringFieldInvalidEscape
Recommended.JsonInput.StringFieldSingleQuoteBoth
Recommended.JsonInput.StringFieldSingleQuoteKey
Recommended.JsonInput.StringFieldSingleQuoteValue
Recommended.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.JsonInput.StringFieldUnterminatedEscape
Recommended.JsonInput.StringFieldUppercaseEscapeLetter
Recommended.JsonInput.TimestampHas3FractionalDigits.Validator
Recommended.JsonInput.TimestampHas6FractionalDigits.Validator
Recommended.JsonInput.TimestampHas9FractionalDigits.Validator
Recommended.JsonInput.TimestampHasZeroFractionalDigit.Validator
Recommended.JsonInput.TimestampZeroNormalized.Validator
Recommended.JsonInput.TrailingCommaInAnObject
Recommended.JsonInput.TrailingCommaInAnObjectWithNewlines
Recommended.JsonInput.TrailingCommaInAnObjectWithSpace
Recommended.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
Recommended.JsonInput.Uint32MapFieldKeyNotQuoted
Recommended.JsonInput.Uint64FieldBeString.Validator
Recommended.JsonInput.Uint64MapFieldKeyNotQuoted
Recommended.ProtobufInput.OneofZeroBool.JsonOutput
Recommended.ProtobufInput.OneofZeroBool.ProtobufOutput
Recommended.ProtobufInput.OneofZeroBytes.JsonOutput
Recommended.ProtobufInput.OneofZeroBytes.ProtobufOutput
Recommended.ProtobufInput.OneofZeroDouble.JsonOutput
Recommended.ProtobufInput.OneofZeroDouble.ProtobufOutput
Recommended.ProtobufInput.OneofZeroEnum.JsonOutput
Recommended.ProtobufInput.OneofZeroEnum.ProtobufOutput
Recommended.ProtobufInput.OneofZeroFloat.JsonOutput
Recommended.ProtobufInput.OneofZeroFloat.ProtobufOutput
Recommended.ProtobufInput.OneofZeroMessage.JsonOutput
Recommended.ProtobufInput.OneofZeroMessage.ProtobufOutput
Recommended.ProtobufInput.OneofZeroString.JsonOutput
Recommended.ProtobufInput.OneofZeroString.ProtobufOutput
Recommended.ProtobufInput.OneofZeroUint32.JsonOutput
Recommended.ProtobufInput.OneofZeroUint32.ProtobufOutput
Recommended.ProtobufInput.OneofZeroUint64.JsonOutput
Recommended.ProtobufInput.OneofZeroUint64.ProtobufOutput
Required.DurationProtoInputTooLarge.JsonOutput
Required.DurationProtoInputTooSmall.JsonOutput
Required.JsonInput.AllFieldAcceptNull.JsonOutput
Required.JsonInput.AllFieldAcceptNull.ProtobufOutput
Required.JsonInput.Any.JsonOutput
Required.JsonInput.Any.ProtobufOutput
Required.JsonInput.AnyNested.JsonOutput
Required.JsonInput.AnyNested.ProtobufOutput
Required.JsonInput.AnyUnorderedTypeTag.JsonOutput
Required.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
Required.JsonInput.AnyWithDuration.JsonOutput
Required.JsonInput.AnyWithDuration.ProtobufOutput
Required.JsonInput.AnyWithFieldMask.JsonOutput
Required.JsonInput.AnyWithFieldMask.ProtobufOutput
Required.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
Required.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
Required.JsonInput.AnyWithStruct.JsonOutput
Required.JsonInput.AnyWithStruct.ProtobufOutput
Required.JsonInput.AnyWithTimestamp.JsonOutput
Required.JsonInput.AnyWithTimestamp.ProtobufOutput
Required.JsonInput.AnyWithValueForInteger.JsonOutput
Required.JsonInput.AnyWithValueForInteger.ProtobufOutput
Required.JsonInput.AnyWithValueForJsonObject.JsonOutput
Required.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
Required.JsonInput.BoolFieldFalse.JsonOutput
Required.JsonInput.BoolFieldFalse.ProtobufOutput
Required.JsonInput.BoolFieldTrue.JsonOutput
Required.JsonInput.BoolFieldTrue.ProtobufOutput
Required.JsonInput.BoolMapEscapedKey.JsonOutput
Required.JsonInput.BoolMapEscapedKey.ProtobufOutput
Required.JsonInput.BoolMapField.JsonOutput
Required.JsonInput.BoolMapField.ProtobufOutput
Required.JsonInput.BytesField.JsonOutput
Required.JsonInput.BytesField.ProtobufOutput
Required.JsonInput.BytesRepeatedField.JsonOutput
Required.JsonInput.BytesRepeatedField.ProtobufOutput
Required.JsonInput.DoubleFieldInfinity.JsonOutput
Required.JsonInput.DoubleFieldInfinity.ProtobufOutput
Required.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
Required.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
Required.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
Required.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
Required.JsonInput.DoubleFieldMinNegativeValue.JsonOutput
Required.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
Required.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
Required.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
Required.JsonInput.DoubleFieldNan.JsonOutput
Required.JsonInput.DoubleFieldNan.ProtobufOutput
Required.JsonInput.DoubleFieldNegativeInfinity.JsonOutput
Required.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
Required.JsonInput.DoubleFieldQuotedValue.JsonOutput
Required.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
Required.JsonInput.DoubleFieldTooLarge
Required.JsonInput.DoubleFieldTooSmall
Required.JsonInput.DurationJsonInputTooLarge
Required.JsonInput.DurationJsonInputTooSmall
Required.JsonInput.DurationMaxValue.JsonOutput
Required.JsonInput.DurationMaxValue.ProtobufOutput
Required.JsonInput.DurationMinValue.JsonOutput
Required.JsonInput.DurationMinValue.ProtobufOutput
Required.JsonInput.DurationMissingS
Required.JsonInput.DurationRepeatedValue.JsonOutput
Required.JsonInput.DurationRepeatedValue.ProtobufOutput
Required.JsonInput.EnumField.JsonOutput
Required.JsonInput.EnumField.ProtobufOutput
Required.JsonInput.EnumFieldNotQuoted
Required.JsonInput.EnumFieldNumericValueNonZero.JsonOutput
Required.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
Required.JsonInput.EnumFieldNumericValueZero.JsonOutput
Required.JsonInput.EnumFieldNumericValueZero.ProtobufOutput
Required.JsonInput.EnumFieldUnknownValue.Validator
Required.JsonInput.EnumRepeatedField.JsonOutput
Required.JsonInput.EnumRepeatedField.ProtobufOutput
Required.JsonInput.FieldMask.JsonOutput
Required.JsonInput.FieldMask.ProtobufOutput
Required.JsonInput.FieldNameEscaped.JsonOutput
Required.JsonInput.FieldNameEscaped.ProtobufOutput
Required.JsonInput.FieldNameInLowerCamelCase.Validator
Required.JsonInput.FieldNameInSnakeCase.JsonOutput
Required.JsonInput.FieldNameInSnakeCase.ProtobufOutput
Required.JsonInput.FieldNameWithMixedCases.JsonOutput
Required.JsonInput.FieldNameWithMixedCases.ProtobufOutput
Required.JsonInput.FieldNameWithMixedCases.Validator
Required.JsonInput.FieldNameWithNumbers.JsonOutput
Required.JsonInput.FieldNameWithNumbers.ProtobufOutput
Required.JsonInput.FieldNameWithNumbers.Validator
Required.JsonInput.FloatFieldInfinity.JsonOutput
Required.JsonInput.FloatFieldInfinity.ProtobufOutput
Required.JsonInput.FloatFieldMaxNegativeValue.JsonOutput
Required.JsonInput.FloatFieldMaxNegativeValue.ProtobufOutput
Required.JsonInput.FloatFieldMaxPositiveValue.JsonOutput
Required.JsonInput.FloatFieldMaxPositiveValue.ProtobufOutput
Required.JsonInput.FloatFieldMinNegativeValue.JsonOutput
Required.JsonInput.FloatFieldMinNegativeValue.ProtobufOutput
Required.JsonInput.FloatFieldMinPositiveValue.JsonOutput
Required.JsonInput.FloatFieldMinPositiveValue.ProtobufOutput
Required.JsonInput.FloatFieldNan.JsonOutput
Required.JsonInput.FloatFieldNan.ProtobufOutput
Required.JsonInput.FloatFieldNegativeInfinity.JsonOutput
Required.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
Required.JsonInput.FloatFieldQuotedValue.JsonOutput
Required.JsonInput.FloatFieldQuotedValue.ProtobufOutput
Required.JsonInput.FloatFieldTooLarge
Required.JsonInput.FloatFieldTooSmall
Required.JsonInput.HelloWorld.JsonOutput
Required.JsonInput.HelloWorld.ProtobufOutput
Required.JsonInput.Int32FieldExponentialFormat.JsonOutput
Required.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
Required.JsonInput.Int32FieldFloatTrailingZero.JsonOutput
Required.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
Required.JsonInput.Int32FieldLeadingSpace
Required.JsonInput.Int32FieldLeadingZero
Required.JsonInput.Int32FieldMaxFloatValue.JsonOutput
Required.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
Required.JsonInput.Int32FieldMaxValue.JsonOutput
Required.JsonInput.Int32FieldMaxValue.ProtobufOutput
Required.JsonInput.Int32FieldMinFloatValue.JsonOutput
Required.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
Required.JsonInput.Int32FieldMinValue.JsonOutput
Required.JsonInput.Int32FieldMinValue.ProtobufOutput
Required.JsonInput.Int32FieldNegativeWithLeadingZero
Required.JsonInput.Int32FieldNotInteger
Required.JsonInput.Int32FieldNotNumber
Required.JsonInput.Int32FieldPlusSign
Required.JsonInput.Int32FieldStringValue.JsonOutput
Required.JsonInput.Int32FieldStringValue.ProtobufOutput
Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput
Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
Required.JsonInput.Int32FieldTooLarge
Required.JsonInput.Int32FieldTooSmall
Required.JsonInput.Int32FieldTrailingSpace
Required.JsonInput.Int32MapEscapedKey.JsonOutput
Required.JsonInput.Int32MapEscapedKey.ProtobufOutput
Required.JsonInput.Int32MapField.JsonOutput
Required.JsonInput.Int32MapField.ProtobufOutput
Required.JsonInput.Int64FieldMaxValue.JsonOutput
Required.JsonInput.Int64FieldMaxValue.ProtobufOutput
Required.JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
Required.JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
Required.JsonInput.Int64FieldMinValue.JsonOutput
Required.JsonInput.Int64FieldMinValue.ProtobufOutput
Required.JsonInput.Int64FieldMinValueNotQuoted.JsonOutput
Required.JsonInput.Int64FieldMinValueNotQuoted.ProtobufOutput
Required.JsonInput.Int64FieldNotInteger
Required.JsonInput.Int64FieldNotNumber
Required.JsonInput.Int64FieldTooLarge
Required.JsonInput.Int64FieldTooSmall
Required.JsonInput.Int64MapEscapedKey.JsonOutput
Required.JsonInput.Int64MapEscapedKey.ProtobufOutput
Required.JsonInput.Int64MapField.JsonOutput
Required.JsonInput.Int64MapField.ProtobufOutput
Required.JsonInput.MessageField.JsonOutput
Required.JsonInput.MessageField.ProtobufOutput
Required.JsonInput.MessageMapField.JsonOutput
Required.JsonInput.MessageMapField.ProtobufOutput
Required.JsonInput.MessageRepeatedField.JsonOutput
Required.JsonInput.MessageRepeatedField.ProtobufOutput
Required.JsonInput.OneofFieldDuplicate
Required.JsonInput.OptionalBoolWrapper.JsonOutput
Required.JsonInput.OptionalBoolWrapper.ProtobufOutput
Required.JsonInput.OptionalBytesWrapper.JsonOutput
Required.JsonInput.OptionalBytesWrapper.ProtobufOutput
Required.JsonInput.OptionalDoubleWrapper.JsonOutput
Required.JsonInput.OptionalDoubleWrapper.ProtobufOutput
Required.JsonInput.OptionalFloatWrapper.JsonOutput
Required.JsonInput.OptionalFloatWrapper.ProtobufOutput
Required.JsonInput.OptionalInt32Wrapper.JsonOutput
Required.JsonInput.OptionalInt32Wrapper.ProtobufOutput
Required.JsonInput.OptionalInt64Wrapper.JsonOutput
Required.JsonInput.OptionalInt64Wrapper.ProtobufOutput
Required.JsonInput.OptionalStringWrapper.JsonOutput
Required.JsonInput.OptionalStringWrapper.ProtobufOutput
Required.JsonInput.OptionalUint32Wrapper.JsonOutput
Required.JsonInput.OptionalUint32Wrapper.ProtobufOutput
Required.JsonInput.OptionalUint64Wrapper.JsonOutput
Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput
Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
Required.JsonInput.OriginalProtoFieldName.JsonOutput
Required.JsonInput.OriginalProtoFieldName.ProtobufOutput
Required.JsonInput.PrimitiveRepeatedField.JsonOutput
Required.JsonInput.PrimitiveRepeatedField.ProtobufOutput
Required.JsonInput.RepeatedBoolWrapper.JsonOutput
Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput
Required.JsonInput.RepeatedBytesWrapper.JsonOutput
Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput
Required.JsonInput.RepeatedDoubleWrapper.JsonOutput
Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotMessage
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotString
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotBool
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotString
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotMessage
Required.JsonInput.RepeatedFloatWrapper.JsonOutput
Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput
Required.JsonInput.RepeatedInt32Wrapper.JsonOutput
Required.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
Required.JsonInput.RepeatedInt64Wrapper.JsonOutput
Required.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
Required.JsonInput.RepeatedStringWrapper.JsonOutput
Required.JsonInput.RepeatedStringWrapper.ProtobufOutput
Required.JsonInput.RepeatedUint32Wrapper.JsonOutput
Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
Required.JsonInput.RepeatedUint64Wrapper.JsonOutput
Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
Required.JsonInput.StringField.JsonOutput
Required.JsonInput.StringField.ProtobufOutput
Required.JsonInput.StringFieldEscape.JsonOutput
Required.JsonInput.StringFieldEscape.ProtobufOutput
Required.JsonInput.StringFieldNotAString
Required.JsonInput.StringFieldSurrogatePair.JsonOutput
Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput
Required.JsonInput.StringFieldUnicode.JsonOutput
Required.JsonInput.StringFieldUnicode.ProtobufOutput
Required.JsonInput.StringFieldUnicodeEscape.JsonOutput
Required.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
Required.JsonInput.StringRepeatedField.JsonOutput
Required.JsonInput.StringRepeatedField.ProtobufOutput
Required.JsonInput.Struct.JsonOutput
Required.JsonInput.Struct.ProtobufOutput
Required.JsonInput.TimestampJsonInputLowercaseT
Required.JsonInput.TimestampJsonInputLowercaseZ
Required.JsonInput.TimestampJsonInputMissingT
Required.JsonInput.TimestampJsonInputMissingZ
Required.JsonInput.TimestampJsonInputTooLarge
Required.JsonInput.TimestampJsonInputTooSmall
Required.JsonInput.TimestampMaxValue.JsonOutput
Required.JsonInput.TimestampMaxValue.ProtobufOutput
Required.JsonInput.TimestampMinValue.JsonOutput
Required.JsonInput.TimestampMinValue.ProtobufOutput
Required.JsonInput.TimestampRepeatedValue.JsonOutput
Required.JsonInput.TimestampRepeatedValue.ProtobufOutput
Required.JsonInput.TimestampWithNegativeOffset.JsonOutput
Required.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
Required.JsonInput.TimestampWithPositiveOffset.JsonOutput
Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
Required.JsonInput.Uint32FieldMaxValue.JsonOutput
Required.JsonInput.Uint32FieldMaxValue.ProtobufOutput
Required.JsonInput.Uint32FieldNotInteger
Required.JsonInput.Uint32FieldNotNumber
Required.JsonInput.Uint32FieldTooLarge
Required.JsonInput.Uint32MapField.JsonOutput
Required.JsonInput.Uint32MapField.ProtobufOutput
Required.JsonInput.Uint64FieldMaxValue.JsonOutput
Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput
Required.JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
Required.JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
Required.JsonInput.Uint64FieldNotInteger
Required.JsonInput.Uint64FieldNotNumber
Required.JsonInput.Uint64FieldTooLarge
Required.JsonInput.Uint64MapField.JsonOutput
Required.JsonInput.Uint64MapField.ProtobufOutput
Required.JsonInput.ValueAcceptBool.JsonOutput
Required.JsonInput.ValueAcceptBool.ProtobufOutput
Required.JsonInput.ValueAcceptFloat.JsonOutput
Required.JsonInput.ValueAcceptFloat.ProtobufOutput
Required.JsonInput.ValueAcceptInteger.JsonOutput
Required.JsonInput.ValueAcceptInteger.ProtobufOutput
Required.JsonInput.ValueAcceptList.JsonOutput
Required.JsonInput.ValueAcceptList.ProtobufOutput
Required.JsonInput.ValueAcceptNull.JsonOutput
Required.JsonInput.ValueAcceptNull.ProtobufOutput
Required.JsonInput.ValueAcceptObject.JsonOutput
Required.JsonInput.ValueAcceptObject.ProtobufOutput
Required.JsonInput.ValueAcceptString.JsonOutput
Required.JsonInput.ValueAcceptString.ProtobufOutput
Required.JsonInput.WrapperTypesWithNullValue.JsonOutput
Required.JsonInput.WrapperTypesWithNullValue.ProtobufOutput
Required.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
Required.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
Required.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
Required.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
Required.ProtobufInput.IllegalZeroFieldNum_Case_0
Required.ProtobufInput.IllegalZeroFieldNum_Case_1
Required.ProtobufInput.IllegalZeroFieldNum_Case_2
Required.ProtobufInput.IllegalZeroFieldNum_Case_3
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.BOOL
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.DOUBLE
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.ENUM
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.FIXED32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.FIXED64
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.FLOAT
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.INT32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.INT64
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SFIXED32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SFIXED64
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SINT32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SINT64
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.STRING
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.UINT32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.UINT64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.BOOL
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.DOUBLE
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.ENUM
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.FIXED32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.FIXED64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.FLOAT
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.INT32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.INT64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SFIXED32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SFIXED64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SINT32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SINT64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.STRING
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.UINT32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.UINT64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.BOOL
Required.ProtobufInput.PrematureEofBeforeUnknownValue.BYTES
Required.ProtobufInput.PrematureEofBeforeUnknownValue.DOUBLE
Required.ProtobufInput.PrematureEofBeforeUnknownValue.ENUM
Required.ProtobufInput.PrematureEofBeforeUnknownValue.FIXED32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.FIXED64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.FLOAT
Required.ProtobufInput.PrematureEofBeforeUnknownValue.INT32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.INT64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.MESSAGE
Required.ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.SINT32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.SINT64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.STRING
Required.ProtobufInput.PrematureEofBeforeUnknownValue.UINT32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.UINT64
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.STRING
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.STRING
Required.ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.BYTES
Required.ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.MESSAGE
Required.ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.STRING
Required.ProtobufInput.PrematureEofInPackedField.BOOL
Required.ProtobufInput.PrematureEofInPackedField.DOUBLE
Required.ProtobufInput.PrematureEofInPackedField.ENUM
Required.ProtobufInput.PrematureEofInPackedField.FIXED32
Required.ProtobufInput.PrematureEofInPackedField.FIXED64
Required.ProtobufInput.PrematureEofInPackedField.FLOAT
Required.ProtobufInput.PrematureEofInPackedField.INT32
Required.ProtobufInput.PrematureEofInPackedField.INT64
Required.ProtobufInput.PrematureEofInPackedField.SFIXED32
Required.ProtobufInput.PrematureEofInPackedField.SFIXED64
Required.ProtobufInput.PrematureEofInPackedField.SINT32
Required.ProtobufInput.PrematureEofInPackedField.SINT64
Required.ProtobufInput.PrematureEofInPackedField.UINT32
Required.ProtobufInput.PrematureEofInPackedField.UINT64
Required.ProtobufInput.PrematureEofInPackedFieldValue.BOOL
Required.ProtobufInput.PrematureEofInPackedFieldValue.DOUBLE
Required.ProtobufInput.PrematureEofInPackedFieldValue.ENUM
Required.ProtobufInput.PrematureEofInPackedFieldValue.FIXED32
Required.ProtobufInput.PrematureEofInPackedFieldValue.FIXED64
Required.ProtobufInput.PrematureEofInPackedFieldValue.FLOAT
Required.ProtobufInput.PrematureEofInPackedFieldValue.INT32
Required.ProtobufInput.PrematureEofInPackedFieldValue.INT64
Required.ProtobufInput.PrematureEofInPackedFieldValue.SFIXED32
Required.ProtobufInput.PrematureEofInPackedFieldValue.SFIXED64
Required.ProtobufInput.PrematureEofInPackedFieldValue.SINT32
Required.ProtobufInput.PrematureEofInPackedFieldValue.SINT64
Required.ProtobufInput.PrematureEofInPackedFieldValue.UINT32
Required.ProtobufInput.PrematureEofInPackedFieldValue.UINT64
Required.ProtobufInput.PrematureEofInSubmessageValue.MESSAGE
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BOOL
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.DOUBLE
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.ENUM
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.FIXED32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.FIXED64
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.FLOAT
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT64
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SFIXED32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SFIXED64
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT64
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.STRING
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.BOOL
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.DOUBLE
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.ENUM
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.FIXED32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.FIXED64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.FLOAT
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.INT32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.INT64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SFIXED32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SFIXED64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SINT32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SINT64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.STRING
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.UINT32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.UINT64
Required.ProtobufInput.PrematureEofInsideUnknownValue.BOOL
Required.ProtobufInput.PrematureEofInsideUnknownValue.BYTES
Required.ProtobufInput.PrematureEofInsideUnknownValue.DOUBLE
Required.ProtobufInput.PrematureEofInsideUnknownValue.ENUM
Required.ProtobufInput.PrematureEofInsideUnknownValue.FIXED32
Required.ProtobufInput.PrematureEofInsideUnknownValue.FIXED64
Required.ProtobufInput.PrematureEofInsideUnknownValue.FLOAT
Required.ProtobufInput.PrematureEofInsideUnknownValue.INT32
Required.ProtobufInput.PrematureEofInsideUnknownValue.INT64
Required.ProtobufInput.PrematureEofInsideUnknownValue.MESSAGE
Required.ProtobufInput.PrematureEofInsideUnknownValue.SFIXED32
Required.ProtobufInput.PrematureEofInsideUnknownValue.SFIXED64
Required.ProtobufInput.PrematureEofInsideUnknownValue.SINT32
Required.ProtobufInput.PrematureEofInsideUnknownValue.SINT64
Required.ProtobufInput.PrematureEofInsideUnknownValue.STRING
Required.ProtobufInput.PrematureEofInsideUnknownValue.UINT32
Required.ProtobufInput.PrematureEofInsideUnknownValue.UINT64
Required.ProtobufInput.RepeatedScalarSelectsLast.BOOL.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.BOOL.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.DOUBLE.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.DOUBLE.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.INT32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.INT64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.INT64.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SINT32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SINT32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SINT64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SINT64.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.UINT32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.BOOL.JsonOutput
Required.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.DOUBLE.JsonOutput
Required.ProtobufInput.ValidDataRepeated.DOUBLE.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.FIXED32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.FIXED32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.FIXED64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.FIXED64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
Required.ProtobufInput.ValidDataRepeated.FLOAT.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.INT32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.INT64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.SFIXED32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.SFIXED32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.SFIXED64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.SFIXED64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.SINT32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.SINT64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.UINT32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.UINT64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.BOOL.JsonOutput
Required.ProtobufInput.ValidDataScalar.BOOL.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.DOUBLE.JsonOutput
Required.ProtobufInput.ValidDataScalar.DOUBLE.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.FIXED32.JsonOutput
Required.ProtobufInput.ValidDataScalar.FIXED32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.FIXED64.JsonOutput
Required.ProtobufInput.ValidDataScalar.FIXED64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.FLOAT.JsonOutput
Required.ProtobufInput.ValidDataScalar.FLOAT.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.INT32.JsonOutput
Required.ProtobufInput.ValidDataScalar.INT32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.INT64.JsonOutput
Required.ProtobufInput.ValidDataScalar.INT64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.SFIXED32.JsonOutput
Required.ProtobufInput.ValidDataScalar.SFIXED32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.SFIXED64.JsonOutput
Required.ProtobufInput.ValidDataScalar.SFIXED64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.SINT32.JsonOutput
Required.ProtobufInput.ValidDataScalar.SINT32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.SINT64.JsonOutput
Required.ProtobufInput.ValidDataScalar.SINT64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.UINT32.JsonOutput
Required.ProtobufInput.ValidDataScalar.UINT32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.UINT64.JsonOutput
Required.ProtobufInput.ValidDataScalar.UINT64.ProtobufOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput

@ -7,21 +7,462 @@
# TODO(haberman): insert links to corresponding bugs tracking the issue.
# Should we use GitHub issues or the Google-internal bug tracker?
Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.JsonInput.BoolFieldAllCapitalFalse
Recommended.JsonInput.BoolFieldAllCapitalTrue
Recommended.JsonInput.BoolFieldCamelCaseFalse
Recommended.JsonInput.BoolFieldCamelCaseTrue
Recommended.JsonInput.BoolFieldDoubleQuotedFalse
Recommended.JsonInput.BoolFieldDoubleQuotedTrue
Recommended.JsonInput.BoolFieldIntegerOne
Recommended.JsonInput.BoolFieldIntegerZero
Recommended.JsonInput.BoolMapFieldKeyNotQuoted
Recommended.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.JsonInput.BytesFieldBase64Url.ProtobufOutput
Recommended.JsonInput.DoubleFieldInfinityNotQuoted
Recommended.JsonInput.DoubleFieldNanNotQuoted
Recommended.JsonInput.DoubleFieldNegativeInfinityNotQuoted
Recommended.JsonInput.DurationHas3FractionalDigits.Validator
Recommended.JsonInput.DurationHas6FractionalDigits.Validator
Recommended.JsonInput.DurationHas9FractionalDigits.Validator
Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator
Recommended.JsonInput.FieldMaskInvalidCharacter
Recommended.JsonInput.FieldNameDuplicate
Recommended.JsonInput.FieldNameDuplicateDifferentCasing1
Recommended.JsonInput.FieldNameDuplicateDifferentCasing2
Recommended.JsonInput.FieldNameNotQuoted
Recommended.JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.Validator
Recommended.JsonInput.FloatFieldInfinityNotQuoted
Recommended.JsonInput.FloatFieldNanNotQuoted
Recommended.JsonInput.FloatFieldNegativeInfinityNotQuoted
Required.JsonInput.BytesFieldInvalidBase64Characters
Recommended.JsonInput.Int32MapFieldKeyNotQuoted
Recommended.JsonInput.Int64FieldBeString.Validator
Recommended.JsonInput.Int64MapFieldKeyNotQuoted
Recommended.JsonInput.JsonWithComments
Recommended.JsonInput.MapFieldKeyIsNull
Recommended.JsonInput.MapFieldValueIsNull
Recommended.JsonInput.MissingCommaMultiline
Recommended.JsonInput.MissingCommaOneLine
Recommended.JsonInput.MultilineNoSpaces.JsonOutput
Recommended.JsonInput.MultilineNoSpaces.ProtobufOutput
Recommended.JsonInput.MultilineWithSpaces.JsonOutput
Recommended.JsonInput.MultilineWithSpaces.ProtobufOutput
Recommended.JsonInput.OneLineNoSpaces.JsonOutput
Recommended.JsonInput.OneLineNoSpaces.ProtobufOutput
Recommended.JsonInput.OneLineWithSpaces.JsonOutput
Recommended.JsonInput.OneLineWithSpaces.ProtobufOutput
Recommended.JsonInput.OneofZeroBool.JsonOutput
Recommended.JsonInput.OneofZeroBool.ProtobufOutput
Recommended.JsonInput.OneofZeroBytes.JsonOutput
Recommended.JsonInput.OneofZeroBytes.ProtobufOutput
Recommended.JsonInput.OneofZeroDouble.JsonOutput
Recommended.JsonInput.OneofZeroDouble.ProtobufOutput
Recommended.JsonInput.OneofZeroEnum.JsonOutput
Recommended.JsonInput.OneofZeroEnum.ProtobufOutput
Recommended.JsonInput.OneofZeroFloat.JsonOutput
Recommended.JsonInput.OneofZeroFloat.ProtobufOutput
Recommended.JsonInput.OneofZeroMessage.JsonOutput
Recommended.JsonInput.OneofZeroMessage.ProtobufOutput
Recommended.JsonInput.OneofZeroString.JsonOutput
Recommended.JsonInput.OneofZeroString.ProtobufOutput
Recommended.JsonInput.OneofZeroUint32.JsonOutput
Recommended.JsonInput.OneofZeroUint32.ProtobufOutput
Recommended.JsonInput.OneofZeroUint64.JsonOutput
Recommended.JsonInput.OneofZeroUint64.ProtobufOutput
Recommended.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.JsonInput.RepeatedFieldPrimitiveElementIsNull
Recommended.JsonInput.RepeatedFieldTrailingComma
Recommended.JsonInput.RepeatedFieldTrailingCommaWithNewlines
Recommended.JsonInput.RepeatedFieldTrailingCommaWithSpace
Recommended.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
Recommended.JsonInput.StringEndsWithEscapeChar
Recommended.JsonInput.StringFieldInvalidEscape
Recommended.JsonInput.StringFieldSingleQuoteBoth
Recommended.JsonInput.StringFieldSingleQuoteKey
Recommended.JsonInput.StringFieldSingleQuoteValue
Recommended.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.JsonInput.StringFieldUnterminatedEscape
Recommended.JsonInput.StringFieldUppercaseEscapeLetter
Recommended.JsonInput.TimestampHas3FractionalDigits.Validator
Recommended.JsonInput.TimestampHas6FractionalDigits.Validator
Recommended.JsonInput.TimestampHas9FractionalDigits.Validator
Recommended.JsonInput.TimestampHasZeroFractionalDigit.Validator
Recommended.JsonInput.TimestampZeroNormalized.Validator
Recommended.JsonInput.TrailingCommaInAnObject
Recommended.JsonInput.TrailingCommaInAnObjectWithNewlines
Recommended.JsonInput.TrailingCommaInAnObjectWithSpace
Recommended.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
Recommended.JsonInput.Uint32MapFieldKeyNotQuoted
Recommended.JsonInput.Uint64FieldBeString.Validator
Recommended.JsonInput.Uint64MapFieldKeyNotQuoted
Recommended.ProtobufInput.OneofZeroBool.JsonOutput
Recommended.ProtobufInput.OneofZeroBool.ProtobufOutput
Recommended.ProtobufInput.OneofZeroBytes.JsonOutput
Recommended.ProtobufInput.OneofZeroBytes.ProtobufOutput
Recommended.ProtobufInput.OneofZeroDouble.JsonOutput
Recommended.ProtobufInput.OneofZeroDouble.ProtobufOutput
Recommended.ProtobufInput.OneofZeroEnum.JsonOutput
Recommended.ProtobufInput.OneofZeroEnum.ProtobufOutput
Recommended.ProtobufInput.OneofZeroFloat.JsonOutput
Recommended.ProtobufInput.OneofZeroFloat.ProtobufOutput
Recommended.ProtobufInput.OneofZeroMessage.JsonOutput
Recommended.ProtobufInput.OneofZeroMessage.ProtobufOutput
Recommended.ProtobufInput.OneofZeroString.JsonOutput
Recommended.ProtobufInput.OneofZeroString.ProtobufOutput
Recommended.ProtobufInput.OneofZeroUint32.JsonOutput
Recommended.ProtobufInput.OneofZeroUint32.ProtobufOutput
Recommended.ProtobufInput.OneofZeroUint64.JsonOutput
Recommended.ProtobufInput.OneofZeroUint64.ProtobufOutput
Required.DurationProtoInputTooLarge.JsonOutput
Required.DurationProtoInputTooSmall.JsonOutput
Required.JsonInput.AllFieldAcceptNull.JsonOutput
Required.JsonInput.AllFieldAcceptNull.ProtobufOutput
Required.JsonInput.Any.JsonOutput
Required.JsonInput.Any.ProtobufOutput
Required.JsonInput.AnyNested.JsonOutput
Required.JsonInput.AnyNested.ProtobufOutput
Required.JsonInput.AnyUnorderedTypeTag.JsonOutput
Required.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
Required.JsonInput.AnyWithDuration.JsonOutput
Required.JsonInput.AnyWithDuration.ProtobufOutput
Required.JsonInput.AnyWithFieldMask.JsonOutput
Required.JsonInput.AnyWithFieldMask.ProtobufOutput
Required.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
Required.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
Required.JsonInput.AnyWithStruct.JsonOutput
Required.JsonInput.AnyWithStruct.ProtobufOutput
Required.JsonInput.AnyWithTimestamp.JsonOutput
Required.JsonInput.AnyWithTimestamp.ProtobufOutput
Required.JsonInput.AnyWithValueForInteger.JsonOutput
Required.JsonInput.AnyWithValueForInteger.ProtobufOutput
Required.JsonInput.AnyWithValueForJsonObject.JsonOutput
Required.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
Required.JsonInput.BoolFieldFalse.JsonOutput
Required.JsonInput.BoolFieldFalse.ProtobufOutput
Required.JsonInput.BoolFieldTrue.JsonOutput
Required.JsonInput.BoolFieldTrue.ProtobufOutput
Required.JsonInput.BoolMapEscapedKey.JsonOutput
Required.JsonInput.BoolMapEscapedKey.ProtobufOutput
Required.JsonInput.BoolMapField.JsonOutput
Required.JsonInput.BoolMapField.ProtobufOutput
Required.JsonInput.BytesField.JsonOutput
Required.JsonInput.BytesField.ProtobufOutput
Required.JsonInput.BytesRepeatedField.JsonOutput
Required.JsonInput.BytesRepeatedField.ProtobufOutput
Required.JsonInput.DoubleFieldInfinity.JsonOutput
Required.JsonInput.DoubleFieldInfinity.ProtobufOutput
Required.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
Required.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
Required.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
Required.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
Required.JsonInput.DoubleFieldMinNegativeValue.JsonOutput
Required.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
Required.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
Required.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
Required.JsonInput.DoubleFieldNan.JsonOutput
Required.JsonInput.DoubleFieldNan.ProtobufOutput
Required.JsonInput.DoubleFieldNegativeInfinity.JsonOutput
Required.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
Required.JsonInput.DoubleFieldQuotedValue.JsonOutput
Required.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
Required.JsonInput.DoubleFieldTooLarge
Required.JsonInput.DoubleFieldTooSmall
Required.JsonInput.DurationJsonInputTooLarge
Required.JsonInput.DurationJsonInputTooSmall
Required.JsonInput.DurationMaxValue.JsonOutput
Required.JsonInput.DurationMaxValue.ProtobufOutput
Required.JsonInput.DurationMinValue.JsonOutput
Required.JsonInput.DurationMinValue.ProtobufOutput
Required.JsonInput.DurationMissingS
Required.JsonInput.DurationRepeatedValue.JsonOutput
Required.JsonInput.DurationRepeatedValue.ProtobufOutput
Required.JsonInput.EnumField.JsonOutput
Required.JsonInput.EnumField.ProtobufOutput
Required.JsonInput.EnumFieldNotQuoted
Required.JsonInput.EnumFieldNumericValueNonZero.JsonOutput
Required.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
Required.JsonInput.EnumFieldNumericValueZero.JsonOutput
Required.JsonInput.EnumFieldNumericValueZero.ProtobufOutput
Required.JsonInput.EnumFieldUnknownValue.Validator
Required.JsonInput.EnumRepeatedField.JsonOutput
Required.JsonInput.EnumRepeatedField.ProtobufOutput
Required.JsonInput.FieldMask.JsonOutput
Required.JsonInput.FieldMask.ProtobufOutput
Required.JsonInput.FieldNameEscaped.JsonOutput
Required.JsonInput.FieldNameEscaped.ProtobufOutput
Required.JsonInput.FieldNameInLowerCamelCase.Validator
Required.JsonInput.FieldNameInSnakeCase.JsonOutput
Required.JsonInput.FieldNameInSnakeCase.ProtobufOutput
Required.JsonInput.FieldNameWithMixedCases.JsonOutput
Required.JsonInput.FieldNameWithMixedCases.ProtobufOutput
Required.JsonInput.FieldNameWithMixedCases.Validator
Required.JsonInput.FieldNameWithNumbers.JsonOutput
Required.JsonInput.FieldNameWithNumbers.ProtobufOutput
Required.JsonInput.FieldNameWithNumbers.Validator
Required.JsonInput.FloatFieldInfinity.JsonOutput
Required.JsonInput.FloatFieldInfinity.ProtobufOutput
Required.JsonInput.FloatFieldMaxNegativeValue.JsonOutput
Required.JsonInput.FloatFieldMaxNegativeValue.ProtobufOutput
Required.JsonInput.FloatFieldMaxPositiveValue.JsonOutput
Required.JsonInput.FloatFieldMaxPositiveValue.ProtobufOutput
Required.JsonInput.FloatFieldMinNegativeValue.JsonOutput
Required.JsonInput.FloatFieldMinNegativeValue.ProtobufOutput
Required.JsonInput.FloatFieldMinPositiveValue.JsonOutput
Required.JsonInput.FloatFieldMinPositiveValue.ProtobufOutput
Required.JsonInput.FloatFieldNan.JsonOutput
Required.JsonInput.FloatFieldNan.ProtobufOutput
Required.JsonInput.FloatFieldNegativeInfinity.JsonOutput
Required.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
Required.JsonInput.FloatFieldQuotedValue.JsonOutput
Required.JsonInput.FloatFieldQuotedValue.ProtobufOutput
Required.JsonInput.FloatFieldTooLarge
Required.JsonInput.FloatFieldTooSmall
Required.JsonInput.HelloWorld.JsonOutput
Required.JsonInput.HelloWorld.ProtobufOutput
Required.JsonInput.Int32FieldExponentialFormat.JsonOutput
Required.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
Required.JsonInput.Int32FieldFloatTrailingZero.JsonOutput
Required.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
Required.JsonInput.Int32FieldLeadingSpace
Required.JsonInput.Int32FieldLeadingZero
Required.JsonInput.Int32FieldMaxFloatValue.JsonOutput
Required.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
Required.JsonInput.Int32FieldMaxValue.JsonOutput
Required.JsonInput.Int32FieldMaxValue.ProtobufOutput
Required.JsonInput.Int32FieldMinFloatValue.JsonOutput
Required.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
Required.JsonInput.Int32FieldMinValue.JsonOutput
Required.JsonInput.Int32FieldMinValue.ProtobufOutput
Required.JsonInput.Int32FieldNegativeWithLeadingZero
Required.JsonInput.Int32FieldNotInteger
Required.JsonInput.Int32FieldNotNumber
Required.JsonInput.Int32FieldPlusSign
Required.JsonInput.Int32FieldStringValue.JsonOutput
Required.JsonInput.Int32FieldStringValue.ProtobufOutput
Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput
Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
Required.JsonInput.Int32FieldTooLarge
Required.JsonInput.Int32FieldTooSmall
Required.JsonInput.Int32FieldTrailingSpace
Required.JsonInput.Int32MapEscapedKey.JsonOutput
Required.JsonInput.Int32MapEscapedKey.ProtobufOutput
Required.JsonInput.Int32MapField.JsonOutput
Required.JsonInput.Int32MapField.ProtobufOutput
Required.JsonInput.Int64FieldMaxValue.JsonOutput
Required.JsonInput.Int64FieldMaxValue.ProtobufOutput
Required.JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
Required.JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
Required.JsonInput.Int64FieldMinValue.JsonOutput
Required.JsonInput.Int64FieldMinValue.ProtobufOutput
Required.JsonInput.Int64FieldMinValueNotQuoted.JsonOutput
Required.JsonInput.Int64FieldMinValueNotQuoted.ProtobufOutput
Required.JsonInput.Int64FieldNotInteger
Required.JsonInput.Int64FieldNotNumber
Required.JsonInput.Int64FieldTooLarge
Required.JsonInput.Int64FieldTooSmall
Required.JsonInput.Int64MapEscapedKey.JsonOutput
Required.JsonInput.Int64MapEscapedKey.ProtobufOutput
Required.JsonInput.Int64MapField.JsonOutput
Required.JsonInput.Int64MapField.ProtobufOutput
Required.JsonInput.MessageField.JsonOutput
Required.JsonInput.MessageField.ProtobufOutput
Required.JsonInput.MessageMapField.JsonOutput
Required.JsonInput.MessageMapField.ProtobufOutput
Required.JsonInput.MessageRepeatedField.JsonOutput
Required.JsonInput.MessageRepeatedField.ProtobufOutput
Required.JsonInput.OneofFieldDuplicate
Required.JsonInput.OptionalBoolWrapper.JsonOutput
Required.JsonInput.OptionalBoolWrapper.ProtobufOutput
Required.JsonInput.OptionalBytesWrapper.JsonOutput
Required.JsonInput.OptionalBytesWrapper.ProtobufOutput
Required.JsonInput.OptionalDoubleWrapper.JsonOutput
Required.JsonInput.OptionalDoubleWrapper.ProtobufOutput
Required.JsonInput.OptionalFloatWrapper.JsonOutput
Required.JsonInput.OptionalFloatWrapper.ProtobufOutput
Required.JsonInput.OptionalInt32Wrapper.JsonOutput
Required.JsonInput.OptionalInt32Wrapper.ProtobufOutput
Required.JsonInput.OptionalInt64Wrapper.JsonOutput
Required.JsonInput.OptionalInt64Wrapper.ProtobufOutput
Required.JsonInput.OptionalStringWrapper.JsonOutput
Required.JsonInput.OptionalStringWrapper.ProtobufOutput
Required.JsonInput.OptionalUint32Wrapper.JsonOutput
Required.JsonInput.OptionalUint32Wrapper.ProtobufOutput
Required.JsonInput.OptionalUint64Wrapper.JsonOutput
Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput
Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
Required.JsonInput.OriginalProtoFieldName.JsonOutput
Required.JsonInput.OriginalProtoFieldName.ProtobufOutput
Required.JsonInput.PrimitiveRepeatedField.JsonOutput
Required.JsonInput.PrimitiveRepeatedField.ProtobufOutput
Required.JsonInput.RepeatedBoolWrapper.JsonOutput
Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput
Required.JsonInput.RepeatedBytesWrapper.JsonOutput
Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput
Required.JsonInput.RepeatedDoubleWrapper.JsonOutput
Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotMessage
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotString
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotBool
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotString
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotMessage
Required.JsonInput.RepeatedFloatWrapper.JsonOutput
Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput
Required.JsonInput.RepeatedInt32Wrapper.JsonOutput
Required.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
Required.JsonInput.RepeatedInt64Wrapper.JsonOutput
Required.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
Required.JsonInput.RepeatedStringWrapper.JsonOutput
Required.JsonInput.RepeatedStringWrapper.ProtobufOutput
Required.JsonInput.RepeatedUint32Wrapper.JsonOutput
Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
Required.JsonInput.RepeatedUint64Wrapper.JsonOutput
Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
Required.JsonInput.StringField.JsonOutput
Required.JsonInput.StringField.ProtobufOutput
Required.JsonInput.StringFieldEscape.JsonOutput
Required.JsonInput.StringFieldEscape.ProtobufOutput
Required.JsonInput.StringFieldNotAString
Required.JsonInput.StringFieldSurrogatePair.JsonOutput
Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput
Required.JsonInput.StringFieldUnicode.JsonOutput
Required.JsonInput.StringFieldUnicode.ProtobufOutput
Required.JsonInput.StringFieldUnicodeEscape.JsonOutput
Required.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
Required.JsonInput.StringRepeatedField.JsonOutput
Required.JsonInput.StringRepeatedField.ProtobufOutput
Required.JsonInput.Struct.JsonOutput
Required.JsonInput.Struct.ProtobufOutput
Required.JsonInput.TimestampJsonInputLowercaseT
Required.JsonInput.TimestampJsonInputLowercaseZ
Required.JsonInput.TimestampJsonInputMissingT
Required.JsonInput.TimestampJsonInputMissingZ
Required.JsonInput.TimestampJsonInputTooLarge
Required.JsonInput.TimestampJsonInputTooSmall
Required.JsonInput.TimestampMaxValue.JsonOutput
Required.JsonInput.TimestampMaxValue.ProtobufOutput
Required.JsonInput.TimestampMinValue.JsonOutput
Required.JsonInput.TimestampMinValue.ProtobufOutput
Required.JsonInput.TimestampRepeatedValue.JsonOutput
Required.JsonInput.TimestampRepeatedValue.ProtobufOutput
Required.JsonInput.TimestampWithNegativeOffset.JsonOutput
Required.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
Required.JsonInput.TimestampWithPositiveOffset.JsonOutput
Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
Required.JsonInput.Uint32FieldMaxValue.JsonOutput
Required.JsonInput.Uint32FieldMaxValue.ProtobufOutput
Required.JsonInput.Uint32FieldNotInteger
Required.JsonInput.Uint32FieldNotNumber
Required.JsonInput.Uint32FieldTooLarge
Required.JsonInput.Uint32MapField.JsonOutput
Required.JsonInput.Uint32MapField.ProtobufOutput
Required.JsonInput.Uint64FieldMaxValue.JsonOutput
Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput
Required.JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
Required.JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
Required.JsonInput.Uint64FieldNotInteger
Required.JsonInput.Uint64FieldNotNumber
Required.JsonInput.Uint64FieldTooLarge
Required.JsonInput.Uint64MapField.JsonOutput
Required.JsonInput.Uint64MapField.ProtobufOutput
Required.JsonInput.ValueAcceptBool.JsonOutput
Required.JsonInput.ValueAcceptBool.ProtobufOutput
Required.JsonInput.ValueAcceptFloat.JsonOutput
Required.JsonInput.ValueAcceptFloat.ProtobufOutput
Required.JsonInput.ValueAcceptInteger.JsonOutput
Required.JsonInput.ValueAcceptInteger.ProtobufOutput
Required.JsonInput.ValueAcceptList.JsonOutput
Required.JsonInput.ValueAcceptList.ProtobufOutput
Required.JsonInput.ValueAcceptNull.JsonOutput
Required.JsonInput.ValueAcceptNull.ProtobufOutput
Required.JsonInput.ValueAcceptObject.JsonOutput
Required.JsonInput.ValueAcceptObject.ProtobufOutput
Required.JsonInput.ValueAcceptString.JsonOutput
Required.JsonInput.ValueAcceptString.ProtobufOutput
Required.JsonInput.WrapperTypesWithNullValue.JsonOutput
Required.JsonInput.WrapperTypesWithNullValue.ProtobufOutput
Required.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
Required.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
Required.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
Required.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
Required.ProtobufInput.IllegalZeroFieldNum_Case_0
Required.ProtobufInput.IllegalZeroFieldNum_Case_1
Required.ProtobufInput.IllegalZeroFieldNum_Case_2
Required.ProtobufInput.IllegalZeroFieldNum_Case_3
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.BOOL
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.DOUBLE
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.ENUM
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.FIXED32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.FIXED64
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.FLOAT
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.INT32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.INT64
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SFIXED32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SFIXED64
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SINT32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SINT64
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.STRING
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.UINT32
Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.UINT64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.BOOL
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.DOUBLE
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.ENUM
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.FIXED32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.FIXED64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.FLOAT
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.INT32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.INT64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SFIXED32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SFIXED64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SINT32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SINT64
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.STRING
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.UINT32
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.UINT64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.BOOL
Required.ProtobufInput.PrematureEofBeforeUnknownValue.BYTES
Required.ProtobufInput.PrematureEofBeforeUnknownValue.DOUBLE
Required.ProtobufInput.PrematureEofBeforeUnknownValue.ENUM
Required.ProtobufInput.PrematureEofBeforeUnknownValue.FIXED32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.FIXED64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.FLOAT
Required.ProtobufInput.PrematureEofBeforeUnknownValue.INT32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.INT64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.MESSAGE
Required.ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.SINT32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.SINT64
Required.ProtobufInput.PrematureEofBeforeUnknownValue.STRING
Required.ProtobufInput.PrematureEofBeforeUnknownValue.UINT32
Required.ProtobufInput.PrematureEofBeforeUnknownValue.UINT64
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.STRING
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.STRING
Required.ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.BYTES
Required.ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.MESSAGE
Required.ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.STRING
Required.ProtobufInput.PrematureEofInPackedField.BOOL
Required.ProtobufInput.PrematureEofInPackedField.DOUBLE
Required.ProtobufInput.PrematureEofInPackedField.ENUM
@ -36,3 +477,149 @@ Required.ProtobufInput.PrematureEofInPackedField.SINT32
Required.ProtobufInput.PrematureEofInPackedField.SINT64
Required.ProtobufInput.PrematureEofInPackedField.UINT32
Required.ProtobufInput.PrematureEofInPackedField.UINT64
Required.ProtobufInput.PrematureEofInPackedFieldValue.BOOL
Required.ProtobufInput.PrematureEofInPackedFieldValue.DOUBLE
Required.ProtobufInput.PrematureEofInPackedFieldValue.ENUM
Required.ProtobufInput.PrematureEofInPackedFieldValue.FIXED32
Required.ProtobufInput.PrematureEofInPackedFieldValue.FIXED64
Required.ProtobufInput.PrematureEofInPackedFieldValue.FLOAT
Required.ProtobufInput.PrematureEofInPackedFieldValue.INT32
Required.ProtobufInput.PrematureEofInPackedFieldValue.INT64
Required.ProtobufInput.PrematureEofInPackedFieldValue.SFIXED32
Required.ProtobufInput.PrematureEofInPackedFieldValue.SFIXED64
Required.ProtobufInput.PrematureEofInPackedFieldValue.SINT32
Required.ProtobufInput.PrematureEofInPackedFieldValue.SINT64
Required.ProtobufInput.PrematureEofInPackedFieldValue.UINT32
Required.ProtobufInput.PrematureEofInPackedFieldValue.UINT64
Required.ProtobufInput.PrematureEofInSubmessageValue.MESSAGE
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BOOL
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.DOUBLE
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.ENUM
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.FIXED32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.FIXED64
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.FLOAT
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT64
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SFIXED32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SFIXED64
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT64
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.STRING
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT32
Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.BOOL
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.BYTES
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.DOUBLE
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.ENUM
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.FIXED32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.FIXED64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.FLOAT
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.INT32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.INT64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SFIXED32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SFIXED64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SINT32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SINT64
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.STRING
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.UINT32
Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.UINT64
Required.ProtobufInput.PrematureEofInsideUnknownValue.BOOL
Required.ProtobufInput.PrematureEofInsideUnknownValue.BYTES
Required.ProtobufInput.PrematureEofInsideUnknownValue.DOUBLE
Required.ProtobufInput.PrematureEofInsideUnknownValue.ENUM
Required.ProtobufInput.PrematureEofInsideUnknownValue.FIXED32
Required.ProtobufInput.PrematureEofInsideUnknownValue.FIXED64
Required.ProtobufInput.PrematureEofInsideUnknownValue.FLOAT
Required.ProtobufInput.PrematureEofInsideUnknownValue.INT32
Required.ProtobufInput.PrematureEofInsideUnknownValue.INT64
Required.ProtobufInput.PrematureEofInsideUnknownValue.MESSAGE
Required.ProtobufInput.PrematureEofInsideUnknownValue.SFIXED32
Required.ProtobufInput.PrematureEofInsideUnknownValue.SFIXED64
Required.ProtobufInput.PrematureEofInsideUnknownValue.SINT32
Required.ProtobufInput.PrematureEofInsideUnknownValue.SINT64
Required.ProtobufInput.PrematureEofInsideUnknownValue.STRING
Required.ProtobufInput.PrematureEofInsideUnknownValue.UINT32
Required.ProtobufInput.PrematureEofInsideUnknownValue.UINT64
Required.ProtobufInput.RepeatedScalarSelectsLast.BOOL.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.BOOL.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.DOUBLE.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.DOUBLE.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.INT32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.INT64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.INT64.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SINT32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SINT32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SINT64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.SINT64.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.UINT32.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.JsonOutput
Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.BOOL.JsonOutput
Required.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.DOUBLE.JsonOutput
Required.ProtobufInput.ValidDataRepeated.DOUBLE.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.FIXED32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.FIXED32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.FIXED64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.FIXED64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
Required.ProtobufInput.ValidDataRepeated.FLOAT.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.INT32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.INT64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.SFIXED32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.SFIXED32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.SFIXED64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.SFIXED64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.SINT32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.SINT64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.UINT32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput
Required.ProtobufInput.ValidDataRepeated.UINT64.JsonOutput
Required.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.BOOL.JsonOutput
Required.ProtobufInput.ValidDataScalar.BOOL.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.DOUBLE.JsonOutput
Required.ProtobufInput.ValidDataScalar.DOUBLE.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.FIXED32.JsonOutput
Required.ProtobufInput.ValidDataScalar.FIXED32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.FIXED64.JsonOutput
Required.ProtobufInput.ValidDataScalar.FIXED64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.FLOAT.JsonOutput
Required.ProtobufInput.ValidDataScalar.FLOAT.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.INT32.JsonOutput
Required.ProtobufInput.ValidDataScalar.INT32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.INT64.JsonOutput
Required.ProtobufInput.ValidDataScalar.INT64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.SFIXED32.JsonOutput
Required.ProtobufInput.ValidDataScalar.SFIXED32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.SFIXED64.JsonOutput
Required.ProtobufInput.ValidDataScalar.SFIXED64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.SINT32.JsonOutput
Required.ProtobufInput.ValidDataScalar.SINT32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.SINT64.JsonOutput
Required.ProtobufInput.ValidDataScalar.SINT64.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.UINT32.JsonOutput
Required.ProtobufInput.ValidDataScalar.UINT32.ProtobufOutput
Required.ProtobufInput.ValidDataScalar.UINT64.JsonOutput
Required.ProtobufInput.ValidDataScalar.UINT64.ProtobufOutput
Required.TimestampProtoInputTooLarge.JsonOutput
Required.TimestampProtoInputTooSmall.JsonOutput

@ -42,12 +42,23 @@ declare -a RUNTIME_PROTO_FILES=(\
google/protobuf/wrappers.proto)
declare -a COMPILER_PROTO_FILES=(\
google/protobuf/compiler/plugin.proto \
google/protobuf/compiler/profile.proto \
)
google/protobuf/compiler/plugin.proto)
CORE_PROTO_IS_CORRECT=0
PROCESS_ROUND=1
BOOTSTRAP_PROTOC=""
while [ $# -gt 0 ]; do
case $1 in
--bootstrap_protoc)
BOOTSTRAP_PROTOC=$2
shift
;;
*)
break
;;
esac
shift
done
TMP=$(mktemp -d)
echo "Updating descriptor protos..."
while [ $CORE_PROTO_IS_CORRECT -ne 1 ]
@ -55,14 +66,20 @@ do
echo "Round $PROCESS_ROUND"
CORE_PROTO_IS_CORRECT=1
make $@ protoc
if test $? -ne 0; then
echo "Failed to build protoc."
exit 1
if [ "$BOOTSTRAP_PROTOC" != "" ]; then
PROTOC=$BOOTSTRAP_PROTOC
BOOTSTRAP_PROTOC=""
else
make $@ protoc
if test $? -ne 0; then
echo "Failed to build protoc."
exit 1
fi
PROTOC="./protoc"
fi
./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:$TMP ${RUNTIME_PROTO_FILES[@]} && \
./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:$TMP ${COMPILER_PROTO_FILES[@]}
$PROTOC --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:$TMP ${RUNTIME_PROTO_FILES[@]} && \
$PROTOC --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:$TMP ${COMPILER_PROTO_FILES[@]}
for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]} ${COMPILER_PROTO_FILES[@]}; do
BASE_NAME=${PROTO_FILE%.*}

@ -5,6 +5,7 @@
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="--proto_path=${test.proto.dir}"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_mset.proto"/>
@ -40,4 +41,4 @@
<arg value="${test.proto.dir}/com/google/protobuf/map_test.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/map_initialization_order_test.proto"/>
</exec>
</project>
</project>

@ -32,6 +32,7 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
import com.google.protobuf.Descriptors.OneofDescriptor;
import com.google.protobuf.Internal.EnumLite;
import java.io.IOException;
@ -162,7 +163,7 @@ public abstract class AbstractMessage
}
return hash;
}
private static ByteString toByteString(Object value) {
if (value instanceof byte[]) {
return ByteString.copyFrom((byte[]) value);
@ -170,7 +171,7 @@ public abstract class AbstractMessage
return (ByteString) value;
}
}
/**
* Compares two bytes fields. The parameters must be either a byte array or a
* ByteString object. They can be of different type though.
@ -181,7 +182,7 @@ public abstract class AbstractMessage
}
return toByteString(a).equals(toByteString(b));
}
/**
* Converts a list of MapEntry messages into a Map used for equals() and
* hashCode().
@ -212,7 +213,7 @@ public abstract class AbstractMessage
}
return result;
}
/**
* Compares two map fields. The parameters must be a list of MapEntry
* messages.
@ -223,13 +224,13 @@ public abstract class AbstractMessage
Map mb = convertMapEntryListToMap((List) b);
return MapFieldLite.equals(ma, mb);
}
/**
* Compares two set of fields.
* This method is used to implement {@link AbstractMessage#equals(Object)}
* and {@link AbstractMutableMessage#equals(Object)}. It takes special care
* of bytes fields because immutable messages and mutable messages use
* different Java type to reprensent a bytes field and this method should be
* different Java type to represent a bytes field and this method should be
* able to compare immutable messages, mutable messages and also an immutable
* message to a mutable message.
*/
@ -275,7 +276,7 @@ public abstract class AbstractMessage
}
return true;
}
/**
* Calculates the hash code of a map field. {@code value} must be a list of
* MapEntry messages.
@ -371,7 +372,7 @@ public abstract class AbstractMessage
public String getInitializationErrorString() {
return MessageReflection.delimitWithCommas(findInitializationErrors());
}
@Override
protected BuilderType internalMergeFrom(AbstractMessageLite other) {
return mergeFrom((Message) other);
@ -432,8 +433,12 @@ public abstract class AbstractMessage
final CodedInputStream input,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
boolean discardUnknown =
getDescriptorForType().getFile().getSyntax() == Syntax.PROTO3
? input.shouldDiscardUnknownFieldsProto3()
: input.shouldDiscardUnknownFields();
final UnknownFieldSet.Builder unknownFields =
UnknownFieldSet.newBuilder(getUnknownFields());
discardUnknown ? null : UnknownFieldSet.newBuilder(getUnknownFields());
while (true) {
final int tag = input.readTag();
if (tag == 0) {
@ -451,7 +456,9 @@ public abstract class AbstractMessage
break;
}
}
setUnknownFields(unknownFields.build());
if (unknownFields != null) {
setUnknownFields(unknownFields.build());
}
return (BuilderType) this;
}

@ -36,7 +36,9 @@ import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* A partial implementation of the {@link MessageLite} interface which
@ -118,8 +120,13 @@ public abstract class AbstractMessageLite<
}
}
protected static <T> void addAll(final Iterable<T> values,
final Collection<? super T> list) {
// For binary compatibility
@Deprecated
protected static <T> void addAll(final Iterable<T> values, final Collection<? super T> list) {
Builder.addAll(values, (List) list);
}
protected static <T> void addAll(final Iterable<T> values, final List<? super T> list) {
Builder.addAll(values, list);
}
@ -334,6 +341,25 @@ public abstract class AbstractMessageLite<
+ " threw an IOException (should never happen).";
}
// We check nulls as we iterate to avoid iterating over values twice.
private static <T> void addAllCheckingNulls(Iterable<T> values, List<? super T> list) {
if (list instanceof ArrayList && values instanceof Collection) {
((ArrayList<T>) list).ensureCapacity(list.size() + ((Collection<T>) values).size());
}
int begin = list.size();
for (T value : values) {
if (value == null) {
// encountered a null value so we must undo our modifications prior to throwing
String message = "Element at index " + (list.size() - begin) + " is null.";
for (int i = list.size() - 1; i >= begin; i--) {
list.remove(i);
}
throw new NullPointerException(message);
}
list.add(value);
}
}
/**
* Construct an UninitializedMessageException reporting missing fields in
* the given message.
@ -343,16 +369,20 @@ public abstract class AbstractMessageLite<
return new UninitializedMessageException(message);
}
// For binary compatibility.
@Deprecated
protected static <T> void addAll(final Iterable<T> values, final Collection<? super T> list) {
addAll(values, (List<T>) list);
}
/**
* Adds the {@code values} to the {@code list}. This is a helper method
* used by generated code. Users should ignore it.
* Adds the {@code values} to the {@code list}. This is a helper method used by generated code.
* Users should ignore it.
*
* @throws NullPointerException if {@code values} or any of the elements of
* {@code values} is null. When that happens, some elements of
* {@code values} may have already been added to the result {@code list}.
* @throws NullPointerException if {@code values} or any of the elements of {@code values} is
* null.
*/
protected static <T> void addAll(final Iterable<T> values,
final Collection<? super T> list) {
protected static <T> void addAll(final Iterable<T> values, final List<? super T> list) {
checkNotNull(values);
if (values instanceof LazyStringList) {
// For StringOrByteStringLists, check the underlying elements to avoid
@ -360,25 +390,31 @@ public abstract class AbstractMessageLite<
// TODO(dweis): Could we just prohibit nulls in all protobuf lists and get rid of this? Is
// if even possible to hit this condition as all protobuf methods check for null first,
// right?
checkForNullValues(((LazyStringList) values).getUnderlyingElements());
list.addAll((Collection<T>) values);
} else if (values instanceof Collection) {
if (!(values instanceof PrimitiveNonBoxingCollection)) {
checkForNullValues(values);
List<?> lazyValues = ((LazyStringList) values).getUnderlyingElements();
LazyStringList lazyList = (LazyStringList) list;
int begin = list.size();
for (Object value : lazyValues) {
if (value == null) {
// encountered a null value so we must undo our modifications prior to throwing
String message = "Element at index " + (lazyList.size() - begin) + " is null.";
for (int i = lazyList.size() - 1; i >= begin; i--) {
lazyList.remove(i);
}
throw new NullPointerException(message);
}
if (value instanceof ByteString) {
lazyList.add((ByteString) value);
} else {
lazyList.add((String) value);
}
}
list.addAll((Collection<T>) values);
} else {
for (final T value : values) {
checkNotNull(value);
list.add(value);
if (values instanceof PrimitiveNonBoxingCollection) {
list.addAll((Collection<T>) values);
} else {
addAllCheckingNulls(values, list);
}
}
}
private static void checkForNullValues(final Iterable<?> values) {
for (final Object value : values) {
checkNotNull(value);
}
}
}
}

@ -34,8 +34,8 @@ import static com.google.protobuf.Internal.EMPTY_BYTE_ARRAY;
import static com.google.protobuf.Internal.EMPTY_BYTE_BUFFER;
import static com.google.protobuf.Internal.UTF_8;
import static com.google.protobuf.Internal.checkNotNull;
import static com.google.protobuf.WireFormat.FIXED_32_SIZE;
import static com.google.protobuf.WireFormat.FIXED_64_SIZE;
import static com.google.protobuf.WireFormat.FIXED32_SIZE;
import static com.google.protobuf.WireFormat.FIXED64_SIZE;
import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
import java.io.ByteArrayOutputStream;
@ -372,6 +372,64 @@ public abstract class CodedInputStream {
return oldLimit;
}
private boolean explicitDiscardUnknownFields = false;
/** TODO(liujisi): flip the default.*/
private static volatile boolean proto3DiscardUnknownFieldsDefault = true;
static void setProto3DiscardUnknownsByDefaultForTest() {
proto3DiscardUnknownFieldsDefault = true;
}
static void setProto3KeepUnknownsByDefaultForTest() {
proto3DiscardUnknownFieldsDefault = false;
}
static boolean getProto3DiscardUnknownFieldsDefault() {
return proto3DiscardUnknownFieldsDefault;
}
/**
* Sets this {@code CodedInputStream} to discard unknown fields. Only applies to full runtime
* messages; lite messages will always preserve unknowns.
*
* <p>Note calling this function alone will have NO immediate effect on the underlying input data.
* The unknown fields will be discarded during parsing. This affects both Proto2 and Proto3 full
* runtime.
*/
final void discardUnknownFields() {
explicitDiscardUnknownFields = true;
}
/**
* Reverts the unknown fields preservation behavior for Proto2 and Proto3 full runtime to their
* default.
*/
final void unsetDiscardUnknownFields() {
explicitDiscardUnknownFields = false;
}
/**
* Whether unknown fields in this input stream should be discarded during parsing into full
* runtime messages.
*/
final boolean shouldDiscardUnknownFields() {
return explicitDiscardUnknownFields;
}
/**
* Whether unknown fields in this input stream should be discarded during parsing for proto3 full
* runtime messages.
*
* <p>This function was temporarily introduced before proto3 unknown fields behavior is changed.
* TODO(liujisi): remove this and related code in GeneratedMessage after proto3 unknown
* fields migration is done.
*/
final boolean shouldDiscardUnknownFieldsProto3() {
return explicitDiscardUnknownFields ? true : proto3DiscardUnknownFieldsDefault;
}
/**
* Resets the current size counter to zero (see {@link #setSizeLimit(int)}). Only valid for {@link
* InputStream}-backed streams.
@ -572,7 +630,7 @@ public abstract class CodedInputStream {
skipRawVarint();
return true;
case WireFormat.WIRETYPE_FIXED64:
skipRawBytes(FIXED_64_SIZE);
skipRawBytes(FIXED64_SIZE);
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
skipRawBytes(readRawVarint32());
@ -585,7 +643,7 @@ public abstract class CodedInputStream {
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
skipRawBytes(FIXED_32_SIZE);
skipRawBytes(FIXED32_SIZE);
return true;
default:
throw InvalidProtocolBufferException.invalidWireType();
@ -1064,12 +1122,12 @@ public abstract class CodedInputStream {
public int readRawLittleEndian32() throws IOException {
int tempPos = pos;
if (limit - tempPos < FIXED_32_SIZE) {
if (limit - tempPos < FIXED32_SIZE) {
throw InvalidProtocolBufferException.truncatedMessage();
}
final byte[] buffer = this.buffer;
pos = tempPos + FIXED_32_SIZE;
pos = tempPos + FIXED32_SIZE;
return (((buffer[tempPos] & 0xff))
| ((buffer[tempPos + 1] & 0xff) << 8)
| ((buffer[tempPos + 2] & 0xff) << 16)
@ -1080,12 +1138,12 @@ public abstract class CodedInputStream {
public long readRawLittleEndian64() throws IOException {
int tempPos = pos;
if (limit - tempPos < FIXED_64_SIZE) {
if (limit - tempPos < FIXED64_SIZE) {
throw InvalidProtocolBufferException.truncatedMessage();
}
final byte[] buffer = this.buffer;
pos = tempPos + FIXED_64_SIZE;
pos = tempPos + FIXED64_SIZE;
return (((buffer[tempPos] & 0xffL))
| ((buffer[tempPos + 1] & 0xffL) << 8)
| ((buffer[tempPos + 2] & 0xffL) << 16)
@ -1290,7 +1348,7 @@ public abstract class CodedInputStream {
skipRawVarint();
return true;
case WireFormat.WIRETYPE_FIXED64:
skipRawBytes(FIXED_64_SIZE);
skipRawBytes(FIXED64_SIZE);
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
skipRawBytes(readRawVarint32());
@ -1303,7 +1361,7 @@ public abstract class CodedInputStream {
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
skipRawBytes(FIXED_32_SIZE);
skipRawBytes(FIXED32_SIZE);
return true;
default:
throw InvalidProtocolBufferException.invalidWireType();
@ -1429,7 +1487,9 @@ public abstract class CodedInputStream {
final int size = readRawVarint32();
if (size > 0 && size <= remaining()) {
// TODO(nathanmittler): Is there a way to avoid this copy?
byte[] bytes = copyToArray(pos, pos + size);
// The same as readBytes' logic
byte[] bytes = new byte[size];
UnsafeUtil.copyMemory(pos, bytes, 0, size);
String result = new String(bytes, UTF_8);
pos += size;
return result;
@ -1449,7 +1509,9 @@ public abstract class CodedInputStream {
final int size = readRawVarint32();
if (size >= 0 && size <= remaining()) {
// TODO(nathanmittler): Is there a way to avoid this copy?
byte[] bytes = copyToArray(pos, pos + size);
// The same as readBytes' logic
byte[] bytes = new byte[size];
UnsafeUtil.copyMemory(pos, bytes, 0, size);
// TODO(martinrb): We could save a pass by validating while decoding.
if (!Utf8.isValidUtf8(bytes)) {
throw InvalidProtocolBufferException.invalidUtf8();
@ -1545,14 +1607,17 @@ public abstract class CodedInputStream {
public ByteString readBytes() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= remaining()) {
ByteBuffer result;
if (immutable && enableAliasing) {
result = slice(pos, pos + size);
final ByteBuffer result = slice(pos, pos + size);
pos += size;
return ByteString.wrap(result);
} else {
result = copy(pos, pos + size);
// Use UnsafeUtil to copy the memory to bytes instead of using ByteBuffer ways.
byte[] bytes = new byte[size];
UnsafeUtil.copyMemory(pos, bytes, 0, size);
pos += size;
return ByteString.wrap(bytes);
}
pos += size;
return ByteString.wrap(result);
}
if (size == 0) {
@ -1573,18 +1638,21 @@ public abstract class CodedInputStream {
public ByteBuffer readByteBuffer() throws IOException {
final int size = readRawVarint32();
if (size > 0 && size <= remaining()) {
ByteBuffer result;
// "Immutable" implies that buffer is backing a ByteString.
// Disallow slicing in this case to prevent the caller from modifying the contents
// of the ByteString.
if (!immutable && enableAliasing) {
result = slice(pos, pos + size);
final ByteBuffer result = slice(pos, pos + size);
pos += size;
return result;
} else {
result = copy(pos, pos + size);
// The same as readBytes' logic
byte[] bytes = new byte[size];
UnsafeUtil.copyMemory(pos, bytes, 0, size);
pos += size;
return ByteBuffer.wrap(bytes);
}
pos += size;
// TODO(nathanmittler): Investigate making the ByteBuffer be made read-only
return result;
}
if (size == 0) {
@ -1785,11 +1853,11 @@ public abstract class CodedInputStream {
public int readRawLittleEndian32() throws IOException {
long tempPos = pos;
if (limit - tempPos < FIXED_32_SIZE) {
if (limit - tempPos < FIXED32_SIZE) {
throw InvalidProtocolBufferException.truncatedMessage();
}
pos = tempPos + FIXED_32_SIZE;
pos = tempPos + FIXED32_SIZE;
return (((UnsafeUtil.getByte(tempPos) & 0xff))
| ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
| ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
@ -1800,11 +1868,11 @@ public abstract class CodedInputStream {
public long readRawLittleEndian64() throws IOException {
long tempPos = pos;
if (limit - tempPos < FIXED_64_SIZE) {
if (limit - tempPos < FIXED64_SIZE) {
throw InvalidProtocolBufferException.truncatedMessage();
}
pos = tempPos + FIXED_64_SIZE;
pos = tempPos + FIXED64_SIZE;
return (((UnsafeUtil.getByte(tempPos) & 0xffL))
| ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
| ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
@ -1943,27 +2011,6 @@ public abstract class CodedInputStream {
buffer.limit(prevLimit);
}
}
private ByteBuffer copy(long begin, long end) throws IOException {
return ByteBuffer.wrap(copyToArray(begin, end));
}
private byte[] copyToArray(long begin, long end) throws IOException {
int prevPos = buffer.position();
int prevLimit = buffer.limit();
try {
buffer.position(bufferPos(begin));
buffer.limit(bufferPos(end));
byte[] bytes = new byte[(int) (end - begin)];
buffer.get(bytes);
return bytes;
} catch (IllegalArgumentException e) {
throw InvalidProtocolBufferException.truncatedMessage();
} finally {
buffer.position(prevPos);
buffer.limit(prevLimit);
}
}
}
/**
@ -2034,7 +2081,7 @@ public abstract class CodedInputStream {
skipRawVarint();
return true;
case WireFormat.WIRETYPE_FIXED64:
skipRawBytes(FIXED_64_SIZE);
skipRawBytes(FIXED64_SIZE);
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
skipRawBytes(readRawVarint32());
@ -2047,7 +2094,7 @@ public abstract class CodedInputStream {
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
skipRawBytes(FIXED_32_SIZE);
skipRawBytes(FIXED32_SIZE);
return true;
default:
throw InvalidProtocolBufferException.invalidWireType();
@ -2332,8 +2379,7 @@ public abstract class CodedInputStream {
if (size == 0) {
return ByteString.EMPTY;
}
// Slow path: Build a byte array first then copy it.
return ByteString.wrap(readRawBytesSlowPath(size));
return readBytesSlowPath(size);
}
@Override
@ -2558,13 +2604,13 @@ public abstract class CodedInputStream {
public int readRawLittleEndian32() throws IOException {
int tempPos = pos;
if (bufferSize - tempPos < FIXED_32_SIZE) {
refillBuffer(FIXED_32_SIZE);
if (bufferSize - tempPos < FIXED32_SIZE) {
refillBuffer(FIXED32_SIZE);
tempPos = pos;
}
final byte[] buffer = this.buffer;
pos = tempPos + FIXED_32_SIZE;
pos = tempPos + FIXED32_SIZE;
return (((buffer[tempPos] & 0xff))
| ((buffer[tempPos + 1] & 0xff) << 8)
| ((buffer[tempPos + 2] & 0xff) << 16)
@ -2575,13 +2621,13 @@ public abstract class CodedInputStream {
public long readRawLittleEndian64() throws IOException {
int tempPos = pos;
if (bufferSize - tempPos < FIXED_64_SIZE) {
refillBuffer(FIXED_64_SIZE);
if (bufferSize - tempPos < FIXED64_SIZE) {
refillBuffer(FIXED64_SIZE);
tempPos = pos;
}
final byte[] buffer = this.buffer;
pos = tempPos + FIXED_64_SIZE;
pos = tempPos + FIXED64_SIZE;
return (((buffer[tempPos] & 0xffL))
| ((buffer[tempPos + 1] & 0xffL) << 8)
| ((buffer[tempPos + 2] & 0xffL) << 16)
@ -2675,7 +2721,13 @@ public abstract class CodedInputStream {
*/
private void refillBuffer(int n) throws IOException {
if (!tryRefillBuffer(n)) {
throw InvalidProtocolBufferException.truncatedMessage();
// We have to distinguish the exception between sizeLimitExceeded and truncatedMessage. So
// we just throw an sizeLimitExceeded exception here if it exceeds the sizeLimit
if (n > sizeLimit - totalBytesRetired - pos) {
throw InvalidProtocolBufferException.sizeLimitExceeded();
} else {
throw InvalidProtocolBufferException.truncatedMessage();
}
}
}
@ -2684,8 +2736,8 @@ public abstract class CodedInputStream {
* buffer. Caller must ensure that the requested space is not yet available, and that the
* requested space is less than BUFFER_SIZE.
*
* @return {@code true} if the bytes could be made available; {@code false} if the end of the
* stream or the current limit was reached.
* @return {@code true} If the bytes could be made available; {@code false} 1. Current at the
* end of the stream 2. The current limit was reached 3. The total size limit was reached
*/
private boolean tryRefillBuffer(int n) throws IOException {
if (pos + n <= bufferSize) {
@ -2693,6 +2745,14 @@ public abstract class CodedInputStream {
"refillBuffer() called when " + n + " bytes were already available in buffer");
}
// Check whether the size of total message needs to read is bigger than the size limit.
// We shouldn't throw an exception here as isAtEnd() function needs to get this function's
// return as the result.
if (n > sizeLimit - totalBytesRetired - pos) {
return false;
}
// Shouldn't throw the exception here either.
if (totalBytesRetired + pos + n > currentLimit) {
// Oops, we hit a limit.
return false;
@ -2712,7 +2772,16 @@ public abstract class CodedInputStream {
pos = 0;
}
int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize);
// Here we should refill the buffer as many bytes as possible.
int bytesRead =
input.read(
buffer,
bufferSize,
Math.min(
// the size of allocated but unused bytes in the buffer
buffer.length - bufferSize,
// do not exceed the total bytes limit
sizeLimit - totalBytesRetired - bufferSize));
if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
throw new IllegalStateException(
"InputStream#read(byte[]) returned invalid result: "
@ -2721,10 +2790,6 @@ public abstract class CodedInputStream {
}
if (bytesRead > 0) {
bufferSize += bytesRead;
// Integer-overflow-conscious check against sizeLimit
if (totalBytesRetired + n - sizeLimit > 0) {
throw InvalidProtocolBufferException.sizeLimitExceeded();
}
recomputeBufferSizeAfterLimit();
return (bufferSize >= n) ? true : tryRefillBuffer(n);
}
@ -2756,6 +2821,49 @@ public abstract class CodedInputStream {
* (bufferSize - pos) && size > 0)
*/
private byte[] readRawBytesSlowPath(final int size) throws IOException {
// Attempt to read the data in one byte array when it's safe to do.
byte[] result = readRawBytesSlowPathOneChunk(size);
if (result != null) {
return result;
}
final int originalBufferPos = pos;
final int bufferedBytes = bufferSize - pos;
// Mark the current buffer consumed.
totalBytesRetired += bufferSize;
pos = 0;
bufferSize = 0;
// Determine the number of bytes we need to read from the input stream.
int sizeLeft = size - bufferedBytes;
// The size is very large. For security reasons we read them in small
// chunks.
List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
// OK, got everything. Now concatenate it all into one buffer.
final byte[] bytes = new byte[size];
// Start by copying the leftover bytes from this.buffer.
System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
// And now all the chunks.
int tempPos = bufferedBytes;
for (final byte[] chunk : chunks) {
System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
tempPos += chunk.length;
}
// Done.
return bytes;
}
/**
* Attempts to read the data in one byte array when it's safe to do. Returns null if the size to
* read is too large and needs to be allocated in smaller chunks for security reasons.
*/
private byte[] readRawBytesSlowPathOneChunk(final int size) throws IOException {
if (size == 0) {
return Internal.EMPTY_BYTE_ARRAY;
}
@ -2776,14 +2884,7 @@ public abstract class CodedInputStream {
throw InvalidProtocolBufferException.truncatedMessage();
}
final int originalBufferPos = pos;
final int bufferedBytes = bufferSize - pos;
// Mark the current buffer consumed.
totalBytesRetired += bufferSize;
pos = 0;
bufferSize = 0;
// Determine the number of bytes we need to read from the input stream.
int sizeLeft = size - bufferedBytes;
// TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
@ -2793,7 +2894,10 @@ public abstract class CodedInputStream {
final byte[] bytes = new byte[size];
// Copy all of the buffered bytes to the result buffer.
System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
System.arraycopy(buffer, pos, bytes, 0, bufferedBytes);
totalBytesRetired += bufferSize;
pos = 0;
bufferSize = 0;
// Fill the remaining bytes from the input stream.
int tempPos = bufferedBytes;
@ -2809,6 +2913,11 @@ public abstract class CodedInputStream {
return bytes;
}
return null;
}
/** Reads the remaining data in small chunks from the input stream. */
private List<byte[]> readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IOException {
// The size is very large. For security reasons, we can't allocate the
// entire byte array yet. The size comes directly from the input, so a
// maliciously-crafted message could provide a bogus very large size in
@ -2834,21 +2943,41 @@ public abstract class CodedInputStream {
chunks.add(chunk);
}
// OK, got everything. Now concatenate it all into one buffer.
final byte[] bytes = new byte[size];
// Start by copying the leftover bytes from this.buffer.
System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
return chunks;
}
// And now all the chunks.
int tempPos = bufferedBytes;
for (final byte[] chunk : chunks) {
System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
tempPos += chunk.length;
/**
* Like readBytes, but caller must have already checked the fast path: (size <= (bufferSize -
* pos) && size > 0 || size == 0)
*/
private ByteString readBytesSlowPath(final int size) throws IOException {
final byte[] result = readRawBytesSlowPathOneChunk(size);
if (result != null) {
return ByteString.wrap(result);
}
// Done.
return bytes;
final int originalBufferPos = pos;
final int bufferedBytes = bufferSize - pos;
// Mark the current buffer consumed.
totalBytesRetired += bufferSize;
pos = 0;
bufferSize = 0;
// Determine the number of bytes we need to read from the input stream.
int sizeLeft = size - bufferedBytes;
// The size is very large. For security reasons we read them in small
// chunks.
List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
// Wrap the byte arrays into a single ByteString.
List<ByteString> byteStrings = new ArrayList<ByteString>(1 + chunks.size());
byteStrings.add(ByteString.copyFrom(buffer, originalBufferPos, bufferedBytes));
for (byte[] chunk : chunks) {
byteStrings.add(ByteString.wrap(chunk));
}
return ByteString.copyFrom(byteStrings);
}
@Override

@ -30,8 +30,8 @@
package com.google.protobuf;
import static com.google.protobuf.WireFormat.FIXED_32_SIZE;
import static com.google.protobuf.WireFormat.FIXED_64_SIZE;
import static com.google.protobuf.WireFormat.FIXED32_SIZE;
import static com.google.protobuf.WireFormat.FIXED64_SIZE;
import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
import static java.lang.Math.max;
@ -59,13 +59,12 @@ import java.util.logging.Logger;
public abstract class CodedOutputStream extends ByteOutput {
private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = UnsafeUtil.hasUnsafeArrayOperations();
private static final long ARRAY_BASE_OFFSET = UnsafeUtil.getArrayBaseOffset();
/**
* @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead.
*/
@Deprecated
public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE;
public static final int LITTLE_ENDIAN_32_SIZE = FIXED32_SIZE;
/**
* The buffer size used in {@link #newInstance(OutputStream)}.
@ -755,7 +754,7 @@ public abstract class CodedOutputStream extends ByteOutput {
* {@code fixed32} field.
*/
public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
return FIXED_32_SIZE;
return FIXED32_SIZE;
}
/**
@ -763,7 +762,7 @@ public abstract class CodedOutputStream extends ByteOutput {
* {@code sfixed32} field.
*/
public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
return FIXED_32_SIZE;
return FIXED32_SIZE;
}
/**
@ -813,7 +812,7 @@ public abstract class CodedOutputStream extends ByteOutput {
* {@code fixed64} field.
*/
public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
return FIXED_64_SIZE;
return FIXED64_SIZE;
}
/**
@ -821,7 +820,7 @@ public abstract class CodedOutputStream extends ByteOutput {
* {@code sfixed64} field.
*/
public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
return FIXED_64_SIZE;
return FIXED64_SIZE;
}
/**
@ -829,7 +828,7 @@ public abstract class CodedOutputStream extends ByteOutput {
* {@code float} field, including tag.
*/
public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) {
return FIXED_32_SIZE;
return FIXED32_SIZE;
}
/**
@ -837,7 +836,7 @@ public abstract class CodedOutputStream extends ByteOutput {
* {@code double} field, including tag.
*/
public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) {
return FIXED_64_SIZE;
return FIXED64_SIZE;
}
/**
@ -1321,15 +1320,12 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public final void writeUInt32NoTag(int value) throws IOException {
if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
long pos = ARRAY_BASE_OFFSET + position;
while (true) {
if ((value & ~0x7F) == 0) {
UnsafeUtil.putByte(buffer, pos++, (byte) value);
position++;
UnsafeUtil.putByte(buffer, position++, (byte) value);
return;
} else {
UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
position++;
UnsafeUtil.putByte(buffer, position++, (byte) ((value & 0x7F) | 0x80));
value >>>= 7;
}
}
@ -1367,15 +1363,12 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public final void writeUInt64NoTag(long value) throws IOException {
if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
long pos = ARRAY_BASE_OFFSET + position;
while (true) {
if ((value & ~0x7FL) == 0) {
UnsafeUtil.putByte(buffer, pos++, (byte) value);
position++;
UnsafeUtil.putByte(buffer, position++, (byte) value);
return;
} else {
UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
position++;
UnsafeUtil.putByte(buffer, position++, (byte) (((int) value & 0x7F) | 0x80));
value >>>= 7;
}
}
@ -1854,7 +1847,7 @@ public abstract class CodedOutputStream extends ByteOutput {
}
static boolean isSupported() {
return UnsafeUtil.hasUnsafeByteBufferOperations() && UnsafeUtil.hasUnsafeCopyMemory();
return UnsafeUtil.hasUnsafeByteBufferOperations();
}
@Override
@ -2030,7 +2023,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed32NoTag(int value) throws IOException {
buffer.putInt(bufferPos(position), value);
position += FIXED_32_SIZE;
position += FIXED32_SIZE;
}
@Override
@ -2064,7 +2057,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed64NoTag(long value) throws IOException {
buffer.putLong(bufferPos(position), value);
position += FIXED_64_SIZE;
position += FIXED64_SIZE;
}
@Override
@ -2081,8 +2074,7 @@ public abstract class CodedOutputStream extends ByteOutput {
String.format("Pos: %d, limit: %d, len: %d", position, limit, length));
}
UnsafeUtil.copyMemory(
value, UnsafeUtil.getArrayBaseOffset() + offset, null, position, length);
UnsafeUtil.copyMemory(value, offset, position, length);
position += length;
}
@ -2249,19 +2241,17 @@ public abstract class CodedOutputStream extends ByteOutput {
*/
final void bufferUInt32NoTag(int value) {
if (HAS_UNSAFE_ARRAY_OPERATIONS) {
final long originalPos = ARRAY_BASE_OFFSET + position;
long pos = originalPos;
final long originalPos = position;
while (true) {
if ((value & ~0x7F) == 0) {
UnsafeUtil.putByte(buffer, pos++, (byte) value);
UnsafeUtil.putByte(buffer, position++, (byte) value);
break;
} else {
UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
UnsafeUtil.putByte(buffer, position++, (byte) ((value & 0x7F) | 0x80));
value >>>= 7;
}
}
int delta = (int) (pos - originalPos);
position += delta;
int delta = (int) (position - originalPos);
totalBytesWritten += delta;
} else {
while (true) {
@ -2284,19 +2274,17 @@ public abstract class CodedOutputStream extends ByteOutput {
*/
final void bufferUInt64NoTag(long value) {
if (HAS_UNSAFE_ARRAY_OPERATIONS) {
final long originalPos = ARRAY_BASE_OFFSET + position;
long pos = originalPos;
final long originalPos = position;
while (true) {
if ((value & ~0x7FL) == 0) {
UnsafeUtil.putByte(buffer, pos++, (byte) value);
UnsafeUtil.putByte(buffer, position++, (byte) value);
break;
} else {
UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
UnsafeUtil.putByte(buffer, position++, (byte) (((int) value & 0x7F) | 0x80));
value >>>= 7;
}
}
int delta = (int) (pos - originalPos);
position += delta;
int delta = (int) (position - originalPos);
totalBytesWritten += delta;
} else {
while (true) {
@ -2322,7 +2310,7 @@ public abstract class CodedOutputStream extends ByteOutput {
buffer[position++] = (byte) ((value >> 8) & 0xFF);
buffer[position++] = (byte) ((value >> 16) & 0xFF);
buffer[position++] = (byte) ((value >> 24) & 0xFF);
totalBytesWritten += FIXED_32_SIZE;
totalBytesWritten += FIXED32_SIZE;
}
/**
@ -2338,7 +2326,7 @@ public abstract class CodedOutputStream extends ByteOutput {
buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
totalBytesWritten += FIXED_64_SIZE;
totalBytesWritten += FIXED64_SIZE;
}
}
@ -2379,7 +2367,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed32(final int fieldNumber, final int value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED32_SIZE);
bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
bufferFixed32NoTag(value);
}
@ -2393,7 +2381,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed64(final int fieldNumber, final long value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED64_SIZE);
bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
bufferFixed64NoTag(value);
}
@ -2519,7 +2507,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed32NoTag(final int value) throws IOException {
flushIfNotAvailable(FIXED_32_SIZE);
flushIfNotAvailable(FIXED32_SIZE);
bufferFixed32NoTag(value);
}
@ -2531,7 +2519,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed64NoTag(final long value) throws IOException {
flushIfNotAvailable(FIXED_64_SIZE);
flushIfNotAvailable(FIXED64_SIZE);
bufferFixed64NoTag(value);
}
@ -2682,7 +2670,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed32(final int fieldNumber, final int value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED32_SIZE);
bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
bufferFixed32NoTag(value);
}
@ -2696,7 +2684,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed64(final int fieldNumber, final long value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED64_SIZE);
bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
bufferFixed64NoTag(value);
}
@ -2822,7 +2810,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed32NoTag(final int value) throws IOException {
flushIfNotAvailable(FIXED_32_SIZE);
flushIfNotAvailable(FIXED32_SIZE);
bufferFixed32NoTag(value);
}
@ -2834,7 +2822,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override
public void writeFixed64NoTag(final long value) throws IOException {
flushIfNotAvailable(FIXED_64_SIZE);
flushIfNotAvailable(FIXED64_SIZE);
bufferFixed64NoTag(value);
}

@ -0,0 +1,71 @@
// 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.
package com.google.protobuf;
/**
* Parsers to discard unknown fields during parsing.
*/
public final class DiscardUnknownFieldsParser {
/**
* Warps a given {@link Parser} into a new {@link Parser} that discards unknown fields during
* parsing.
*
* <p>Usage example:
* <pre>{@code
* private final static Parser<Foo> FOO_PARSER = DiscardUnknownFieldsParser.wrap(Foo.parser());
* Foo parseFooDiscardUnknown(ByteBuffer input) throws IOException {
* return FOO_PARSER.parseFrom(input);
* }
* }</pre>
*
* <p>Like all other implementations of {@code Parser}, this parser is stateless and thread-safe.
*
* @param parser The delegated parser that parses messages.
* @return a {@link Parser} that will discard unknown fields during parsing.
*/
public static final <T extends Message> Parser<T> wrap(final Parser<T> parser) {
return new AbstractParser<T>() {
@Override
public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
try {
input.discardUnknownFields();
return parser.parsePartialFrom(input, extensionRegistry);
} finally {
input.unsetDiscardUnknownFields();
}
}
};
}
private DiscardUnknownFieldsParser() {}
}

@ -590,9 +590,8 @@ public final class DynamicMessage extends AbstractMessage {
@Override
public Builder setUnknownFields(UnknownFieldSet unknownFields) {
if (getDescriptorForType().getFile().getSyntax()
== Descriptors.FileDescriptor.Syntax.PROTO3) {
// Proto3 discards unknown fields.
if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3
&& CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
return this;
}
this.unknownFields = unknownFields;
@ -601,9 +600,8 @@ public final class DynamicMessage extends AbstractMessage {
@Override
public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
if (getDescriptorForType().getFile().getSyntax()
== Descriptors.FileDescriptor.Syntax.PROTO3) {
// Proto3 discards unknown fields.
if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3
&& CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
return this;
}
this.unknownFields =

@ -58,10 +58,7 @@ public abstract class Extension<ContainingType extends MessageLite, Type>
PROTO1,
}
protected ExtensionType getExtensionType() {
// TODO(liujisi): make this abstract after we fix proto1.
return ExtensionType.IMMUTABLE;
}
protected abstract ExtensionType getExtensionType();
/**
* Type of a message extension.
@ -70,7 +67,7 @@ public abstract class Extension<ContainingType extends MessageLite, Type>
PROTO1,
PROTO2,
}
/**
* If the extension is a message extension (i.e., getLiteType() == MESSAGE),
* returns the type of the message, otherwise undefined.

@ -34,7 +34,7 @@ import static com.google.protobuf.ExtensionRegistryLite.EMPTY_REGISTRY_LITE;
/**
* A factory object to create instances of {@link ExtensionRegistryLite}.
*
*
* <p>
* This factory detects (via reflection) if the full (non-Lite) protocol buffer libraries
* are available, and if so, the instances returned are actually {@link ExtensionRegistry}.
@ -82,6 +82,7 @@ final class ExtensionRegistryFactory {
return EMPTY_REGISTRY_LITE;
}
static boolean isFullRegistry(ExtensionRegistryLite registry) {
return EXTENSION_REGISTRY_CLASS != null
&& EXTENSION_REGISTRY_CLASS.isAssignableFrom(registry.getClass());
@ -90,6 +91,6 @@ final class ExtensionRegistryFactory {
private static final ExtensionRegistryLite invokeSubclassFactory(String methodName)
throws Exception {
return (ExtensionRegistryLite) EXTENSION_REGISTRY_CLASS
.getMethod(methodName).invoke(null);
.getDeclaredMethod(methodName).invoke(null);
}
}

@ -107,11 +107,12 @@ public abstract class GeneratedMessageLite<
@SuppressWarnings("unchecked") // Guaranteed by runtime
@Override
public int hashCode() {
if (memoizedHashCode == 0) {
HashCodeVisitor visitor = new HashCodeVisitor();
visit(visitor, (MessageType) this);
memoizedHashCode = visitor.hashCode;
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
HashCodeVisitor visitor = new HashCodeVisitor();
visit(visitor, (MessageType) this);
memoizedHashCode = visitor.hashCode;
return memoizedHashCode;
}
@ -331,7 +332,7 @@ public abstract class GeneratedMessageLite<
if (isBuilt) {
MessageType newInstance =
(MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
newInstance.visit(MergeFromVisitor.INSTANCE, instance);
mergeFromInstance(newInstance, instance);
instance = newInstance;
isBuilt = false;
}
@ -386,10 +387,14 @@ public abstract class GeneratedMessageLite<
/** All subclasses implement this. */
public BuilderType mergeFrom(MessageType message) {
copyOnWrite();
instance.visit(MergeFromVisitor.INSTANCE, message);
mergeFromInstance(instance, message);
return (BuilderType) this;
}
private void mergeFromInstance(MessageType dest, MessageType src) {
dest.visit(MergeFromVisitor.INSTANCE, src);
}
@Override
public MessageType getDefaultInstanceForType() {
return defaultInstance;
@ -1713,7 +1718,6 @@ public abstract class GeneratedMessageLite<
Object visitOneofLong(boolean minePresent, Object mine, Object other);
Object visitOneofString(boolean minePresent, Object mine, Object other);
Object visitOneofByteString(boolean minePresent, Object mine, Object other);
Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other);
Object visitOneofMessage(boolean minePresent, Object mine, Object other);
void visitOneofNotSet(boolean minePresent);
@ -1721,7 +1725,6 @@ public abstract class GeneratedMessageLite<
* Message fields use null sentinals.
*/
<T extends MessageLite> T visitMessage(T mine, T other);
LazyFieldLite visitLazyMessage(LazyFieldLite mine, LazyFieldLite other);
<T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other);
BooleanList visitBooleanList(BooleanList mine, BooleanList other);
@ -1864,14 +1867,6 @@ public abstract class GeneratedMessageLite<
throw NOT_EQUALS;
}
@Override
public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
if (minePresent && mine.equals(other)) {
return mine;
}
throw NOT_EQUALS;
}
@Override
public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
if (minePresent && ((GeneratedMessageLite<?, ?>) mine).equals(this, (MessageLite) other)) {
@ -1902,21 +1897,6 @@ public abstract class GeneratedMessageLite<
return mine;
}
@Override
public LazyFieldLite visitLazyMessage(
LazyFieldLite mine, LazyFieldLite other) {
if (mine == null && other == null) {
return null;
}
if (mine == null || other == null) {
throw NOT_EQUALS;
}
if (mine.equals(other)) {
return mine;
}
throw NOT_EQUALS;
}
@Override
public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
if (!mine.equals(other)) {
@ -2093,12 +2073,6 @@ public abstract class GeneratedMessageLite<
return mine;
}
@Override
public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
hashCode = (53 * hashCode) + mine.hashCode();
return mine;
}
@Override
public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
return visitMessage((MessageLite) mine, (MessageLite) other);
@ -2127,18 +2101,6 @@ public abstract class GeneratedMessageLite<
return mine;
}
@Override
public LazyFieldLite visitLazyMessage(LazyFieldLite mine, LazyFieldLite other) {
final int protoHash;
if (mine != null) {
protoHash = mine.hashCode();
} else {
protoHash = 37;
}
hashCode = (53 * hashCode) + protoHash;
return mine;
}
@Override
public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
hashCode = (53 * hashCode) + mine.hashCode();
@ -2281,13 +2243,6 @@ public abstract class GeneratedMessageLite<
return other;
}
@Override
public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
LazyFieldLite lazy = minePresent ? (LazyFieldLite) mine : new LazyFieldLite();
lazy.merge((LazyFieldLite) other);
return lazy;
}
@Override
public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
if (minePresent) {
@ -2311,17 +2266,6 @@ public abstract class GeneratedMessageLite<
return mine != null ? mine : other;
}
@Override
public LazyFieldLite visitLazyMessage(LazyFieldLite mine, LazyFieldLite other) {
if (other != null) {
if (mine == null) {
mine = new LazyFieldLite();
}
mine.merge(other);
}
return mine;
}
@Override
public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
int size = mine.size();

@ -30,6 +30,8 @@
package com.google.protobuf;
import static com.google.protobuf.Internal.checkNotNull;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.EnumDescriptor;
import com.google.protobuf.Descriptors.EnumValueDescriptor;
@ -47,7 +49,6 @@ import com.google.protobuf.Descriptors.OneofDescriptor;
// to be able to use GeneratedMessage.GeneratedExtension. The GeneratedExtension definition in
// this file is also excluded from opensource to avoid conflict.
import com.google.protobuf.GeneratedMessage.GeneratedExtension;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamException;
@ -277,13 +278,30 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
/**
* Called by subclasses to parse an unknown field.
*
* @return {@code true} unless the tag is an end-group tag.
*/
protected boolean parseUnknownField(
CodedInputStream input,
UnknownFieldSet.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
int tag)
throws IOException {
if (input.shouldDiscardUnknownFields()) {
return input.skipField(tag);
}
return unknownFields.mergeFieldFrom(tag, input);
}
protected boolean parseUnknownFieldProto3(
CodedInputStream input,
UnknownFieldSet.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag)
throws IOException {
if (input.shouldDiscardUnknownFieldsProto3()) {
return input.skipField(tag);
}
return unknownFields.mergeFieldFrom(tag, input);
}
@ -619,15 +637,22 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return (BuilderType) this;
}
protected BuilderType setUnknownFieldsProto3(final UnknownFieldSet unknownFields) {
if (CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
return (BuilderType) this;
}
this.unknownFields = unknownFields;
onChanged();
return (BuilderType) this;
}
@Override
public BuilderType mergeUnknownFields(
final UnknownFieldSet unknownFields) {
this.unknownFields =
return setUnknownFields(
UnknownFieldSet.newBuilder(this.unknownFields)
.mergeFrom(unknownFields)
.build();
onChanged();
return (BuilderType) this;
.build());
}
@Override
@ -665,18 +690,6 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return unknownFields;
}
/**
* Called by subclasses to parse an unknown field.
* @return {@code true} unless the tag is an end-group tag.
*/
protected boolean parseUnknownField(
final CodedInputStream input,
final UnknownFieldSet.Builder unknownFields,
final ExtensionRegistryLite extensionRegistry,
final int tag) throws IOException {
return unknownFields.mergeFieldFrom(tag, input);
}
/**
* Implementation of {@link BuilderParent} for giving to our children. This
* small inner class makes it so we don't publicly expose the BuilderParent
@ -987,8 +1000,23 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
return MessageReflection.mergeFieldFrom(
input, unknownFields, extensionRegistry, getDescriptorForType(),
new MessageReflection.ExtensionAdapter(extensions), tag);
input, input.shouldDiscardUnknownFields() ? null : unknownFields, extensionRegistry,
getDescriptorForType(), new MessageReflection.ExtensionAdapter(extensions), tag);
}
@Override
protected boolean parseUnknownFieldProto3(
CodedInputStream input,
UnknownFieldSet.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
return MessageReflection.mergeFieldFrom(
input,
input.shouldDiscardUnknownFieldsProto3() ? null : unknownFields,
extensionRegistry,
getDescriptorForType(),
new MessageReflection.ExtensionAdapter(extensions),
tag);
}
@ -1458,21 +1486,6 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return super.isInitialized() && extensionsAreInitialized();
}
/**
* Called by subclasses to parse an unknown field or an extension.
* @return {@code true} unless the tag is an end-group tag.
*/
@Override
protected boolean parseUnknownField(
final CodedInputStream input,
final UnknownFieldSet.Builder unknownFields,
final ExtensionRegistryLite extensionRegistry,
final int tag) throws IOException {
return MessageReflection.mergeFieldFrom(
input, unknownFields, extensionRegistry, getDescriptorForType(),
new MessageReflection.BuilderAdapter(this), tag);
}
// ---------------------------------------------------------------
// Reflection
@ -2277,7 +2290,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
public Object getRepeatedRaw(Builder builder, int index) {
return getRepeated(builder, index);
}
@Override
public void setRepeated(Builder builder, int index, Object value) {
getMutableMapField(builder).getMutableList().set(index, coerceType((Message) value));
@ -2678,7 +2691,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return (Extension<MessageType, T>) extension;
}
protected static int computeStringSize(final int fieldNumber, final Object value) {
if (value instanceof String) {
return CodedOutputStream.computeStringSize(fieldNumber, (String) value);
@ -2686,7 +2699,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value);
}
}
protected static int computeStringSizeNoTag(final Object value) {
if (value instanceof String) {
return CodedOutputStream.computeStringSizeNoTag((String) value);
@ -2694,7 +2707,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
}
}
protected static void writeString(
CodedOutputStream output, final int fieldNumber, final Object value) throws IOException {
if (value instanceof String) {
@ -2703,7 +2716,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
output.writeBytes(fieldNumber, (ByteString) value);
}
}
protected static void writeStringNoTag(
CodedOutputStream output, final Object value) throws IOException {
if (value instanceof String) {

@ -414,9 +414,8 @@ public final class Internal {
}
}
/**
* An empty byte array constant used in generated code.
*/
/** An empty byte array constant used in generated code. */
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
/**

@ -50,6 +50,10 @@ public class InvalidProtocolBufferException extends IOException {
super(e.getMessage(), e);
}
public InvalidProtocolBufferException(final String description, IOException e) {
super(description, e);
}
/**
* Attaches an unfinished message to the exception to support best-effort
* parsing in {@code Parser} interface.

@ -31,7 +31,6 @@
package com.google.protobuf;
import com.google.protobuf.Descriptors.FieldDescriptor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -714,12 +713,14 @@ class MessageReflection {
}
/**
* Parses a single field into MergeTarget. The target can be Message.Builder,
* FieldSet or MutableMessage.
* Parses a single field into MergeTarget. The target can be Message.Builder, FieldSet or
* MutableMessage.
*
* Package-private because it is used by GeneratedMessage.ExtendableMessage.
* <p>Package-private because it is used by GeneratedMessage.ExtendableMessage.
*
* @param tag The tag, which should have already been read.
* @param unknownFields If not null, unknown fields will be merged to this {@link
* UnknownFieldSet}, otherwise unknown fields will be discarded.
* @return {@code true} unless the tag is an end-group tag.
*/
static boolean mergeFieldFrom(
@ -728,7 +729,8 @@ class MessageReflection {
ExtensionRegistryLite extensionRegistry,
Descriptors.Descriptor type,
MergeTarget target,
int tag) throws IOException {
int tag)
throws IOException {
if (type.getOptions().getMessageSetWireFormat() &&
tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
mergeMessageSetExtensionFromCodedStream(
@ -792,7 +794,11 @@ class MessageReflection {
}
if (unknown) { // Unknown field or wrong wire type. Skip.
return unknownFields.mergeFieldFrom(tag, input);
if (unknownFields != null) {
return unknownFields.mergeFieldFrom(tag, input);
} else {
return input.skipField(tag);
}
}
if (packed) {
@ -844,7 +850,9 @@ class MessageReflection {
// If the number isn't recognized as a valid value for this enum,
// drop it.
if (value == null) {
unknownFields.mergeVarintField(fieldNumber, rawValue);
if (unknownFields != null) {
unknownFields.mergeVarintField(fieldNumber, rawValue);
}
return true;
}
}
@ -947,7 +955,7 @@ class MessageReflection {
mergeMessageSetExtensionFromBytes(
rawBytes, extension, extensionRegistry, target);
} else { // We don't know how to parse this. Ignore it.
if (rawBytes != null) {
if (rawBytes != null && unknownFields != null) {
unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
.addLengthDelimited(rawBytes).build());
}

@ -34,7 +34,6 @@ import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.EnumDescriptor;
import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.CharBuffer;
@ -56,14 +55,7 @@ import java.util.regex.Pattern;
public final class TextFormat {
private TextFormat() {}
private static final Logger logger =
Logger.getLogger(TextFormat.class.getName());
private static final Printer DEFAULT_PRINTER = new Printer();
private static final Printer SINGLE_LINE_PRINTER =
(new Printer()).setSingleLineMode(true);
private static final Printer UNICODE_PRINTER =
(new Printer()).setEscapeNonAscii(false);
private static final Logger logger = Logger.getLogger(TextFormat.class.getName());
/**
* Outputs a textual representation of the Protocol Message supplied into
@ -73,14 +65,14 @@ public final class TextFormat {
public static void print(
final MessageOrBuilder message, final Appendable output)
throws IOException {
DEFAULT_PRINTER.print(message, new TextGenerator(output));
Printer.DEFAULT.print(message, multiLineOutput(output));
}
/** Outputs a textual representation of {@code fields} to {@code output}. */
public static void print(final UnknownFieldSet fields,
final Appendable output)
throws IOException {
DEFAULT_PRINTER.printUnknownFields(fields, new TextGenerator(output));
Printer.DEFAULT.printUnknownFields(fields, multiLineOutput(output));
}
/**
@ -90,7 +82,7 @@ public final class TextFormat {
public static void printUnicode(
final MessageOrBuilder message, final Appendable output)
throws IOException {
UNICODE_PRINTER.print(message, new TextGenerator(output));
Printer.UNICODE.print(message, multiLineOutput(output));
}
/**
@ -100,7 +92,7 @@ public final class TextFormat {
public static void printUnicode(final UnknownFieldSet fields,
final Appendable output)
throws IOException {
UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(output));
Printer.UNICODE.printUnknownFields(fields, multiLineOutput(output));
}
/**
@ -109,10 +101,9 @@ public final class TextFormat {
*/
public static String shortDebugString(final MessageOrBuilder message) {
try {
final StringBuilder sb = new StringBuilder();
SINGLE_LINE_PRINTER.print(message, new TextGenerator(sb));
// Single line mode currently might have an extra space at the end.
return sb.toString().trim();
final StringBuilder text = new StringBuilder();
Printer.DEFAULT.print(message, singleLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
@ -125,11 +116,11 @@ public final class TextFormat {
public static String shortDebugString(final FieldDescriptor field,
final Object value) {
try {
final StringBuilder sb = new StringBuilder();
SINGLE_LINE_PRINTER.printField(field, value, new TextGenerator(sb));
return sb.toString().trim();
final StringBuilder text = new StringBuilder();
Printer.DEFAULT.printField(field, value, singleLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
throw new IllegalStateException(e);
}
}
@ -139,10 +130,9 @@ public final class TextFormat {
*/
public static String shortDebugString(final UnknownFieldSet fields) {
try {
final StringBuilder sb = new StringBuilder();
SINGLE_LINE_PRINTER.printUnknownFields(fields, new TextGenerator(sb));
// Single line mode currently might have an extra space at the end.
return sb.toString().trim();
final StringBuilder text = new StringBuilder();
Printer.DEFAULT.printUnknownFields(fields, singleLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
@ -183,7 +173,7 @@ public final class TextFormat {
public static String printToUnicodeString(final MessageOrBuilder message) {
try {
final StringBuilder text = new StringBuilder();
UNICODE_PRINTER.print(message, new TextGenerator(text));
Printer.UNICODE.print(message, multiLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
@ -197,7 +187,7 @@ public final class TextFormat {
public static String printToUnicodeString(final UnknownFieldSet fields) {
try {
final StringBuilder text = new StringBuilder();
UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(text));
Printer.UNICODE.printUnknownFields(fields, multiLineOutput(text));
return text.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
@ -208,7 +198,7 @@ public final class TextFormat {
final Object value,
final Appendable output)
throws IOException {
DEFAULT_PRINTER.printField(field, value, new TextGenerator(output));
Printer.DEFAULT.printField(field, value, multiLineOutput(output));
}
public static String printFieldToString(final FieldDescriptor field,
@ -222,6 +212,23 @@ public final class TextFormat {
}
}
/**
* Outputs a unicode textual representation of the value of given field value.
*
* <p>Same as {@code printFieldValue()}, except that non-ASCII characters in string type fields
* are not escaped in backslash+octals.
*
* @param field the descriptor of the field
* @param value the value of the field
* @param output the output to which to append the formatted value
* @throws ClassCastException if the value is not appropriate for the given field descriptor
* @throws IOException if there is an exception writing to the output
*/
public static void printUnicodeFieldValue(
final FieldDescriptor field, final Object value, final Appendable output) throws IOException {
Printer.UNICODE.printFieldValue(field, value, multiLineOutput(output));
}
/**
* Outputs a textual representation of the value of given field value.
*
@ -236,7 +243,7 @@ public final class TextFormat {
final Object value,
final Appendable output)
throws IOException {
DEFAULT_PRINTER.printFieldValue(field, value, new TextGenerator(output));
Printer.DEFAULT.printFieldValue(field, value, multiLineOutput(output));
}
/**
@ -253,7 +260,7 @@ public final class TextFormat {
final Object value,
final Appendable output)
throws IOException {
printUnknownFieldValue(tag, value, new TextGenerator(output));
printUnknownFieldValue(tag, value, multiLineOutput(output));
}
private static void printUnknownFieldValue(final int tag,
@ -277,7 +284,7 @@ public final class TextFormat {
generator.print("\"");
break;
case WireFormat.WIRETYPE_START_GROUP:
DEFAULT_PRINTER.printUnknownFields((UnknownFieldSet) value, generator);
Printer.DEFAULT.printUnknownFields((UnknownFieldSet) value, generator);
break;
default:
throw new IllegalArgumentException("Bad tag: " + tag);
@ -286,24 +293,16 @@ public final class TextFormat {
/** Helper class for converting protobufs to text. */
private static final class Printer {
/** Whether to omit newlines from the output. */
boolean singleLineMode = false;
// Printer instance which escapes non-ASCII characters.
static final Printer DEFAULT = new Printer(true);
// Printer instance which emits Unicode (it still escapes newlines and quotes in strings).
static final Printer UNICODE = new Printer(false);
/** Whether to escape non ASCII characters with backslash and octal. */
boolean escapeNonAscii = true;
private Printer() {}
private final boolean escapeNonAscii;
/** Setter of singleLineMode */
private Printer setSingleLineMode(boolean singleLineMode) {
this.singleLineMode = singleLineMode;
return this;
}
/** Setter of escapeNonAscii */
private Printer setEscapeNonAscii(boolean escapeNonAscii) {
private Printer(boolean escapeNonAscii) {
this.escapeNonAscii = escapeNonAscii;
return this;
}
private void print(
@ -355,12 +354,9 @@ public final class TextFormat {
}
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
if (singleLineMode) {
generator.print(" { ");
} else {
generator.print(" {\n");
generator.indent();
}
generator.print(" {");
generator.eol();
generator.indent();
} else {
generator.print(": ");
}
@ -368,19 +364,10 @@ public final class TextFormat {
printFieldValue(field, value, generator);
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
if (singleLineMode) {
generator.print("} ");
} else {
generator.outdent();
generator.print("}\n");
}
} else {
if (singleLineMode) {
generator.print(" ");
} else {
generator.print("\n");
}
generator.outdent();
generator.print("}");
}
generator.eol();
}
private void printFieldValue(final FieldDescriptor field,
@ -469,19 +456,13 @@ public final class TextFormat {
field.getLengthDelimitedList(), generator);
for (final UnknownFieldSet value : field.getGroupList()) {
generator.print(entry.getKey().toString());
if (singleLineMode) {
generator.print(" { ");
} else {
generator.print(" {\n");
generator.indent();
}
generator.print(" {");
generator.eol();
generator.indent();
printUnknownFields(value, generator);
if (singleLineMode) {
generator.print("} ");
} else {
generator.outdent();
generator.print("}\n");
}
generator.outdent();
generator.print("}");
generator.eol();
}
}
}
@ -495,7 +476,7 @@ public final class TextFormat {
generator.print(String.valueOf(number));
generator.print(": ");
printUnknownFieldValue(wireType, value, generator);
generator.print(singleLineMode ? " " : "\n");
generator.eol();
}
}
}
@ -521,16 +502,29 @@ public final class TextFormat {
}
}
/**
private static TextGenerator multiLineOutput(Appendable output) {
return new TextGenerator(output, false);
}
private static TextGenerator singleLineOutput(Appendable output) {
return new TextGenerator(output, true);
}
/**
* An inner class for writing text to the output stream.
*/
private static final class TextGenerator {
private final Appendable output;
private final StringBuilder indent = new StringBuilder();
private boolean atStartOfLine = true;
private final boolean singleLineMode;
// While technically we are "at the start of a line" at the very beginning of the output, all
// we would do in response to this is emit the (zero length) indentation, so it has no effect.
// Setting it false here does however suppress an unwanted leading space in single-line mode.
private boolean atStartOfLine = false;
private TextGenerator(final Appendable output) {
private TextGenerator(final Appendable output, boolean singleLineMode) {
this.output = output;
this.singleLineMode = singleLineMode;
}
/**
@ -552,35 +546,31 @@ public final class TextFormat {
throw new IllegalArgumentException(
" Outdent() without matching Indent().");
}
indent.delete(length - 2, length);
indent.setLength(length - 2);
}
/**
* Print text to the output stream.
* Print text to the output stream. Bare newlines are never expected to be passed to this
* method; to indicate the end of a line, call "eol()".
*/
public void print(final CharSequence text) throws IOException {
final int size = text.length();
int pos = 0;
for (int i = 0; i < size; i++) {
if (text.charAt(i) == '\n') {
write(text.subSequence(pos, i + 1));
pos = i + 1;
atStartOfLine = true;
}
if (atStartOfLine) {
atStartOfLine = false;
output.append(singleLineMode ? " " : indent);
}
write(text.subSequence(pos, size));
output.append(text);
}
private void write(final CharSequence data) throws IOException {
if (data.length() == 0) {
return;
}
if (atStartOfLine) {
atStartOfLine = false;
output.append(indent);
/**
* Signifies reaching the "end of the current line" in the output. In single-line mode, this
* does not result in a newline being emitted, but ensures that a separating space is written
* before the next output.
*/
public void eol() throws IOException {
if (!singleLineMode) {
output.append("\n");
}
output.append(data);
atStartOfLine = true;
}
}
@ -1469,9 +1459,15 @@ public final class TextFormat {
extensionRegistry, name.toString());
if (extension == null) {
unknownFields.add((tokenizer.getPreviousLine() + 1) + ":" +
(tokenizer.getPreviousColumn() + 1) + ":\t" +
type.getFullName() + ".[" + name + "]");
unknownFields.add(
(tokenizer.getPreviousLine() + 1)
+ ":"
+ (tokenizer.getPreviousColumn() + 1)
+ ":\t"
+ type.getFullName()
+ ".["
+ name
+ "]");
} else {
if (extension.descriptor.getContainingType() != type) {
throw tokenizer.parseExceptionPreviousToken(
@ -1506,9 +1502,14 @@ public final class TextFormat {
}
if (field == null) {
unknownFields.add((tokenizer.getPreviousLine() + 1) + ":" +
(tokenizer.getPreviousColumn() + 1) + ":\t" +
type.getFullName() + "." + name);
unknownFields.add(
(tokenizer.getPreviousLine() + 1)
+ ":"
+ (tokenizer.getPreviousColumn() + 1)
+ ":\t"
+ type.getFullName()
+ "."
+ name);
}
}

@ -715,7 +715,7 @@ public final class UnknownFieldSet implements MessageLite {
* @see UnknownFieldSet
*/
public static final class Field {
Field() {}
private Field() {}
/** Construct a new {@link Builder}. */
public static Builder newBuilder() {

@ -47,8 +47,29 @@ final class UnsafeUtil {
private static final boolean HAS_UNSAFE_BYTEBUFFER_OPERATIONS =
supportsUnsafeByteBufferOperations();
private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations();
private static final boolean HAS_UNSAFE_COPY_MEMORY = supportsUnsafeCopyMemory();
private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset();
private static final long BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset(byte[].class);
// Micro-optimization: we can assume a scale of 1 and skip the multiply
// private static final long BYTE_ARRAY_INDEX_SCALE = 1;
private static final long BOOLEAN_ARRAY_BASE_OFFSET = arrayBaseOffset(boolean[].class);
private static final long BOOLEAN_ARRAY_INDEX_SCALE = arrayIndexScale(boolean[].class);
private static final long INT_ARRAY_BASE_OFFSET = arrayBaseOffset(int[].class);
private static final long INT_ARRAY_INDEX_SCALE = arrayIndexScale(int[].class);
private static final long LONG_ARRAY_BASE_OFFSET = arrayBaseOffset(long[].class);
private static final long LONG_ARRAY_INDEX_SCALE = arrayIndexScale(long[].class);
private static final long FLOAT_ARRAY_BASE_OFFSET = arrayBaseOffset(float[].class);
private static final long FLOAT_ARRAY_INDEX_SCALE = arrayIndexScale(float[].class);
private static final long DOUBLE_ARRAY_BASE_OFFSET = arrayBaseOffset(double[].class);
private static final long DOUBLE_ARRAY_INDEX_SCALE = arrayIndexScale(double[].class);
private static final long OBJECT_ARRAY_BASE_OFFSET = arrayBaseOffset(Object[].class);
private static final long OBJECT_ARRAY_INDEX_SCALE = arrayIndexScale(Object[].class);
private static final long BUFFER_ADDRESS_OFFSET = fieldOffset(bufferAddressField());
private UnsafeUtil() {}
@ -57,10 +78,6 @@ final class UnsafeUtil {
return HAS_UNSAFE_ARRAY_OPERATIONS;
}
static boolean hasUnsafeCopyMemory() {
return HAS_UNSAFE_COPY_MEMORY;
}
static boolean hasUnsafeByteBufferOperations() {
return HAS_UNSAFE_BYTEBUFFER_OPERATIONS;
}
@ -69,8 +86,12 @@ final class UnsafeUtil {
return MEMORY_ACCESSOR.objectFieldOffset(field);
}
static long getArrayBaseOffset() {
return ARRAY_BASE_OFFSET;
private static int arrayBaseOffset(Class<?> clazz) {
return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayBaseOffset(clazz) : -1;
}
private static int arrayIndexScale(Class<?> clazz) {
return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayIndexScale(clazz) : -1;
}
static byte getByte(Object target, long offset) {
@ -129,9 +150,82 @@ final class UnsafeUtil {
MEMORY_ACCESSOR.putObject(target, offset, value);
}
static void copyMemory(
Object src, long srcOffset, Object target, long targetOffset, long length) {
MEMORY_ACCESSOR.copyMemory(src, srcOffset, target, targetOffset, length);
static byte getByte(byte[] target, long index) {
return MEMORY_ACCESSOR.getByte(target, BYTE_ARRAY_BASE_OFFSET + index);
}
static void putByte(byte[] target, long index, byte value) {
MEMORY_ACCESSOR.putByte(target, BYTE_ARRAY_BASE_OFFSET + index, value);
}
static int getInt(int[] target, long index) {
return MEMORY_ACCESSOR.getInt(target, INT_ARRAY_BASE_OFFSET + (index * INT_ARRAY_INDEX_SCALE));
}
static void putInt(int[] target, long index, int value) {
MEMORY_ACCESSOR.putInt(target, INT_ARRAY_BASE_OFFSET + (index * INT_ARRAY_INDEX_SCALE), value);
}
static long getLong(long[] target, long index) {
return MEMORY_ACCESSOR.getLong(
target, LONG_ARRAY_BASE_OFFSET + (index * LONG_ARRAY_INDEX_SCALE));
}
static void putLong(long[] target, long index, long value) {
MEMORY_ACCESSOR.putLong(
target, LONG_ARRAY_BASE_OFFSET + (index * LONG_ARRAY_INDEX_SCALE), value);
}
static boolean getBoolean(boolean[] target, long index) {
return MEMORY_ACCESSOR.getBoolean(
target, BOOLEAN_ARRAY_BASE_OFFSET + (index * BOOLEAN_ARRAY_INDEX_SCALE));
}
static void putBoolean(boolean[] target, long index, boolean value) {
MEMORY_ACCESSOR.putBoolean(
target, BOOLEAN_ARRAY_BASE_OFFSET + (index * BOOLEAN_ARRAY_INDEX_SCALE), value);
}
static float getFloat(float[] target, long index) {
return MEMORY_ACCESSOR.getFloat(
target, FLOAT_ARRAY_BASE_OFFSET + (index * FLOAT_ARRAY_INDEX_SCALE));
}
static void putFloat(float[] target, long index, float value) {
MEMORY_ACCESSOR.putFloat(
target, FLOAT_ARRAY_BASE_OFFSET + (index * FLOAT_ARRAY_INDEX_SCALE), value);
}
static double getDouble(double[] target, long index) {
return MEMORY_ACCESSOR.getDouble(
target, DOUBLE_ARRAY_BASE_OFFSET + (index * DOUBLE_ARRAY_INDEX_SCALE));
}
static void putDouble(double[] target, long index, double value) {
MEMORY_ACCESSOR.putDouble(
target, DOUBLE_ARRAY_BASE_OFFSET + (index * DOUBLE_ARRAY_INDEX_SCALE), value);
}
static Object getObject(Object[] target, long index) {
return MEMORY_ACCESSOR.getObject(
target, OBJECT_ARRAY_BASE_OFFSET + (index * OBJECT_ARRAY_INDEX_SCALE));
}
static void putObject(Object[] target, long index, Object value) {
MEMORY_ACCESSOR.putObject(
target, OBJECT_ARRAY_BASE_OFFSET + (index * OBJECT_ARRAY_INDEX_SCALE), value);
}
static void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
MEMORY_ACCESSOR.copyMemory(src, srcIndex, targetOffset, length);
}
static void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
MEMORY_ACCESSOR.copyMemory(srcOffset, target, targetIndex, length);
}
static void copyMemory(byte[] src, long srcIndex, byte[] target, long targetIndex, long length) {
System.arraycopy(src, (int) srcIndex, target, (int) targetIndex, (int) length);
}
static byte getByte(long address) {
@ -221,6 +315,7 @@ final class UnsafeUtil {
Class<?> clazz = UNSAFE.getClass();
clazz.getMethod("objectFieldOffset", Field.class);
clazz.getMethod("arrayBaseOffset", Class.class);
clazz.getMethod("arrayIndexScale", Class.class);
clazz.getMethod("getInt", Object.class, long.class);
clazz.getMethod("putInt", Object.class, long.class, int.class);
clazz.getMethod("getLong", Object.class, long.class);
@ -245,27 +340,6 @@ final class UnsafeUtil {
return false;
}
/**
* Indicates whether or not unsafe copyMemory(object, long, object, long, long) operations are
* supported on this platform.
*/
private static boolean supportsUnsafeCopyMemory() {
if (UNSAFE == null) {
return false;
}
try {
Class<?> clazz = UNSAFE.getClass();
clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
return true;
} catch (Throwable e) {
logger.log(
Level.WARNING,
"copyMemory is missing from platform - proto runtime falling back to safer methods.");
}
return false;
}
private static boolean supportsUnsafeByteBufferOperations() {
if (UNSAFE == null) {
return false;
@ -283,6 +357,7 @@ final class UnsafeUtil {
clazz.getMethod("getLong", long.class);
clazz.getMethod("putLong", long.class, long.class);
clazz.getMethod("copyMemory", long.class, long.class, long.class);
clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
return true;
} catch (Throwable e) {
logger.log(
@ -307,13 +382,6 @@ final class UnsafeUtil {
return field(Buffer.class, "address");
}
/**
* Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not available.
*/
private static int byteArrayBaseOffset() {
return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayBaseOffset(byte[].class) : -1;
}
/**
* Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not
* available.
@ -394,6 +462,10 @@ final class UnsafeUtil {
return unsafe.arrayBaseOffset(clazz);
}
public final int arrayIndexScale(Class<?> clazz) {
return unsafe.arrayIndexScale(clazz);
}
public abstract byte getByte(long address);
public abstract void putByte(long address, byte value);
@ -408,10 +480,11 @@ final class UnsafeUtil {
public abstract void copyMemory(long srcAddress, long targetAddress, long length);
public abstract void copyMemory(
Object src, long srcOffset, Object target, long targetOffset, long length);
public abstract Object getStaticObject(Field field);
public abstract void copyMemory(long srcOffset, byte[] target, long targetIndex, long length);
public abstract void copyMemory(byte[] src, long srcIndex, long targetOffset, long length);
}
private static final class JvmMemoryAccessor extends MemoryAccessor {
@ -490,16 +563,20 @@ final class UnsafeUtil {
unsafe.putDouble(target, offset, value);
}
@Override
public void copyMemory(
Object src, long srcOffset, Object target, long targetOffset, long length) {
unsafe.copyMemory(src, srcOffset, target, targetOffset, length);
}
@Override
public void copyMemory(long srcAddress, long targetAddress, long length) {
unsafe.copyMemory(srcAddress, targetAddress, length);
}
@Override
public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length);
}
@Override
public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length);
}
@Override
public Object getStaticObject(Field field) {

@ -31,7 +31,6 @@
package com.google.protobuf;
import static com.google.protobuf.UnsafeUtil.addressOffset;
import static com.google.protobuf.UnsafeUtil.getArrayBaseOffset;
import static com.google.protobuf.UnsafeUtil.hasUnsafeArrayOperations;
import static com.google.protobuf.UnsafeUtil.hasUnsafeByteBufferOperations;
import static java.lang.Character.MAX_SURROGATE;
@ -1001,8 +1000,8 @@ final class Utf8 {
throw new ArrayIndexOutOfBoundsException(
String.format("Array length=%d, index=%d, limit=%d", bytes.length, index, limit));
}
long offset = getArrayBaseOffset() + index;
final long offsetLimit = getArrayBaseOffset() + limit;
long offset = index;
final long offsetLimit = limit;
if (state != COMPLETE) {
// The previous decoding operation was incomplete (or malformed).
// We look for a well-formed sequence consisting of bytes from
@ -1187,7 +1186,7 @@ final class Utf8 {
@Override
int encodeUtf8(final CharSequence in, final byte[] out, final int offset, final int length) {
long outIx = getArrayBaseOffset() + offset;
long outIx = offset;
final long outLimit = outIx + length;
final int inLimit = in.length();
if (inLimit > length || out.length - length < offset) {
@ -1204,7 +1203,7 @@ final class Utf8 {
}
if (inIx == inLimit) {
// We're done, it was ASCII encoded.
return (int) (outIx - getArrayBaseOffset());
return (int) outIx;
}
for (char c; inIx < inLimit; ++inIx) {
@ -1243,7 +1242,7 @@ final class Utf8 {
}
// All bytes have been encoded.
return (int) (outIx - getArrayBaseOffset());
return (int) outIx;
}
@Override
@ -1321,31 +1320,17 @@ final class Utf8 {
*/
private static int unsafeEstimateConsecutiveAscii(
byte[] bytes, long offset, final int maxChars) {
int remaining = maxChars;
if (remaining < UNSAFE_COUNT_ASCII_THRESHOLD) {
if (maxChars < UNSAFE_COUNT_ASCII_THRESHOLD) {
// Don't bother with small strings.
return 0;
}
// Read bytes until 8-byte aligned so that we can read longs in the loop below.
// Byte arrays are already either 8 or 16-byte aligned, so we just need to make sure that
// the index (relative to the start of the array) is also 8-byte aligned. We do this by
// ANDing the index with 7 to determine the number of bytes that need to be read before
// we're 8-byte aligned.
final int unaligned = 8 - ((int) offset & 7);
for (int j = unaligned; j > 0; j--) {
for (int i = 0; i < maxChars; i++) {
if (UnsafeUtil.getByte(bytes, offset++) < 0) {
return unaligned - j;
return i;
}
}
// This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
// To speed things up further, we're reading longs instead of bytes so we use a mask to
// determine if any byte in the current long is non-ASCII.
remaining -= unaligned;
for (; remaining >= 8 && (UnsafeUtil.getLong(bytes, offset) & ASCII_MASK_LONG) == 0;
offset += 8, remaining -= 8) {}
return maxChars - remaining;
return maxChars;
}
/**

@ -47,8 +47,10 @@ public final class WireFormat {
// Do not allow instantiation.
private WireFormat() {}
static final int FIXED_32_SIZE = 4;
static final int FIXED_64_SIZE = 8;
static final int FIXED32_SIZE = 4;
static final int FIXED64_SIZE = 8;
static final int MAX_VARINT32_SIZE = 5;
static final int MAX_VARINT64_SIZE = 10;
static final int MAX_VARINT_SIZE = 10;
public static final int WIRETYPE_VARINT = 0;

@ -41,6 +41,7 @@ import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import junit.framework.TestCase;
/**
@ -613,6 +614,82 @@ 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");
ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, bytes.length);
int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
output.writeRawVarint32(tag);
output.writeRawVarint32(bytes.length);
output.writeRawBytes(bytes);
output.writeRawVarint32(tag);
output.writeRawVarint32(bytes.length);
output.writeRawBytes(bytes);
output.writeRawByte(4);
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);
input.setSizeLimit(rawInput.length - 1);
input.readString();
input.readString();
try {
input.readRawByte(); // Hits limit.
fail("Should have thrown an exception!");
} catch (InvalidProtocolBufferException expected) {
checkSizeLimitExceeded(expected);
}
}
}
public void testIsAtEnd() throws Exception {
CodedInputStream input = CodedInputStream.newInstance(
new ByteArrayInputStream(new byte[5]));
try {
for (int i = 0; i < 5; i++) {
assertEquals(false, input.isAtEnd());
input.readRawByte();
}
assertEquals(true, input.isAtEnd());
} catch (Exception e) {
fail("Catch exception in the testIsAtEnd");
}
}
public void testCurrentLimitExceeded() throws Exception {
byte[] bytes = "123456789".getBytes("UTF-8");
ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, bytes.length);
int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
output.writeRawVarint32(tag);
output.writeRawVarint32(bytes.length);
output.writeRawBytes(bytes);
output.flush();
byte[] rawInput = rawOutput.toByteArray();
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
input.pushLimit(5);
try {
input.readString();
fail("Should have thrown an exception");
} catch (InvalidProtocolBufferException expected) {
assertEquals(expected.getMessage(),
InvalidProtocolBufferException.truncatedMessage().getMessage());
}
}
public void testSizeLimitMultipleMessages() throws Exception {
// NOTE: Size limit only applies to the stream-backed CIS.
@ -807,6 +884,52 @@ public class CodedInputStreamTest extends TestCase {
}
}
public void testReadLargeByteStringFromInputStream() throws Exception {
byte[] bytes = new byte[1024 * 1024];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) (i & 0xFF);
}
ByteString.Output rawOutput = ByteString.newOutput();
CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
output.writeRawVarint32(bytes.length);
output.writeRawBytes(bytes);
output.flush();
byte[] data = rawOutput.toByteString().toByteArray();
CodedInputStream input = CodedInputStream.newInstance(
new ByteArrayInputStream(data) {
@Override
public synchronized int available() {
return 0;
}
});
ByteString result = input.readBytes();
assertEquals(ByteString.copyFrom(bytes), result);
}
public void testReadLargeByteArrayFromInputStream() throws Exception {
byte[] bytes = new byte[1024 * 1024];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) (i & 0xFF);
}
ByteString.Output rawOutput = ByteString.newOutput();
CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
output.writeRawVarint32(bytes.length);
output.writeRawBytes(bytes);
output.flush();
byte[] data = rawOutput.toByteString().toByteArray();
CodedInputStream input = CodedInputStream.newInstance(
new ByteArrayInputStream(data) {
@Override
public synchronized int available() {
return 0;
}
});
byte[] result = input.readByteArray();
assertTrue(Arrays.equals(bytes, result));
}
public void testReadByteBuffer() throws Exception {
ByteString.Output rawOutput = ByteString.newOutput();
CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);

@ -0,0 +1,157 @@
// 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.
package com.google.protobuf;
import static org.junit.Assert.assertEquals;
import protobuf_unittest.UnittestProto;
import proto3_unittest.UnittestProto3;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for discard or preserve unknown fields. */
@RunWith(JUnit4.class)
public class DiscardUnknownFieldsTest {
@Test
public void testProto2() throws Exception {
testProto2Message(
UnittestProto.TestEmptyMessage.getDefaultInstance());
testProto2Message(
UnittestProto.TestEmptyMessageWithExtensions.getDefaultInstance());
testProto2Message(
DynamicMessage.getDefaultInstance(UnittestProto.TestEmptyMessage.getDescriptor()));
testProto2Message(
DynamicMessage.getDefaultInstance(
UnittestProto.TestEmptyMessageWithExtensions.getDescriptor()));
}
@Test
public void testProto3() throws Exception {
testProto3Message(UnittestProto3.TestEmptyMessage.getDefaultInstance());
testProto3Message(
DynamicMessage.getDefaultInstance(UnittestProto3.TestEmptyMessage.getDescriptor()));
}
private static void testProto2Message(Message message) throws Exception {
assertUnknownFieldsDefaultPreserved(message);
assertUnknownFieldsExplicitlyDiscarded(message);
assertReuseCodedInputStreamPreserve(message);
assertUnknownFieldsInUnknownFieldSetArePreserve(message);
}
private static void testProto3Message(Message message) throws Exception {
CodedInputStream.setProto3KeepUnknownsByDefaultForTest();
assertUnknownFieldsDefaultPreserved(message);
assertUnknownFieldsExplicitlyDiscarded(message);
assertReuseCodedInputStreamPreserve(message);
assertUnknownFieldsInUnknownFieldSetArePreserve(message);
CodedInputStream.setProto3DiscardUnknownsByDefaultForTest();
assertUnknownFieldsDefaultDiscarded(message);
assertUnknownFieldsExplicitlyDiscarded(message);
assertUnknownFieldsInUnknownFieldSetAreDiscarded(message);
}
private static void assertReuseCodedInputStreamPreserve(Message message) throws Exception {
final int messageSize = payload.size();
byte[] copied = new byte[messageSize * 2];
payload.copyTo(copied, 0);
payload.copyTo(copied, messageSize);
CodedInputStream input = CodedInputStream.newInstance(copied);
{
// Use DiscardUnknownFieldsParser to parse the first payload.
int oldLimit = input.pushLimit(messageSize);
Message parsed = DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(input);
assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
input.popLimit(oldLimit);
}
{
// Use the normal parser to parse the remaining payload should have unknown fields preserved.
Message parsed = message.getParserForType().parseFrom(input);
assertEquals(message.getClass().getName(), payload, parsed.toByteString());
}
}
/**
* {@link Message.Builder#setUnknownFields(UnknownFieldSet)} and {@link
* Message.Builder#mergeUnknownFields(UnknownFieldSet)} should preserve the unknown fields.
*/
private static void assertUnknownFieldsInUnknownFieldSetArePreserve(Message message)
throws Exception {
UnknownFieldSet unknownFields = UnknownFieldSet.newBuilder().mergeFrom(payload).build();
Message built = message.newBuilderForType().setUnknownFields(unknownFields).build();
assertEquals(message.getClass().getName(), payload, built.toByteString());
}
/**
* {@link Message.Builder#setUnknownFields(UnknownFieldSet)} and {@link
* Message.Builder#mergeUnknownFields(UnknownFieldSet)} should discard the unknown fields.
*/
private static void assertUnknownFieldsInUnknownFieldSetAreDiscarded(Message message)
throws Exception {
UnknownFieldSet unknownFields = UnknownFieldSet.newBuilder().mergeFrom(payload).build();
Message built = message.newBuilderForType().setUnknownFields(unknownFields).build();
assertEquals(message.getClass().getName(), 0, built.getSerializedSize());
}
private static void assertUnknownFieldsDefaultPreserved(MessageLite message) throws Exception {
{
MessageLite parsed = message.getParserForType().parseFrom(payload);
assertEquals(message.getClass().getName(), payload, parsed.toByteString());
}
{
MessageLite parsed = message.newBuilderForType().mergeFrom(payload).build();
assertEquals(message.getClass().getName(), payload, parsed.toByteString());
}
}
private static void assertUnknownFieldsDefaultDiscarded(MessageLite message) throws Exception {
{
MessageLite parsed = message.getParserForType().parseFrom(payload);
assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
}
{
MessageLite parsed = message.newBuilderForType().mergeFrom(payload).build();
assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
}
}
private static void assertUnknownFieldsExplicitlyDiscarded(Message message) throws Exception {
Message parsed =
DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(payload);
assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
}
private static final ByteString payload =
TestUtilLite.getAllLiteSetBuilder().build().toByteString();
}

@ -108,7 +108,7 @@ public class FieldPresenceTest extends TestCase {
assertFalse(TestAllTypes.newBuilder().build().hasOptionalNestedMessage());
assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage());
// oneof fields don't have hasFoo() methods (even for message types).
// oneof fields don't have hasFoo() methods for non-message types.
assertHasMethodRemoved(
UnittestProto.TestAllTypes.class,
TestAllTypes.class,
@ -121,10 +121,8 @@ public class FieldPresenceTest extends TestCase {
UnittestProto.TestAllTypes.class,
TestAllTypes.class,
"OneofBytes");
assertHasMethodRemoved(
UnittestProto.TestAllTypes.class,
TestAllTypes.class,
"OneofNestedMessage");
assertFalse(TestAllTypes.newBuilder().build().hasOneofNestedMessage());
assertFalse(TestAllTypes.newBuilder().hasOneofNestedMessage());
assertHasMethodRemoved(
UnittestProto.TestAllTypes.Builder.class,
@ -138,10 +136,6 @@ public class FieldPresenceTest extends TestCase {
UnittestProto.TestAllTypes.Builder.class,
TestAllTypes.Builder.class,
"OneofBytes");
assertHasMethodRemoved(
UnittestProto.TestAllTypes.Builder.class,
TestAllTypes.Builder.class,
"OneofNestedMessage");
}
public void testOneofEquals() throws Exception {

@ -923,15 +923,9 @@ public class GeneratedMessageTest extends TestCase {
}
public void testEnumValues() {
assertEquals(
TestAllTypes.NestedEnum.BAR.getNumber(),
TestAllTypes.NestedEnum.BAR_VALUE);
assertEquals(
TestAllTypes.NestedEnum.BAZ.getNumber(),
TestAllTypes.NestedEnum.BAZ_VALUE);
assertEquals(
TestAllTypes.NestedEnum.FOO.getNumber(),
TestAllTypes.NestedEnum.FOO_VALUE);
assertEquals(TestAllTypes.NestedEnum.BAR_VALUE, TestAllTypes.NestedEnum.BAR.getNumber());
assertEquals(TestAllTypes.NestedEnum.BAZ_VALUE, TestAllTypes.NestedEnum.BAZ.getNumber());
assertEquals(TestAllTypes.NestedEnum.FOO_VALUE, TestAllTypes.NestedEnum.FOO.getNumber());
}
public void testNonNestedExtensionInitialization() {
@ -1319,51 +1313,51 @@ public class GeneratedMessageTest extends TestCase {
assertFalse(builder.clearFooInt().hasFooInt());
TestOneof2 message2 = builder.build();
assertFalse(message2.hasFooInt());
assertEquals(message2.getFooInt(), 0);
assertEquals(0, message2.getFooInt());
}
// Enum
{
TestOneof2.Builder builder = TestOneof2.newBuilder();
assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.FOO);
assertEquals(TestOneof2.NestedEnum.FOO, builder.getFooEnum());
assertTrue(builder.setFooEnum(TestOneof2.NestedEnum.BAR).hasFooEnum());
assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.BAR);
assertEquals(TestOneof2.NestedEnum.BAR, builder.getFooEnum());
TestOneof2 message = builder.buildPartial();
assertTrue(message.hasFooEnum());
assertEquals(message.getFooEnum(), TestOneof2.NestedEnum.BAR);
assertEquals(TestOneof2.NestedEnum.BAR, message.getFooEnum());
assertFalse(builder.clearFooEnum().hasFooEnum());
TestOneof2 message2 = builder.build();
assertFalse(message2.hasFooEnum());
assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.FOO);
assertEquals(TestOneof2.NestedEnum.FOO, message2.getFooEnum());
}
// String
{
TestOneof2.Builder builder = TestOneof2.newBuilder();
assertEquals(builder.getFooString(), "");
assertEquals("", builder.getFooString());
builder.setFooString("foo");
assertTrue(builder.hasFooString());
assertEquals(builder.getFooString(), "foo");
assertEquals("foo", builder.getFooString());
TestOneof2 message = builder.buildPartial();
assertTrue(message.hasFooString());
assertEquals(message.getFooString(), "foo");
assertEquals("foo", message.getFooString());
assertEquals(message.getFooStringBytes(), TestUtil.toBytes("foo"));
assertFalse(builder.clearFooString().hasFooString());
TestOneof2 message2 = builder.buildPartial();
assertFalse(message2.hasFooString());
assertEquals(message2.getFooString(), "");
assertEquals("", message2.getFooString());
assertEquals(message2.getFooStringBytes(), TestUtil.toBytes(""));
// Get method should not change the oneof value.
builder.setFooInt(123);
assertEquals(builder.getFooString(), "");
assertEquals("", builder.getFooString());
assertEquals(builder.getFooStringBytes(), TestUtil.toBytes(""));
assertEquals(123, builder.getFooInt());
message = builder.build();
assertEquals(message.getFooString(), "");
assertEquals("", message.getFooString());
assertEquals(message.getFooStringBytes(), TestUtil.toBytes(""));
assertEquals(123, message.getFooInt());
}
@ -1371,38 +1365,38 @@ public class GeneratedMessageTest extends TestCase {
// Cord
{
TestOneof2.Builder builder = TestOneof2.newBuilder();
assertEquals(builder.getFooCord(), "");
assertEquals("", builder.getFooCord());
builder.setFooCord("foo");
assertTrue(builder.hasFooCord());
assertEquals(builder.getFooCord(), "foo");
assertEquals("foo", builder.getFooCord());
TestOneof2 message = builder.buildPartial();
assertTrue(message.hasFooCord());
assertEquals(message.getFooCord(), "foo");
assertEquals("foo", message.getFooCord());
assertEquals(message.getFooCordBytes(), TestUtil.toBytes("foo"));
assertFalse(builder.clearFooCord().hasFooCord());
TestOneof2 message2 = builder.build();
assertFalse(message2.hasFooCord());
assertEquals(message2.getFooCord(), "");
assertEquals("", message2.getFooCord());
assertEquals(message2.getFooCordBytes(), TestUtil.toBytes(""));
}
// StringPiece
{
TestOneof2.Builder builder = TestOneof2.newBuilder();
assertEquals(builder.getFooStringPiece(), "");
assertEquals("", builder.getFooStringPiece());
builder.setFooStringPiece("foo");
assertTrue(builder.hasFooStringPiece());
assertEquals(builder.getFooStringPiece(), "foo");
assertEquals("foo", builder.getFooStringPiece());
TestOneof2 message = builder.buildPartial();
assertTrue(message.hasFooStringPiece());
assertEquals(message.getFooStringPiece(), "foo");
assertEquals("foo", message.getFooStringPiece());
assertEquals(message.getFooStringPieceBytes(), TestUtil.toBytes("foo"));
assertFalse(builder.clearFooStringPiece().hasFooStringPiece());
TestOneof2 message2 = builder.build();
assertFalse(message2.hasFooStringPiece());
assertEquals(message2.getFooStringPiece(), "");
assertEquals("", message2.getFooStringPiece());
assertEquals(message2.getFooStringPieceBytes(), TestUtil.toBytes(""));
}
@ -1410,20 +1404,20 @@ public class GeneratedMessageTest extends TestCase {
{
// set
TestOneof2.Builder builder = TestOneof2.newBuilder();
assertEquals(builder.getFooMessage().getQuxInt(), 0);
assertEquals(0, builder.getFooMessage().getQuxInt());
builder.setFooMessage(
TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build());
assertTrue(builder.hasFooMessage());
assertEquals(builder.getFooMessage().getQuxInt(), 234);
assertEquals(234, builder.getFooMessage().getQuxInt());
TestOneof2 message = builder.buildPartial();
assertTrue(message.hasFooMessage());
assertEquals(message.getFooMessage().getQuxInt(), 234);
assertEquals(234, message.getFooMessage().getQuxInt());
// clear
assertFalse(builder.clearFooMessage().hasFooString());
message = builder.build();
assertFalse(message.hasFooMessage());
assertEquals(message.getFooMessage().getQuxInt(), 0);
assertEquals(0, message.getFooMessage().getQuxInt());
// nested builder
builder = TestOneof2.newBuilder();
@ -1432,10 +1426,10 @@ public class GeneratedMessageTest extends TestCase {
assertFalse(builder.hasFooMessage());
builder.getFooMessageBuilder().setQuxInt(123);
assertTrue(builder.hasFooMessage());
assertEquals(builder.getFooMessage().getQuxInt(), 123);
assertEquals(123, builder.getFooMessage().getQuxInt());
message = builder.build();
assertTrue(message.hasFooMessage());
assertEquals(message.getFooMessage().getQuxInt(), 123);
assertEquals(123, message.getFooMessage().getQuxInt());
}
// LazyMessage is tested in LazyMessageLiteTest.java
@ -1448,7 +1442,7 @@ public class GeneratedMessageTest extends TestCase {
TestOneof2 message = builder.setFooInt(123).build();
TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
assertTrue(message2.hasFooInt());
assertEquals(message2.getFooInt(), 123);
assertEquals(123, message2.getFooInt());
}
// String
@ -1457,7 +1451,7 @@ public class GeneratedMessageTest extends TestCase {
TestOneof2 message = builder.setFooString("foo").build();
TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
assertTrue(message2.hasFooString());
assertEquals(message2.getFooString(), "foo");
assertEquals("foo", message2.getFooString());
}
// Enum
@ -1466,7 +1460,7 @@ public class GeneratedMessageTest extends TestCase {
TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build();
TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
assertTrue(message2.hasFooEnum());
assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
assertEquals(TestOneof2.NestedEnum.BAR, message2.getFooEnum());
}
// Message
@ -1476,7 +1470,7 @@ public class GeneratedMessageTest extends TestCase {
TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build();
TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
assertTrue(message2.hasFooMessage());
assertEquals(message2.getFooMessage().getQuxInt(), 234);
assertEquals(234, message2.getFooMessage().getQuxInt());
}
}
@ -1488,7 +1482,7 @@ public class GeneratedMessageTest extends TestCase {
ByteString serialized = message.toByteString();
TestOneof2 message2 = TestOneof2.parseFrom(serialized);
assertTrue(message2.hasFooInt());
assertEquals(message2.getFooInt(), 123);
assertEquals(123, message2.getFooInt());
}
// String
@ -1498,7 +1492,7 @@ public class GeneratedMessageTest extends TestCase {
ByteString serialized = message.toByteString();
TestOneof2 message2 = TestOneof2.parseFrom(serialized);
assertTrue(message2.hasFooString());
assertEquals(message2.getFooString(), "foo");
assertEquals("foo", message2.getFooString());
}
// Enum
@ -1508,7 +1502,7 @@ public class GeneratedMessageTest extends TestCase {
ByteString serialized = message.toByteString();
TestOneof2 message2 = TestOneof2.parseFrom(serialized);
assertTrue(message2.hasFooEnum());
assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
assertEquals(TestOneof2.NestedEnum.BAR, message2.getFooEnum());
}
// Message
@ -1519,7 +1513,7 @@ public class GeneratedMessageTest extends TestCase {
ByteString serialized = message.toByteString();
TestOneof2 message2 = TestOneof2.parseFrom(serialized);
assertTrue(message2.hasFooMessage());
assertEquals(message2.getFooMessage().getQuxInt(), 234);
assertEquals(234, message2.getFooMessage().getQuxInt());
}
}

@ -33,6 +33,7 @@ package com.google.protobuf;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
import com.google.protobuf.UnittestImportLite.ImportEnumLite;
import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
import com.google.protobuf.UnittestLite.ForeignEnumLite;
@ -52,7 +53,12 @@ import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
/**
@ -155,6 +161,31 @@ public class LiteTest extends TestCase {
// expected.
}
}
public void testMemoization() throws Exception {
TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet();
// Test serialized size is memoized
message.memoizedSerializedSize = -1;
int size = message.getSerializedSize();
assertTrue(size > 0);
assertEquals(size, message.memoizedSerializedSize);
// Test hashCode is memoized
assertEquals(0, message.memoizedHashCode);
int hashCode = message.hashCode();
assertTrue(hashCode != 0);
assertEquals(hashCode, message.memoizedHashCode);
// Test isInitialized is memoized
Field memo = message.getClass().getDeclaredField("memoizedIsInitialized");
memo.setAccessible(true);
memo.set(message, (byte) -1);
boolean initialized = message.isInitialized();
assertTrue(initialized);
// We have to cast to Byte first. Casting to byte causes a type error
assertEquals(1, ((Byte) memo.get(message)).intValue());
}
public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
// Since builders are implemented as a thin wrapper around a message
@ -2378,4 +2409,187 @@ public class LiteTest extends TestCase {
expected.getUnfinishedMessage());
}
}
// Make sure we haven't screwed up the code generation for packing fields by default.
public void testPackedSerialization() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
builder.addRepeatedInt32(4321);
builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
TestAllTypes message = builder.build();
CodedInputStream in = CodedInputStream.newInstance(message.toByteArray());
while (!in.isAtEnd()) {
int tag = in.readTag();
assertEquals(WireFormat.WIRETYPE_LENGTH_DELIMITED, WireFormat.getTagWireType(tag));
in.skipField(tag);
}
}
public void testAddAllIteratesOnce() {
TestAllTypesLite message =
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()))
.build();
}
public void testAddAllIteratesOnce_throwsOnNull() {
TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
try {
builder.addAllRepeatedBool(new OneTimeIterableList(true, false, (Boolean) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 2 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedBoolCount());
}
try {
builder.addAllRepeatedBool(new OneTimeIterable(true, false, (Boolean) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 2 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedBoolCount());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedBool(new OneTimeIterableList((Boolean) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 0 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedBoolCount());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedInt32(new OneTimeIterableList((Integer) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 0 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedInt32Count());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedInt64(new OneTimeIterableList((Long) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 0 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedInt64Count());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedFloat(new OneTimeIterableList((Float) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 0 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedFloatCount());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedDouble(new OneTimeIterableList((Double) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 0 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedDoubleCount());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedBytes(new OneTimeIterableList((ByteString) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 0 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedBytesCount());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedString(new OneTimeIterableList("", "", (String) null, ""));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 2 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedStringCount());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedString(new OneTimeIterable("", "", (String) null, ""));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 2 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedStringCount());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedString(new OneTimeIterableList((String) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 0 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedStringCount());
}
try {
builder = TestAllTypesLite.newBuilder();
builder.addAllRepeatedNestedMessage(new OneTimeIterableList((NestedMessage) null));
fail();
} catch (NullPointerException expected) {
assertEquals("Element at index 0 is null.", expected.getMessage());
assertEquals(0, builder.getRepeatedNestedMessageCount());
}
}
private static final class OneTimeIterableList<T> extends ArrayList<T> {
private boolean wasIterated = false;
OneTimeIterableList(T... contents) {
addAll(Arrays.asList(contents));
}
@Override
public Iterator<T> iterator() {
if (wasIterated) {
fail();
}
wasIterated = true;
return super.iterator();
}
}
private static final class OneTimeIterable<T> implements Iterable<T> {
private final List<T> list;
private boolean wasIterated = false;
OneTimeIterable(T... contents) {
list = Arrays.asList(contents);
}
@Override
public Iterator<T> iterator() {
if (wasIterated) {
fail();
}
wasIterated = true;
return list.iterator();
}
}
}

@ -408,12 +408,12 @@ public final class MapForProto2LiteTest extends TestCase {
TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToInt32Field(5, bytes)
.build());
assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0);
assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToStringField(stringKey, 5)
.build());
assertEquals(map.getInt32ToStringFieldOrDefault(0, null), "");
assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToBytesField(stringKey, 5)
@ -423,7 +423,7 @@ public final class MapForProto2LiteTest extends TestCase {
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToEnumField(stringKey, bytes)
.build());
assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO);
assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
try {
tryParseTestMap(BizarroTestMap.newBuilder()
@ -439,7 +439,7 @@ public final class MapForProto2LiteTest extends TestCase {
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putStringToInt32Field(stringKey, bytes)
.build());
assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0);
assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
}
public void testMergeFrom() throws Exception {

@ -546,12 +546,12 @@ public class MapForProto2Test extends TestCase {
TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToInt32Field(5, bytes)
.build());
assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0);
assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToStringField(stringKey, 5)
.build());
assertEquals(map.getInt32ToStringFieldOrDefault(0, null), "");
assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToBytesField(stringKey, 5)
@ -561,7 +561,7 @@ public class MapForProto2Test extends TestCase {
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToEnumField(stringKey, bytes)
.build());
assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO);
assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
try {
tryParseTestMap(BizarroTestMap.newBuilder()
@ -577,7 +577,7 @@ public class MapForProto2Test extends TestCase {
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putStringToInt32Field(stringKey, bytes)
.build());
assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0);
assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
}
public void testMergeFrom() throws Exception {

@ -576,12 +576,12 @@ public class MapTest extends TestCase {
TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToInt32Field(5, bytes)
.build());
assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0);
assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToStringField(stringKey, 5)
.build());
assertEquals(map.getInt32ToStringFieldOrDefault(0, null), "");
assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToBytesField(stringKey, 5)
@ -591,7 +591,7 @@ public class MapTest extends TestCase {
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putInt32ToEnumField(stringKey, bytes)
.build());
assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO);
assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
try {
tryParseTestMap(BizarroTestMap.newBuilder()
@ -607,7 +607,7 @@ public class MapTest extends TestCase {
map = tryParseTestMap(BizarroTestMap.newBuilder()
.putStringToInt32Field(stringKey, bytes)
.build());
assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0);
assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
}
public void testMergeFrom() throws Exception {

@ -321,8 +321,10 @@ public class MessageTest extends TestCase {
assertTrue(result.getField(result.getDescriptorForType()
.findFieldByName("repeated_foreign_message")) instanceof List<?>);
assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
.findFieldByName("repeated_foreign_message")), 0);
assertEquals(
0,
result.getRepeatedFieldCount(
result.getDescriptorForType().findFieldByName("repeated_foreign_message")));
}
/** Test reading repeated message from DynamicMessage. */
@ -345,7 +347,9 @@ public class MessageTest extends TestCase {
assertTrue(result.getField(result.getDescriptorForType()
.findFieldByName("repeated_foreign_message")) instanceof List<?>);
assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
.findFieldByName("repeated_foreign_message")), 2);
assertEquals(
2,
result.getRepeatedFieldCount(
result.getDescriptorForType().findFieldByName("repeated_foreign_message")));
}
}

@ -92,5 +92,31 @@ public class TestBadIdentifiers extends TestCase {
assertEquals(0L, message.getExtension(
TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue());
assertEquals("", message.getFieldName32());
assertEquals("", message.getFieldName33());
assertEquals(0, message.get2Conflict34());
assertEquals(0, message.get2Conflict35());
}
public void testNumberFields() throws Exception {
TestBadIdentifiersProto.TestLeadingNumberFields message =
TestBadIdentifiersProto.TestLeadingNumberFields.getDefaultInstance();
// Make sure generated accessors are properly named.
assertFalse(message.has30DayImpressions());
assertEquals(0, message.get30DayImpressions());
assertEquals(0, message.get60DayImpressionsCount());
assertEquals(0, message.get60DayImpressionsList().size());
assertFalse(message.has2Underscores());
assertEquals("", message.get2Underscores());
assertEquals(0, message.get2RepeatedUnderscoresCount());
assertEquals(0, message.get2RepeatedUnderscoresList().size());
assertFalse(message.has32());
assertEquals(0, message.get32());
assertEquals(0, message.get64Count());
assertEquals(0, message.get64List().size());
}
}

@ -0,0 +1,83 @@
// 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.
package com.google.protobuf;
import junit.framework.TestCase;
/**
* Tests that proto2 api generation doesn't cause compile errors when compiling protocol buffers
* that have names that would otherwise conflict if not fully qualified (like @Deprecated
* and @Override).
*
* <p>Forked from {@link TestBadIdentifiers}.
*
* @author jonp@google.com (Jon Perlow)
*/
public final class TestBadIdentifiersLite extends TestCase {
public void testCompilation() {
// If this compiles, it means the generation was correct.
TestBadIdentifiersProto.Deprecated.newBuilder();
TestBadIdentifiersProto.Override.newBuilder();
}
public void testConflictingFieldNames() throws Exception {
TestBadIdentifiersProto.TestConflictingFieldNames message =
TestBadIdentifiersProto.TestConflictingFieldNames.getDefaultInstance();
// Make sure generated accessors are properly named.
assertEquals(0, message.getInt32Field1Count());
assertEquals(0, message.getEnumField2Count());
assertEquals(0, message.getStringField3Count());
assertEquals(0, message.getBytesField4Count());
assertEquals(0, message.getMessageField5Count());
assertEquals(0, message.getInt32FieldCount11());
assertEquals(0, message.getEnumFieldCount12().getNumber());
assertEquals("", message.getStringFieldCount13());
assertEquals(ByteString.EMPTY, message.getBytesFieldCount14());
assertEquals(0, message.getMessageFieldCount15().getSerializedSize());
assertEquals(0, message.getInt32Field21Count());
assertEquals(0, message.getEnumField22Count());
assertEquals(0, message.getStringField23Count());
assertEquals(0, message.getBytesField24Count());
assertEquals(0, message.getMessageField25Count());
assertEquals(0, message.getInt32Field1List().size());
assertEquals(0, message.getInt32FieldList31());
assertEquals(0, message.getInt64FieldCount());
assertEquals(0L, message.getExtension(
TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount).longValue());
assertEquals(0L, message.getExtension(
TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue());
}
}

@ -30,8 +30,6 @@
package com.google.protobuf;
import static com.google.common.truth.Truth.assertThat;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
@ -1079,12 +1077,12 @@ public class TextFormatTest extends TestCase {
{
TestMap.Builder dest = TestMap.newBuilder();
TextFormat.merge(text, dest);
assertThat(dest.build()).isEqualTo(message);
assertEquals(message, dest.build());
}
{
TestMap.Builder dest = TestMap.newBuilder();
parserWithOverwriteForbidden.merge(text, dest);
assertThat(dest.build()).isEqualTo(message);
assertEquals(message, dest.build());
}
}
@ -1096,10 +1094,10 @@ public class TextFormatTest extends TestCase {
TestMap.Builder dest = TestMap.newBuilder();
parserWithOverwriteForbidden.merge(text, dest);
TestMap message = dest.build();
assertThat(message.getStringToInt32Field().size()).isEqualTo(2);
assertThat(message.getInt32ToMessageField().size()).isEqualTo(2);
assertThat(message.getStringToInt32Field().get("x")).isEqualTo(10);
assertThat(message.getInt32ToMessageField().get(2).getValue()).isEqualTo(200);
assertEquals(2, message.getStringToInt32Field().size());
assertEquals(2, message.getInt32ToMessageField().size());
assertEquals(10, message.getStringToInt32Field().get("x").intValue());
assertEquals(200, message.getInt32ToMessageField().get(2).getValue());
}
public void testMapShortFormEmpty() throws Exception {
@ -1108,8 +1106,8 @@ public class TextFormatTest extends TestCase {
TestMap.Builder dest = TestMap.newBuilder();
parserWithOverwriteForbidden.merge(text, dest);
TestMap message = dest.build();
assertThat(message.getStringToInt32Field().size()).isEqualTo(0);
assertThat(message.getInt32ToMessageField().size()).isEqualTo(0);
assertEquals(0, message.getStringToInt32Field().size());
assertEquals(0, message.getInt32ToMessageField().size());
}
public void testMapShortFormTrailingComma() throws Exception {
@ -1119,7 +1117,7 @@ public class TextFormatTest extends TestCase {
parserWithOverwriteForbidden.merge(text, dest);
fail("Expected parse exception.");
} catch (TextFormat.ParseException e) {
assertThat(e).hasMessageThat().isEqualTo("1:48: Expected \"{\".");
assertEquals("1:48: Expected \"{\".", e.getMessage());
}
}
@ -1134,8 +1132,8 @@ public class TextFormatTest extends TestCase {
TestMap.Builder builder = TestMap.newBuilder();
defaultParser.merge(text, builder);
TestMap map = builder.build();
assertThat(map.getInt32ToInt32Field().size()).isEqualTo(2);
assertThat(map.getInt32ToInt32Field().get(1).intValue()).isEqualTo(30);
assertEquals(2, map.getInt32ToInt32Field().size());
assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
}
{
@ -1144,8 +1142,8 @@ public class TextFormatTest extends TestCase {
TestMap.Builder builder = TestMap.newBuilder();
defaultParser.merge(text, builder);
TestMap map = builder.build();
assertThat(map.getInt32ToInt32Field().size()).isEqualTo(2);
assertThat(map.getInt32ToInt32Field().get(1).intValue()).isEqualTo(30);
assertEquals(2, map.getInt32ToInt32Field().size());
assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
}
}

@ -36,7 +36,6 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
import com.google.protobuf.TextFormat.ParseException;
import junit.framework.TestCase;
/**
@ -151,18 +150,15 @@ public class UnknownEnumValueTest extends TestCase {
assertEquals(4321, unknown4321.getNumber());
assertEquals(5432, unknown5432.getNumber());
assertEquals(6543, unknown6543.getNumber());
// Unknown EnumValueDescriptor will map to UNRECOGNIZED.
assertEquals(
TestAllTypes.NestedEnum.valueOf(unknown4321),
TestAllTypes.NestedEnum.UNRECOGNIZED);
TestAllTypes.NestedEnum.UNRECOGNIZED, TestAllTypes.NestedEnum.valueOf(unknown4321));
assertEquals(
TestAllTypes.NestedEnum.valueOf(unknown5432),
TestAllTypes.NestedEnum.UNRECOGNIZED);
TestAllTypes.NestedEnum.UNRECOGNIZED, TestAllTypes.NestedEnum.valueOf(unknown5432));
assertEquals(
TestAllTypes.NestedEnum.valueOf(unknown6543),
TestAllTypes.NestedEnum.UNRECOGNIZED);
TestAllTypes.NestedEnum.UNRECOGNIZED, TestAllTypes.NestedEnum.valueOf(unknown6543));
// Setters also accept unknown EnumValueDescriptor.
builder.setField(optionalNestedEnumField, unknown6543);
builder.setRepeatedField(repeatedNestedEnumField, 0, unknown4321);

@ -148,6 +148,12 @@ message TestConflictingFieldNames {
// the method getInt32FieldList().
required int32 int32_field_list = 31; // NO_PROTO3
// These field pairs have the same Java converted name
optional string field_name = 32; // NO_PROTO3
optional string field__name = 33; // NO_PROTO3
optional int32 _2conflict = 34; // NO_PROTO3
optional int32 __2conflict = 35;
extensions 1000 to max; // NO_PROTO3
repeated int64 int64_field = 41;
@ -166,3 +172,14 @@ message TestMapField {
map<int32, int32> map_field = 1;
}
message TestLeadingNumberFields {
optional int32 _30day_impressions = 1;
repeated string _60day_impressions = 2;
optional string __2_underscores = 3;
repeated string __2repeated_underscores = 4;
optional int32 _32 = 32;
repeated int64 _64 = 64;
}

@ -83,6 +83,17 @@ public final class Durations {
return COMPARATOR;
}
/**
* Compares two durations. The value returned is identical to what would be returned by:
* {@code Durations.comparator().compare(x, y)}.
*
* @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if {@code x < y};
* and a value greater than {@code 0} if {@code x > y}
*/
public static int compare(Duration x, Duration y) {
return COMPARATOR.compare(x, y);
}
/**
* Returns true if the given {@link Duration} is valid. The {@code seconds} value must be in the
* range [-315,576,000,000, +315,576,000,000]. The {@code nanos} value must be in the range

@ -311,16 +311,19 @@ public class FieldMaskUtil {
return replacePrimitiveFields;
}
public void setReplaceMessageFields(boolean value) {
public MergeOptions setReplaceMessageFields(boolean value) {
replaceMessageFields = value;
return this;
}
public void setReplaceRepeatedFields(boolean value) {
public MergeOptions setReplaceRepeatedFields(boolean value) {
replaceRepeatedFields = value;
return this;
}
public void setReplacePrimitiveFields(boolean value) {
public MergeOptions setReplacePrimitiveFields(boolean value) {
replacePrimitiveFields = value;
return this;
}
}

@ -1686,7 +1686,11 @@ public class JsonFormat {
}
private ByteString parseBytes(JsonElement json) throws InvalidProtocolBufferException {
return ByteString.copyFrom(BaseEncoding.base64().decode(json.getAsString()));
try {
return ByteString.copyFrom(BaseEncoding.base64().decode(json.getAsString()));
} catch (IllegalArgumentException e) {
return ByteString.copyFrom(BaseEncoding.base64Url().decode(json.getAsString()));
}
}
private EnumValueDescriptor parseEnum(EnumDescriptor enumDescriptor, JsonElement json)

@ -114,6 +114,17 @@ public final class Timestamps {
return COMPARATOR;
}
/**
* Compares two timestamps. The value returned is identical to what would be returned by:
* {@code Timestamps.comparator().compare(x, y)}.
*
* @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if {@code x < y};
* and a value greater than {@code 0} if {@code x > y}
*/
public static int compare(Timestamp x, Timestamp y) {
return COMPARATOR.compare(x, y);
}
/**
* Returns true if the given {@link Timestamp} is valid. The {@code seconds} value must be in the
* range [-62,135,596,800, +253,402,300,799] (i.e., between 0001-01-01T00:00:00Z and

@ -73,7 +73,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import junit.framework.TestCase;
@ -1144,7 +1143,8 @@ public class JsonFormatTest extends TestCase {
}
public void testParserAcceptBase64Variants() throws Exception {
assertAccepts("optionalBytes", "AQI");
assertAccepts("optionalBytes", "AQI"); // No padding
assertAccepts("optionalBytes", "-_w"); // base64Url, no padding
}
public void testParserRejectInvalidEnumValue() throws Exception {

@ -390,11 +390,13 @@ jspb.BinaryEncoder.prototype.writeDouble = function(value) {
/**
* Writes a boolean value to the buffer as a varint.
* @param {boolean} value The value to write.
* Writes a boolean value to the buffer as a varint. We allow numbers as input
* because the JSPB code generator uses 0/1 instead of true/false to save space
* in the string representation of the proto.
* @param {boolean|number} value The value to write.
*/
jspb.BinaryEncoder.prototype.writeBool = function(value) {
goog.asserts.assert(goog.isBoolean(value));
goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value));
this.buffer_.push(value ? 1 : 0);
};

@ -970,10 +970,6 @@ jspb.utils.byteSourceToUint8Array = function(data) {
return /** @type {!Uint8Array} */(new Uint8Array(data));
}
if (data.constructor === Buffer) {
return /** @type {!Uint8Array} */(new Uint8Array(data));
}
if (data.constructor === Array) {
data = /** @type {!Array.<number>} */(data);
return /** @type {!Uint8Array} */(new Uint8Array(data));

@ -235,7 +235,7 @@ jspb.BinaryWriter.prototype.getResultBuffer = function() {
/**
* Converts the encoded data into a bas64-encoded string.
* Converts the encoded data into a base64-encoded string.
* @return {string}
*/
jspb.BinaryWriter.prototype.getResultBase64String = function() {
@ -716,13 +716,15 @@ jspb.BinaryWriter.prototype.writeDouble = function(field, value) {
/**
* Writes a boolean field to the buffer.
* Writes a boolean field to the buffer. We allow numbers as input
* because the JSPB code generator uses 0/1 instead of true/false to save space
* in the string representation of the proto.
* @param {number} field The field number.
* @param {boolean?} value The value to write.
* @param {boolean?|number?} value The value to write.
*/
jspb.BinaryWriter.prototype.writeBool = function(field, value) {
if (value == null) return;
goog.asserts.assert(goog.isBoolean(value));
goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value));
this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
this.encoder_.writeBool(value);
};

@ -0,0 +1,355 @@
// 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.
/**
* @fileoverview Test cases for Int64-manipulation functions.
*
* Test suite is written using Jasmine -- see http://jasmine.github.io/
*
* @author cfallin@google.com (Chris Fallin)
*/
goog.require('goog.testing.asserts');
goog.require('jspb.arith.Int64');
goog.require('jspb.arith.UInt64');
describe('binaryArithTest', function() {
/**
* Tests comparison operations.
*/
it('testCompare', function() {
var a = new jspb.arith.UInt64(1234, 5678);
var b = new jspb.arith.UInt64(1234, 5678);
assertEquals(a.cmp(b), 0);
assertEquals(b.cmp(a), 0);
b.lo -= 1;
assertEquals(a.cmp(b), 1);
assertEquals(b.cmp(a), -1);
b.lo += 2;
assertEquals(a.cmp(b), -1);
assertEquals(b.cmp(a), 1);
b.lo = a.lo;
b.hi = a.hi - 1;
assertEquals(a.cmp(b), 1);
assertEquals(b.cmp(a), -1);
assertEquals(a.zero(), false);
assertEquals(a.msb(), false);
assertEquals(a.lsb(), false);
a.hi = 0;
a.lo = 0;
assertEquals(a.zero(), true);
a.hi = 0x80000000;
assertEquals(a.zero(), false);
assertEquals(a.msb(), true);
a.lo = 0x00000001;
assertEquals(a.lsb(), true);
});
/**
* Tests shifts.
*/
it('testShifts', function() {
var a = new jspb.arith.UInt64(1, 0);
assertEquals(a.lo, 1);
assertEquals(a.hi, 0);
var orig = a;
a = a.leftShift();
assertEquals(orig.lo, 1); // original unmodified.
assertEquals(orig.hi, 0);
assertEquals(a.lo, 2);
assertEquals(a.hi, 0);
a = a.leftShift();
assertEquals(a.lo, 4);
assertEquals(a.hi, 0);
for (var i = 0; i < 29; i++) {
a = a.leftShift();
}
assertEquals(a.lo, 0x80000000);
assertEquals(a.hi, 0);
a = a.leftShift();
assertEquals(a.lo, 0);
assertEquals(a.hi, 1);
a = a.leftShift();
assertEquals(a.lo, 0);
assertEquals(a.hi, 2);
a = a.rightShift();
a = a.rightShift();
assertEquals(a.lo, 0x80000000);
assertEquals(a.hi, 0);
a = a.rightShift();
assertEquals(a.lo, 0x40000000);
assertEquals(a.hi, 0);
});
/**
* Tests additions.
*/
it('testAdd', function() {
var a = new jspb.arith.UInt64(/* lo = */ 0x89abcdef,
/* hi = */ 0x01234567);
var b = new jspb.arith.UInt64(/* lo = */ 0xff52ab91,
/* hi = */ 0x92fa2123);
// Addition with carry.
var c = a.add(b);
assertEquals(a.lo, 0x89abcdef); // originals unmodified.
assertEquals(a.hi, 0x01234567);
assertEquals(b.lo, 0xff52ab91);
assertEquals(b.hi, 0x92fa2123);
assertEquals(c.lo, 0x88fe7980);
assertEquals(c.hi, 0x941d668b);
// Simple addition without carry.
a.lo = 2;
a.hi = 0;
b.lo = 3;
b.hi = 0;
c = a.add(b);
assertEquals(c.lo, 5);
assertEquals(c.hi, 0);
});
/**
* Test subtractions.
*/
it('testSub', function() {
var kLength = 10;
var hiValues = [0x1682ef32,
0x583902f7,
0xb62f5955,
0x6ea99bbf,
0x25a39c20,
0x0700a08b,
0x00f7304d,
0x91a5b5af,
0x89077fd2,
0xe09e347c];
var loValues = [0xe1538b18,
0xbeacd556,
0x74100758,
0x96e3cb26,
0x56c37c3f,
0xe00b3f7d,
0x859f25d7,
0xc2ee614a,
0xe1d21cd7,
0x30aae6a4];
for (var i = 0; i < kLength; i++) {
for (var j = 0; j < kLength; j++) {
var a = new jspb.arith.UInt64(loValues[i], hiValues[j]);
var b = new jspb.arith.UInt64(loValues[j], hiValues[i]);
var c = a.add(b).sub(b);
assertEquals(c.hi, a.hi);
assertEquals(c.lo, a.lo);
}
}
});
/**
* Tests 32-by-32 multiplication.
*/
it('testMul32x32', function() {
var testData = [
// a b low(a*b) high(a*b)
[0xc0abe2f8, 0x1607898a, 0x5de711b0, 0x109471b8],
[0x915eb3cb, 0x4fb66d0e, 0xbd0d441a, 0x2d43d0bc],
[0xfe4efe70, 0x80b48c37, 0xbcddea10, 0x7fdada0c],
[0xe222fd4a, 0xe43d524a, 0xd5e0eb64, 0xc99d549c],
[0xd171f469, 0xb94ebd01, 0x4be17969, 0x979bc4fa],
[0x829cc1df, 0xe2598b38, 0xf4157dc8, 0x737c12ad],
[0xf10c3767, 0x8382881e, 0x942b3612, 0x7bd428b8],
[0xb0f6dd24, 0x232597e1, 0x079c98a4, 0x184bbce7],
[0xfcdb05a7, 0x902f55bc, 0x636199a4, 0x8e69f412],
[0x0dd0bfa9, 0x916e27b1, 0x6e2542d9, 0x07d92e65]
];
for (var i = 0; i < testData.length; i++) {
var a = testData[i][0] >>> 0;
var b = testData[i][1] >>> 0;
var cLow = testData[i][2] >>> 0;
var cHigh = testData[i][3] >>> 0;
var c = jspb.arith.UInt64.mul32x32(a, b);
assertEquals(c.lo, cLow);
assertEquals(c.hi, cHigh);
}
});
/**
* Tests 64-by-32 multiplication.
*/
it('testMul', function() {
// 64x32 bits produces 96 bits of product. The multiplication function under
// test truncates the top 32 bits, so we compare against a 64-bit expected
// product.
var testData = [
// low(a) high(a) low(a*b) high(a*b)
[0xec10955b, 0x360eb168, 0x4b7f3f5b, 0xbfcb7c59, 0x9517da5f],
[0x42b000fc, 0x9d101642, 0x6fa1ab72, 0x2584c438, 0x6a9e6d2b],
[0xf42d4fb4, 0xae366403, 0xa65a1000, 0x92434000, 0x1ff978df],
[0x17e2f56b, 0x25487693, 0xf13f98c7, 0x73794e2d, 0xa96b0c6a],
[0x492f241f, 0x76c0eb67, 0x7377ac44, 0xd4336c3c, 0xfc4b1ebe],
[0xd6b92321, 0xe184fa48, 0xd6e76904, 0x93141584, 0xcbf44da1],
[0x4bf007ea, 0x968c0a9e, 0xf5e4026a, 0x4fdb1ae4, 0x61b9fb7d],
[0x10a83be7, 0x2d685ba6, 0xc9e5fb7f, 0x2ad43499, 0x3742473d],
[0x2f261829, 0x1aca681a, 0x3d3494e3, 0x8213205b, 0x283719f8],
[0xe4f2ce21, 0x2e74b7bd, 0xd801b38b, 0xbc17feeb, 0xc6c44e0f]
];
for (var i = 0; i < testData.length; i++) {
var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
var prod = a.mul(testData[i][2]);
assertEquals(prod.lo, testData[i][3]);
assertEquals(prod.hi, testData[i][4]);
}
});
/**
* Tests 64-div-by-32 division.
*/
it('testDiv', function() {
// Compute a/b, yielding quot = a/b and rem = a%b.
var testData = [
// --- divisors in (0, 2^32-1) to test full divisor range
// low(a) high(a) b low(quot) high(quot) rem
[0x712443f1, 0xe85cefcc, 0xc1a7050b, 0x332c79ad, 0x00000001, 0x92ffa882],
[0x11912915, 0xb2699eb5, 0x30467cbe, 0xb21b4be4, 0x00000003, 0x283465dd],
[0x0d917982, 0x201f2a6e, 0x3f35bf03, 0x8217c8e4, 0x00000000, 0x153402d6],
[0xa072c108, 0x74020c96, 0xc60568fd, 0x95f9613e, 0x00000000, 0x3f4676c2],
[0xd845d5d8, 0xcdd235c4, 0x20426475, 0x6154e78b, 0x00000006, 0x202fb751],
[0xa4dbf71f, 0x9e90465e, 0xf08e022f, 0xa8be947f, 0x00000000, 0xbe43b5ce],
[0x3dbe627f, 0xa791f4b9, 0x28a5bd89, 0x1f5dfe93, 0x00000004, 0x02bf9ed4],
[0x5c1c53ee, 0xccf5102e, 0x198576e7, 0x07e3ae31, 0x00000008, 0x02ea8fb7],
[0xfef1e581, 0x04714067, 0xca6540c1, 0x059e73ec, 0x00000000, 0x31658095],
[0x1e2dd90c, 0x13dd6667, 0x8b2184c3, 0x248d1a42, 0x00000000, 0x4ca6d0c6],
// --- divisors in (0, 2^16-1) to test larger quotient high-words
// low(a) high(a) b low(quot) high(quot) rem
[0x86722b47, 0x2cd57c9a, 0x00003123, 0x2ae41b7a, 0x0000e995, 0x00000f99],
[0x1dd7884c, 0xf5e839bc, 0x00009eeb, 0x5c886242, 0x00018c21, 0x000099b6],
[0x5c53d625, 0x899fc7e5, 0x000087d7, 0xd625007a, 0x0001035c, 0x000019af],
[0x6932d932, 0x9d0a5488, 0x000051fb, 0x9d976143, 0x0001ea63, 0x00004981],
[0x4d18bb85, 0x0c92fb31, 0x00001d9f, 0x03265ab4, 0x00006cac, 0x000001b9],
[0xbe756768, 0xdea67ccb, 0x00008a03, 0x58add442, 0x00019cff, 0x000056a2],
[0xe2466f9a, 0x2521f114, 0x0000c350, 0xa0c0860d, 0x000030ab, 0x0000a48a],
[0xf00ddad1, 0xe2f5446a, 0x00002cfc, 0x762697a6, 0x00050b96, 0x00000b69],
[0xa879152a, 0x0a70e0a5, 0x00007cdf, 0xb44151b3, 0x00001567, 0x0000363d],
[0x7179a74c, 0x46083fff, 0x0000253c, 0x4d39ba6e, 0x0001e17f, 0x00000f84]
];
for (var i = 0; i < testData.length; i++) {
var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
var result = a.div(testData[i][2]);
var quotient = result[0];
var remainder = result[1];
assertEquals(quotient.lo, testData[i][3]);
assertEquals(quotient.hi, testData[i][4]);
assertEquals(remainder.lo, testData[i][5]);
}
});
/**
* Tests .toString() and .fromString().
*/
it('testStrings', function() {
var testData = [
[0x5e84c935, 0xcae33d0e, '14619595947299359029'],
[0x62b3b8b8, 0x93480544, '10612738313170434232'],
[0x319bfb13, 0xc01c4172, '13843011313344445203'],
[0x5b8a65fb, 0xa5885b31, '11927883880638080507'],
[0x6bdb80f1, 0xb0d1b16b, '12741159895737008369'],
[0x4b82b442, 0x2e0d8c97, '3318463081876730946'],
[0x780d5208, 0x7d76752c, '9040542135845999112'],
[0x2e46800f, 0x0993778d, '690026616168284175'],
[0xf00a7e32, 0xcd8e3931, '14811839111111540274'],
[0x1baeccd6, 0x923048c4, '10533999535534820566'],
[0x03669d29, 0xbff3ab72, '13831587386756603177'],
[0x2526073e, 0x01affc81, '121593346566522686'],
[0xc24244e0, 0xd7f40d0e, '15561076969511732448'],
[0xc56a341e, 0xa68b66a7, '12000798502816461854'],
[0x8738d64d, 0xbfe78604, '13828168534871037517'],
[0x5baff03b, 0xd7572aea, '15516918227177304123'],
[0x4a843d8a, 0x864e132b, '9677693725920476554'],
[0x25b4e94d, 0x22b54dc6, '2500990681505655117'],
[0x6bbe664b, 0x55a5cc0e, '6171563226690381387'],
[0xee916c81, 0xb00aabb3, '12685140089732426881']
];
for (var i = 0; i < testData.length; i++) {
var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
var roundtrip = jspb.arith.UInt64.fromString(a.toString());
assertEquals(roundtrip.lo, a.lo);
assertEquals(roundtrip.hi, a.hi);
assertEquals(a.toString(), testData[i][2]);
}
});
/**
* Tests signed Int64s. These are built on UInt64s, so we only need to test
* the explicit overrides: .toString() and .fromString().
*/
it('testSignedInt64', function() {
var testStrings = [
'-7847499644178593666',
'3771946501229139523',
'2872856549054995060',
'-5780049594274350904',
'3383785956695105201',
'2973055184857072610',
'-3879428459215627206',
'4589812431064156631',
'8484075557333689940',
'1075325817098092407',
'-4346697501012292314',
'2488620459718316637',
'6112655187423520672',
'-3655278273928612104',
'3439154019435803196',
'1004112478843763757',
'-6587790776614368413',
'664320065099714586',
'4760412909973292912',
'-7911903989602274672'
];
for (var i = 0; i < testStrings.length; i++) {
var roundtrip =
jspb.arith.Int64.fromString(testStrings[i]).toString();
assertEquals(roundtrip, testStrings[i]);
}
});
});

@ -0,0 +1,334 @@
// 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.
/**
* @fileoverview Test cases for jspb's binary protocol buffer decoder.
*
* There are two particular magic numbers that need to be pointed out -
* 2^64-1025 is the largest number representable as both a double and an
* unsigned 64-bit integer, and 2^63-513 is the largest number representable as
* both a double and a signed 64-bit integer.
*
* Test suite is written using Jasmine -- see http://jasmine.github.io/
*
* @author aappleby@google.com (Austin Appleby)
*/
goog.require('goog.testing.asserts');
goog.require('jspb.BinaryConstants');
goog.require('jspb.BinaryDecoder');
goog.require('jspb.BinaryEncoder');
/**
* Tests encoding and decoding of unsigned types.
* @param {Function} readValue
* @param {Function} writeValue
* @param {number} epsilon
* @param {number} upperLimit
* @param {Function} filter
* @suppress {missingProperties|visibility}
*/
function doTestUnsignedValue(readValue,
writeValue, epsilon, upperLimit, filter) {
var encoder = new jspb.BinaryEncoder();
// Encode zero and limits.
writeValue.call(encoder, filter(0));
writeValue.call(encoder, filter(epsilon));
writeValue.call(encoder, filter(upperLimit));
// Encode positive values.
for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
writeValue.call(encoder, filter(cursor));
}
var decoder = jspb.BinaryDecoder.alloc(encoder.end());
// Check zero and limits.
assertEquals(filter(0), readValue.call(decoder));
assertEquals(filter(epsilon), readValue.call(decoder));
assertEquals(filter(upperLimit), readValue.call(decoder));
// Check positive values.
for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
if (filter(cursor) != readValue.call(decoder)) throw 'fail!';
}
// Encoding values outside the valid range should assert.
assertThrows(function() {writeValue.call(encoder, -1);});
assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
}
/**
* Tests encoding and decoding of signed types.
* @param {Function} readValue
* @param {Function} writeValue
* @param {number} epsilon
* @param {number} lowerLimit
* @param {number} upperLimit
* @param {Function} filter
* @suppress {missingProperties}
*/
function doTestSignedValue(readValue,
writeValue, epsilon, lowerLimit, upperLimit, filter) {
var encoder = new jspb.BinaryEncoder();
// Encode zero and limits.
writeValue.call(encoder, filter(lowerLimit));
writeValue.call(encoder, filter(-epsilon));
writeValue.call(encoder, filter(0));
writeValue.call(encoder, filter(epsilon));
writeValue.call(encoder, filter(upperLimit));
var inputValues = [];
// Encode negative values.
for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
var val = filter(cursor);
writeValue.call(encoder, val);
inputValues.push(val);
}
// Encode positive values.
for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
var val = filter(cursor);
writeValue.call(encoder, val);
inputValues.push(val);
}
var decoder = jspb.BinaryDecoder.alloc(encoder.end());
// Check zero and limits.
assertEquals(filter(lowerLimit), readValue.call(decoder));
assertEquals(filter(-epsilon), readValue.call(decoder));
assertEquals(filter(0), readValue.call(decoder));
assertEquals(filter(epsilon), readValue.call(decoder));
assertEquals(filter(upperLimit), readValue.call(decoder));
// Verify decoded values.
for (var i = 0; i < inputValues.length; i++) {
assertEquals(inputValues[i], readValue.call(decoder));
}
// Encoding values outside the valid range should assert.
assertThrows(function() {writeValue.call(encoder, lowerLimit * 1.1);});
assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
}
describe('binaryDecoderTest', function() {
/**
* Tests the decoder instance cache.
*/
it('testInstanceCache', /** @suppress {visibility} */ function() {
// Empty the instance caches.
jspb.BinaryDecoder.instanceCache_ = [];
// Allocating and then freeing a decoder should put it in the instance
// cache.
jspb.BinaryDecoder.alloc().free();
assertEquals(1, jspb.BinaryDecoder.instanceCache_.length);
// Allocating and then freeing three decoders should leave us with three in
// the cache.
var decoder1 = jspb.BinaryDecoder.alloc();
var decoder2 = jspb.BinaryDecoder.alloc();
var decoder3 = jspb.BinaryDecoder.alloc();
decoder1.free();
decoder2.free();
decoder3.free();
assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
});
/**
* Tests reading 64-bit integers as hash strings.
*/
it('testHashStrings', function() {
var encoder = new jspb.BinaryEncoder();
var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00);
var hashB = String.fromCharCode(0x12, 0x34, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00);
var hashC = String.fromCharCode(0x12, 0x34, 0x56, 0x78,
0x87, 0x65, 0x43, 0x21);
var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF);
encoder.writeVarintHash64(hashA);
encoder.writeVarintHash64(hashB);
encoder.writeVarintHash64(hashC);
encoder.writeVarintHash64(hashD);
encoder.writeFixedHash64(hashA);
encoder.writeFixedHash64(hashB);
encoder.writeFixedHash64(hashC);
encoder.writeFixedHash64(hashD);
var decoder = jspb.BinaryDecoder.alloc(encoder.end());
assertEquals(hashA, decoder.readVarintHash64());
assertEquals(hashB, decoder.readVarintHash64());
assertEquals(hashC, decoder.readVarintHash64());
assertEquals(hashD, decoder.readVarintHash64());
assertEquals(hashA, decoder.readFixedHash64());
assertEquals(hashB, decoder.readFixedHash64());
assertEquals(hashC, decoder.readFixedHash64());
assertEquals(hashD, decoder.readFixedHash64());
});
/**
* Verifies that misuse of the decoder class triggers assertions.
* @suppress {checkTypes|visibility}
*/
it('testDecodeErrors', function() {
// Reading a value past the end of the stream should trigger an assertion.
var decoder = jspb.BinaryDecoder.alloc([0, 1, 2]);
assertThrows(function() {decoder.readUint64()});
// Overlong varints should trigger assertions.
decoder.setBlock([255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 0]);
assertThrows(function() {decoder.readUnsignedVarint64()});
decoder.reset();
assertThrows(function() {decoder.readSignedVarint64()});
decoder.reset();
assertThrows(function() {decoder.readZigzagVarint64()});
// Positive 32-bit varints encoded with 1 bits in positions 33 through 35
// should trigger assertions.
decoder.setBlock([255, 255, 255, 255, 0x1F]);
assertThrows(function() {decoder.readUnsignedVarint32()});
decoder.setBlock([255, 255, 255, 255, 0x2F]);
assertThrows(function() {decoder.readUnsignedVarint32()});
decoder.setBlock([255, 255, 255, 255, 0x4F]);
assertThrows(function() {decoder.readUnsignedVarint32()});
// Negative 32-bit varints encoded with non-1 bits in the high dword should
// trigger assertions.
decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]);
assertThrows(function() {decoder.readUnsignedVarint32()});
decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]);
assertThrows(function() {decoder.readUnsignedVarint32()});
});
/**
* Tests encoding and decoding of unsigned integers.
*/
it('testUnsignedIntegers', function() {
doTestUnsignedValue(
jspb.BinaryDecoder.prototype.readUint8,
jspb.BinaryEncoder.prototype.writeUint8,
1, 0xFF, Math.round);
doTestUnsignedValue(
jspb.BinaryDecoder.prototype.readUint16,
jspb.BinaryEncoder.prototype.writeUint16,
1, 0xFFFF, Math.round);
doTestUnsignedValue(
jspb.BinaryDecoder.prototype.readUint32,
jspb.BinaryEncoder.prototype.writeUint32,
1, 0xFFFFFFFF, Math.round);
doTestUnsignedValue(
jspb.BinaryDecoder.prototype.readUint64,
jspb.BinaryEncoder.prototype.writeUint64,
1, Math.pow(2, 64) - 1025, Math.round);
});
/**
* Tests encoding and decoding of signed integers.
*/
it('testSignedIntegers', function() {
doTestSignedValue(
jspb.BinaryDecoder.prototype.readInt8,
jspb.BinaryEncoder.prototype.writeInt8,
1, -0x80, 0x7F, Math.round);
doTestSignedValue(
jspb.BinaryDecoder.prototype.readInt16,
jspb.BinaryEncoder.prototype.writeInt16,
1, -0x8000, 0x7FFF, Math.round);
doTestSignedValue(
jspb.BinaryDecoder.prototype.readInt32,
jspb.BinaryEncoder.prototype.writeInt32,
1, -0x80000000, 0x7FFFFFFF, Math.round);
doTestSignedValue(
jspb.BinaryDecoder.prototype.readInt64,
jspb.BinaryEncoder.prototype.writeInt64,
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
});
/**
* Tests encoding and decoding of floats.
*/
it('testFloats', function() {
/**
* @param {number} x
* @return {number}
*/
function truncate(x) {
var temp = new Float32Array(1);
temp[0] = x;
return temp[0];
}
doTestSignedValue(
jspb.BinaryDecoder.prototype.readFloat,
jspb.BinaryEncoder.prototype.writeFloat,
jspb.BinaryConstants.FLOAT32_EPS,
-jspb.BinaryConstants.FLOAT32_MAX,
jspb.BinaryConstants.FLOAT32_MAX,
truncate);
doTestSignedValue(
jspb.BinaryDecoder.prototype.readDouble,
jspb.BinaryEncoder.prototype.writeDouble,
jspb.BinaryConstants.FLOAT64_EPS * 10,
-jspb.BinaryConstants.FLOAT64_MAX,
jspb.BinaryConstants.FLOAT64_MAX,
function(x) { return x; });
});
});

@ -0,0 +1,628 @@
// 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.
// Test suite is written using Jasmine -- see http://jasmine.github.io/
goog.require('goog.crypt.base64');
goog.require('goog.testing.asserts');
goog.require('jspb.Message');
// CommonJS-LoadFromFile: ../testbinary_pb proto.jspb.test
goog.require('proto.jspb.test.ExtendsWithMessage');
goog.require('proto.jspb.test.ForeignEnum');
goog.require('proto.jspb.test.ForeignMessage');
goog.require('proto.jspb.test.TestAllTypes');
goog.require('proto.jspb.test.TestExtendable');
goog.require('proto.jspb.test.extendOptionalBool');
goog.require('proto.jspb.test.extendOptionalBytes');
goog.require('proto.jspb.test.extendOptionalDouble');
goog.require('proto.jspb.test.extendOptionalFixed32');
goog.require('proto.jspb.test.extendOptionalFixed64');
goog.require('proto.jspb.test.extendOptionalFloat');
goog.require('proto.jspb.test.extendOptionalForeignEnum');
goog.require('proto.jspb.test.extendOptionalInt32');
goog.require('proto.jspb.test.extendOptionalInt64');
goog.require('proto.jspb.test.extendOptionalSfixed32');
goog.require('proto.jspb.test.extendOptionalSfixed64');
goog.require('proto.jspb.test.extendOptionalSint32');
goog.require('proto.jspb.test.extendOptionalSint64');
goog.require('proto.jspb.test.extendOptionalString');
goog.require('proto.jspb.test.extendOptionalUint32');
goog.require('proto.jspb.test.extendOptionalUint64');
goog.require('proto.jspb.test.extendPackedRepeatedBoolList');
goog.require('proto.jspb.test.extendPackedRepeatedDoubleList');
goog.require('proto.jspb.test.extendPackedRepeatedFixed32List');
goog.require('proto.jspb.test.extendPackedRepeatedFixed64List');
goog.require('proto.jspb.test.extendPackedRepeatedFloatList');
goog.require('proto.jspb.test.extendPackedRepeatedForeignEnumList');
goog.require('proto.jspb.test.extendPackedRepeatedInt32List');
goog.require('proto.jspb.test.extendPackedRepeatedInt64List');
goog.require('proto.jspb.test.extendPackedRepeatedSfixed32List');
goog.require('proto.jspb.test.extendPackedRepeatedSfixed64List');
goog.require('proto.jspb.test.extendPackedRepeatedSint32List');
goog.require('proto.jspb.test.extendPackedRepeatedSint64List');
goog.require('proto.jspb.test.extendPackedRepeatedUint32List');
goog.require('proto.jspb.test.extendPackedRepeatedUint64List');
goog.require('proto.jspb.test.extendRepeatedBoolList');
goog.require('proto.jspb.test.extendRepeatedBytesList');
goog.require('proto.jspb.test.extendRepeatedDoubleList');
goog.require('proto.jspb.test.extendRepeatedFixed32List');
goog.require('proto.jspb.test.extendRepeatedFixed64List');
goog.require('proto.jspb.test.extendRepeatedFloatList');
goog.require('proto.jspb.test.extendRepeatedForeignEnumList');
goog.require('proto.jspb.test.extendRepeatedInt32List');
goog.require('proto.jspb.test.extendRepeatedInt64List');
goog.require('proto.jspb.test.extendRepeatedSfixed32List');
goog.require('proto.jspb.test.extendRepeatedSfixed64List');
goog.require('proto.jspb.test.extendRepeatedSint32List');
goog.require('proto.jspb.test.extendRepeatedSint64List');
goog.require('proto.jspb.test.extendRepeatedStringList');
goog.require('proto.jspb.test.extendRepeatedUint32List');
goog.require('proto.jspb.test.extendRepeatedUint64List');
var suite = {};
var BYTES = new Uint8Array([1, 2, 8, 9]);
var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
/**
* Helper: fill all fields on a TestAllTypes message.
* @param {proto.jspb.test.TestAllTypes} msg
*/
function fillAllFields(msg) {
msg.setOptionalInt32(-42);
// can be exactly represented by JS number (64-bit double, i.e., 52-bit
// mantissa).
msg.setOptionalInt64(-0x7fffffff00000000);
msg.setOptionalUint32(0x80000000);
msg.setOptionalUint64(0xf000000000000000);
msg.setOptionalSint32(-100);
msg.setOptionalSint64(-0x8000000000000000);
msg.setOptionalFixed32(1234);
msg.setOptionalFixed64(0x1234567800000000);
msg.setOptionalSfixed32(-1234);
msg.setOptionalSfixed64(-0x1234567800000000);
msg.setOptionalFloat(1.5);
msg.setOptionalDouble(-1.5);
msg.setOptionalBool(true);
msg.setOptionalString('hello world');
msg.setOptionalBytes(BYTES);
msg.setOptionalGroup(new proto.jspb.test.TestAllTypes.OptionalGroup());
msg.getOptionalGroup().setA(100);
var submsg = new proto.jspb.test.ForeignMessage();
submsg.setC(16);
msg.setOptionalForeignMessage(submsg);
msg.setOptionalForeignEnum(proto.jspb.test.ForeignEnum.FOREIGN_FOO);
msg.setOneofString('oneof');
msg.setRepeatedInt32List([-42]);
msg.setRepeatedInt64List([-0x7fffffff00000000]);
msg.setRepeatedUint32List([0x80000000]);
msg.setRepeatedUint64List([0xf000000000000000]);
msg.setRepeatedSint32List([-100]);
msg.setRepeatedSint64List([-0x8000000000000000]);
msg.setRepeatedFixed32List([1234]);
msg.setRepeatedFixed64List([0x1234567800000000]);
msg.setRepeatedSfixed32List([-1234]);
msg.setRepeatedSfixed64List([-0x1234567800000000]);
msg.setRepeatedFloatList([1.5]);
msg.setRepeatedDoubleList([-1.5]);
msg.setRepeatedBoolList([true]);
msg.setRepeatedStringList(['hello world']);
msg.setRepeatedBytesList([BYTES, BYTES]);
msg.setRepeatedGroupList([new proto.jspb.test.TestAllTypes.RepeatedGroup()]);
msg.getRepeatedGroupList()[0].setA(100);
submsg = new proto.jspb.test.ForeignMessage();
submsg.setC(1000);
msg.setRepeatedForeignMessageList([submsg]);
msg.setRepeatedForeignEnumList([proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
msg.setPackedRepeatedInt32List([-42]);
msg.setPackedRepeatedInt64List([-0x7fffffff00000000]);
msg.setPackedRepeatedUint32List([0x80000000]);
msg.setPackedRepeatedUint64List([0xf000000000000000]);
msg.setPackedRepeatedSint32List([-100]);
msg.setPackedRepeatedSint64List([-0x8000000000000000]);
msg.setPackedRepeatedFixed32List([1234]);
msg.setPackedRepeatedFixed64List([0x1234567800000000]);
msg.setPackedRepeatedSfixed32List([-1234]);
msg.setPackedRepeatedSfixed64List([-0x1234567800000000]);
msg.setPackedRepeatedFloatList([1.5]);
msg.setPackedRepeatedDoubleList([-1.5]);
msg.setPackedRepeatedBoolList([true]);
}
/**
* Helper: compare a bytes field to an expected value
* @param {Uint8Array|string} arr
* @param {Uint8Array} expected
* @return {boolean}
*/
function bytesCompare(arr, expected) {
if (goog.isString(arr)) {
arr = goog.crypt.base64.decodeStringToUint8Array(arr);
}
if (arr.length != expected.length) {
return false;
}
for (var i = 0; i < arr.length; i++) {
if (arr[i] != expected[i]) {
return false;
}
}
return true;
}
/**
* Helper: verify contents of given TestAllTypes message as set by
* fillAllFields().
* @param {proto.jspb.test.TestAllTypes} original
* @param {proto.jspb.test.TestAllTypes} copy
*/
function checkAllFields(original, copy) {
assertTrue(jspb.Message.equals(original, copy));
assertEquals(copy.getOptionalInt32(), -42);
assertEquals(copy.getOptionalInt64(), -0x7fffffff00000000);
assertEquals(copy.getOptionalUint32(), 0x80000000);
assertEquals(copy.getOptionalUint64(), 0xf000000000000000);
assertEquals(copy.getOptionalSint32(), -100);
assertEquals(copy.getOptionalSint64(), -0x8000000000000000);
assertEquals(copy.getOptionalFixed32(), 1234);
assertEquals(copy.getOptionalFixed64(), 0x1234567800000000);
assertEquals(copy.getOptionalSfixed32(), -1234);
assertEquals(copy.getOptionalSfixed64(), -0x1234567800000000);
assertEquals(copy.getOptionalFloat(), 1.5);
assertEquals(copy.getOptionalDouble(), -1.5);
assertEquals(copy.getOptionalBool(), true);
assertEquals(copy.getOptionalString(), 'hello world');
assertEquals(true, bytesCompare(copy.getOptionalBytes(), BYTES));
assertEquals(true, bytesCompare(copy.getOptionalBytes_asU8(), BYTES));
assertEquals(
copy.getOptionalBytes_asB64(), goog.crypt.base64.encodeByteArray(BYTES));
assertEquals(copy.getOptionalGroup().getA(), 100);
assertEquals(copy.getOptionalForeignMessage().getC(), 16);
assertEquals(copy.getOptionalForeignEnum(),
proto.jspb.test.ForeignEnum.FOREIGN_FOO);
assertEquals(copy.getOneofString(), 'oneof');
assertEquals(copy.getOneofFieldCase(),
proto.jspb.test.TestAllTypes.OneofFieldCase.ONEOF_STRING);
assertElementsEquals(copy.getRepeatedInt32List(), [-42]);
assertElementsEquals(copy.getRepeatedInt64List(), [-0x7fffffff00000000]);
assertElementsEquals(copy.getRepeatedUint32List(), [0x80000000]);
assertElementsEquals(copy.getRepeatedUint64List(), [0xf000000000000000]);
assertElementsEquals(copy.getRepeatedSint32List(), [-100]);
assertElementsEquals(copy.getRepeatedSint64List(), [-0x8000000000000000]);
assertElementsEquals(copy.getRepeatedFixed32List(), [1234]);
assertElementsEquals(copy.getRepeatedFixed64List(), [0x1234567800000000]);
assertElementsEquals(copy.getRepeatedSfixed32List(), [-1234]);
assertElementsEquals(copy.getRepeatedSfixed64List(), [-0x1234567800000000]);
assertElementsEquals(copy.getRepeatedFloatList(), [1.5]);
assertElementsEquals(copy.getRepeatedDoubleList(), [-1.5]);
assertElementsEquals(copy.getRepeatedBoolList(), [true]);
assertElementsEquals(copy.getRepeatedStringList(), ['hello world']);
assertEquals(copy.getRepeatedBytesList().length, 2);
assertEquals(true, bytesCompare(copy.getRepeatedBytesList_asU8()[0], BYTES));
assertEquals(true, bytesCompare(copy.getRepeatedBytesList()[0], BYTES));
assertEquals(true, bytesCompare(copy.getRepeatedBytesList_asU8()[1], BYTES));
assertEquals(copy.getRepeatedBytesList_asB64()[0], BYTES_B64);
assertEquals(copy.getRepeatedBytesList_asB64()[1], BYTES_B64);
assertEquals(copy.getRepeatedGroupList().length, 1);
assertEquals(copy.getRepeatedGroupList()[0].getA(), 100);
assertEquals(copy.getRepeatedForeignMessageList().length, 1);
assertEquals(copy.getRepeatedForeignMessageList()[0].getC(), 1000);
assertElementsEquals(copy.getRepeatedForeignEnumList(),
[proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
assertElementsEquals(copy.getPackedRepeatedInt32List(), [-42]);
assertElementsEquals(copy.getPackedRepeatedInt64List(),
[-0x7fffffff00000000]);
assertElementsEquals(copy.getPackedRepeatedUint32List(), [0x80000000]);
assertElementsEquals(copy.getPackedRepeatedUint64List(),
[0xf000000000000000]);
assertElementsEquals(copy.getPackedRepeatedSint32List(), [-100]);
assertElementsEquals(copy.getPackedRepeatedSint64List(),
[-0x8000000000000000]);
assertElementsEquals(copy.getPackedRepeatedFixed32List(), [1234]);
assertElementsEquals(copy.getPackedRepeatedFixed64List(),
[0x1234567800000000]);
assertElementsEquals(copy.getPackedRepeatedSfixed32List(), [-1234]);
assertElementsEquals(copy.getPackedRepeatedSfixed64List(),
[-0x1234567800000000]);
assertElementsEquals(copy.getPackedRepeatedFloatList(), [1.5]);
assertElementsEquals(copy.getPackedRepeatedDoubleList(), [-1.5]);
}
/**
* Helper: verify that all expected extensions are present.
* @param {!proto.jspb.test.TestExtendable} msg
*/
function checkExtensions(msg) {
assertEquals(-42,
msg.getExtension(proto.jspb.test.extendOptionalInt32));
assertEquals(-0x7fffffff00000000,
msg.getExtension(proto.jspb.test.extendOptionalInt64));
assertEquals(0x80000000,
msg.getExtension(proto.jspb.test.extendOptionalUint32));
assertEquals(0xf000000000000000,
msg.getExtension(proto.jspb.test.extendOptionalUint64));
assertEquals(-100,
msg.getExtension(proto.jspb.test.extendOptionalSint32));
assertEquals(-0x8000000000000000,
msg.getExtension(proto.jspb.test.extendOptionalSint64));
assertEquals(1234,
msg.getExtension(proto.jspb.test.extendOptionalFixed32));
assertEquals(0x1234567800000000,
msg.getExtension(proto.jspb.test.extendOptionalFixed64));
assertEquals(-1234,
msg.getExtension(proto.jspb.test.extendOptionalSfixed32));
assertEquals(-0x1234567800000000,
msg.getExtension(proto.jspb.test.extendOptionalSfixed64));
assertEquals(1.5,
msg.getExtension(proto.jspb.test.extendOptionalFloat));
assertEquals(-1.5,
msg.getExtension(proto.jspb.test.extendOptionalDouble));
assertEquals(true,
msg.getExtension(proto.jspb.test.extendOptionalBool));
assertEquals('hello world',
msg.getExtension(proto.jspb.test.extendOptionalString));
assertEquals(
true, bytesCompare(
msg.getExtension(proto.jspb.test.extendOptionalBytes), BYTES));
assertEquals(16,
msg.getExtension(
proto.jspb.test.ExtendsWithMessage.optionalExtension).getFoo());
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedInt32List),
[-42]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedInt64List),
[-0x7fffffff00000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedUint32List),
[0x80000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedUint64List),
[0xf000000000000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedSint32List),
[-100]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedSint64List),
[-0x8000000000000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedFixed32List),
[1234]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedFixed64List),
[0x1234567800000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedSfixed32List),
[-1234]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedSfixed64List),
[-0x1234567800000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedFloatList),
[1.5]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedDoubleList),
[-1.5]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedBoolList),
[true]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedStringList),
['hello world']);
assertEquals(
true,
bytesCompare(
msg.getExtension(proto.jspb.test.extendRepeatedBytesList)[0], BYTES));
assertEquals(1000,
msg.getExtension(
proto.jspb.test.ExtendsWithMessage.repeatedExtensionList)[0]
.getFoo());
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendRepeatedForeignEnumList),
[proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedInt32List),
[-42]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedInt64List),
[-0x7fffffff00000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedUint32List),
[0x80000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedUint64List),
[0xf000000000000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedSint32List),
[-100]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedSint64List),
[-0x8000000000000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed32List),
[1234]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed64List),
[0x1234567800000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed32List),
[-1234]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed64List),
[-0x1234567800000000]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedFloatList),
[1.5]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedDoubleList),
[-1.5]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedBoolList),
[true]);
assertElementsEquals(
msg.getExtension(proto.jspb.test.extendPackedRepeatedForeignEnumList),
[proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
}
describe('protoBinaryTest', function() {
/**
* Tests a basic serialization-deserializaton round-trip with all supported
* field types (on the TestAllTypes message type).
*/
it('testRoundTrip', function() {
var msg = new proto.jspb.test.TestAllTypes();
fillAllFields(msg);
var encoded = msg.serializeBinary();
var decoded = proto.jspb.test.TestAllTypes.deserializeBinary(encoded);
checkAllFields(msg, decoded);
});
/**
* Test that base64 string and Uint8Array are interchangeable in bytes fields.
*/
it('testBytesFieldsGettersInterop', function() {
var msg = new proto.jspb.test.TestAllTypes();
// Set from a base64 string and check all the getters work.
msg.setOptionalBytes(BYTES_B64);
assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
// Test binary serialize round trip doesn't break it.
msg = proto.jspb.test.TestAllTypes.deserializeBinary(msg.serializeBinary());
assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
msg = new proto.jspb.test.TestAllTypes();
// Set from a Uint8Array and check all the getters work.
msg.setOptionalBytes(BYTES);
assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
});
/**
* Test that bytes setters will receive result of any of the getters.
*/
it('testBytesFieldsSettersInterop', function() {
var msg = new proto.jspb.test.TestAllTypes();
msg.setOptionalBytes(BYTES);
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
msg.setOptionalBytes(msg.getOptionalBytes());
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
msg.setOptionalBytes(msg.getOptionalBytes_asB64());
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
msg.setOptionalBytes(msg.getOptionalBytes_asU8());
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
});
/**
* Test that bytes setters will receive result of any of the getters.
*/
it('testRepeatedBytesGetters', function() {
var msg = new proto.jspb.test.TestAllTypes();
function assertGetters() {
assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[0]));
assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[1]));
assertTrue(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array);
assertTrue(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array);
assertTrue(bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
assertTrue(bytesCompare(msg.getRepeatedBytesList()[1], BYTES));
assertTrue(bytesCompare(msg.getRepeatedBytesList_asB64()[0], BYTES));
assertTrue(bytesCompare(msg.getRepeatedBytesList_asB64()[1], BYTES));
assertTrue(bytesCompare(msg.getRepeatedBytesList_asU8()[0], BYTES));
assertTrue(bytesCompare(msg.getRepeatedBytesList_asU8()[1], BYTES));
}
msg.setRepeatedBytesList([BYTES, BYTES]);
assertGetters();
msg.setRepeatedBytesList([BYTES_B64, BYTES_B64]);
assertGetters();
msg.setRepeatedBytesList([]);
assertEquals(0, msg.getRepeatedBytesList().length);
assertEquals(0, msg.getRepeatedBytesList_asB64().length);
assertEquals(0, msg.getRepeatedBytesList_asU8().length);
});
/**
* Helper: fill all extension values.
* @param {proto.jspb.test.TestExtendable} msg
*/
function fillExtensions(msg) {
msg.setExtension(
proto.jspb.test.extendOptionalInt32, -42);
msg.setExtension(
proto.jspb.test.extendOptionalInt64, -0x7fffffff00000000);
msg.setExtension(
proto.jspb.test.extendOptionalUint32, 0x80000000);
msg.setExtension(
proto.jspb.test.extendOptionalUint64, 0xf000000000000000);
msg.setExtension(
proto.jspb.test.extendOptionalSint32, -100);
msg.setExtension(
proto.jspb.test.extendOptionalSint64, -0x8000000000000000);
msg.setExtension(
proto.jspb.test.extendOptionalFixed32, 1234);
msg.setExtension(
proto.jspb.test.extendOptionalFixed64, 0x1234567800000000);
msg.setExtension(
proto.jspb.test.extendOptionalSfixed32, -1234);
msg.setExtension(
proto.jspb.test.extendOptionalSfixed64, -0x1234567800000000);
msg.setExtension(
proto.jspb.test.extendOptionalFloat, 1.5);
msg.setExtension(
proto.jspb.test.extendOptionalDouble, -1.5);
msg.setExtension(
proto.jspb.test.extendOptionalBool, true);
msg.setExtension(
proto.jspb.test.extendOptionalString, 'hello world');
msg.setExtension(proto.jspb.test.extendOptionalBytes, BYTES);
var submsg = new proto.jspb.test.ExtendsWithMessage();
submsg.setFoo(16);
msg.setExtension(
proto.jspb.test.ExtendsWithMessage.optionalExtension, submsg);
msg.setExtension(
proto.jspb.test.extendOptionalForeignEnum,
proto.jspb.test.ForeignEnum.FOREIGN_FOO);
msg.setExtension(
proto.jspb.test.extendRepeatedInt32List, [-42]);
msg.setExtension(
proto.jspb.test.extendRepeatedInt64List, [-0x7fffffff00000000]);
msg.setExtension(
proto.jspb.test.extendRepeatedUint32List, [0x80000000]);
msg.setExtension(
proto.jspb.test.extendRepeatedUint64List, [0xf000000000000000]);
msg.setExtension(
proto.jspb.test.extendRepeatedSint32List, [-100]);
msg.setExtension(
proto.jspb.test.extendRepeatedSint64List, [-0x8000000000000000]);
msg.setExtension(
proto.jspb.test.extendRepeatedFixed32List, [1234]);
msg.setExtension(
proto.jspb.test.extendRepeatedFixed64List, [0x1234567800000000]);
msg.setExtension(
proto.jspb.test.extendRepeatedSfixed32List, [-1234]);
msg.setExtension(
proto.jspb.test.extendRepeatedSfixed64List, [-0x1234567800000000]);
msg.setExtension(
proto.jspb.test.extendRepeatedFloatList, [1.5]);
msg.setExtension(
proto.jspb.test.extendRepeatedDoubleList, [-1.5]);
msg.setExtension(
proto.jspb.test.extendRepeatedBoolList, [true]);
msg.setExtension(
proto.jspb.test.extendRepeatedStringList, ['hello world']);
msg.setExtension(proto.jspb.test.extendRepeatedBytesList, [BYTES]);
submsg = new proto.jspb.test.ExtendsWithMessage();
submsg.setFoo(1000);
msg.setExtension(
proto.jspb.test.ExtendsWithMessage.repeatedExtensionList, [submsg]);
msg.setExtension(proto.jspb.test.extendRepeatedForeignEnumList,
[proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedInt32List, [-42]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedInt64List, [-0x7fffffff00000000]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedUint32List, [0x80000000]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedUint64List, [0xf000000000000000]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedSint32List, [-100]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedSint64List, [-0x8000000000000000]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedFixed32List, [1234]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedFixed64List, [0x1234567800000000]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedSfixed32List, [-1234]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedSfixed64List,
[-0x1234567800000000]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedFloatList, [1.5]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedDoubleList, [-1.5]);
msg.setExtension(
proto.jspb.test.extendPackedRepeatedBoolList, [true]);
msg.setExtension(proto.jspb.test.extendPackedRepeatedForeignEnumList,
[proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
}
/**
* Tests extension serialization and deserialization.
*/
it('testExtensions', function() {
var msg = new proto.jspb.test.TestExtendable();
fillExtensions(msg);
var encoded = msg.serializeBinary();
var decoded = proto.jspb.test.TestExtendable.deserializeBinary(encoded);
checkExtensions(decoded);
});
});

@ -0,0 +1,922 @@
// 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.
/**
* @fileoverview Test cases for jspb's binary protocol buffer reader.
*
* There are two particular magic numbers that need to be pointed out -
* 2^64-1025 is the largest number representable as both a double and an
* unsigned 64-bit integer, and 2^63-513 is the largest number representable as
* both a double and a signed 64-bit integer.
*
* Test suite is written using Jasmine -- see http://jasmine.github.io/
*
* @author aappleby@google.com (Austin Appleby)
*/
goog.require('goog.testing.asserts');
goog.require('jspb.BinaryConstants');
goog.require('jspb.BinaryDecoder');
goog.require('jspb.BinaryReader');
goog.require('jspb.BinaryWriter');
describe('binaryReaderTest', function() {
/**
* Tests the reader instance cache.
*/
it('testInstanceCaches', /** @suppress {visibility} */ function() {
var writer = new jspb.BinaryWriter();
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
writer.writeMessage(1, dummyMessage, goog.nullFunction);
writer.writeMessage(2, dummyMessage, goog.nullFunction);
var buffer = writer.getResultBuffer();
// Empty the instance caches.
jspb.BinaryReader.instanceCache_ = [];
// Allocating and then freeing three decoders should leave us with three in
// the cache.
var decoder1 = jspb.BinaryDecoder.alloc();
var decoder2 = jspb.BinaryDecoder.alloc();
var decoder3 = jspb.BinaryDecoder.alloc();
decoder1.free();
decoder2.free();
decoder3.free();
assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
assertEquals(0, jspb.BinaryReader.instanceCache_.length);
// Allocating and then freeing a reader should remove one decoder from its
// cache, but it should stay stuck to the reader afterwards since we can't
// have a reader without a decoder.
jspb.BinaryReader.alloc().free();
assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
assertEquals(1, jspb.BinaryReader.instanceCache_.length);
// Allocating a reader should remove a reader from the cache.
var reader = jspb.BinaryReader.alloc(buffer);
assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
assertEquals(0, jspb.BinaryReader.instanceCache_.length);
// Processing the message reuses the current reader.
reader.nextField();
assertEquals(1, reader.getFieldNumber());
reader.readMessage(dummyMessage, function() {
assertEquals(0, jspb.BinaryReader.instanceCache_.length);
});
reader.nextField();
assertEquals(2, reader.getFieldNumber());
reader.readMessage(dummyMessage, function() {
assertEquals(0, jspb.BinaryReader.instanceCache_.length);
});
assertEquals(false, reader.nextField());
assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
assertEquals(0, jspb.BinaryReader.instanceCache_.length);
// Freeing the reader should put it back into the cache.
reader.free();
assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
assertEquals(1, jspb.BinaryReader.instanceCache_.length);
});
/**
* @param {number} x
* @return {number}
*/
function truncate(x) {
var temp = new Float32Array(1);
temp[0] = x;
return temp[0];
}
/**
* Verifies that misuse of the reader class triggers assertions.
*/
it('testReadErrors', /** @suppress {checkTypes|visibility} */ function() {
// Calling readMessage on a non-delimited field should trigger an
// assertion.
var reader = jspb.BinaryReader.alloc([8, 1]);
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
reader.nextField();
assertThrows(function() {
reader.readMessage(dummyMessage, goog.nullFunction);
});
// Reading past the end of the stream should trigger an assertion.
reader = jspb.BinaryReader.alloc([9, 1]);
reader.nextField();
assertThrows(function() {reader.readFixed64()});
// Reading past the end of a submessage should trigger an assertion.
reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
reader.nextField();
reader.readMessage(dummyMessage, function() {
reader.nextField();
assertThrows(function() {reader.readFixed32()});
});
// Skipping an invalid field should trigger an assertion.
reader = jspb.BinaryReader.alloc([12, 1]);
reader.nextWireType_ = 1000;
assertThrows(function() {reader.skipField()});
// Reading fields with the wrong wire type should assert.
reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
reader.nextField();
assertThrows(function() {reader.readInt32()});
assertThrows(function() {reader.readInt32String()});
assertThrows(function() {reader.readInt64()});
assertThrows(function() {reader.readInt64String()});
assertThrows(function() {reader.readUint32()});
assertThrows(function() {reader.readUint32String()});
assertThrows(function() {reader.readUint64()});
assertThrows(function() {reader.readUint64String()});
assertThrows(function() {reader.readSint32()});
assertThrows(function() {reader.readBool()});
assertThrows(function() {reader.readEnum()});
reader = jspb.BinaryReader.alloc([8, 1]);
reader.nextField();
assertThrows(function() {reader.readFixed32()});
assertThrows(function() {reader.readFixed64()});
assertThrows(function() {reader.readSfixed32()});
assertThrows(function() {reader.readSfixed64()});
assertThrows(function() {reader.readFloat()});
assertThrows(function() {reader.readDouble()});
assertThrows(function() {reader.readString()});
assertThrows(function() {reader.readBytes()});
});
/**
* Tests encoding and decoding of unsigned field types.
* @param {Function} readField
* @param {Function} writeField
* @param {number} epsilon
* @param {number} upperLimit
* @param {Function} filter
* @private
* @suppress {missingProperties}
*/
var doTestUnsignedField_ = function(readField,
writeField, epsilon, upperLimit, filter) {
assertNotNull(readField);
assertNotNull(writeField);
var writer = new jspb.BinaryWriter();
// Encode zero and limits.
writeField.call(writer, 1, filter(0));
writeField.call(writer, 2, filter(epsilon));
writeField.call(writer, 3, filter(upperLimit));
// Encode positive values.
for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
writeField.call(writer, 4, filter(cursor));
}
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
// Check zero and limits.
reader.nextField();
assertEquals(1, reader.getFieldNumber());
assertEquals(filter(0), readField.call(reader));
reader.nextField();
assertEquals(2, reader.getFieldNumber());
assertEquals(filter(epsilon), readField.call(reader));
reader.nextField();
assertEquals(3, reader.getFieldNumber());
assertEquals(filter(upperLimit), readField.call(reader));
// Check positive values.
for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
reader.nextField();
if (4 != reader.getFieldNumber()) throw 'fail!';
if (filter(cursor) != readField.call(reader)) throw 'fail!';
}
};
/**
* Tests encoding and decoding of signed field types.
* @param {Function} readField
* @param {Function} writeField
* @param {number} epsilon
* @param {number} lowerLimit
* @param {number} upperLimit
* @param {Function} filter
* @private
* @suppress {missingProperties}
*/
var doTestSignedField_ = function(readField,
writeField, epsilon, lowerLimit, upperLimit, filter) {
var writer = new jspb.BinaryWriter();
// Encode zero and limits.
writeField.call(writer, 1, filter(lowerLimit));
writeField.call(writer, 2, filter(-epsilon));
writeField.call(writer, 3, filter(0));
writeField.call(writer, 4, filter(epsilon));
writeField.call(writer, 5, filter(upperLimit));
var inputValues = [];
// Encode negative values.
for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
var val = filter(cursor);
writeField.call(writer, 6, val);
inputValues.push({
fieldNumber: 6,
value: val
});
}
// Encode positive values.
for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
var val = filter(cursor);
writeField.call(writer, 7, val);
inputValues.push({
fieldNumber: 7,
value: val
});
}
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
// Check zero and limits.
reader.nextField();
assertEquals(1, reader.getFieldNumber());
assertEquals(filter(lowerLimit), readField.call(reader));
reader.nextField();
assertEquals(2, reader.getFieldNumber());
assertEquals(filter(-epsilon), readField.call(reader));
reader.nextField();
assertEquals(3, reader.getFieldNumber());
assertEquals(filter(0), readField.call(reader));
reader.nextField();
assertEquals(4, reader.getFieldNumber());
assertEquals(filter(epsilon), readField.call(reader));
reader.nextField();
assertEquals(5, reader.getFieldNumber());
assertEquals(filter(upperLimit), readField.call(reader));
for (var i = 0; i < inputValues.length; i++) {
var expected = inputValues[i];
reader.nextField();
assertEquals(expected.fieldNumber, reader.getFieldNumber());
assertEquals(expected.value, readField.call(reader));
}
};
/**
* Tests fields that use varint encoding.
*/
it('testVarintFields', function() {
assertNotUndefined(jspb.BinaryReader.prototype.readUint32);
assertNotUndefined(jspb.BinaryWriter.prototype.writeUint32);
assertNotUndefined(jspb.BinaryReader.prototype.readUint64);
assertNotUndefined(jspb.BinaryWriter.prototype.writeUint64);
assertNotUndefined(jspb.BinaryReader.prototype.readBool);
assertNotUndefined(jspb.BinaryWriter.prototype.writeBool);
doTestUnsignedField_(
jspb.BinaryReader.prototype.readUint32,
jspb.BinaryWriter.prototype.writeUint32,
1, Math.pow(2, 32) - 1, Math.round);
doTestUnsignedField_(
jspb.BinaryReader.prototype.readUint64,
jspb.BinaryWriter.prototype.writeUint64,
1, Math.pow(2, 64) - 1025, Math.round);
doTestSignedField_(
jspb.BinaryReader.prototype.readInt32,
jspb.BinaryWriter.prototype.writeInt32,
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
doTestSignedField_(
jspb.BinaryReader.prototype.readInt64,
jspb.BinaryWriter.prototype.writeInt64,
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
doTestSignedField_(
jspb.BinaryReader.prototype.readEnum,
jspb.BinaryWriter.prototype.writeEnum,
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
doTestUnsignedField_(
jspb.BinaryReader.prototype.readBool,
jspb.BinaryWriter.prototype.writeBool,
1, 1, function(x) { return !!x; });
});
/**
* Tests reading a field from hexadecimal string (format: '08 BE EF').
* @param {Function} readField
* @param {number} expected
* @param {string} hexString
*/
function doTestHexStringVarint_(readField, expected, hexString) {
var bytesCount = (hexString.length + 1) / 3;
var bytes = new Uint8Array(bytesCount);
for (var i = 0; i < bytesCount; i++) {
bytes[i] = parseInt(hexString.substring(i * 3, i * 3 + 2), 16);
}
var reader = jspb.BinaryReader.alloc(bytes);
reader.nextField();
assertEquals(expected, readField.call(reader));
}
/**
* Tests non-canonical redundant varint decoding.
*/
it('testRedundantVarintFields', function() {
assertNotNull(jspb.BinaryReader.prototype.readUint32);
assertNotNull(jspb.BinaryReader.prototype.readUint64);
assertNotNull(jspb.BinaryReader.prototype.readSint32);
assertNotNull(jspb.BinaryReader.prototype.readSint64);
// uint32 and sint32 take no more than 5 bytes
// 08 - field prefix (type = 0 means varint)
doTestHexStringVarint_(
jspb.BinaryReader.prototype.readUint32,
12, '08 8C 80 80 80 00');
// 11 stands for -6 in zigzag encoding
doTestHexStringVarint_(
jspb.BinaryReader.prototype.readSint32,
-6, '08 8B 80 80 80 00');
// uint64 and sint64 take no more than 10 bytes
// 08 - field prefix (type = 0 means varint)
doTestHexStringVarint_(
jspb.BinaryReader.prototype.readUint64,
12, '08 8C 80 80 80 80 80 80 80 80 00');
// 11 stands for -6 in zigzag encoding
doTestHexStringVarint_(
jspb.BinaryReader.prototype.readSint64,
-6, '08 8B 80 80 80 80 80 80 80 80 00');
});
/**
* Tests 64-bit fields that are handled as strings.
*/
it('testStringInt64Fields', function() {
var writer = new jspb.BinaryWriter();
var testSignedData = [
'2730538252207801776',
'-2688470994844604560',
'3398529779486536359',
'3568577411627971000',
'272477188847484900',
'-6649058714086158188',
'-7695254765712060806',
'-4525541438037104029',
'-4993706538836508568',
'4990160321893729138'
];
var testUnsignedData = [
'7822732630241694882',
'6753602971916687352',
'2399935075244442116',
'8724292567325338867',
'16948784802625696584',
'4136275908516066934',
'3575388346793700364',
'5167142028379259461',
'1557573948689737699',
'17100725280812548567'
];
for (var i = 0; i < testSignedData.length; i++) {
writer.writeInt64String(2 * i + 1, testSignedData[i]);
writer.writeUint64String(2 * i + 2, testUnsignedData[i]);
}
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
for (var i = 0; i < testSignedData.length; i++) {
reader.nextField();
assertEquals(2 * i + 1, reader.getFieldNumber());
assertEquals(testSignedData[i], reader.readInt64String());
reader.nextField();
assertEquals(2 * i + 2, reader.getFieldNumber());
assertEquals(testUnsignedData[i], reader.readUint64String());
}
});
/**
* Tests fields that use zigzag encoding.
*/
it('testZigzagFields', function() {
doTestSignedField_(
jspb.BinaryReader.prototype.readSint32,
jspb.BinaryWriter.prototype.writeSint32,
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
doTestSignedField_(
jspb.BinaryReader.prototype.readSint64,
jspb.BinaryWriter.prototype.writeSint64,
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
});
/**
* Tests fields that use fixed-length encoding.
*/
it('testFixedFields', function() {
doTestUnsignedField_(
jspb.BinaryReader.prototype.readFixed32,
jspb.BinaryWriter.prototype.writeFixed32,
1, Math.pow(2, 32) - 1, Math.round);
doTestUnsignedField_(
jspb.BinaryReader.prototype.readFixed64,
jspb.BinaryWriter.prototype.writeFixed64,
1, Math.pow(2, 64) - 1025, Math.round);
doTestSignedField_(
jspb.BinaryReader.prototype.readSfixed32,
jspb.BinaryWriter.prototype.writeSfixed32,
1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
doTestSignedField_(
jspb.BinaryReader.prototype.readSfixed64,
jspb.BinaryWriter.prototype.writeSfixed64,
1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
});
/**
* Tests floating point fields.
*/
it('testFloatFields', function() {
doTestSignedField_(
jspb.BinaryReader.prototype.readFloat,
jspb.BinaryWriter.prototype.writeFloat,
jspb.BinaryConstants.FLOAT32_MIN,
-jspb.BinaryConstants.FLOAT32_MAX,
jspb.BinaryConstants.FLOAT32_MAX,
truncate);
doTestSignedField_(
jspb.BinaryReader.prototype.readDouble,
jspb.BinaryWriter.prototype.writeDouble,
jspb.BinaryConstants.FLOAT64_EPS * 10,
-jspb.BinaryConstants.FLOAT64_MIN,
jspb.BinaryConstants.FLOAT64_MIN,
function(x) { return x; });
});
/**
* Tests length-delimited string fields.
*/
it('testStringFields', function() {
var s1 = 'The quick brown fox jumps over the lazy dog.';
var s2 = '人人生而自由,在尊嚴和權利上一律平等。';
var writer = new jspb.BinaryWriter();
writer.writeString(1, s1);
writer.writeString(2, s2);
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
reader.nextField();
assertEquals(1, reader.getFieldNumber());
assertEquals(s1, reader.readString());
reader.nextField();
assertEquals(2, reader.getFieldNumber());
assertEquals(s2, reader.readString());
});
/**
* Tests length-delimited byte fields.
*/
it('testByteFields', function() {
var message = [];
var lowerLimit = 1;
var upperLimit = 256;
var scale = 1.1;
var writer = new jspb.BinaryWriter();
for (var cursor = lowerLimit; cursor < upperLimit; cursor *= 1.1) {
var len = Math.round(cursor);
var bytes = [];
for (var i = 0; i < len; i++) bytes.push(i % 256);
writer.writeBytes(len, bytes);
}
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
for (var cursor = lowerLimit; reader.nextField(); cursor *= 1.1) {
var len = Math.round(cursor);
if (len != reader.getFieldNumber()) throw 'fail!';
var bytes = reader.readBytes();
if (len != bytes.length) throw 'fail!';
for (var i = 0; i < bytes.length; i++) {
if (i % 256 != bytes[i]) throw 'fail!';
}
}
});
/**
* Tests nested messages.
*/
it('testNesting', function() {
var writer = new jspb.BinaryWriter();
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
writer.writeInt32(1, 100);
// Add one message with 3 int fields.
writer.writeMessage(2, dummyMessage, function() {
writer.writeInt32(3, 300);
writer.writeInt32(4, 400);
writer.writeInt32(5, 500);
});
// Add one empty message.
writer.writeMessage(6, dummyMessage, goog.nullFunction);
writer.writeInt32(7, 700);
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
// Validate outermost message.
reader.nextField();
assertEquals(1, reader.getFieldNumber());
assertEquals(100, reader.readInt32());
reader.nextField();
assertEquals(2, reader.getFieldNumber());
reader.readMessage(dummyMessage, function() {
// Validate embedded message 1.
reader.nextField();
assertEquals(3, reader.getFieldNumber());
assertEquals(300, reader.readInt32());
reader.nextField();
assertEquals(4, reader.getFieldNumber());
assertEquals(400, reader.readInt32());
reader.nextField();
assertEquals(5, reader.getFieldNumber());
assertEquals(500, reader.readInt32());
assertEquals(false, reader.nextField());
});
reader.nextField();
assertEquals(6, reader.getFieldNumber());
reader.readMessage(dummyMessage, function() {
// Validate embedded message 2.
assertEquals(false, reader.nextField());
});
reader.nextField();
assertEquals(7, reader.getFieldNumber());
assertEquals(700, reader.readInt32());
assertEquals(false, reader.nextField());
});
/**
* Tests skipping fields of each type by interleaving them with sentinel
* values and skipping everything that's not a sentinel.
*/
it('testSkipField', function() {
var writer = new jspb.BinaryWriter();
var sentinel = 123456789;
// Write varint fields of different sizes.
writer.writeInt32(1, sentinel);
writer.writeInt32(1, 1);
writer.writeInt32(1, 1000);
writer.writeInt32(1, 1000000);
writer.writeInt32(1, 1000000000);
// Write fixed 64-bit encoded fields.
writer.writeInt32(2, sentinel);
writer.writeDouble(2, 1);
writer.writeFixed64(2, 1);
writer.writeSfixed64(2, 1);
// Write fixed 32-bit encoded fields.
writer.writeInt32(3, sentinel);
writer.writeFloat(3, 1);
writer.writeFixed32(3, 1);
writer.writeSfixed32(3, 1);
// Write delimited fields.
writer.writeInt32(4, sentinel);
writer.writeBytes(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
writer.writeString(4, 'The quick brown fox jumps over the lazy dog');
// Write a group with a nested group inside.
writer.writeInt32(5, sentinel);
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
writer.writeGroup(5, dummyMessage, function() {
writer.writeInt64(42, 42);
writer.writeGroup(6, dummyMessage, function() {
writer.writeInt64(84, 42);
});
});
// Write final sentinel.
writer.writeInt32(6, sentinel);
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
function skip(field, count) {
for (var i = 0; i < count; i++) {
reader.nextField();
if (field != reader.getFieldNumber()) throw 'fail!';
reader.skipField();
}
}
reader.nextField();
assertEquals(1, reader.getFieldNumber());
assertEquals(sentinel, reader.readInt32());
skip(1, 4);
reader.nextField();
assertEquals(2, reader.getFieldNumber());
assertEquals(sentinel, reader.readInt32());
skip(2, 3);
reader.nextField();
assertEquals(3, reader.getFieldNumber());
assertEquals(sentinel, reader.readInt32());
skip(3, 3);
reader.nextField();
assertEquals(4, reader.getFieldNumber());
assertEquals(sentinel, reader.readInt32());
skip(4, 2);
reader.nextField();
assertEquals(5, reader.getFieldNumber());
assertEquals(sentinel, reader.readInt32());
skip(5, 1);
reader.nextField();
assertEquals(6, reader.getFieldNumber());
assertEquals(sentinel, reader.readInt32());
});
/**
* Tests packed fields.
*/
it('testPackedFields', function() {
var writer = new jspb.BinaryWriter();
var sentinel = 123456789;
var unsignedData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var signedData = [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10];
var floatData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
var doubleData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
var boolData = [true, false, true, true, false, false, true, false];
for (var i = 0; i < floatData.length; i++) {
floatData[i] = truncate(floatData[i]);
}
writer.writeInt32(1, sentinel);
writer.writePackedInt32(2, signedData);
writer.writePackedInt64(2, signedData);
writer.writePackedUint32(2, unsignedData);
writer.writePackedUint64(2, unsignedData);
writer.writePackedSint32(2, signedData);
writer.writePackedSint64(2, signedData);
writer.writePackedFixed32(2, unsignedData);
writer.writePackedFixed64(2, unsignedData);
writer.writePackedSfixed32(2, signedData);
writer.writePackedSfixed64(2, signedData);
writer.writePackedFloat(2, floatData);
writer.writePackedDouble(2, doubleData);
writer.writePackedBool(2, boolData);
writer.writePackedEnum(2, unsignedData);
writer.writeInt32(3, sentinel);
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
reader.nextField();
assertEquals(sentinel, reader.readInt32());
reader.nextField();
assertElementsEquals(reader.readPackedInt32(), signedData);
reader.nextField();
assertElementsEquals(reader.readPackedInt64(), signedData);
reader.nextField();
assertElementsEquals(reader.readPackedUint32(), unsignedData);
reader.nextField();
assertElementsEquals(reader.readPackedUint64(), unsignedData);
reader.nextField();
assertElementsEquals(reader.readPackedSint32(), signedData);
reader.nextField();
assertElementsEquals(reader.readPackedSint64(), signedData);
reader.nextField();
assertElementsEquals(reader.readPackedFixed32(), unsignedData);
reader.nextField();
assertElementsEquals(reader.readPackedFixed64(), unsignedData);
reader.nextField();
assertElementsEquals(reader.readPackedSfixed32(), signedData);
reader.nextField();
assertElementsEquals(reader.readPackedSfixed64(), signedData);
reader.nextField();
assertElementsEquals(reader.readPackedFloat(), floatData);
reader.nextField();
assertElementsEquals(reader.readPackedDouble(), doubleData);
reader.nextField();
assertElementsEquals(reader.readPackedBool(), boolData);
reader.nextField();
assertElementsEquals(reader.readPackedEnum(), unsignedData);
reader.nextField();
assertEquals(sentinel, reader.readInt32());
});
/**
* Byte blobs inside nested messages should always have their byte offset set
* relative to the start of the outermost blob, not the start of their parent
* blob.
*/
it('testNestedBlobs', function() {
// Create a proto consisting of two nested messages, with the inner one
// containing a blob of bytes.
var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED;
var blob = [1, 2, 3, 4, 5];
var writer = new jspb.BinaryWriter();
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
writer.writeMessage(1, dummyMessage, function() {
writer.writeMessage(1, dummyMessage, function() {
writer.writeBytes(1, blob);
});
});
// Peel off the outer two message layers. Each layer should have two bytes
// of overhead, one for the field tag and one for the length of the inner
// blob.
var decoder1 = new jspb.BinaryDecoder(writer.getResultBuffer());
assertEquals(fieldTag, decoder1.readUnsignedVarint32());
assertEquals(blob.length + 4, decoder1.readUnsignedVarint32());
var decoder2 = new jspb.BinaryDecoder(decoder1.readBytes(blob.length + 4));
assertEquals(fieldTag, decoder2.readUnsignedVarint32());
assertEquals(blob.length + 2, decoder2.readUnsignedVarint32());
assertEquals(fieldTag, decoder2.readUnsignedVarint32());
assertEquals(blob.length, decoder2.readUnsignedVarint32());
var bytes = decoder2.readBytes(blob.length);
assertElementsEquals(bytes, blob);
});
/**
* Tests read callbacks.
*/
it('testReadCallbacks', function() {
var writer = new jspb.BinaryWriter();
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
// Add an int, a submessage, and another int.
writer.writeInt32(1, 100);
writer.writeMessage(2, dummyMessage, function() {
writer.writeInt32(3, 300);
writer.writeInt32(4, 400);
writer.writeInt32(5, 500);
});
writer.writeInt32(7, 700);
// Create the reader and register a custom read callback.
var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
/**
* @param {!jspb.BinaryReader} reader
* @return {*}
*/
function readCallback(reader) {
reader.nextField();
assertEquals(3, reader.getFieldNumber());
assertEquals(300, reader.readInt32());
reader.nextField();
assertEquals(4, reader.getFieldNumber());
assertEquals(400, reader.readInt32());
reader.nextField();
assertEquals(5, reader.getFieldNumber());
assertEquals(500, reader.readInt32());
assertEquals(false, reader.nextField());
};
reader.registerReadCallback('readCallback', readCallback);
// Read the container message.
reader.nextField();
assertEquals(1, reader.getFieldNumber());
assertEquals(100, reader.readInt32());
reader.nextField();
assertEquals(2, reader.getFieldNumber());
reader.readMessage(dummyMessage, function() {
// Decode the embedded message using the registered callback.
reader.runReadCallback('readCallback');
});
reader.nextField();
assertEquals(7, reader.getFieldNumber());
assertEquals(700, reader.readInt32());
assertEquals(false, reader.nextField());
});
});

@ -0,0 +1,668 @@
// 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.
/**
* @fileoverview Test cases for jspb's helper functions.
*
* Test suite is written using Jasmine -- see http://jasmine.github.io/
*
* @author aappleby@google.com (Austin Appleby)
*/
goog.require('goog.crypt.base64');
goog.require('goog.testing.asserts');
goog.require('jspb.BinaryConstants');
goog.require('jspb.BinaryWriter');
goog.require('jspb.utils');
/**
* @param {number} x
* @return {number}
*/
function truncate(x) {
var temp = new Float32Array(1);
temp[0] = x;
return temp[0];
}
/**
* Converts an 64-bit integer in split representation to a 64-bit hash string
* (8 bits encoded per character).
* @param {number} bitsLow The low 32 bits of the split 64-bit integer.
* @param {number} bitsHigh The high 32 bits of the split 64-bit integer.
* @return {string} The encoded hash string, 8 bits per character.
*/
function toHashString(bitsLow, bitsHigh) {
return String.fromCharCode((bitsLow >>> 0) & 0xFF,
(bitsLow >>> 8) & 0xFF,
(bitsLow >>> 16) & 0xFF,
(bitsLow >>> 24) & 0xFF,
(bitsHigh >>> 0) & 0xFF,
(bitsHigh >>> 8) & 0xFF,
(bitsHigh >>> 16) & 0xFF,
(bitsHigh >>> 24) & 0xFF);
}
describe('binaryUtilsTest', function() {
/**
* Tests lossless binary-to-decimal conversion.
*/
it('testDecimalConversion', function() {
// Check some magic numbers.
var result =
jspb.utils.joinUnsignedDecimalString(0x89e80001, 0x8ac72304);
assertEquals('10000000000000000001', result);
result = jspb.utils.joinUnsignedDecimalString(0xacd05f15, 0x1b69b4b);
assertEquals('123456789123456789', result);
result = jspb.utils.joinUnsignedDecimalString(0xeb1f0ad2, 0xab54a98c);
assertEquals('12345678901234567890', result);
result = jspb.utils.joinUnsignedDecimalString(0xe3b70cb1, 0x891087b8);
assertEquals('9876543210987654321', result);
// Check limits.
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00000000);
assertEquals('0', result);
result = jspb.utils.joinUnsignedDecimalString(0xFFFFFFFF, 0xFFFFFFFF);
assertEquals('18446744073709551615', result);
// Check each bit of the low dword.
for (var i = 0; i < 32; i++) {
var low = (1 << i) >>> 0;
result = jspb.utils.joinUnsignedDecimalString(low, 0);
assertEquals('' + Math.pow(2, i), result);
}
// Check the first 20 bits of the high dword.
for (var i = 0; i < 20; i++) {
var high = (1 << i) >>> 0;
result = jspb.utils.joinUnsignedDecimalString(0, high);
assertEquals('' + Math.pow(2, 32 + i), result);
}
// V8's internal double-to-string conversion is inaccurate for values above
// 2^52, even if they're representable integers - check the rest of the bits
// manually against the correct string representations of 2^N.
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00100000);
assertEquals('4503599627370496', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00200000);
assertEquals('9007199254740992', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00400000);
assertEquals('18014398509481984', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00800000);
assertEquals('36028797018963968', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x01000000);
assertEquals('72057594037927936', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x02000000);
assertEquals('144115188075855872', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x04000000);
assertEquals('288230376151711744', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x08000000);
assertEquals('576460752303423488', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x10000000);
assertEquals('1152921504606846976', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x20000000);
assertEquals('2305843009213693952', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x40000000);
assertEquals('4611686018427387904', result);
result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x80000000);
assertEquals('9223372036854775808', result);
});
/**
* Going from hash strings to decimal strings should also be lossless.
*/
it('testHashToDecimalConversion', function() {
var result;
var convert = jspb.utils.hash64ToDecimalString;
result = convert(toHashString(0x00000000, 0x00000000), false);
assertEquals('0', result);
result = convert(toHashString(0x00000000, 0x00000000), true);
assertEquals('0', result);
result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), false);
assertEquals('18446744073709551615', result);
result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), true);
assertEquals('-1', result);
result = convert(toHashString(0x00000000, 0x80000000), false);
assertEquals('9223372036854775808', result);
result = convert(toHashString(0x00000000, 0x80000000), true);
assertEquals('-9223372036854775808', result);
result = convert(toHashString(0xacd05f15, 0x01b69b4b), false);
assertEquals('123456789123456789', result);
result = convert(toHashString(~0xacd05f15 + 1, ~0x01b69b4b), true);
assertEquals('-123456789123456789', result);
// And converting arrays of hashes should work the same way.
result = jspb.utils.hash64ArrayToDecimalStrings([
toHashString(0xFFFFFFFF, 0xFFFFFFFF),
toHashString(0x00000000, 0x80000000),
toHashString(0xacd05f15, 0x01b69b4b)], false);
assertEquals(3, result.length);
assertEquals('18446744073709551615', result[0]);
assertEquals('9223372036854775808', result[1]);
assertEquals('123456789123456789', result[2]);
});
/*
* Going from decimal strings to hash strings should be lossless.
*/
it('testDecimalToHashConversion', function() {
var result;
var convert = jspb.utils.decimalStringToHash64;
result = convert('0');
assertEquals(String.fromCharCode.apply(null,
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
result = convert('-1');
assertEquals(String.fromCharCode.apply(null,
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
result = convert('18446744073709551615');
assertEquals(String.fromCharCode.apply(null,
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
result = convert('9223372036854775808');
assertEquals(String.fromCharCode.apply(null,
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
result = convert('-9223372036854775808');
assertEquals(String.fromCharCode.apply(null,
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
result = convert('123456789123456789');
assertEquals(String.fromCharCode.apply(null,
[0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]), result);
result = convert('-123456789123456789');
assertEquals(String.fromCharCode.apply(null,
[0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE]), result);
});
/**
* Going from hash strings to hex strings should be lossless.
*/
it('testHashToHexConversion', function() {
var result;
var convert = jspb.utils.hash64ToHexString;
result = convert(toHashString(0x00000000, 0x00000000));
assertEquals('0x0000000000000000', result);
result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF));
assertEquals('0xffffffffffffffff', result);
result = convert(toHashString(0x12345678, 0x9ABCDEF0));
assertEquals('0x9abcdef012345678', result);
});
/**
* Going from hex strings to hash strings should be lossless.
*/
it('testHexToHashConversion', function() {
var result;
var convert = jspb.utils.hexStringToHash64;
result = convert('0x0000000000000000');
assertEquals(String.fromCharCode.apply(null,
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
result = convert('0xffffffffffffffff');
assertEquals(String.fromCharCode.apply(null,
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
// Hex string is big-endian, hash string is little-endian.
result = convert('0x123456789ABCDEF0');
assertEquals(String.fromCharCode.apply(null,
[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]), result);
// Capitalization should not matter.
result = convert('0x0000abcdefABCDEF');
assertEquals(String.fromCharCode.apply(null,
[0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00]), result);
});
/**
* Going from numbers to hash strings should be lossless for up to 53 bits of
* precision.
*/
it('testNumberToHashConversion', function() {
var result;
var convert = jspb.utils.numberToHash64;
result = convert(0x0000000000000);
assertEquals('0x0000000000000000', jspb.utils.hash64ToHexString(result));
result = convert(0xFFFFFFFFFFFFF);
assertEquals('0x000fffffffffffff', jspb.utils.hash64ToHexString(result));
result = convert(0x123456789ABCD);
assertEquals('0x000123456789abcd', jspb.utils.hash64ToHexString(result));
result = convert(0xDCBA987654321);
assertEquals('0x000dcba987654321', jspb.utils.hash64ToHexString(result));
// 53 bits of precision should not be truncated.
result = convert(0x10000000000001);
assertEquals('0x0010000000000001', jspb.utils.hash64ToHexString(result));
// 54 bits of precision should be truncated.
result = convert(0x20000000000001);
assertNotEquals(
'0x0020000000000001', jspb.utils.hash64ToHexString(result));
});
/**
* Sanity check the behavior of Javascript's strings when doing funny things
* with unicode characters.
*/
it('sanityCheckUnicodeStrings', function() {
var strings = new Array(65536);
// All possible unsigned 16-bit values should be storable in a string, they
// shouldn't do weird things with the length of the string, and they should
// come back out of the string unchanged.
for (var i = 0; i < 65536; i++) {
strings[i] = 'a' + String.fromCharCode(i) + 'a';
if (3 != strings[i].length) throw 'fail!';
if (i != strings[i].charCodeAt(1)) throw 'fail!';
}
// Each unicode character should compare equal to itself and not equal to a
// different unicode character.
for (var i = 0; i < 65536; i++) {
if (strings[i] != strings[i]) throw 'fail!';
if (strings[i] == strings[(i + 1) % 65536]) throw 'fail!';
}
});
/**
* Tests conversion from 32-bit floating point numbers to split64 numbers.
*/
it('testFloat32ToSplit64', function() {
var f32_eps = jspb.BinaryConstants.FLOAT32_EPS;
var f32_min = jspb.BinaryConstants.FLOAT32_MIN;
var f32_max = jspb.BinaryConstants.FLOAT32_MAX;
// NaN.
jspb.utils.splitFloat32(NaN);
if (!isNaN(jspb.utils.joinFloat32(jspb.utils.split64Low,
jspb.utils.split64High))) {
throw 'fail!';
}
/**
* @param {number} x
* @param {number=} opt_bits
*/
function test(x, opt_bits) {
jspb.utils.splitFloat32(x);
if (goog.isDef(opt_bits)) {
if (opt_bits != jspb.utils.split64Low) throw 'fail!';
}
if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low,
jspb.utils.split64High)) {
throw 'fail!';
}
}
// Positive and negative infinity.
test(Infinity, 0x7f800000);
test(-Infinity, 0xff800000);
// Positive and negative zero.
test(0, 0x00000000);
test(-0, 0x80000000);
// Positive and negative epsilon.
test(f32_eps, 0x00000001);
test(-f32_eps, 0x80000001);
// Positive and negative min.
test(f32_min, 0x00800000);
test(-f32_min, 0x80800000);
// Positive and negative max.
test(f32_max, 0x7F7FFFFF);
test(-f32_max, 0xFF7FFFFF);
// Various positive values.
var cursor = f32_eps * 10;
while (cursor != Infinity) {
test(cursor);
cursor *= 1.1;
}
// Various negative values.
cursor = -f32_eps * 10;
while (cursor != -Infinity) {
test(cursor);
cursor *= 1.1;
}
});
/**
* Tests conversion from 64-bit floating point numbers to split64 numbers.
*/
it('testFloat64ToSplit64', function() {
var f64_eps = jspb.BinaryConstants.FLOAT64_EPS;
var f64_min = jspb.BinaryConstants.FLOAT64_MIN;
var f64_max = jspb.BinaryConstants.FLOAT64_MAX;
// NaN.
jspb.utils.splitFloat64(NaN);
if (!isNaN(jspb.utils.joinFloat64(jspb.utils.split64Low,
jspb.utils.split64High))) {
throw 'fail!';
}
/**
* @param {number} x
* @param {number=} opt_highBits
* @param {number=} opt_lowBits
*/
function test(x, opt_highBits, opt_lowBits) {
jspb.utils.splitFloat64(x);
if (goog.isDef(opt_highBits)) {
if (opt_highBits != jspb.utils.split64High) throw 'fail!';
}
if (goog.isDef(opt_lowBits)) {
if (opt_lowBits != jspb.utils.split64Low) throw 'fail!';
}
if (x != jspb.utils.joinFloat64(jspb.utils.split64Low,
jspb.utils.split64High)) {
throw 'fail!';
}
}
// Positive and negative infinity.
test(Infinity, 0x7ff00000, 0x00000000);
test(-Infinity, 0xfff00000, 0x00000000);
// Positive and negative zero.
test(0, 0x00000000, 0x00000000);
test(-0, 0x80000000, 0x00000000);
// Positive and negative epsilon.
test(f64_eps, 0x00000000, 0x00000001);
test(-f64_eps, 0x80000000, 0x00000001);
// Positive and negative min.
test(f64_min, 0x00100000, 0x00000000);
test(-f64_min, 0x80100000, 0x00000000);
// Positive and negative max.
test(f64_max, 0x7FEFFFFF, 0xFFFFFFFF);
test(-f64_max, 0xFFEFFFFF, 0xFFFFFFFF);
// Various positive values.
var cursor = f64_eps * 10;
while (cursor != Infinity) {
test(cursor);
cursor *= 1.1;
}
// Various negative values.
cursor = -f64_eps * 10;
while (cursor != -Infinity) {
test(cursor);
cursor *= 1.1;
}
});
/**
* Tests counting packed varints.
*/
it('testCountVarints', function() {
var values = [];
for (var i = 1; i < 1000000000; i *= 1.1) {
values.push(Math.floor(i));
}
var writer = new jspb.BinaryWriter();
writer.writePackedUint64(1, values);
var buffer = new Uint8Array(writer.getResultBuffer());
// We should have two more varints than we started with - one for the field
// tag, one for the packed length.
assertEquals(values.length + 2,
jspb.utils.countVarints(buffer, 0, buffer.length));
});
/**
* Tests counting matching varint fields.
*/
it('testCountVarintFields', function() {
var writer = new jspb.BinaryWriter();
var count = 0;
for (var i = 1; i < 1000000000; i *= 1.1) {
writer.writeUint64(1, Math.floor(i));
count++;
}
writer.writeString(2, 'terminator');
var buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countVarintFields(buffer, 0, buffer.length, 1));
writer = new jspb.BinaryWriter();
count = 0;
for (var i = 1; i < 1000000000; i *= 1.1) {
writer.writeUint64(123456789, Math.floor(i));
count++;
}
writer.writeString(2, 'terminator');
buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789));
});
/**
* Tests counting matching fixed32 fields.
*/
it('testCountFixed32Fields', function() {
var writer = new jspb.BinaryWriter();
var count = 0;
for (var i = 1; i < 1000000000; i *= 1.1) {
writer.writeFixed32(1, Math.floor(i));
count++;
}
writer.writeString(2, 'terminator');
var buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1));
writer = new jspb.BinaryWriter();
count = 0;
for (var i = 1; i < 1000000000; i *= 1.1) {
writer.writeFixed32(123456789, Math.floor(i));
count++;
}
writer.writeString(2, 'terminator');
buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789));
});
/**
* Tests counting matching fixed64 fields.
*/
it('testCountFixed64Fields', function() {
var writer = new jspb.BinaryWriter();
var count = 0;
for (var i = 1; i < 1000000000; i *= 1.1) {
writer.writeDouble(1, i);
count++;
}
writer.writeString(2, 'terminator');
var buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1));
writer = new jspb.BinaryWriter();
count = 0;
for (var i = 1; i < 1000000000; i *= 1.1) {
writer.writeDouble(123456789, i);
count++;
}
writer.writeString(2, 'terminator');
buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789));
});
/**
* Tests counting matching delimited fields.
*/
it('testCountDelimitedFields', function() {
var writer = new jspb.BinaryWriter();
var count = 0;
for (var i = 1; i < 1000; i *= 1.1) {
writer.writeBytes(1, [Math.floor(i)]);
count++;
}
writer.writeString(2, 'terminator');
var buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1));
writer = new jspb.BinaryWriter();
count = 0;
for (var i = 1; i < 1000; i *= 1.1) {
writer.writeBytes(123456789, [Math.floor(i)]);
count++;
}
writer.writeString(2, 'terminator');
buffer = new Uint8Array(writer.getResultBuffer());
assertEquals(count,
jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789));
});
/**
* Tests byte format for debug strings.
*/
it('testDebugBytesToTextFormat', function() {
assertEquals('""', jspb.utils.debugBytesToTextFormat(null));
assertEquals('"\\x00\\x10\\xff"',
jspb.utils.debugBytesToTextFormat([0, 16, 255]));
});
/**
* Tests converting byte blob sources into byte blobs.
*/
it('testByteSourceToUint8Array', function() {
var convert = jspb.utils.byteSourceToUint8Array;
var sourceData = [];
for (var i = 0; i < 256; i++) {
sourceData.push(i);
}
var sourceBytes = new Uint8Array(sourceData);
var sourceBuffer = sourceBytes.buffer;
var sourceBase64 = goog.crypt.base64.encodeByteArray(sourceData);
var sourceString = String.fromCharCode.apply(null, sourceData);
function check(result) {
assertEquals(Uint8Array, result.constructor);
assertEquals(sourceData.length, result.length);
for (var i = 0; i < result.length; i++) {
assertEquals(sourceData[i], result[i]);
}
}
// Converting Uint8Arrays into Uint8Arrays should be a no-op.
assertEquals(sourceBytes, convert(sourceBytes));
// Converting Array.<numbers> into Uint8Arrays should work.
check(convert(sourceData));
// Converting ArrayBuffers into Uint8Arrays should work.
check(convert(sourceBuffer));
// Converting base64-encoded strings into Uint8Arrays should work.
check(convert(sourceBase64));
});
});

@ -0,0 +1,122 @@
// 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.
/**
* @fileoverview Test cases for jspb's binary protocol buffer writer. In
* practice BinaryWriter is used to drive the Decoder and Reader test cases,
* so only writer-specific tests are here.
*
* Test suite is written using Jasmine -- see http://jasmine.github.io/
*
* @author aappleby@google.com (Austin Appleby)
*/
goog.require('goog.crypt');
goog.require('goog.testing.asserts');
goog.require('jspb.BinaryWriter');
/**
* @param {function()} func This function should throw an error when run.
*/
function assertFails(func) {
var e = assertThrows(func);
//assertNotNull(e.toString().match(/Error/));
}
describe('binaryWriterTest', function() {
/**
* Verifies that misuse of the writer class triggers assertions.
*/
it('testWriteErrors', function() {
// Submessages with invalid field indices should assert.
var writer = new jspb.BinaryWriter();
var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
assertFails(function() {
writer.writeMessage(-1, dummyMessage, goog.nullFunction);
});
// Writing invalid field indices should assert.
writer = new jspb.BinaryWriter();
assertFails(function() {writer.writeUint64(-1, 1);});
// Writing out-of-range field values should assert.
writer = new jspb.BinaryWriter();
assertFails(function() {writer.writeInt32(1, -Infinity);});
assertFails(function() {writer.writeInt32(1, Infinity);});
assertFails(function() {writer.writeInt64(1, -Infinity);});
assertFails(function() {writer.writeInt64(1, Infinity);});
assertFails(function() {writer.writeUint32(1, -1);});
assertFails(function() {writer.writeUint32(1, Infinity);});
assertFails(function() {writer.writeUint64(1, -1);});
assertFails(function() {writer.writeUint64(1, Infinity);});
assertFails(function() {writer.writeSint32(1, -Infinity);});
assertFails(function() {writer.writeSint32(1, Infinity);});
assertFails(function() {writer.writeSint64(1, -Infinity);});
assertFails(function() {writer.writeSint64(1, Infinity);});
assertFails(function() {writer.writeFixed32(1, -1);});
assertFails(function() {writer.writeFixed32(1, Infinity);});
assertFails(function() {writer.writeFixed64(1, -1);});
assertFails(function() {writer.writeFixed64(1, Infinity);});
assertFails(function() {writer.writeSfixed32(1, -Infinity);});
assertFails(function() {writer.writeSfixed32(1, Infinity);});
assertFails(function() {writer.writeSfixed64(1, -Infinity);});
assertFails(function() {writer.writeSfixed64(1, Infinity);});
});
/**
* Basic test of retrieving the result as a Uint8Array buffer
*/
it('testGetResultBuffer', function() {
var expected = '0864120b48656c6c6f20776f726c641a0301020320c801';
var writer = new jspb.BinaryWriter();
writer.writeUint32(1, 100);
writer.writeString(2, 'Hello world');
writer.writeBytes(3, new Uint8Array([1, 2, 3]));
writer.writeUint32(4, 200);
var buffer = writer.getResultBuffer();
assertEquals(expected, goog.crypt.byteArrayToHex(buffer));
});
});

@ -0,0 +1,40 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2016 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 = "proto3";
option java_package = "com.google.apps.jspb.proto";
option java_multiple_files = true;
package jspb.test.importing;
message ImportedMessage {
string string_value = 1;
}

@ -0,0 +1,42 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2016 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 = "proto3";
option java_package = "com.google.apps.jspb.proto";
option java_multiple_files = true;
package jspb.test.framing;
import "test6/test6.proto";
message FramingMessage {
jspb.test.importing.ImportedMessage imported_message = 1;
}

@ -0,0 +1,51 @@
// 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.
// Author: mwr@google.com (Mark Rawling)
syntax = "proto2";
option java_package = "com.google.apps.jspb.proto";
option java_multiple_files = true;
package jspb.test;
// legacy data, must be nested
message data {
message NestedData {
required string str = 1;
}
}
// new data, does not require nesting
message UnnestedData {
required string str = 1;
}

@ -0,0 +1,105 @@
// 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.
goog.setTestOnly();
goog.require('goog.testing.asserts');
// CommonJS-LoadFromFile: google-protobuf
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.Simple1');
describe('debugTest', function() {
it('testSimple1', function() {
if (COMPILED) {
return;
}
var message = new proto.jspb.test.Simple1();
message.setAString('foo');
assertObjectEquals({
$name: 'proto.jspb.test.Simple1',
'aString': 'foo',
'aRepeatedStringList': []
}, jspb.debug.dump(message));
message.setABoolean(true);
message.setARepeatedStringList(['1', '2']);
assertObjectEquals({
$name: 'proto.jspb.test.Simple1',
'aString': 'foo',
'aRepeatedStringList': ['1', '2'],
'aBoolean': true
}, jspb.debug.dump(message));
message.clearAString();
assertObjectEquals({
$name: 'proto.jspb.test.Simple1',
'aRepeatedStringList': ['1', '2'],
'aBoolean': true
}, jspb.debug.dump(message));
});
it('testExtensions', function() {
if (COMPILED) {
return;
}
var extension = new proto.jspb.test.IsExtension();
extension.setExt1('ext1field');
var extendable = new proto.jspb.test.HasExtensions();
extendable.setStr1('v1');
extendable.setStr2('v2');
extendable.setStr3('v3');
extendable.setExtension(proto.jspb.test.IsExtension.extField, extension);
assertObjectEquals({
'$name': 'proto.jspb.test.HasExtensions',
'str1': 'v1',
'str2': 'v2',
'str3': 'v3',
'$extensions': {
'extField': {
'$name': 'proto.jspb.test.IsExtension',
'ext1': 'ext1field'
},
'repeatedSimpleList': []
}
}, jspb.debug.dump(extendable));
});
});

@ -0,0 +1,301 @@
// 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.
goog.require('goog.testing.asserts');
goog.require('goog.userAgent');
// CommonJS-LoadFromFile: testbinary_pb proto.jspb.test
goog.require('proto.jspb.test.MapValueEnum');
goog.require('proto.jspb.test.MapValueMessage');
goog.require('proto.jspb.test.TestMapFields');
// CommonJS-LoadFromFile: test_pb proto.jspb.test
goog.require('proto.jspb.test.MapValueMessageNoBinary');
goog.require('proto.jspb.test.TestMapFieldsNoBinary');
/**
* Helper: check that the given map has exactly this set of (sorted) entries.
* @param {!jspb.Map} map
* @param {!Array<!Array<?>>} entries
*/
function checkMapEquals(map, entries) {
var arr = map.toArray();
assertEquals(arr.length, entries.length);
for (var i = 0; i < arr.length; i++) {
assertElementsEquals(arr[i], entries[i]);
}
}
/**
* Converts an ES6 iterator to an array.
* @template T
* @param {!Iterator<T>} iter an iterator
* @return {!Array<T>}
*/
function toArray(iter) {
var arr = [];
while (true) {
var val = iter.next();
if (val.done) {
break;
}
arr.push(val.value);
}
return arr;
}
/**
* Helper: generate test methods for this TestMapFields class.
* @param {?} msgInfo
* @param {?} submessageCtor
* @param {!string} suffix
*/
function makeTests(msgInfo, submessageCtor, suffix) {
/**
* Helper: fill all maps on a TestMapFields.
* @param {?} msg
*/
var fillMapFields = function(msg) {
msg.getMapStringStringMap().set('asdf', 'jkl;').set('key 2', 'hello world');
msg.getMapStringInt32Map().set('a', 1).set('b', -2);
msg.getMapStringInt64Map().set('c', 0x100000000).set('d', 0x200000000);
msg.getMapStringBoolMap().set('e', true).set('f', false);
msg.getMapStringDoubleMap().set('g', 3.14159).set('h', 2.71828);
msg.getMapStringEnumMap()
.set('i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR)
.set('j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ);
msg.getMapStringMsgMap()
.set('k', new submessageCtor())
.set('l', new submessageCtor());
msg.getMapStringMsgMap().get('k').setFoo(42);
msg.getMapStringMsgMap().get('l').setFoo(84);
msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b');
msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd');
msg.getMapBoolStringMap().set(false, 'e').set(true, 'f');
};
/**
* Helper: check all maps on a TestMapFields.
* @param {?} msg
*/
var checkMapFields = function(msg) {
checkMapEquals(msg.getMapStringStringMap(), [
['asdf', 'jkl;'],
['key 2', 'hello world']
]);
checkMapEquals(msg.getMapStringInt32Map(), [
['a', 1],
['b', -2]
]);
checkMapEquals(msg.getMapStringInt64Map(), [
['c', 0x100000000],
['d', 0x200000000]
]);
checkMapEquals(msg.getMapStringBoolMap(), [
['e', true],
['f', false]
]);
checkMapEquals(msg.getMapStringDoubleMap(), [
['g', 3.14159],
['h', 2.71828]
]);
checkMapEquals(msg.getMapStringEnumMap(), [
['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
]);
checkMapEquals(msg.getMapInt32StringMap(), [
[-1, 'a'],
[42, 'b']
]);
checkMapEquals(msg.getMapInt64StringMap(), [
[0x123456789abc, 'c'],
[0xcba987654321, 'd']
]);
checkMapEquals(msg.getMapBoolStringMap(), [
[false, 'e'],
[true, 'f']
]);
assertEquals(msg.getMapStringMsgMap().getLength(), 2);
assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42);
assertEquals(msg.getMapStringMsgMap().get('l').getFoo(), 84);
var entries = toArray(msg.getMapStringMsgMap().entries());
assertEquals(entries.length, 2);
entries.forEach(function(entry) {
var key = entry[0];
var val = entry[1];
assert(val === msg.getMapStringMsgMap().get(key));
});
msg.getMapStringMsgMap().forEach(function(val, key) {
assert(val === msg.getMapStringMsgMap().get(key));
});
};
it('testMapStringStringField' + suffix, function() {
var msg = new msgInfo.constructor();
assertEquals(msg.getMapStringStringMap().getLength(), 0);
assertEquals(msg.getMapStringInt32Map().getLength(), 0);
assertEquals(msg.getMapStringInt64Map().getLength(), 0);
assertEquals(msg.getMapStringBoolMap().getLength(), 0);
assertEquals(msg.getMapStringDoubleMap().getLength(), 0);
assertEquals(msg.getMapStringEnumMap().getLength(), 0);
assertEquals(msg.getMapStringMsgMap().getLength(), 0);
// Re-create to clear out any internally-cached wrappers, etc.
msg = new msgInfo.constructor();
var m = msg.getMapStringStringMap();
assertEquals(m.has('asdf'), false);
assertEquals(m.get('asdf'), undefined);
m.set('asdf', 'hello world');
assertEquals(m.has('asdf'), true);
assertEquals(m.get('asdf'), 'hello world');
m.set('jkl;', 'key 2');
assertEquals(m.has('jkl;'), true);
assertEquals(m.get('jkl;'), 'key 2');
assertEquals(m.getLength(), 2);
var it = m.entries();
assertElementsEquals(it.next().value, ['asdf', 'hello world']);
assertElementsEquals(it.next().value, ['jkl;', 'key 2']);
assertEquals(it.next().done, true);
checkMapEquals(m, [
['asdf', 'hello world'],
['jkl;', 'key 2']
]);
m.del('jkl;');
assertEquals(m.has('jkl;'), false);
assertEquals(m.get('jkl;'), undefined);
assertEquals(m.getLength(), 1);
it = m.keys();
assertEquals(it.next().value, 'asdf');
assertEquals(it.next().done, true);
it = m.values();
assertEquals(it.next().value, 'hello world');
assertEquals(it.next().done, true);
var count = 0;
m.forEach(function(value, key, map) {
assertEquals(map, m);
assertEquals(key, 'asdf');
assertEquals(value, 'hello world');
count++;
});
assertEquals(count, 1);
m.clear();
assertEquals(m.getLength(), 0);
});
/**
* Tests operations on maps with all key and value types.
*/
it('testAllMapTypes' + suffix, function() {
var msg = new msgInfo.constructor();
fillMapFields(msg);
checkMapFields(msg);
});
if (msgInfo.deserializeBinary) {
/**
* Tests serialization and deserialization in binary format.
*/
it('testBinaryFormat' + suffix, function() {
if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
// IE8/9 currently doesn't support binary format because they lack
// TypedArray.
return;
}
// Check that the format is correct.
var msg = new msgInfo.constructor();
msg.getMapStringStringMap().set('A', 'a');
var serialized = msg.serializeBinary();
var expectedSerialized = [
0x0a, 0x6, // field 1 (map_string_string), delimited, length 6
0x0a, 0x1, // field 1 in submessage (key), delimited, length 1
0x41, // ASCII 'A'
0x12, 0x1, // field 2 in submessage (value), delimited, length 1
0x61 // ASCII 'a'
];
assertEquals(serialized.length, expectedSerialized.length);
for (var i = 0; i < serialized.length; i++) {
assertEquals(serialized[i], expectedSerialized[i]);
}
// Check that all map fields successfully round-trip.
msg = new msgInfo.constructor();
fillMapFields(msg);
serialized = msg.serializeBinary();
var decoded = msgInfo.deserializeBinary(serialized);
checkMapFields(decoded);
});
}
/**
* Exercises the lazy map<->underlying array sync.
*/
it('testLazyMapSync' + suffix, function() {
// Start with a JSPB array containing a few map entries.
var entries = [
['a', 'entry 1'],
['c', 'entry 2'],
['b', 'entry 3']
];
var msg = new msgInfo.constructor([entries]);
assertEquals(entries.length, 3);
assertEquals(entries[0][0], 'a');
assertEquals(entries[1][0], 'c');
assertEquals(entries[2][0], 'b');
msg.getMapStringStringMap().del('a');
assertEquals(entries.length, 3); // not yet sync'd
msg.toArray(); // force a sync
assertEquals(entries.length, 2);
assertEquals(entries[0][0], 'b'); // now in sorted order
assertEquals(entries[1][0], 'c');
var a = msg.toArray();
assertEquals(a[0], entries); // retains original reference
});
}
describe('mapsTest', function() {
makeTests({
constructor: proto.jspb.test.TestMapFields,
deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary
}, proto.jspb.test.MapValueMessage, "_Binary");
makeTests({
constructor: proto.jspb.test.TestMapFieldsNoBinary,
deserializeBinary: null
}, proto.jspb.test.MapValueMessageNoBinary, "_NoBinary");
});

File diff suppressed because it is too large Load Diff

@ -0,0 +1,329 @@
// 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.
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');
var BYTES = new Uint8Array([1, 2, 8, 9]);
var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
/**
* Helper: compare a bytes field to an expected value
* @param {Uint8Array|string} arr
* @param {Uint8Array} expected
* @return {boolean}
*/
function bytesCompare(arr, expected) {
if (goog.isString(arr)) {
arr = goog.crypt.base64.decodeStringToUint8Array(arr);
}
if (arr.length != expected.length) {
return false;
}
for (var i = 0; i < arr.length; i++) {
if (arr[i] != expected[i]) {
return false;
}
}
return true;
}
describe('proto3Test', function() {
/**
* Test defaults for proto3 message fields.
*/
it('testProto3FieldDefaults', function() {
var msg = new proto.jspb.test.TestProto3();
assertEquals(msg.getOptionalInt32(), 0);
assertEquals(msg.getOptionalInt64(), 0);
assertEquals(msg.getOptionalUint32(), 0);
assertEquals(msg.getOptionalUint64(), 0);
assertEquals(msg.getOptionalSint32(), 0);
assertEquals(msg.getOptionalSint64(), 0);
assertEquals(msg.getOptionalFixed32(), 0);
assertEquals(msg.getOptionalFixed64(), 0);
assertEquals(msg.getOptionalSfixed32(), 0);
assertEquals(msg.getOptionalSfixed64(), 0);
assertEquals(msg.getOptionalFloat(), 0);
assertEquals(msg.getOptionalDouble(), 0);
assertEquals(msg.getOptionalString(), '');
// TODO(b/26173701): when we change bytes fields default getter to return
// Uint8Array, we'll want to switch this assertion to match the u8 case.
assertEquals(typeof msg.getOptionalBytes(), 'string');
assertEquals(msg.getOptionalBytes_asU8() instanceof Uint8Array, true);
assertEquals(typeof msg.getOptionalBytes_asB64(), 'string');
assertEquals(msg.getOptionalBytes().length, 0);
assertEquals(msg.getOptionalBytes_asU8().length, 0);
assertEquals(msg.getOptionalBytes_asB64(), '');
assertEquals(msg.getOptionalForeignEnum(),
proto.jspb.test.Proto3Enum.PROTO3_FOO);
assertEquals(msg.getOptionalForeignMessage(), undefined);
assertEquals(msg.getOptionalForeignMessage(), undefined);
assertEquals(msg.getRepeatedInt32List().length, 0);
assertEquals(msg.getRepeatedInt64List().length, 0);
assertEquals(msg.getRepeatedUint32List().length, 0);
assertEquals(msg.getRepeatedUint64List().length, 0);
assertEquals(msg.getRepeatedSint32List().length, 0);
assertEquals(msg.getRepeatedSint64List().length, 0);
assertEquals(msg.getRepeatedFixed32List().length, 0);
assertEquals(msg.getRepeatedFixed64List().length, 0);
assertEquals(msg.getRepeatedSfixed32List().length, 0);
assertEquals(msg.getRepeatedSfixed64List().length, 0);
assertEquals(msg.getRepeatedFloatList().length, 0);
assertEquals(msg.getRepeatedDoubleList().length, 0);
assertEquals(msg.getRepeatedStringList().length, 0);
assertEquals(msg.getRepeatedBytesList().length, 0);
assertEquals(msg.getRepeatedForeignEnumList().length, 0);
assertEquals(msg.getRepeatedForeignMessageList().length, 0);
});
/**
* Test that all fields can be set and read via a serialization roundtrip.
*/
it('testProto3FieldSetGet', function() {
var msg = new proto.jspb.test.TestProto3();
msg.setOptionalInt32(-42);
msg.setOptionalInt64(-0x7fffffff00000000);
msg.setOptionalUint32(0x80000000);
msg.setOptionalUint64(0xf000000000000000);
msg.setOptionalSint32(-100);
msg.setOptionalSint64(-0x8000000000000000);
msg.setOptionalFixed32(1234);
msg.setOptionalFixed64(0x1234567800000000);
msg.setOptionalSfixed32(-1234);
msg.setOptionalSfixed64(-0x1234567800000000);
msg.setOptionalFloat(1.5);
msg.setOptionalDouble(-1.5);
msg.setOptionalBool(true);
msg.setOptionalString('hello world');
msg.setOptionalBytes(BYTES);
var submsg = new proto.jspb.test.ForeignMessage();
submsg.setC(16);
msg.setOptionalForeignMessage(submsg);
msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
msg.setRepeatedInt32List([-42]);
msg.setRepeatedInt64List([-0x7fffffff00000000]);
msg.setRepeatedUint32List([0x80000000]);
msg.setRepeatedUint64List([0xf000000000000000]);
msg.setRepeatedSint32List([-100]);
msg.setRepeatedSint64List([-0x8000000000000000]);
msg.setRepeatedFixed32List([1234]);
msg.setRepeatedFixed64List([0x1234567800000000]);
msg.setRepeatedSfixed32List([-1234]);
msg.setRepeatedSfixed64List([-0x1234567800000000]);
msg.setRepeatedFloatList([1.5]);
msg.setRepeatedDoubleList([-1.5]);
msg.setRepeatedBoolList([true]);
msg.setRepeatedStringList(['hello world']);
msg.setRepeatedBytesList([BYTES]);
submsg = new proto.jspb.test.ForeignMessage();
submsg.setC(1000);
msg.setRepeatedForeignMessageList([submsg]);
msg.setRepeatedForeignEnumList([proto.jspb.test.Proto3Enum.PROTO3_BAR]);
msg.setOneofString('asdf');
var serialized = msg.serializeBinary();
msg = proto.jspb.test.TestProto3.deserializeBinary(serialized);
assertEquals(msg.getOptionalInt32(), -42);
assertEquals(msg.getOptionalInt64(), -0x7fffffff00000000);
assertEquals(msg.getOptionalUint32(), 0x80000000);
assertEquals(msg.getOptionalUint64(), 0xf000000000000000);
assertEquals(msg.getOptionalSint32(), -100);
assertEquals(msg.getOptionalSint64(), -0x8000000000000000);
assertEquals(msg.getOptionalFixed32(), 1234);
assertEquals(msg.getOptionalFixed64(), 0x1234567800000000);
assertEquals(msg.getOptionalSfixed32(), -1234);
assertEquals(msg.getOptionalSfixed64(), -0x1234567800000000);
assertEquals(msg.getOptionalFloat(), 1.5);
assertEquals(msg.getOptionalDouble(), -1.5);
assertEquals(msg.getOptionalBool(), true);
assertEquals(msg.getOptionalString(), 'hello world');
assertEquals(true, bytesCompare(msg.getOptionalBytes(), BYTES));
assertEquals(msg.getOptionalForeignMessage().getC(), 16);
assertEquals(msg.getOptionalForeignEnum(),
proto.jspb.test.Proto3Enum.PROTO3_BAR);
assertElementsEquals(msg.getRepeatedInt32List(), [-42]);
assertElementsEquals(msg.getRepeatedInt64List(), [-0x7fffffff00000000]);
assertElementsEquals(msg.getRepeatedUint32List(), [0x80000000]);
assertElementsEquals(msg.getRepeatedUint64List(), [0xf000000000000000]);
assertElementsEquals(msg.getRepeatedSint32List(), [-100]);
assertElementsEquals(msg.getRepeatedSint64List(), [-0x8000000000000000]);
assertElementsEquals(msg.getRepeatedFixed32List(), [1234]);
assertElementsEquals(msg.getRepeatedFixed64List(), [0x1234567800000000]);
assertElementsEquals(msg.getRepeatedSfixed32List(), [-1234]);
assertElementsEquals(msg.getRepeatedSfixed64List(), [-0x1234567800000000]);
assertElementsEquals(msg.getRepeatedFloatList(), [1.5]);
assertElementsEquals(msg.getRepeatedDoubleList(), [-1.5]);
assertElementsEquals(msg.getRepeatedBoolList(), [true]);
assertElementsEquals(msg.getRepeatedStringList(), ['hello world']);
assertEquals(msg.getRepeatedBytesList().length, 1);
assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
assertEquals(msg.getRepeatedForeignMessageList().length, 1);
assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000);
assertElementsEquals(msg.getRepeatedForeignEnumList(),
[proto.jspb.test.Proto3Enum.PROTO3_BAR]);
assertEquals(msg.getOneofString(), 'asdf');
});
/**
* Test that oneofs continue to have a notion of field presence.
*/
it('testOneofs', function() {
var msg = new proto.jspb.test.TestProto3();
assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined);
assertEquals(msg.getOneofString(), '');
assertEquals(msg.getOneofBytes(), '');
assertFalse(msg.hasOneofUint32());
assertFalse(msg.hasOneofString());
assertFalse(msg.hasOneofBytes());
msg.setOneofUint32(42);
assertEquals(msg.getOneofUint32(), 42);
assertEquals(msg.getOneofForeignMessage(), undefined);
assertEquals(msg.getOneofString(), '');
assertEquals(msg.getOneofBytes(), '');
assertTrue(msg.hasOneofUint32());
assertFalse(msg.hasOneofString());
assertFalse(msg.hasOneofBytes());
var submsg = new proto.jspb.test.ForeignMessage();
msg.setOneofForeignMessage(submsg);
assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), submsg);
assertEquals(msg.getOneofString(), '');
assertEquals(msg.getOneofBytes(), '');
assertFalse(msg.hasOneofUint32());
assertFalse(msg.hasOneofString());
assertFalse(msg.hasOneofBytes());
msg.setOneofString('hello');
assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined);
assertEquals(msg.getOneofString(), 'hello');
assertEquals(msg.getOneofBytes(), '');
assertFalse(msg.hasOneofUint32());
assertTrue(msg.hasOneofString());
assertFalse(msg.hasOneofBytes());
msg.setOneofBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
assertEquals(msg.getOneofUint32(), 0);
assertEquals(msg.getOneofForeignMessage(), undefined);
assertEquals(msg.getOneofString(), '');
assertEquals(msg.getOneofBytes_asB64(),
goog.crypt.base64.encodeString('\u00FF\u00FF'));
assertFalse(msg.hasOneofUint32());
assertFalse(msg.hasOneofString());
assertTrue(msg.hasOneofBytes());
});
/**
* Test that "default"-valued primitive fields are not emitted on the wire.
*/
it('testNoSerializeDefaults', function() {
var msg = new proto.jspb.test.TestProto3();
// Set each primitive to a non-default value, then back to its default, to
// ensure that the serialization is actually checking the value and not just
// whether it has ever been set.
msg.setOptionalInt32(42);
msg.setOptionalInt32(0);
msg.setOptionalDouble(3.14);
msg.setOptionalDouble(0.0);
msg.setOptionalBool(true);
msg.setOptionalBool(false);
msg.setOptionalString('hello world');
msg.setOptionalString('');
msg.setOptionalBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
msg.setOptionalBytes('');
msg.setOptionalForeignMessage(new proto.jspb.test.ForeignMessage());
msg.setOptionalForeignMessage(null);
msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO);
msg.setOneofUint32(32);
msg.clearOneofUint32();
var serialized = msg.serializeBinary();
assertEquals(0, serialized.length);
});
/**
* Test that base64 string and Uint8Array are interchangeable in bytes fields.
*/
it('testBytesFieldsInterop', function() {
var msg = new proto.jspb.test.TestProto3();
// Set as a base64 string and check all the getters work.
msg.setOptionalBytes(BYTES_B64);
assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
// Test binary serialize round trip doesn't break it.
msg = proto.jspb.test.TestProto3.deserializeBinary(msg.serializeBinary());
assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
msg = new proto.jspb.test.TestProto3();
// Set as a Uint8Array and check all the getters work.
msg.setOptionalBytes(BYTES);
assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
});
});

@ -0,0 +1,89 @@
// 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 = "proto3";
import "testbinary.proto";
package jspb.test;
message TestProto3 {
int32 optional_int32 = 1;
int64 optional_int64 = 2;
uint32 optional_uint32 = 3;
uint64 optional_uint64 = 4;
sint32 optional_sint32 = 5;
sint64 optional_sint64 = 6;
fixed32 optional_fixed32 = 7;
fixed64 optional_fixed64 = 8;
sfixed32 optional_sfixed32 = 9;
sfixed64 optional_sfixed64 = 10;
float optional_float = 11;
double optional_double = 12;
bool optional_bool = 13;
string optional_string = 14;
bytes optional_bytes = 15;
ForeignMessage optional_foreign_message = 19;
Proto3Enum optional_foreign_enum = 22;
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
repeated uint32 repeated_uint32 = 33;
repeated uint64 repeated_uint64 = 34;
repeated sint32 repeated_sint32 = 35;
repeated sint64 repeated_sint64 = 36;
repeated fixed32 repeated_fixed32 = 37;
repeated fixed64 repeated_fixed64 = 38;
repeated sfixed32 repeated_sfixed32 = 39;
repeated sfixed64 repeated_sfixed64 = 40;
repeated float repeated_float = 41;
repeated double repeated_double = 42;
repeated bool repeated_bool = 43;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated ForeignMessage repeated_foreign_message = 49;
repeated Proto3Enum repeated_foreign_enum = 52;
oneof oneof_field {
uint32 oneof_uint32 = 111;
ForeignMessage oneof_foreign_message = 112;
string oneof_string = 113;
bytes oneof_bytes = 114;
}
}
enum Proto3Enum {
PROTO3_FOO = 0;
PROTO3_BAR = 1;
PROTO3_BAZ = 2;
}

@ -0,0 +1,262 @@
// 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.
// Author: mwr@google.com (Mark Rawling)
syntax = "proto2";
option java_package = "com.google.apps.jspb.proto";
option java_multiple_files = true;
import "google/protobuf/descriptor.proto";
package jspb.test;
message Empty {
}
enum OuterEnum {
FOO = 1;
BAR = 2;
}
message EnumContainer {
optional OuterEnum outer_enum = 1;
}
message Simple1 {
required string a_string = 1;
repeated string a_repeated_string = 2;
optional bool a_boolean = 3;
}
// A message that differs from Simple1 only by name
message Simple2 {
required string a_string = 1;
repeated string a_repeated_string = 2;
}
message SpecialCases {
required string normal = 1;
// Examples of Js reserved names that are converted to pb_<name>.
required string default = 2;
required string function = 3;
required string var = 4;
}
message OptionalFields {
message Nested {
optional int32 an_int = 1;
}
optional string a_string = 1;
required bool a_bool = 2;
optional Nested a_nested_message = 3;
repeated Nested a_repeated_message = 4;
repeated string a_repeated_string = 5;
}
message HasExtensions {
optional string str1 = 1;
optional string str2 = 2;
optional string str3 = 3;
extensions 10 to max;
}
message Complex {
message Nested {
required int32 an_int = 2;
}
required string a_string = 1;
required bool an_out_of_order_bool = 9;
optional Nested a_nested_message = 4;
repeated Nested a_repeated_message = 5;
repeated string a_repeated_string = 7;
}
message OuterMessage {
// Make sure this doesn't conflict with the other Complex message.
message Complex {
optional int32 inner_complex_field = 1;
}
}
message IsExtension {
extend HasExtensions {
optional IsExtension ext_field = 100;
}
optional string ext1 = 1;
// Extensions of proto2 Descriptor messages will be ignored.
extend google.protobuf.EnumOptions {
optional string simple_option = 42113038;
}
}
message IndirectExtension {
extend HasExtensions {
optional Simple1 simple = 101;
optional string str = 102;
repeated string repeated_str = 103;
repeated Simple1 repeated_simple = 104;
}
}
extend HasExtensions {
optional Simple1 simple1 = 105;
}
message DefaultValues {
enum Enum {
E1 = 13;
E2 = 77;
}
optional string string_field = 1 [default="default<>\'\"abc"];
optional bool bool_field = 2 [default=true];
optional int64 int_field = 3 [default=11];
optional Enum enum_field = 4 [default=E1];
optional string empty_field = 6 [default=""];
optional bytes bytes_field = 8 [default="moo"]; // Base64 encoding is "bW9v"
}
message FloatingPointFields {
optional float optional_float_field = 1;
required float required_float_field = 2;
repeated float repeated_float_field = 3;
optional float default_float_field = 4 [default = 2.0];
optional double optional_double_field = 5;
required double required_double_field = 6;
repeated double repeated_double_field = 7;
optional double default_double_field = 8 [default = 2.0];
}
message TestClone {
optional string str = 1;
optional Simple1 simple1 = 3;
repeated Simple1 simple2 = 5;
optional bytes bytes_field = 6;
optional string unused = 7;
extensions 10 to max;
}
message CloneExtension {
extend TestClone {
optional CloneExtension ext_field = 100;
}
optional string ext = 2;
}
message TestGroup {
repeated group RepeatedGroup = 1 {
required string id = 1;
repeated bool some_bool = 2;
}
required group RequiredGroup = 2 {
required string id = 1;
}
optional group OptionalGroup = 3 {
required string id = 1;
}
optional string id = 4;
required Simple2 required_simple = 5;
optional Simple2 optional_simple = 6;
}
message TestGroup1 {
optional TestGroup.RepeatedGroup group = 1;
}
message TestReservedNames {
optional int32 extension = 1;
extensions 10 to max;
}
message TestReservedNamesExtension {
extend TestReservedNames {
optional int32 foo = 10;
}
}
message TestMessageWithOneof {
oneof partial_oneof {
string pone = 3;
string pthree = 5;
}
oneof recursive_oneof {
TestMessageWithOneof rone = 6;
string rtwo = 7;
}
optional bool normal_field = 8;
repeated string repeated_field = 9;
oneof default_oneof_a {
int32 aone = 10 [default = 1234];
int32 atwo = 11;
}
oneof default_oneof_b {
int32 bone = 12;
int32 btwo = 13 [default = 1234];
}
}
message TestEndsWithBytes {
optional int32 value = 1;
optional bytes data = 2;
}
message TestMapFieldsNoBinary {
map<string, string> map_string_string = 1;
map<string, int32> map_string_int32 = 2;
map<string, int64> map_string_int64 = 3;
map<string, bool> map_string_bool = 4;
map<string, double> map_string_double = 5;
map<string, MapValueEnumNoBinary> map_string_enum = 6;
map<string, MapValueMessageNoBinary> map_string_msg = 7;
map<int32, string> map_int32_string = 8;
map<int64, string> map_int64_string = 9;
map<bool, string> map_bool_string = 10;
optional TestMapFieldsNoBinary test_map_fields = 11;
map<string, TestMapFieldsNoBinary> map_string_testmapfields = 12;
}
enum MapValueEnumNoBinary {
MAP_VALUE_FOO_NOBINARY = 0;
MAP_VALUE_BAR_NOBINARY = 1;
MAP_VALUE_BAZ_NOBINARY = 2;
}
message MapValueMessageNoBinary {
optional int32 foo = 1;
}

@ -0,0 +1,54 @@
// 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";
option java_package = "com.google.apps.jspb.proto";
option java_multiple_files = true;
package jspb.test;
message TestExtensionsMessage {
optional int32 intfield = 1;
extensions 100 to max;
}
message ExtensionMessage {
extend TestExtensionsMessage {
optional ExtensionMessage ext_field = 100;
}
optional string ext1 = 1;
}
// Floating extensions are only supported when generating a _lib.js library.
extend TestExtensionsMessage {
optional ExtensionMessage floating_msg_field = 101;
optional string floating_str_field = 102;
}

@ -0,0 +1,53 @@
// 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";
option java_package = "com.google.apps.jspb.proto";
option java_multiple_files = true;
package jspb.exttest;
message TestExtensionsMessage {
optional int32 intfield = 1;
extensions 100 to max;
}
message ExtensionMessage {
extend TestExtensionsMessage {
optional ExtensionMessage ext_field = 100;
}
optional string ext1 = 1;
}
extend TestExtensionsMessage {
optional ExtensionMessage floating_msg_field = 101;
optional string floating_str_field = 102;
}

@ -0,0 +1,42 @@
// 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";
option java_package = "com.google.apps.jspb.proto";
option java_multiple_files = true;
package jspb.exttest;
import "test3.proto";
extend TestExtensionsMessage {
optional ExtensionMessage floating_msg_field_two = 103;
}

@ -0,0 +1,44 @@
// 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";
option java_package = "com.google.apps.jspb.proto";
option java_multiple_files = true;
package jspb.exttest.beta;
message TestBetaExtensionsMessage {
extensions 100 to max;
}
extend TestBetaExtensionsMessage {
optional string floating_str_field = 101;
}

@ -0,0 +1,212 @@
// 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.
// LINT: ALLOW_GROUPS
syntax = "proto2";
package jspb.test;
// These types are borrowed from `unittest.proto` in the protobuf tree. We want
// to ensure that the binary-format support will handle all field types
// properly.
message TestAllTypes {
optional int32 optional_int32 = 1;
optional int64 optional_int64 = 2;
optional uint32 optional_uint32 = 3;
optional uint64 optional_uint64 = 4;
optional sint32 optional_sint32 = 5;
optional sint64 optional_sint64 = 6;
optional fixed32 optional_fixed32 = 7;
optional fixed64 optional_fixed64 = 8;
optional sfixed32 optional_sfixed32 = 9;
optional sfixed64 optional_sfixed64 = 10;
optional float optional_float = 11;
optional double optional_double = 12;
optional bool optional_bool = 13;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional group OptionalGroup = 16 {
optional int32 a = 17;
}
optional ForeignMessage optional_foreign_message = 19;
optional ForeignEnum optional_foreign_enum = 22;
// Repeated
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
repeated uint32 repeated_uint32 = 33;
repeated uint64 repeated_uint64 = 34;
repeated sint32 repeated_sint32 = 35;
repeated sint64 repeated_sint64 = 36;
repeated fixed32 repeated_fixed32 = 37;
repeated fixed64 repeated_fixed64 = 38;
repeated sfixed32 repeated_sfixed32 = 39;
repeated sfixed64 repeated_sfixed64 = 40;
repeated float repeated_float = 41;
repeated double repeated_double = 42;
repeated bool repeated_bool = 43;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated group RepeatedGroup = 46 {
optional int32 a = 47;
}
repeated ForeignMessage repeated_foreign_message = 49;
repeated ForeignEnum repeated_foreign_enum = 52;
// Packed repeated
repeated int32 packed_repeated_int32 = 61 [packed=true];
repeated int64 packed_repeated_int64 = 62 [packed=true];
repeated uint32 packed_repeated_uint32 = 63 [packed=true];
repeated uint64 packed_repeated_uint64 = 64 [packed=true];
repeated sint32 packed_repeated_sint32 = 65 [packed=true];
repeated sint64 packed_repeated_sint64 = 66 [packed=true];
repeated fixed32 packed_repeated_fixed32 = 67 [packed=true];
repeated fixed64 packed_repeated_fixed64 = 68 [packed=true];
repeated sfixed32 packed_repeated_sfixed32 = 69 [packed=true];
repeated sfixed64 packed_repeated_sfixed64 = 70 [packed=true];
repeated float packed_repeated_float = 71 [packed=true];
repeated double packed_repeated_double = 72 [packed=true];
repeated bool packed_repeated_bool = 73 [packed=true];
oneof oneof_field {
uint32 oneof_uint32 = 111;
ForeignMessage oneof_foreign_message = 112;
string oneof_string = 113;
bytes oneof_bytes = 114;
}
}
message ForeignMessage {
optional int32 c = 1;
}
enum ForeignEnum {
FOREIGN_FOO = 4;
FOREIGN_BAR = 5;
FOREIGN_BAZ = 6;
}
message TestExtendable {
extensions 1 to max;
}
message ExtendsWithMessage {
extend TestExtendable {
optional ExtendsWithMessage optional_extension = 19;
repeated ExtendsWithMessage repeated_extension = 49;
}
optional int32 foo = 1;
}
extend TestExtendable {
optional int32 extend_optional_int32 = 1;
optional int64 extend_optional_int64 = 2;
optional uint32 extend_optional_uint32 = 3;
optional uint64 extend_optional_uint64 = 4;
optional sint32 extend_optional_sint32 = 5;
optional sint64 extend_optional_sint64 = 6;
optional fixed32 extend_optional_fixed32 = 7;
optional fixed64 extend_optional_fixed64 = 8;
optional sfixed32 extend_optional_sfixed32 = 9;
optional sfixed64 extend_optional_sfixed64 = 10;
optional float extend_optional_float = 11;
optional double extend_optional_double = 12;
optional bool extend_optional_bool = 13;
optional string extend_optional_string = 14;
optional bytes extend_optional_bytes = 15;
optional ForeignEnum extend_optional_foreign_enum = 22;
repeated int32 extend_repeated_int32 = 31;
repeated int64 extend_repeated_int64 = 32;
repeated uint32 extend_repeated_uint32 = 33;
repeated uint64 extend_repeated_uint64 = 34;
repeated sint32 extend_repeated_sint32 = 35;
repeated sint64 extend_repeated_sint64 = 36;
repeated fixed32 extend_repeated_fixed32 = 37;
repeated fixed64 extend_repeated_fixed64 = 38;
repeated sfixed32 extend_repeated_sfixed32 = 39;
repeated sfixed64 extend_repeated_sfixed64 = 40;
repeated float extend_repeated_float = 41;
repeated double extend_repeated_double = 42;
repeated bool extend_repeated_bool = 43;
repeated string extend_repeated_string = 44;
repeated bytes extend_repeated_bytes = 45;
repeated ForeignEnum extend_repeated_foreign_enum = 52;
repeated int32 extend_packed_repeated_int32 = 61 [packed=true];
repeated int64 extend_packed_repeated_int64 = 62 [packed=true];
repeated uint32 extend_packed_repeated_uint32 = 63 [packed=true];
repeated uint64 extend_packed_repeated_uint64 = 64 [packed=true];
repeated sint32 extend_packed_repeated_sint32 = 65 [packed=true];
repeated sint64 extend_packed_repeated_sint64 = 66 [packed=true];
repeated fixed32 extend_packed_repeated_fixed32 = 67 [packed=true];
repeated fixed64 extend_packed_repeated_fixed64 = 68 [packed=true];
repeated sfixed32 extend_packed_repeated_sfixed32 = 69 [packed=true];
repeated sfixed64 extend_packed_repeated_sfixed64 = 70 [packed=true];
repeated float extend_packed_repeated_float = 71 [packed=true];
repeated double extend_packed_repeated_double = 72 [packed=true];
repeated bool extend_packed_repeated_bool = 73 [packed=true];
repeated ForeignEnum extend_packed_repeated_foreign_enum = 82
[packed=true];
}
message TestMapFields {
map<string, string> map_string_string = 1;
map<string, int32> map_string_int32 = 2;
map<string, int64> map_string_int64 = 3;
map<string, bool> map_string_bool = 4;
map<string, double> map_string_double = 5;
map<string, MapValueEnum> map_string_enum = 6;
map<string, MapValueMessage> map_string_msg = 7;
map<int32, string> map_int32_string = 8;
map<int64, string> map_int64_string = 9;
map<bool, string> map_bool_string = 10;
optional TestMapFields test_map_fields = 11;
map<string, TestMapFields> map_string_testmapfields = 12;
}
enum MapValueEnum {
MAP_VALUE_FOO = 0;
MAP_VALUE_BAR = 1;
MAP_VALUE_BAZ = 2;
}
message MapValueMessage {
optional int32 foo = 1;
}

@ -0,0 +1,34 @@
// 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 javatests.com.google.apps.jspb;

@ -41,7 +41,6 @@ goog.provide('jspb.Message');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.crypt.base64');
goog.require('goog.json');
goog.require('jspb.Map');
// Not needed in compilation units that have no protos with xids.
@ -192,8 +191,8 @@ goog.define('jspb.Message.GENERATE_FROM_OBJECT', !goog.DISALLOW_TEST_ONLY_CODE);
/**
* @define {boolean} Whether to generate toString methods for objects. Turn
* this off if you do use toString in your project and want to trim it from
* compiled JS.
* this off if you do not use toString in your project and want to trim it
* from the compiled JS.
*/
goog.define('jspb.Message.GENERATE_TO_STRING', true);
@ -351,7 +350,7 @@ jspb.Message.initialize = function(
// which would otherwise go unused.
msg.arrayIndexOffset_ = messageId === 0 ? -1 : 0;
msg.array = data;
jspb.Message.materializeExtensionObject_(msg, suggestedPivot);
jspb.Message.initPivotAndExtensionObject_(msg, suggestedPivot);
msg.convertedFloatingPointFields_ = {};
if (repeatedFields) {
@ -364,6 +363,7 @@ jspb.Message.initialize = function(
jspb.Message.EMPTY_LIST_SENTINEL_ :
[]);
} else {
jspb.Message.maybeInitEmptyExtensionObject_(msg);
msg.extensionObject_[fieldNumber] =
msg.extensionObject_[fieldNumber] ||
(jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ?
@ -408,17 +408,16 @@ jspb.Message.isArray_ = function(o) {
/**
* Ensures that the array contains an extension object if necessary.
* If the array contains an extension object in its last position, then the
* object is kept in place and its position is used as the pivot. If not, then
* create an extension object using suggestedPivot. If suggestedPivot is -1,
* we don't have an extension object at all, in which case all fields are stored
* in the array.
* object is kept in place and its position is used as the pivot. If not,
* decides the pivot of the message based on suggestedPivot without
* materializing the extension object.
*
* @param {!jspb.Message} msg The JsPb proto to modify.
* @param {number} suggestedPivot See description for initialize().
* @private
*/
jspb.Message.materializeExtensionObject_ = function(msg, suggestedPivot) {
jspb.Message.initPivotAndExtensionObject_ = function(msg, suggestedPivot) {
if (msg.array.length) {
var foundIndex = msg.array.length - 1;
var obj = msg.array[foundIndex];
@ -434,26 +433,17 @@ jspb.Message.materializeExtensionObject_ = function(msg, suggestedPivot) {
return;
}
}
// This complexity exists because we keep all extension fields in the
// extensionObject_ regardless of proto field number. Changing this would
// simplify the code here, but it would require changing the serialization
// format from the server, which is not backwards compatible.
// TODO(jshneier): Should we just treat extension fields the same as
// non-extension fields, and select whether they appear in the object or in
// the array purely based on tag number? This would allow simplifying all the
// get/setExtension logic, but it would require the breaking change described
// above.
if (suggestedPivot > -1) {
msg.pivot_ = suggestedPivot;
var pivotIndex = jspb.Message.getIndex_(msg, suggestedPivot);
if (!jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
msg.extensionObject_ = msg.array[pivotIndex] = {};
} else {
// Initialize to null to avoid changing the shape of the proto when it
// gets eventually set.
msg.extensionObject_ = null;
}
// Avoid changing the shape of the proto with an empty extension object by
// deferring the materialization of the extension object until the first
// time a field set into it (may be due to getting a repeated proto field
// from it, in which case a new empty array is set into it at first).
msg.extensionObject_ = null;
} else {
// suggestedPivot is -1, which means that we don't have an extension object
// at all, in which case all fields are stored in the array.
msg.pivot_ = Number.MAX_VALUE;
}
};
@ -513,7 +503,7 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions,
for (var fieldNumber in extensions) {
var fieldInfo = extensions[fieldNumber];
var value = getExtensionFn.call(proto, fieldInfo);
if (goog.isDefAndNotNull(value)) {
if (value != null) {
for (var name in fieldInfo.fieldName) {
if (fieldInfo.fieldName.hasOwnProperty(name)) {
break; // the compiled field name
@ -557,7 +547,7 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
'without binary serialization support');
}
var value = getExtensionFn.call(proto, fieldInfo);
if (goog.isDefAndNotNull(value)) {
if (value != null) {
if (fieldInfo.isMessageType()) {
// If the message type of the extension was generated without binary
// support, there may not be a binary message serializer function, and
@ -647,6 +637,9 @@ jspb.Message.getField = function(msg, fieldNumber) {
}
return val;
} else {
if (!msg.extensionObject_) {
return undefined;
}
var val = msg.extensionObject_[fieldNumber];
if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
return msg.extensionObject_[fieldNumber] = [];
@ -656,6 +649,32 @@ jspb.Message.getField = function(msg, fieldNumber) {
};
/**
* Gets the value of a non-extension repeated field.
* @param {!jspb.Message} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @return {!Array}
* The field's value.
* @protected
*/
jspb.Message.getRepeatedField = function(msg, fieldNumber) {
if (fieldNumber < msg.pivot_) {
var index = jspb.Message.getIndex_(msg, fieldNumber);
var val = msg.array[index];
if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
return msg.array[index] = [];
}
return val;
}
var val = msg.extensionObject_[fieldNumber];
if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
return msg.extensionObject_[fieldNumber] = [];
}
return val;
};
/**
* Gets the value of an optional float or double field.
* @param {!jspb.Message} msg A jspb proto.
@ -678,7 +697,7 @@ jspb.Message.getOptionalFloatingPointField = function(msg, fieldNumber) {
* @protected
*/
jspb.Message.getRepeatedFloatingPointField = function(msg, fieldNumber) {
var values = jspb.Message.getField(msg, fieldNumber);
var values = jspb.Message.getRepeatedField(msg, fieldNumber);
if (!msg.convertedFloatingPointFields_) {
msg.convertedFloatingPointFields_ = {};
}
@ -864,6 +883,7 @@ jspb.Message.setField = function(msg, fieldNumber, value) {
if (fieldNumber < msg.pivot_) {
msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = value;
} else {
jspb.Message.maybeInitEmptyExtensionObject_(msg);
msg.extensionObject_[fieldNumber] = value;
}
};
@ -878,7 +898,7 @@ jspb.Message.setField = function(msg, fieldNumber, value) {
* @protected
*/
jspb.Message.addToRepeatedField = function(msg, fieldNumber, value, opt_index) {
var arr = jspb.Message.getField(msg, fieldNumber);
var arr = jspb.Message.getRepeatedField(msg, fieldNumber);
if (opt_index != undefined) {
arr.splice(opt_index, 0, value);
} else {
@ -1006,7 +1026,7 @@ jspb.Message.wrapRepeatedField_ = function(msg, ctor, fieldNumber) {
msg.wrappers_ = {};
}
if (!msg.wrappers_[fieldNumber]) {
var data = jspb.Message.getField(msg, fieldNumber);
var data = jspb.Message.getRepeatedField(msg, fieldNumber);
for (var wrappers = [], i = 0; i < data.length; i++) {
wrappers[i] = new ctor(data[i]);
}
@ -1101,7 +1121,7 @@ jspb.Message.addToRepeatedWrapperField = function(
wrapperArray = msg.wrappers_[fieldNumber] = [];
}
var insertedValue = value ? value : new ctor();
var array = jspb.Message.getField(msg, fieldNumber);
var array = jspb.Message.getRepeatedField(msg, fieldNumber);
if (index != undefined) {
wrapperArray.splice(index, 0, insertedValue);
array.splice(index, 0, insertedValue.toArray());

@ -33,6 +33,7 @@
goog.setTestOnly();
goog.require('goog.json');
goog.require('goog.string');
goog.require('goog.testing.asserts');
goog.require('goog.userAgent');
@ -64,11 +65,13 @@ goog.require('proto.jspb.test.floatingStrField');
goog.require('proto.jspb.test.HasExtensions');
goog.require('proto.jspb.test.IndirectExtension');
goog.require('proto.jspb.test.IsExtension');
goog.require('proto.jspb.test.MessageWithLargeFieldTags');
goog.require('proto.jspb.test.OptionalFields');
goog.require('proto.jspb.test.OuterEnum');
goog.require('proto.jspb.test.OuterMessage.Complex');
goog.require('proto.jspb.test.Simple1');
goog.require('proto.jspb.test.Simple2');
goog.require('proto.jspb.test.SingularsWithLargeFieldTags');
goog.require('proto.jspb.test.SpecialCases');
goog.require('proto.jspb.test.TestClone');
goog.require('proto.jspb.test.TestEndsWithBytes');
@ -83,8 +86,6 @@ goog.require('proto.jspb.test.ExtensionMessage');
goog.require('proto.jspb.test.TestExtensionsMessage');
describe('Message test suite', function() {
it('testEmptyProto', function() {
var empty1 = new proto.jspb.test.Empty([]);
@ -273,12 +274,6 @@ describe('Message test suite', function() {
assertFalse(response.hasEnumField());
});
it('testMessageRegistration', /** @suppress {visibility} */ function() {
// goog.require(SomeResponse) will include its library, which will in
// turn add SomeResponse to the message registry.
assertEquals(jspb.Message.registry_['res'], proto.jspb.test.SomeResponse);
});
it('testClearFields', function() {
var data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
var foo = new proto.jspb.test.OptionalFields(data);
@ -661,12 +656,7 @@ describe('Message test suite', function() {
it('testInitialization_emptyArray', function() {
var msg = new proto.jspb.test.HasExtensions([]);
if (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
assertArrayEquals([], msg.toArray());
} else {
// Extension object is created past all regular fields.
assertArrayEquals([,,, {}], msg.toArray());
}
assertArrayEquals([], msg.toArray());
});
it('testInitialization_justExtensionObject', function() {

@ -86,4 +86,5 @@ enum Proto3Enum {
PROTO3_FOO = 0;
PROTO3_BAR = 1;
PROTO3_BAZ = 2;
MSG_PROTO3_BAH = 3;
}

@ -235,6 +235,13 @@ message TestEndsWithBytes {
}
message Int64Types {
optional int64 int64_normal = 1 [jstype=JS_NORMAL];
optional sint64 int64_string = 2 [jstype=JS_STRING];
optional uint64 int64_number = 3 [jstype=JS_NUMBER];
}
message TestMapFieldsNoBinary {
map<string, string> map_string_string = 1;
@ -271,3 +278,4 @@ message Deeply {
}
}
}

@ -370,9 +370,8 @@ class TextFormatTest(unittest.TestCase):
def testMergeBadExtension(self):
message = unittest_pb2.TestAllExtensions()
text = '[unknown_extension]: 8\n'
self.assertRaisesWithMessage(
self.assertRaises(
text_format.ParseError,
'1:2 : Extension "unknown_extension" not registered.',
text_format.Merge, text, message)
message = unittest_pb2.TestAllTypes()
self.assertRaisesWithMessage(

@ -406,6 +406,8 @@ class FieldDescriptor(DescriptorBase):
containing_oneof: (OneofDescriptor) If the field is a member of a oneof
union, contains its descriptor. Otherwise, None.
file: (FileDescriptor) Reference to file descriptor.
"""
# Must be consistent with C++ FieldDescriptor::Type enum in
@ -490,7 +492,8 @@ class FieldDescriptor(DescriptorBase):
def __new__(cls, name, full_name, index, number, type, cpp_type, label,
default_value, message_type, enum_type, containing_type,
is_extension, extension_scope, options=None,
has_default_value=True, containing_oneof=None, json_name=None):
has_default_value=True, containing_oneof=None, json_name=None,
file=None):
_message.Message._CheckCalledFromGeneratedFile()
if is_extension:
return _message.default_pool.FindExtensionByName(full_name)
@ -500,7 +503,8 @@ class FieldDescriptor(DescriptorBase):
def __init__(self, name, full_name, index, number, type, cpp_type, label,
default_value, message_type, enum_type, containing_type,
is_extension, extension_scope, options=None,
has_default_value=True, containing_oneof=None, json_name=None):
has_default_value=True, containing_oneof=None, json_name=None,
file=None):
"""The arguments are as described in the description of FieldDescriptor
attributes above.
@ -511,6 +515,7 @@ class FieldDescriptor(DescriptorBase):
super(FieldDescriptor, self).__init__(options, 'FieldOptions')
self.name = name
self.full_name = full_name
self.file = file
self._camelcase_name = None
if json_name is None:
self.json_name = _ToJsonName(name)

@ -134,8 +134,7 @@ def _ExtractSymbols(desc_proto, package):
Yields:
The fully qualified name found in the descriptor.
"""
message_name = '.'.join((package, desc_proto.name))
message_name = package + '.' + desc_proto.name if package else desc_proto.name
yield message_name
for nested_type in desc_proto.nested_type:
for symbol in _ExtractSymbols(nested_type, message_name):

@ -257,7 +257,7 @@ class DescriptorPool(object):
self._AddFileDescriptor(file_desc)
# TODO(jieluo): This is a temporary solution for FieldDescriptor.file.
# Remove it when FieldDescriptor.file is added in code gen.
for extension in file_desc.extensions_by_name.values():
for extension in file_desc.extensions_by_name.itervalues():
self._file_desc_by_toplevel_extension[
extension.full_name] = file_desc
@ -328,6 +328,11 @@ class DescriptorPool(object):
except KeyError:
pass
try:
return self._service_descriptors[symbol].file
except KeyError:
pass
try:
return self._FindFileContainingSymbolInDb(symbol)
except KeyError:
@ -344,7 +349,6 @@ class DescriptorPool(object):
message = self.FindMessageTypeByName(message_name)
assert message.extensions_by_name[extension_name]
return message.file
except KeyError:
raise KeyError('Cannot find a file containing %s' % symbol)
@ -557,7 +561,8 @@ class DescriptorPool(object):
for index, extension_proto in enumerate(file_proto.extension):
extension_desc = self._MakeFieldDescriptor(
extension_proto, file_proto.package, index, is_extension=True)
extension_proto, file_proto.package, index, file_descriptor,
is_extension=True)
extension_desc.containing_type = self._GetTypeFromScope(
file_descriptor.package, extension_proto.extendee, scope)
self._SetFieldType(extension_proto, extension_desc,
@ -623,10 +628,10 @@ class DescriptorPool(object):
enums = [
self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
for enum in desc_proto.enum_type]
fields = [self._MakeFieldDescriptor(field, desc_name, index)
fields = [self._MakeFieldDescriptor(field, desc_name, index, file_desc)
for index, field in enumerate(desc_proto.field)]
extensions = [
self._MakeFieldDescriptor(extension, desc_name, index,
self._MakeFieldDescriptor(extension, desc_name, index, file_desc,
is_extension=True)
for index, extension in enumerate(desc_proto.extension)]
oneofs = [
@ -708,7 +713,7 @@ class DescriptorPool(object):
return desc
def _MakeFieldDescriptor(self, field_proto, message_name, index,
is_extension=False):
file_desc, is_extension=False):
"""Creates a field descriptor from a FieldDescriptorProto.
For message and enum type fields, this method will do a look up
@ -721,6 +726,7 @@ class DescriptorPool(object):
field_proto: The proto describing the field.
message_name: The name of the containing message.
index: Index of the field
file_desc: The file containing the field descriptor.
is_extension: Indication that this field is for an extension.
Returns:
@ -747,7 +753,8 @@ class DescriptorPool(object):
default_value=None,
is_extension=is_extension,
extension_scope=None,
options=_OptionsOrNone(field_proto))
options=_OptionsOrNone(field_proto),
file=file_desc)
def _SetAllFieldTypes(self, package, desc_proto, scope):
"""Sets all the descriptor's fields's types.

@ -100,6 +100,27 @@ if _implementation_version_str != '2':
_implementation_version = int(_implementation_version_str)
# Detect if serialization should be deterministic by default
try:
# The presence of this module in a build allows the proto implementation to
# be upgraded merely via build deps.
#
# NOTE: Merely importing this automatically enables deterministic proto
# serialization for C++ code, but we still need to export it as a boolean so
# that we can do the same for `_implementation_type == 'python'`.
#
# NOTE2: It is possible for C++ code to enable deterministic serialization by
# default _without_ affecting Python code, if the C++ implementation is not in
# use by this module. That is intended behavior, so we don't actually expose
# this boolean outside of this module.
#
# pylint: disable=g-import-not-at-top,unused-import
from google.protobuf import enable_deterministic_proto_serialization
_python_deterministic_proto_serialization = True
except ImportError:
_python_deterministic_proto_serialization = False
# Usage of this function is discouraged. Clients shouldn't care which
# implementation of the API is in use. Note that there is no guarantee
# that differences between APIs will be maintained.
@ -111,3 +132,8 @@ def Type():
# See comment on 'Type' above.
def Version():
return _implementation_version
# For internal use only
def IsPythonDefaultSerializationDeterministic():
return _python_deterministic_proto_serialization

@ -131,11 +131,19 @@ class DescriptorPoolTest(unittest.TestCase):
self.assertEqual('google/protobuf/internal/factory_test2.proto',
file_desc4.name)
file_desc5 = self.pool.FindFileContainingSymbol(
'protobuf_unittest.TestService')
self.assertIsInstance(file_desc5, descriptor.FileDescriptor)
self.assertEqual('google/protobuf/unittest.proto',
file_desc5.name)
# Tests the generated pool.
assert descriptor_pool.Default().FindFileContainingSymbol(
'google.protobuf.python.internal.Factory2Message.one_more_field')
assert descriptor_pool.Default().FindFileContainingSymbol(
'google.protobuf.python.internal.another_field')
assert descriptor_pool.Default().FindFileContainingSymbol(
'protobuf_unittest.TestService')
def testFindFileContainingSymbolFailure(self):
with self.assertRaises(KeyError):
@ -506,10 +514,10 @@ class MessageType(object):
subtype.CheckType(test, desc, name, file_desc)
for index, (name, field) in enumerate(self.field_list):
field.CheckField(test, desc, name, index)
field.CheckField(test, desc, name, index, file_desc)
for index, (name, field) in enumerate(self.extensions):
field.CheckField(test, desc, name, index)
field.CheckField(test, desc, name, index, file_desc)
class EnumField(object):
@ -519,7 +527,7 @@ class EnumField(object):
self.type_name = type_name
self.default_value = default_value
def CheckField(self, test, msg_desc, name, index):
def CheckField(self, test, msg_desc, name, index, file_desc):
field_desc = msg_desc.fields_by_name[name]
enum_desc = msg_desc.enum_types_by_name[self.type_name]
test.assertEqual(name, field_desc.name)
@ -536,6 +544,7 @@ class EnumField(object):
test.assertFalse(enum_desc.values_by_name[self.default_value].has_options)
test.assertEqual(msg_desc, field_desc.containing_type)
test.assertEqual(enum_desc, field_desc.enum_type)
test.assertEqual(file_desc, enum_desc.file)
class MessageField(object):
@ -544,7 +553,7 @@ class MessageField(object):
self.number = number
self.type_name = type_name
def CheckField(self, test, msg_desc, name, index):
def CheckField(self, test, msg_desc, name, index, file_desc):
field_desc = msg_desc.fields_by_name[name]
field_type_desc = msg_desc.nested_types_by_name[self.type_name]
test.assertEqual(name, field_desc.name)
@ -558,6 +567,7 @@ class MessageField(object):
test.assertFalse(field_desc.has_default_value)
test.assertEqual(msg_desc, field_desc.containing_type)
test.assertEqual(field_type_desc, field_desc.message_type)
test.assertEqual(file_desc, field_desc.file)
class StringField(object):
@ -566,7 +576,7 @@ class StringField(object):
self.number = number
self.default_value = default_value
def CheckField(self, test, msg_desc, name, index):
def CheckField(self, test, msg_desc, name, index, file_desc):
field_desc = msg_desc.fields_by_name[name]
test.assertEqual(name, field_desc.name)
expected_field_full_name = '.'.join([msg_desc.full_name, name])
@ -578,6 +588,7 @@ class StringField(object):
field_desc.cpp_type)
test.assertTrue(field_desc.has_default_value)
test.assertEqual(self.default_value, field_desc.default_value)
test.assertEqual(file_desc, field_desc.file)
class ExtensionField(object):
@ -586,7 +597,7 @@ class ExtensionField(object):
self.number = number
self.extended_type = extended_type
def CheckField(self, test, msg_desc, name, index):
def CheckField(self, test, msg_desc, name, index, file_desc):
field_desc = msg_desc.extensions_by_name[name]
test.assertEqual(name, field_desc.name)
expected_field_full_name = '.'.join([msg_desc.full_name, name])
@ -601,6 +612,7 @@ class ExtensionField(object):
test.assertEqual(msg_desc, field_desc.extension_scope)
test.assertEqual(msg_desc, field_desc.message_type)
test.assertEqual(self.extended_type, field_desc.containing_type.name)
test.assertEqual(file_desc, field_desc.file)
class AddDescriptorTest(unittest.TestCase):
@ -746,15 +758,10 @@ class AddDescriptorTest(unittest.TestCase):
self.assertIs(options, file_descriptor.GetOptions())
@unittest.skipIf(
api_implementation.Type() != 'cpp',
'default_pool is only supported by the C++ implementation')
class DefaultPoolTest(unittest.TestCase):
def testFindMethods(self):
# pylint: disable=g-import-not-at-top
from google.protobuf.pyext import _message
pool = _message.default_pool
pool = descriptor_pool.Default()
self.assertIs(
pool.FindFileByName('google/protobuf/unittest.proto'),
unittest_pb2.DESCRIPTOR)
@ -764,20 +771,23 @@ class DefaultPoolTest(unittest.TestCase):
self.assertIs(
pool.FindFieldByName('protobuf_unittest.TestAllTypes.optional_int32'),
unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optional_int32'])
self.assertIs(
pool.FindExtensionByName('protobuf_unittest.optional_int32_extension'),
unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension'])
self.assertIs(
pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'),
unittest_pb2.ForeignEnum.DESCRIPTOR)
if api_implementation.Type() != 'cpp':
self.skipTest('Only the C++ implementation correctly indexes all types')
self.assertIs(
pool.FindExtensionByName('protobuf_unittest.optional_int32_extension'),
unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension'])
self.assertIs(
pool.FindOneofByName('protobuf_unittest.TestAllTypes.oneof_field'),
unittest_pb2.TestAllTypes.DESCRIPTOR.oneofs_by_name['oneof_field'])
self.assertIs(
pool.FindServiceByName('protobuf_unittest.TestService'),
unittest_pb2.DESCRIPTOR.services_by_name['TestService'])
def testAddFileDescriptor(self):
# pylint: disable=g-import-not-at-top
from google.protobuf.pyext import _message
pool = _message.default_pool
pool = descriptor_pool.Default()
file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto')
pool.Add(file_desc)
pool.AddSerializedFile(file_desc.SerializeToString())

@ -521,6 +521,12 @@ class GeneratedDescriptorTest(unittest.TestCase):
del enum
self.assertEqual('FOO', next(values_iter).name)
def testServiceDescriptor(self):
service_descriptor = unittest_pb2.DESCRIPTOR.services_by_name['TestService']
self.assertEqual(service_descriptor.name, 'TestService')
self.assertEqual(service_descriptor.methods[0].name, 'Foo')
self.assertIs(service_descriptor.file, unittest_pb2.DESCRIPTOR)
class DescriptorCopyToProtoTest(unittest.TestCase):
"""Tests for CopyTo functions of Descriptor."""

@ -372,7 +372,7 @@ def MapSizer(field_descriptor, is_message_map):
def _VarintEncoder():
"""Return an encoder for a basic varint value (does not include tag)."""
def EncodeVarint(write, value):
def EncodeVarint(write, value, unused_deterministic):
bits = value & 0x7f
value >>= 7
while value:
@ -388,7 +388,7 @@ def _SignedVarintEncoder():
"""Return an encoder for a basic signed varint value (does not include
tag)."""
def EncodeSignedVarint(write, value):
def EncodeSignedVarint(write, value, unused_deterministic):
if value < 0:
value += (1 << 64)
bits = value & 0x7f
@ -411,7 +411,7 @@ def _VarintBytes(value):
called at startup time so it doesn't need to be fast."""
pieces = []
_EncodeVarint(pieces.append, value)
_EncodeVarint(pieces.append, value, True)
return b"".join(pieces)
@ -440,27 +440,27 @@ def _SimpleEncoder(wire_type, encode_value, compute_value_size):
if is_packed:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
local_EncodeVarint = _EncodeVarint
def EncodePackedField(write, value):
def EncodePackedField(write, value, deterministic):
write(tag_bytes)
size = 0
for element in value:
size += compute_value_size(element)
local_EncodeVarint(write, size)
local_EncodeVarint(write, size, deterministic)
for element in value:
encode_value(write, element)
encode_value(write, element, deterministic)
return EncodePackedField
elif is_repeated:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeRepeatedField(write, value):
def EncodeRepeatedField(write, value, deterministic):
for element in value:
write(tag_bytes)
encode_value(write, element)
encode_value(write, element, deterministic)
return EncodeRepeatedField
else:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeField(write, value):
def EncodeField(write, value, deterministic):
write(tag_bytes)
return encode_value(write, value)
return encode_value(write, value, deterministic)
return EncodeField
return SpecificEncoder
@ -474,27 +474,27 @@ def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value):
if is_packed:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
local_EncodeVarint = _EncodeVarint
def EncodePackedField(write, value):
def EncodePackedField(write, value, deterministic):
write(tag_bytes)
size = 0
for element in value:
size += compute_value_size(modify_value(element))
local_EncodeVarint(write, size)
local_EncodeVarint(write, size, deterministic)
for element in value:
encode_value(write, modify_value(element))
encode_value(write, modify_value(element), deterministic)
return EncodePackedField
elif is_repeated:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeRepeatedField(write, value):
def EncodeRepeatedField(write, value, deterministic):
for element in value:
write(tag_bytes)
encode_value(write, modify_value(element))
encode_value(write, modify_value(element), deterministic)
return EncodeRepeatedField
else:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeField(write, value):
def EncodeField(write, value, deterministic):
write(tag_bytes)
return encode_value(write, modify_value(value))
return encode_value(write, modify_value(value), deterministic)
return EncodeField
return SpecificEncoder
@ -515,22 +515,22 @@ def _StructPackEncoder(wire_type, format):
if is_packed:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
local_EncodeVarint = _EncodeVarint
def EncodePackedField(write, value):
def EncodePackedField(write, value, deterministic):
write(tag_bytes)
local_EncodeVarint(write, len(value) * value_size)
local_EncodeVarint(write, len(value) * value_size, deterministic)
for element in value:
write(local_struct_pack(format, element))
return EncodePackedField
elif is_repeated:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeRepeatedField(write, value):
def EncodeRepeatedField(write, value, unused_deterministic):
for element in value:
write(tag_bytes)
write(local_struct_pack(format, element))
return EncodeRepeatedField
else:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeField(write, value):
def EncodeField(write, value, unused_deterministic):
write(tag_bytes)
return write(local_struct_pack(format, value))
return EncodeField
@ -581,9 +581,9 @@ def _FloatingPointEncoder(wire_type, format):
if is_packed:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
local_EncodeVarint = _EncodeVarint
def EncodePackedField(write, value):
def EncodePackedField(write, value, deterministic):
write(tag_bytes)
local_EncodeVarint(write, len(value) * value_size)
local_EncodeVarint(write, len(value) * value_size, deterministic)
for element in value:
# This try/except block is going to be faster than any code that
# we could write to check whether element is finite.
@ -594,7 +594,7 @@ def _FloatingPointEncoder(wire_type, format):
return EncodePackedField
elif is_repeated:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeRepeatedField(write, value):
def EncodeRepeatedField(write, value, unused_deterministic):
for element in value:
write(tag_bytes)
try:
@ -604,7 +604,7 @@ def _FloatingPointEncoder(wire_type, format):
return EncodeRepeatedField
else:
tag_bytes = TagBytes(field_number, wire_type)
def EncodeField(write, value):
def EncodeField(write, value, unused_deterministic):
write(tag_bytes)
try:
write(local_struct_pack(format, value))
@ -650,9 +650,9 @@ def BoolEncoder(field_number, is_repeated, is_packed):
if is_packed:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
local_EncodeVarint = _EncodeVarint
def EncodePackedField(write, value):
def EncodePackedField(write, value, deterministic):
write(tag_bytes)
local_EncodeVarint(write, len(value))
local_EncodeVarint(write, len(value), deterministic)
for element in value:
if element:
write(true_byte)
@ -661,7 +661,7 @@ def BoolEncoder(field_number, is_repeated, is_packed):
return EncodePackedField
elif is_repeated:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
def EncodeRepeatedField(write, value):
def EncodeRepeatedField(write, value, unused_deterministic):
for element in value:
write(tag_bytes)
if element:
@ -671,7 +671,7 @@ def BoolEncoder(field_number, is_repeated, is_packed):
return EncodeRepeatedField
else:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
def EncodeField(write, value):
def EncodeField(write, value, unused_deterministic):
write(tag_bytes)
if value:
return write(true_byte)
@ -687,18 +687,18 @@ def StringEncoder(field_number, is_repeated, is_packed):
local_len = len
assert not is_packed
if is_repeated:
def EncodeRepeatedField(write, value):
def EncodeRepeatedField(write, value, deterministic):
for element in value:
encoded = element.encode('utf-8')
write(tag)
local_EncodeVarint(write, local_len(encoded))
local_EncodeVarint(write, local_len(encoded), deterministic)
write(encoded)
return EncodeRepeatedField
else:
def EncodeField(write, value):
def EncodeField(write, value, deterministic):
encoded = value.encode('utf-8')
write(tag)
local_EncodeVarint(write, local_len(encoded))
local_EncodeVarint(write, local_len(encoded), deterministic)
return write(encoded)
return EncodeField
@ -711,16 +711,16 @@ def BytesEncoder(field_number, is_repeated, is_packed):
local_len = len
assert not is_packed
if is_repeated:
def EncodeRepeatedField(write, value):
def EncodeRepeatedField(write, value, deterministic):
for element in value:
write(tag)
local_EncodeVarint(write, local_len(element))
local_EncodeVarint(write, local_len(element), deterministic)
write(element)
return EncodeRepeatedField
else:
def EncodeField(write, value):
def EncodeField(write, value, deterministic):
write(tag)
local_EncodeVarint(write, local_len(value))
local_EncodeVarint(write, local_len(value), deterministic)
return write(value)
return EncodeField
@ -732,16 +732,16 @@ def GroupEncoder(field_number, is_repeated, is_packed):
end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP)
assert not is_packed
if is_repeated:
def EncodeRepeatedField(write, value):
def EncodeRepeatedField(write, value, deterministic):
for element in value:
write(start_tag)
element._InternalSerialize(write)
element._InternalSerialize(write, deterministic)
write(end_tag)
return EncodeRepeatedField
else:
def EncodeField(write, value):
def EncodeField(write, value, deterministic):
write(start_tag)
value._InternalSerialize(write)
value._InternalSerialize(write, deterministic)
return write(end_tag)
return EncodeField
@ -753,17 +753,17 @@ def MessageEncoder(field_number, is_repeated, is_packed):
local_EncodeVarint = _EncodeVarint
assert not is_packed
if is_repeated:
def EncodeRepeatedField(write, value):
def EncodeRepeatedField(write, value, deterministic):
for element in value:
write(tag)
local_EncodeVarint(write, element.ByteSize())
element._InternalSerialize(write)
local_EncodeVarint(write, element.ByteSize(), deterministic)
element._InternalSerialize(write, deterministic)
return EncodeRepeatedField
else:
def EncodeField(write, value):
def EncodeField(write, value, deterministic):
write(tag)
local_EncodeVarint(write, value.ByteSize())
return value._InternalSerialize(write)
local_EncodeVarint(write, value.ByteSize(), deterministic)
return value._InternalSerialize(write, deterministic)
return EncodeField
@ -790,10 +790,10 @@ def MessageSetItemEncoder(field_number):
end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP)
local_EncodeVarint = _EncodeVarint
def EncodeField(write, value):
def EncodeField(write, value, deterministic):
write(start_bytes)
local_EncodeVarint(write, value.ByteSize())
value._InternalSerialize(write)
local_EncodeVarint(write, value.ByteSize(), deterministic)
value._InternalSerialize(write, deterministic)
return write(end_bytes)
return EncodeField
@ -818,9 +818,10 @@ def MapEncoder(field_descriptor):
message_type = field_descriptor.message_type
encode_message = MessageEncoder(field_descriptor.number, False, False)
def EncodeField(write, value):
for key in value:
def EncodeField(write, value, deterministic):
value_keys = sorted(value.iterkeys()) if deterministic else value.iterkeys()
for key in value_keys:
entry_msg = message_type._concrete_class(key=key, value=value[key])
encode_message(write, entry_msg)
encode_message(write, entry_msg, deterministic)
return EncodeField

@ -97,3 +97,8 @@ message MessageWithNestedEnumOnly {
extend Factory1Message {
optional string another_field = 1002;
}
message MessageWithOption {
option no_standard_descriptor_accessor = true;
optional int32 field1 = 1;
}

@ -49,6 +49,7 @@ from google.protobuf import field_mask_pb2
from google.protobuf import struct_pb2
from google.protobuf import timestamp_pb2
from google.protobuf import wrappers_pb2
from google.protobuf import unittest_mset_pb2
from google.protobuf.internal import well_known_types
from google.protobuf import json_format
from google.protobuf.util import json_format_proto3_pb2
@ -158,6 +159,84 @@ class JsonFormatTest(JsonFormatBase):
json_format.Parse(text, parsed_message)
self.assertEqual(message, parsed_message)
def testExtensionToJsonAndBack(self):
message = unittest_mset_pb2.TestMessageSetContainer()
ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
message.message_set.Extensions[ext1].i = 23
message.message_set.Extensions[ext2].str = 'foo'
message_text = json_format.MessageToJson(
message
)
parsed_message = unittest_mset_pb2.TestMessageSetContainer()
json_format.Parse(message_text, parsed_message)
self.assertEqual(message, parsed_message)
def testExtensionToDictAndBack(self):
message = unittest_mset_pb2.TestMessageSetContainer()
ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
message.message_set.Extensions[ext1].i = 23
message.message_set.Extensions[ext2].str = 'foo'
message_dict = json_format.MessageToDict(
message
)
parsed_message = unittest_mset_pb2.TestMessageSetContainer()
json_format.ParseDict(message_dict, parsed_message)
self.assertEqual(message, parsed_message)
def testExtensionSerializationDictMatchesProto3Spec(self):
"""See go/proto3-json-spec for spec.
"""
message = unittest_mset_pb2.TestMessageSetContainer()
ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
message.message_set.Extensions[ext1].i = 23
message.message_set.Extensions[ext2].str = 'foo'
message_dict = json_format.MessageToDict(
message
)
golden_dict = {
'messageSet': {
'[protobuf_unittest.'
'TestMessageSetExtension1.messageSetExtension]': {
'i': 23,
},
'[protobuf_unittest.'
'TestMessageSetExtension2.messageSetExtension]': {
'str': u'foo',
},
},
}
self.assertEqual(golden_dict, message_dict)
def testExtensionSerializationJsonMatchesProto3Spec(self):
"""See go/proto3-json-spec for spec.
"""
message = unittest_mset_pb2.TestMessageSetContainer()
ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
message.message_set.Extensions[ext1].i = 23
message.message_set.Extensions[ext2].str = 'foo'
message_text = json_format.MessageToJson(
message
)
ext1_text = ('protobuf_unittest.TestMessageSetExtension1.'
'messageSetExtension')
ext2_text = ('protobuf_unittest.TestMessageSetExtension2.'
'messageSetExtension')
golden_text = ('{"messageSet": {'
' "[%s]": {'
' "i": 23'
' },'
' "[%s]": {'
' "str": "foo"'
' }'
'}}') % (ext1_text, ext2_text)
self.assertEqual(json.loads(golden_text), json.loads(message_text))
def testJsonEscapeString(self):
message = json_format_proto3_pb2.TestMessage()
if sys.version_info[0] < 3:
@ -768,7 +847,7 @@ class JsonFormatTest(JsonFormatBase):
text = '{"value": "0000-01-01T00:00:00Z"}'
self.assertRaisesRegexp(
json_format.ParseError,
'Failed to parse value field: year is out of range.',
'Failed to parse value field: year (0 )?is out of range.',
json_format.Parse, text, message)
# Time bigger than maxinum time.
message.value.seconds = 253402300800
@ -840,6 +919,12 @@ class JsonFormatTest(JsonFormatBase):
json_format.Parse('{"int32_value": 12345}', message)
self.assertEqual(12345, message.int32_value)
def testIndent(self):
message = json_format_proto3_pb2.TestMessage()
message.int32_value = 12345
self.assertEqual('{\n"int32Value": 12345\n}',
json_format.MessageToJson(message, indent=0))
def testParseDict(self):
expected = 12345
js_dict = {'int32Value': expected}
@ -862,6 +947,22 @@ class JsonFormatTest(JsonFormatBase):
parsed_message = json_format_proto3_pb2.TestCustomJsonName()
self.CheckParseBack(message, parsed_message)
def testSortKeys(self):
# Testing sort_keys is not perfectly working, as by random luck we could
# get the output sorted. We just use a selection of names.
message = json_format_proto3_pb2.TestMessage(bool_value=True,
int32_value=1,
int64_value=3,
uint32_value=4,
string_value='bla')
self.assertEqual(
json_format.MessageToJson(message, sort_keys=True),
# We use json.dumps() instead of a hardcoded string due to differences
# between Python 2 and Python 3.
json.dumps({'boolValue': True, 'int32Value': 1, 'int64Value': '3',
'uint32Value': 4, 'stringValue': 'bla'},
indent=2, sort_keys=True))
if __name__ == '__main__':
unittest.main()

@ -136,6 +136,39 @@ class MessageTest(BaseTestCase):
golden_copy = copy.deepcopy(golden_message)
self.assertEqual(golden_data, golden_copy.SerializeToString())
def testDeterminismParameters(self, message_module):
# This message is always deterministically serialized, even if determinism
# is disabled, so we can use it to verify that all the determinism
# parameters work correctly.
golden_data = (b'\xe2\x02\nOne string'
b'\xe2\x02\nTwo string'
b'\xe2\x02\nRed string'
b'\xe2\x02\x0bBlue string')
golden_message = message_module.TestAllTypes()
golden_message.repeated_string.extend([
'One string',
'Two string',
'Red string',
'Blue string',
])
self.assertEqual(golden_data,
golden_message.SerializeToString(deterministic=None))
self.assertEqual(golden_data,
golden_message.SerializeToString(deterministic=False))
self.assertEqual(golden_data,
golden_message.SerializeToString(deterministic=True))
class BadArgError(Exception):
pass
class BadArg(object):
def __nonzero__(self):
raise BadArgError()
with self.assertRaises(BadArgError):
golden_message.SerializeToString(deterministic=BadArg())
def testPickleSupport(self, message_module):
golden_data = test_util.GoldenFileData('golden_message')
golden_message = message_module.TestAllTypes()
@ -377,6 +410,7 @@ class MessageTest(BaseTestCase):
self.assertEqual(message.repeated_int32[0], 1)
self.assertEqual(message.repeated_int32[1], 2)
self.assertEqual(message.repeated_int32[2], 3)
self.assertEqual(str(message.repeated_int32), str([1, 2, 3]))
message.repeated_float.append(1.1)
message.repeated_float.append(1.3)
@ -393,6 +427,7 @@ class MessageTest(BaseTestCase):
self.assertEqual(message.repeated_string[0], 'a')
self.assertEqual(message.repeated_string[1], 'b')
self.assertEqual(message.repeated_string[2], 'c')
self.assertEqual(str(message.repeated_string), str([u'a', u'b', u'c']))
message.repeated_bytes.append(b'a')
message.repeated_bytes.append(b'c')
@ -401,6 +436,7 @@ class MessageTest(BaseTestCase):
self.assertEqual(message.repeated_bytes[0], b'a')
self.assertEqual(message.repeated_bytes[1], b'b')
self.assertEqual(message.repeated_bytes[2], b'c')
self.assertEqual(str(message.repeated_bytes), str([b'a', b'b', b'c']))
def testSortingRepeatedScalarFieldsCustomComparator(self, message_module):
"""Check some different types with custom comparator."""
@ -439,6 +475,8 @@ class MessageTest(BaseTestCase):
self.assertEqual(message.repeated_nested_message[3].bb, 4)
self.assertEqual(message.repeated_nested_message[4].bb, 5)
self.assertEqual(message.repeated_nested_message[5].bb, 6)
self.assertEqual(str(message.repeated_nested_message),
'[bb: 1\n, bb: 2\n, bb: 3\n, bb: 4\n, bb: 5\n, bb: 6\n]')
def testSortingRepeatedCompositeFieldsStable(self, message_module):
"""Check passing a custom comparator to sort a repeated composite field."""
@ -1266,6 +1304,14 @@ class Proto3Test(BaseTestCase):
self.assertEqual(1234567, m2.optional_nested_enum)
self.assertEqual(7654321, m2.repeated_nested_enum[0])
# ParseFromString in Proto2 should accept unknown enums too.
m3 = unittest_pb2.TestAllTypes()
m3.ParseFromString(serialized)
m2.Clear()
m2.ParseFromString(m3.SerializeToString())
self.assertEqual(1234567, m2.optional_nested_enum)
self.assertEqual(7654321, m2.repeated_nested_enum[0])
# Map isn't really a proto3-only feature. But there is no proto2 equivalent
# of google/protobuf/map_unittest.proto right now, so it's not easy to
# test both with the same test like we do for the other proto2/proto3 tests.
@ -1437,6 +1483,23 @@ class Proto3Test(BaseTestCase):
self.assertIn(-456, msg2.map_int32_foreign_message)
self.assertEqual(2, len(msg2.map_int32_foreign_message))
def testNestedMessageMapItemDelete(self):
msg = map_unittest_pb2.TestMap()
msg.map_int32_all_types[1].optional_nested_message.bb = 1
del msg.map_int32_all_types[1]
msg.map_int32_all_types[2].optional_nested_message.bb = 2
self.assertEqual(1, len(msg.map_int32_all_types))
msg.map_int32_all_types[1].optional_nested_message.bb = 1
self.assertEqual(2, len(msg.map_int32_all_types))
serialized = msg.SerializeToString()
msg2 = map_unittest_pb2.TestMap()
msg2.ParseFromString(serialized)
keys = [1, 2]
# The loop triggers PyErr_Occurred() in c extension.
for key in keys:
del msg2.map_int32_all_types[key]
def testMapByteSize(self):
msg = map_unittest_pb2.TestMap()
msg.map_int32_int32[1] = 1
@ -1651,6 +1714,35 @@ class Proto3Test(BaseTestCase):
items2 = msg.map_string_string.items()
self.assertEqual(items1, items2)
def testMapDeterministicSerialization(self):
golden_data = (b'r\x0c\n\x07init_op\x12\x01d'
b'r\n\n\x05item1\x12\x01e'
b'r\n\n\x05item2\x12\x01f'
b'r\n\n\x05item3\x12\x01g'
b'r\x0b\n\x05item4\x12\x02QQ'
b'r\x12\n\rlocal_init_op\x12\x01a'
b'r\x0e\n\tsummaries\x12\x01e'
b'r\x18\n\x13trainable_variables\x12\x01b'
b'r\x0e\n\tvariables\x12\x01c')
msg = map_unittest_pb2.TestMap()
msg.map_string_string['local_init_op'] = 'a'
msg.map_string_string['trainable_variables'] = 'b'
msg.map_string_string['variables'] = 'c'
msg.map_string_string['init_op'] = 'd'
msg.map_string_string['summaries'] = 'e'
msg.map_string_string['item1'] = 'e'
msg.map_string_string['item2'] = 'f'
msg.map_string_string['item3'] = 'g'
msg.map_string_string['item4'] = 'QQ'
# If deterministic serialization is not working correctly, this will be
# "flaky" depending on the exact python dict hash seed.
#
# Fortunately, there are enough items in this map that it is extremely
# unlikely to ever hit the "right" in-order combination, so the test
# itself should fail reliably.
self.assertEqual(golden_data, msg.SerializeToString(deterministic=True))
def testMapIterationClearMessage(self):
# Iterator needs to work even if message and map are deleted.
msg = map_unittest_pb2.TestMap()

@ -47,4 +47,5 @@ message DynamicMessageType {
extend ExtendedMessage {
optional int32 dynamic_int32_extension = 100;
optional DynamicMessageType dynamic_message_extension = 101;
repeated DynamicMessageType repeated_dynamic_message_extension = 102;
}

@ -58,6 +58,7 @@ import weakref
import six
# We use "as" to avoid name collisions with variables.
from google.protobuf.internal import api_implementation
from google.protobuf.internal import containers
from google.protobuf.internal import decoder
from google.protobuf.internal import encoder
@ -1026,29 +1027,34 @@ def _AddByteSizeMethod(message_descriptor, cls):
def _AddSerializeToStringMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
def SerializeToString(self):
def SerializeToString(self, **kwargs):
# Check if the message has all of its required fields set.
errors = []
if not self.IsInitialized():
raise message_mod.EncodeError(
'Message %s is missing required fields: %s' % (
self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
return self.SerializePartialToString()
return self.SerializePartialToString(**kwargs)
cls.SerializeToString = SerializeToString
def _AddSerializePartialToStringMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
def SerializePartialToString(self):
def SerializePartialToString(self, **kwargs):
out = BytesIO()
self._InternalSerialize(out.write)
self._InternalSerialize(out.write, **kwargs)
return out.getvalue()
cls.SerializePartialToString = SerializePartialToString
def InternalSerialize(self, write_bytes):
def InternalSerialize(self, write_bytes, deterministic=None):
if deterministic is None:
deterministic = (
api_implementation.IsPythonDefaultSerializationDeterministic())
else:
deterministic = bool(deterministic)
for field_descriptor, field_value in self.ListFields():
field_descriptor._encoder(write_bytes, field_value)
field_descriptor._encoder(write_bytes, field_value, deterministic)
for tag_bytes, value_bytes in self._unknown_fields:
write_bytes(tag_bytes)
write_bytes(value_bytes)

@ -452,16 +452,18 @@ class TextFormatTest(TextFormatBase):
text_format.Parse(text_format.MessageToString(m), m2)
self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
def testMergeMultipleOneof(self, message_module):
m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"'])
m2 = message_module.TestAllTypes()
text_format.Merge(m_string, m2)
self.assertEqual('oneof_string', m2.WhichOneof('oneof_field'))
def testParseMultipleOneof(self, message_module):
m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"'])
m2 = message_module.TestAllTypes()
if message_module is unittest_pb2:
with self.assertRaisesRegexp(text_format.ParseError,
' is specified along with field '):
text_format.Parse(m_string, m2)
else:
with self.assertRaisesRegexp(text_format.ParseError,
' is specified along with field '):
text_format.Parse(m_string, m2)
self.assertEqual('oneof_string', m2.WhichOneof('oneof_field'))
# These are tests that aren't fundamentally specific to proto2, but are at
@ -1026,8 +1028,7 @@ class Proto3Tests(unittest.TestCase):
packed_message.data = 'string1'
message.repeated_any_value.add().Pack(packed_message)
self.assertEqual(
text_format.MessageToString(message,
descriptor_pool=descriptor_pool.Default()),
text_format.MessageToString(message),
'repeated_any_value {\n'
' [type.googleapis.com/protobuf_unittest.OneString] {\n'
' data: "string0"\n'
@ -1039,18 +1040,6 @@ class Proto3Tests(unittest.TestCase):
' }\n'
'}\n')
def testPrintMessageExpandAnyNoDescriptorPool(self):
packed_message = unittest_pb2.OneString()
packed_message.data = 'string'
message = any_test_pb2.TestAny()
message.any_value.Pack(packed_message)
self.assertEqual(
text_format.MessageToString(message, descriptor_pool=None),
'any_value {\n'
' type_url: "type.googleapis.com/protobuf_unittest.OneString"\n'
' value: "\\n\\006string"\n'
'}\n')
def testPrintMessageExpandAnyDescriptorPoolMissingType(self):
packed_message = unittest_pb2.OneString()
packed_message.data = 'string'
@ -1071,8 +1060,7 @@ class Proto3Tests(unittest.TestCase):
message.any_value.Pack(packed_message)
self.assertEqual(
text_format.MessageToString(message,
pointy_brackets=True,
descriptor_pool=descriptor_pool.Default()),
pointy_brackets=True),
'any_value <\n'
' [type.googleapis.com/protobuf_unittest.OneString] <\n'
' data: "string"\n'
@ -1086,8 +1074,7 @@ class Proto3Tests(unittest.TestCase):
message.any_value.Pack(packed_message)
self.assertEqual(
text_format.MessageToString(message,
as_one_line=True,
descriptor_pool=descriptor_pool.Default()),
as_one_line=True),
'any_value {'
' [type.googleapis.com/protobuf_unittest.OneString]'
' { data: "string" } '
@ -1115,12 +1102,12 @@ class Proto3Tests(unittest.TestCase):
' data: "string"\n'
' }\n'
'}\n')
text_format.Merge(text, message, descriptor_pool=descriptor_pool.Default())
text_format.Merge(text, message)
packed_message = unittest_pb2.OneString()
message.any_value.Unpack(packed_message)
self.assertEqual('string', packed_message.data)
message.Clear()
text_format.Parse(text, message, descriptor_pool=descriptor_pool.Default())
text_format.Parse(text, message)
packed_message = unittest_pb2.OneString()
message.any_value.Unpack(packed_message)
self.assertEqual('string', packed_message.data)
@ -1137,7 +1124,7 @@ class Proto3Tests(unittest.TestCase):
' data: "string1"\n'
' }\n'
'}\n')
text_format.Merge(text, message, descriptor_pool=descriptor_pool.Default())
text_format.Merge(text, message)
packed_message = unittest_pb2.OneString()
message.repeated_any_value[0].Unpack(packed_message)
self.assertEqual('string0', packed_message.data)
@ -1151,22 +1138,22 @@ class Proto3Tests(unittest.TestCase):
' data: "string"\n'
' >\n'
'}\n')
text_format.Merge(text, message, descriptor_pool=descriptor_pool.Default())
text_format.Merge(text, message)
packed_message = unittest_pb2.OneString()
message.any_value.Unpack(packed_message)
self.assertEqual('string', packed_message.data)
def testMergeExpandedAnyNoDescriptorPool(self):
def testMergeAlternativeUrl(self):
message = any_test_pb2.TestAny()
text = ('any_value {\n'
' [type.googleapis.com/protobuf_unittest.OneString] {\n'
' [type.otherapi.com/protobuf_unittest.OneString] {\n'
' data: "string"\n'
' }\n'
'}\n')
with self.assertRaises(text_format.ParseError) as e:
text_format.Merge(text, message, descriptor_pool=None)
self.assertEqual(str(e.exception),
'Descriptor pool required to parse expanded Any field')
text_format.Merge(text, message)
packed_message = unittest_pb2.OneString()
self.assertEqual('type.otherapi.com/protobuf_unittest.OneString',
message.any_value.type_url)
def testMergeExpandedAnyDescriptorPoolMissingType(self):
message = any_test_pb2.TestAny()
@ -1425,5 +1412,101 @@ class TokenizerTest(unittest.TestCase):
tokenizer.ConsumeCommentOrTrailingComment())
self.assertTrue(tokenizer.AtEnd())
# Tests for pretty printer functionality.
@_parameterized.Parameters((unittest_pb2), (unittest_proto3_arena_pb2))
class PrettyPrinterTest(TextFormatBase):
def testPrettyPrintNoMatch(self, message_module):
def printer(message, indent, as_one_line):
del message, indent, as_one_line
return None
message = message_module.TestAllTypes()
msg = message.repeated_nested_message.add()
msg.bb = 42
self.CompareToGoldenText(
text_format.MessageToString(
message, as_one_line=True, message_formatter=printer),
'repeated_nested_message { bb: 42 }')
def testPrettyPrintOneLine(self, message_module):
def printer(m, indent, as_one_line):
del indent, as_one_line
if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR:
return 'My lucky number is %s' % m.bb
message = message_module.TestAllTypes()
msg = message.repeated_nested_message.add()
msg.bb = 42
self.CompareToGoldenText(
text_format.MessageToString(
message, as_one_line=True, message_formatter=printer),
'repeated_nested_message { My lucky number is 42 }')
def testPrettyPrintMultiLine(self, message_module):
def printer(m, indent, as_one_line):
if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR:
line_deliminator = (' ' if as_one_line else '\n') + ' ' * indent
return 'My lucky number is:%s%s' % (line_deliminator, m.bb)
return None
message = message_module.TestAllTypes()
msg = message.repeated_nested_message.add()
msg.bb = 42
self.CompareToGoldenText(
text_format.MessageToString(
message, as_one_line=True, message_formatter=printer),
'repeated_nested_message { My lucky number is: 42 }')
self.CompareToGoldenText(
text_format.MessageToString(
message, as_one_line=False, message_formatter=printer),
'repeated_nested_message {\n My lucky number is:\n 42\n}\n')
def testPrettyPrintEntireMessage(self, message_module):
def printer(m, indent, as_one_line):
del indent, as_one_line
if m.DESCRIPTOR == message_module.TestAllTypes.DESCRIPTOR:
return 'The is the message!'
return None
message = message_module.TestAllTypes()
self.CompareToGoldenText(
text_format.MessageToString(
message, as_one_line=False, message_formatter=printer),
'The is the message!\n')
self.CompareToGoldenText(
text_format.MessageToString(
message, as_one_line=True, message_formatter=printer),
'The is the message!')
def testPrettyPrintMultipleParts(self, message_module):
def printer(m, indent, as_one_line):
del indent, as_one_line
if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR:
return 'My lucky number is %s' % m.bb
return None
message = message_module.TestAllTypes()
message.optional_int32 = 61
msg = message.repeated_nested_message.add()
msg.bb = 42
msg = message.repeated_nested_message.add()
msg.bb = 99
msg = message.optional_nested_message
msg.bb = 1
self.CompareToGoldenText(
text_format.MessageToString(
message, as_one_line=True, message_formatter=printer),
('optional_int32: 61 '
'optional_nested_message { My lucky number is 1 } '
'repeated_nested_message { My lucky number is 42 } '
'repeated_nested_message { My lucky number is 99 }'))
if __name__ == '__main__':
unittest.main()

@ -350,12 +350,12 @@ class Duration(object):
self.nanos, _NANOS_PER_MICROSECOND))
def FromTimedelta(self, td):
"""Convertd timedelta to Duration."""
"""Converts timedelta to Duration."""
self._NormalizeDuration(td.seconds + td.days * _SECONDS_PER_DAY,
td.microseconds * _NANOS_PER_MICROSECOND)
def _NormalizeDuration(self, seconds, nanos):
"""Set Duration by seconds and nonas."""
"""Set Duration by seconds and nanos."""
# Force nanos to be negative if the duration is negative.
if seconds < 0 and nanos > 0:
seconds += 1

@ -284,7 +284,7 @@ class TimeUtilTest(TimeUtilTestBase):
'1972-01-01T01:00:00.01+08',)
self.assertRaisesRegexp(
ValueError,
'year is out of range',
'year (0 )?is out of range',
message.FromJsonString,
'0000-01-01T00:00:00Z')
message.seconds = 253402300800

@ -74,6 +74,9 @@ _UNPAIRED_SURROGATE_PATTERN = re.compile(six.u(
r'[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]'
))
_VALID_EXTENSION_NAME = re.compile(r'\[[a-zA-Z0-9\._]*\]$')
class Error(Exception):
"""Top-level module error for json_format."""
@ -88,7 +91,9 @@ class ParseError(Error):
def MessageToJson(message,
including_default_value_fields=False,
preserving_proto_field_name=False):
preserving_proto_field_name=False,
indent=2,
sort_keys=False):
"""Converts protobuf message to JSON format.
Args:
@ -100,19 +105,24 @@ def MessageToJson(message,
preserving_proto_field_name: If True, use the original proto field
names as defined in the .proto file. If False, convert the field
names to lowerCamelCase.
indent: The JSON object will be pretty-printed with this indent level.
An indent level of 0 or negative will only insert newlines.
sort_keys: If True, then the output will be sorted by field names.
Returns:
A string containing the JSON formatted protocol buffer message.
"""
printer = _Printer(including_default_value_fields,
preserving_proto_field_name)
return printer.ToJsonString(message)
return printer.ToJsonString(message, indent, sort_keys)
def MessageToDict(message,
including_default_value_fields=False,
preserving_proto_field_name=False):
"""Converts protobuf message to a JSON dictionary.
"""Converts protobuf message to a dictionary.
When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
Args:
message: The protocol buffers message instance to serialize.
@ -125,7 +135,7 @@ def MessageToDict(message,
names to lowerCamelCase.
Returns:
A dict representation of the JSON formatted protocol buffer message.
A dict representation of the protocol buffer message.
"""
printer = _Printer(including_default_value_fields,
preserving_proto_field_name)
@ -148,9 +158,9 @@ class _Printer(object):
self.including_default_value_fields = including_default_value_fields
self.preserving_proto_field_name = preserving_proto_field_name
def ToJsonString(self, message):
def ToJsonString(self, message, indent, sort_keys):
js = self._MessageToJsonObject(message)
return json.dumps(js, indent=2)
return json.dumps(js, indent=indent, sort_keys=sort_keys)
def _MessageToJsonObject(self, message):
"""Converts message to an object according to Proto3 JSON Specification."""
@ -192,6 +202,14 @@ class _Printer(object):
# Convert a repeated field.
js[name] = [self._FieldToJsonObject(field, k)
for k in value]
elif field.is_extension:
f = field
if (f.containing_type.GetOptions().message_set_wire_format and
f.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
f.label == descriptor.FieldDescriptor.LABEL_OPTIONAL):
f = f.message_type
name = '[%s.%s]' % (f.full_name, name)
js[name] = self._FieldToJsonObject(field, value)
else:
js[name] = self._FieldToJsonObject(field, value)
@ -433,12 +451,23 @@ class _Parser(object):
field = fields_by_json_name.get(name, None)
if not field:
field = message_descriptor.fields_by_name.get(name, None)
if not field and _VALID_EXTENSION_NAME.match(name):
if not message_descriptor.is_extendable:
raise ParseError('Message type {0} does not have extensions'.format(
message_descriptor.full_name))
identifier = name[1:-1] # strip [] brackets
identifier = '.'.join(identifier.split('.')[:-1])
# pylint: disable=protected-access
field = message.Extensions._FindExtensionByName(identifier)
# pylint: enable=protected-access
if not field:
if self.ignore_unknown_fields:
continue
raise ParseError(
'Message type "{0}" has no field named "{1}".'.format(
message_descriptor.full_name, name))
('Message type "{0}" has no field named "{1}".\n'
' Available Fields(except extensions): {2}').format(
message_descriptor.full_name, name,
message_descriptor.fields))
if name in names:
raise ParseError('Message type "{0}" should not have multiple '
'"{1}" fields.'.format(
@ -491,7 +520,10 @@ class _Parser(object):
getattr(message, field.name).append(
_ConvertScalarFieldValue(item, field))
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
sub_message = getattr(message, field.name)
if field.is_extension:
sub_message = message.Extensions[field]
else:
sub_message = getattr(message, field.name)
sub_message.SetInParent()
self.ConvertMessage(value, sub_message)
else:
@ -532,8 +564,8 @@ class _Parser(object):
def _ConvertGenericMessage(self, value, message):
"""Convert a JSON representation into message with FromJsonString."""
# Durantion, Timestamp, FieldMask have FromJsonString method to do the
# convert. Users can also call the method directly.
# Duration, Timestamp, FieldMask have a FromJsonString method to do the
# conversion. Users can also call the method directly.
message.FromJsonString(value)
def _ConvertValueMessage(self, value, message):

@ -184,9 +184,15 @@ class Message(object):
self.Clear()
self.MergeFromString(serialized)
def SerializeToString(self):
def SerializeToString(self, **kwargs):
"""Serializes the protocol message to a binary string.
Arguments:
**kwargs: Keyword arguments to the serialize method, accepts
the following keyword args:
deterministic: If true, requests deterministic serialization of the
protobuf, with predictable ordering of map keys.
Returns:
A binary string representation of the message if all of the required
fields in the message are set (i.e. the message is initialized).
@ -196,12 +202,18 @@ class Message(object):
"""
raise NotImplementedError
def SerializePartialToString(self):
def SerializePartialToString(self, **kwargs):
"""Serializes the protocol message to a binary string.
This method is similar to SerializeToString but doesn't check if the
message is initialized.
Arguments:
**kwargs: Keyword arguments to the serialize method, accepts
the following keyword args:
deterministic: If true, requests deterministic serialization of the
protobuf, with predictable ordering of map keys.
Returns:
A string representation of the partial message.
"""

@ -66,7 +66,7 @@ class MessageFactory(object):
Returns:
A class describing the passed in descriptor.
"""
if descriptor.full_name not in self._classes:
if descriptor not in self._classes:
descriptor_name = descriptor.name
if str is bytes: # PY2
descriptor_name = descriptor.name.encode('ascii', 'ignore')
@ -75,16 +75,16 @@ class MessageFactory(object):
(message.Message,),
{'DESCRIPTOR': descriptor, '__module__': None})
# If module not set, it wrongly points to the reflection.py module.
self._classes[descriptor.full_name] = result_class
self._classes[descriptor] = result_class
for field in descriptor.fields:
if field.message_type:
self.GetPrototype(field.message_type)
for extension in result_class.DESCRIPTOR.extensions:
if extension.containing_type.full_name not in self._classes:
if extension.containing_type not in self._classes:
self.GetPrototype(extension.containing_type)
extended_class = self._classes[extension.containing_type.full_name]
extended_class = self._classes[extension.containing_type]
extended_class.RegisterExtension(extension)
return self._classes[descriptor.full_name]
return self._classes[descriptor]
def GetMessages(self, files):
"""Gets all the messages from a specified file.
@ -116,9 +116,9 @@ class MessageFactory(object):
# an error if they were different.
for extension in file_desc.extensions_by_name.values():
if extension.containing_type.full_name not in self._classes:
if extension.containing_type not in self._classes:
self.GetPrototype(extension.containing_type)
extended_class = self._classes[extension.containing_type.full_name]
extended_class = self._classes[extension.containing_type]
extended_class.RegisterExtension(extension)
return result

@ -709,6 +709,10 @@ static PyObject* GetJsonName(PyBaseDescriptor* self, void *closure) {
return PyString_FromCppString(_GetDescriptor(self)->json_name());
}
static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
}
static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->type());
}
@ -899,6 +903,7 @@ static PyGetSetDef Getters[] = {
{ "name", (getter)GetName, NULL, "Unqualified name"},
{ "camelcase_name", (getter)GetCamelcaseName, NULL, "Camelcase name"},
{ "json_name", (getter)GetJsonName, NULL, "Json name"},
{ "file", (getter)GetFile, NULL, "File Descriptor"},
{ "type", (getter)GetType, NULL, "C++ Type"},
{ "cpp_type", (getter)GetCppType, NULL, "C++ Type"},
{ "label", (getter)GetLabel, NULL, "Label"},
@ -1570,6 +1575,10 @@ static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
return PyString_FromCppString(_GetDescriptor(self)->full_name());
}
static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
}
static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
return PyInt_FromLong(_GetDescriptor(self)->index());
}
@ -1611,6 +1620,7 @@ static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
static PyGetSetDef Getters[] = {
{ "name", (getter)GetName, NULL, "Name", NULL},
{ "full_name", (getter)GetFullName, NULL, "Full name", NULL},
{ "file", (getter)GetFile, NULL, "File descriptor"},
{ "index", (getter)GetIndex, NULL, "Index", NULL},
{ "methods", (getter)GetMethods, NULL, "Methods", NULL},

@ -712,8 +712,30 @@ int MapReflectionFriend::MessageMapSetItem(PyObject* _self, PyObject* key,
}
// Delete key from map.
if (reflection->DeleteMapValue(message, self->parent_field_descriptor,
if (reflection->ContainsMapKey(*message, self->parent_field_descriptor,
map_key)) {
// Delete key from CMessage dict.
MapValueRef value;
reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
map_key, &value);
ScopedPyObjectPtr key(PyLong_FromVoidPtr(value.MutableMessageValue()));
// PyDict_DelItem will have key error if the key is not in the map. We do
// not want to call PyErr_Clear() which may clear other errors. Thus
// PyDict_Contains() check is called before delete.
int contains = PyDict_Contains(self->message_dict, key.get());
if (contains < 0) {
return -1;
}
if (contains) {
if (PyDict_DelItem(self->message_dict, key.get()) < 0) {
return -1;
}
}
// Delete key from map.
reflection->DeleteMapValue(message, self->parent_field_descriptor,
map_key);
return 0;
} else {
PyErr_Format(PyExc_KeyError, "Key not present in map");

@ -52,6 +52,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/util/message_differencer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
@ -1808,8 +1809,25 @@ static string GetMessageName(CMessage* self) {
}
}
static PyObject* SerializeToString(CMessage* self, PyObject* args) {
if (!self->message->IsInitialized()) {
static PyObject* InternalSerializeToString(
CMessage* self, PyObject* args, PyObject* kwargs,
bool require_initialized) {
// Parse the "deterministic" kwarg; defaults to False.
static char* kwlist[] = { "deterministic", 0 };
PyObject* deterministic_obj = Py_None;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
&deterministic_obj)) {
return NULL;
}
// Preemptively convert to a bool first, so we don't need to back out of
// allocating memory if this raises an exception.
// NOTE: This is unused later if deterministic == Py_None, but that's fine.
int deterministic = PyObject_IsTrue(deterministic_obj);
if (deterministic < 0) {
return NULL;
}
if (require_initialized && !self->message->IsInitialized()) {
ScopedPyObjectPtr errors(FindInitializationErrors(self));
if (errors == NULL) {
return NULL;
@ -1847,24 +1865,36 @@ static PyObject* SerializeToString(CMessage* self, PyObject* args) {
GetMessageName(self).c_str(), PyString_AsString(joined.get()));
return NULL;
}
int size = self->message->ByteSize();
if (size <= 0) {
// Ok, arguments parsed and errors checked, now encode to a string
const size_t size = self->message->ByteSizeLong();
if (size == 0) {
return PyBytes_FromString("");
}
PyObject* result = PyBytes_FromStringAndSize(NULL, size);
if (result == NULL) {
return NULL;
}
char* buffer = PyBytes_AS_STRING(result);
self->message->SerializeWithCachedSizesToArray(
reinterpret_cast<uint8*>(buffer));
io::ArrayOutputStream out(PyBytes_AS_STRING(result), size);
io::CodedOutputStream coded_out(&out);
if (deterministic_obj != Py_None) {
coded_out.SetSerializationDeterministic(deterministic);
}
self->message->SerializeWithCachedSizes(&coded_out);
GOOGLE_CHECK(!coded_out.HadError());
return result;
}
static PyObject* SerializePartialToString(CMessage* self) {
string contents;
self->message->SerializePartialToString(&contents);
return PyBytes_FromStringAndSize(contents.c_str(), contents.size());
static PyObject* SerializeToString(
CMessage* self, PyObject* args, PyObject* kwargs) {
return InternalSerializeToString(self, args, kwargs,
/*require_initialized=*/true);
}
static PyObject* SerializePartialToString(
CMessage* self, PyObject* args, PyObject* kwargs) {
return InternalSerializeToString(self, args, kwargs,
/*require_initialized=*/false);
}
// Formats proto fields for ascii dumps using python formatting functions where
@ -2535,7 +2565,10 @@ PyObject* Reduce(CMessage* self) {
if (state == NULL) {
return NULL;
}
ScopedPyObjectPtr serialized(SerializePartialToString(self));
string contents;
self->message->SerializePartialToString(&contents);
ScopedPyObjectPtr serialized(
PyBytes_FromStringAndSize(contents.c_str(), contents.size()));
if (serialized == NULL) {
return NULL;
}
@ -2656,9 +2689,10 @@ static PyMethodDef Methods[] = {
{ "RegisterExtension", (PyCFunction)RegisterExtension, METH_O | METH_CLASS,
"Registers an extension with the current message." },
{ "SerializePartialToString", (PyCFunction)SerializePartialToString,
METH_NOARGS,
METH_VARARGS | METH_KEYWORDS,
"Serializes the message to a string, even if it isn't initialized." },
{ "SerializeToString", (PyCFunction)SerializeToString, METH_NOARGS,
{ "SerializeToString", (PyCFunction)SerializeToString,
METH_VARARGS | METH_KEYWORDS,
"Serializes the message to a string, only for initialized messages." },
{ "SetInParent", (PyCFunction)SetInParent, METH_NOARGS,
"Sets the has bit of the given field in its parent message." },

@ -133,11 +133,7 @@ int RegisterMessageClass(PyMessageFactory* self,
CMessageClass* GetOrCreateMessageClass(PyMessageFactory* self,
const Descriptor* descriptor) {
// This is the same implementation as MessageFactory.GetPrototype().
ScopedPyObjectPtr py_descriptor(
PyMessageDescriptor_FromDescriptor(descriptor));
if (py_descriptor == NULL) {
return NULL;
}
// Do not create a MessageClass that already exists.
hash_map<const Descriptor*, CMessageClass*>::iterator it =
self->classes_by_descriptor->find(descriptor);
@ -145,6 +141,11 @@ CMessageClass* GetOrCreateMessageClass(PyMessageFactory* self,
Py_INCREF(it->second);
return it->second;
}
ScopedPyObjectPtr py_descriptor(
PyMessageDescriptor_FromDescriptor(descriptor));
if (py_descriptor == NULL) {
return NULL;
}
// Create a new message class.
ScopedPyObjectPtr args(Py_BuildValue(
"s(){sOsOsO}", descriptor->name().c_str(),

@ -46,6 +46,7 @@
#include <google/protobuf/pyext/descriptor.h>
#include <google/protobuf/pyext/descriptor_pool.h>
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/message_factory.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#include <google/protobuf/reflection.h>
@ -137,9 +138,12 @@ static PyObject* AddToAttached(RepeatedCompositeContainer* self,
if (cmessage::AssureWritable(self->parent) == -1)
return NULL;
Message* message = self->message;
Message* sub_message =
message->GetReflection()->AddMessage(message,
self->parent_field_descriptor);
message->GetReflection()->AddMessage(
message,
self->parent_field_descriptor,
self->child_message_class->py_message_factory->message_factory);
CMessage* cmsg = cmessage::NewEmptyMessage(self->child_message_class);
if (cmsg == NULL)
return NULL;
@ -335,6 +339,18 @@ static PyObject* RichCompare(RepeatedCompositeContainer* self,
}
}
static PyObject* ToStr(RepeatedCompositeContainer* self) {
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
if (full_slice == NULL) {
return NULL;
}
ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
if (list == NULL) {
return NULL;
}
return PyObject_Repr(list.get());
}
// ---------------------------------------------------------------------
// sort()
@ -607,7 +623,7 @@ PyTypeObject RepeatedCompositeContainer_Type = {
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
(reprfunc)repeated_composite_container::ToStr, // tp_repr
0, // tp_as_number
&repeated_composite_container::SqMethods, // tp_as_sequence
&repeated_composite_container::MpMethods, // tp_as_mapping

@ -656,6 +656,18 @@ static PyObject* Pop(RepeatedScalarContainer* self,
return item;
}
static PyObject* ToStr(RepeatedScalarContainer* self) {
ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
if (full_slice == NULL) {
return NULL;
}
ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
if (list == NULL) {
return NULL;
}
return PyObject_Repr(list.get());
}
// The private constructor of RepeatedScalarContainer objects.
PyObject *NewContainer(
CMessage* parent, const FieldDescriptor* parent_field_descriptor) {
@ -778,7 +790,7 @@ PyTypeObject RepeatedScalarContainer_Type = {
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
(reprfunc)repeated_scalar_container::ToStr, // tp_repr
0, // tp_as_number
&repeated_scalar_container::SqMethods, // tp_as_sequence
&repeated_scalar_container::MpMethods, // tp_as_mapping

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save